Friday, December 30, 2011

Duplicate CFArgument Gotcha!

Today I was debugging a component which returned a query for a paginated display.

This component has the page number and limit passed in, but also has default values set in the CFArgument tags.

At some point during development (probably while copy-pasting a bunch of cfargument tags for quick editing of names and default values) one of the arguments was left twice.

At appeared something like this:

<cfcomponent ...>
<cffunction name="queryrecs" access="public" output="No" returntype="query">
<cfargument name="someid" type="numeric" required="No" default="0">
<cfargument name="something" type="string" required="No" default="">
<cfargument name="somethingelse" type="string" required="No" default="">
<cfargument name="anotherthing" type="string" required="No" default="">
<cfargument name="page" type="numeric" required="No" default="1">
<cfargument name="limit" type="numeric" required="No" default="10">
<cfargument name="limit" type="numeric" required="No" default="10">

<cfset var pagerecs = "">
<cfquery name="pagerecs">
select ...
from ...
where ...
LIMIT #arguments.limit# OFFSET #(arguments.page-1)*arguments.limit#
</cfquery>
<cfreturn pagerecs />
</cffunction>
</cfcomponent>


Notice the two limit arguments. This is really bad. When the method is called and the "limit" parameter passed in the first cfargument tag catches the passed in "limit" parameter and the second "limit" cfargument tag overwrites the passed in set value in the ARGUMENTS scope to the default value.

It's just something to be mindful of when things aren't working as expected.

That's a wrap!

Saturday, December 17, 2011

Focus Text Input at the End of the Value [SOLVED CROSS BROWSER]

I just saved the world! It didn't notice, so I have to blog about it.

I discovered a super simple, fully cross-browser compatible, solution to focusing a text input at the end of the current value.

I needed to do this as part of the application I am currently working on. The html block, including the search input field, are returned form an ajax call and replace the existing HTML within the specified block. After the ajax call returns and replaces the content it needs to focus the input field at the end of the input value.

Moving the cursor, cross-browser friendly, is always messy. I had been dealing with character codes to clear the field on escape and to submit on the enter key, so I get this idea, 'Why not append the 'character' from the key code for the "END" key onto the input value after focusing it?' If that worked, someone would have done it before. In theory this would be done by appending String.fromCharCode(35) to the current value. Would that move the cursor to the end? I try it, it doesn't work.

My next idea was to just set the value as the "END" key. My thought was that it's not a visible character, so maybe it's a more of an instruction key, so-to-speak, and won't mess things up. I try it, it blanks out the value - not what I wanted, but it was worth a try.

So then I try saving the original value in a variable, then set the value to "END" key (clearing the input as before), then re-set the value to the original value. 'This is nuts!' I'm thinking to myself, 'Why am I even trying this?' but I try it anyway. It worked, wait, what??? Yes, it worked!!! I couldn't believe it. I had to test it a hundred times. It's working solid. Unbelievable. I even put the cursor in the middle of the word and hit enter (triggering the ajax) and it replaces the content block, focuses the input, and the cursor appears at the end right where I want it. This is too cool. I'm in Firefox, I re-test it in Chrome, Safari, both work. This is crazy-good news! I'm thinking, but it's sure to fail in IE, everything cool always fails in IE. I'm on my macbook pro, so I load up my Virtualbox with multiple IE's installed on an old Windows XP instance and I test my code. Low and behold, it works in IE7 and in IE8. I'm astonished! Litterally, my jaw dropped, followed by that irresistible smile of success.

I'm still not entire sure *why* it's actually working. The 'END' key must be sticky in some manner so that when the value is replaced it's inserted in front of the cursor. It doesn't make perfect sense that the cursor would stay at the end of the string following the value being reset by javascript while the input is in focus. There's a lot going on there. But something about it being sticky to the end, and not at a specific character position, is my only guess as to 'why' this works. I'm just flipping happy that it does - and fully cross-browser compatible to boot!

Here's my code sample:

var $t = $("#myinput")  //cache the target so we're not parsing for it multiple times
v
ar oldv = $t.val();  // remember the original value
$t.focus().val(String.fromCharCode(35)).val(oldv);
  // focus it, set as 'END' key, reset to original

That's it. A simply awesome solution.

Friday, December 9, 2011

Prevent Railo's Default FLEX Integration From Generating WEB-INF Directories in Every Web Subdirectory

I recently upgraded to a new AWS server and started from scratch with Apache + Tomcat + Railo 3.3. This comes with a short vertical learning curve in regards to learning Tomcat set-up woes and new railo server.xml default settings. The last of which was the biggest surprise and confusingly new issue until I learned how easy it was to resolve.

New Railo installs, by default, are set up to integrate with FLEX. This should either be an option during installation, or... it should be an option during installation. I had never used the new railo-...-installer.run program, I really liked it a lot, but I really wish it had asked me if I wanted FLEX integration in the process. It's a small thing, but it's always the smallest things that make the biggest difference. It's okay, I'm still a [Railo] believer.

So, to fix this issue, go to the bottom of /opt/railo/lib/railo-server/context/railo-server.xml (or where ever you have your Railo engine installed)

Change:
<flex configuration="xml"/>

To:
<flex configuration="manual"/>

Then you cango to your website root directory and run:
$ ls -alR | grep 'WEB-INF'


That will show all of the 'WEB-INF' directories that you don't need (in your /images, /css, /js, ...) that you should delete with following command:
$ sudo rm -RIf ./css/WEB-INF
$ sudo rm -RIf ./images/WEB-INF
$ sudo rm -RIf ./js/WEB-INF
... etc., etc.


Notes on the above: the 'R' = recursive, the 'I' (capital i, not lowercase L) ignores errors, and the 'f'' means 'force' to ignore 'are you sure' confirmation questions.

Then you can go into the Railo SERVER admin and Restart the server there, or recycle Tomcat and that will regenerate the one and only required 'WEB-INF' in the web root directory.


- UPDATE -
It turns out the above was not the only issue, as it was not completely resolved. After a lot more testing I found that I had also incorrectly set up my Tomcat Virtual Hosts. On this Ubuntu Railo-Tomcat server the Tomcat server.xml is located in /opt/railo/tomcat/conf/server.xml. My site's host xml was not set up correctly - missing the attribute 'autoDeploy' in conjunction with having an unwanted 'appBase' attribute. (See the first and second wrong ways below.)

My first WRING way:
<host name="www.website1.com" appbase="/var/www/website1">
<context path="" docbase="">
...
</host>


My Second WRONG way:
<host name="www.website1.com" appbase="/var/www" autoDeploy="false">
<context path="" docbase="website1">
...
</host>

// this actually worked, but we don't need appBase at all for CFM. the reason the first attempt above was screwing things up is that not setting 'autoDeploy' at all defaulted to 'true'. Setting it to false fixed the WEB-INF in the sub-directories, but it's still not right.

Here is the RIGHT way:
<host name="www.website1.com">
<context path="" docbase="/var/www/website1">
...
</host>



That's today's lesson learned.

Flexible Width Text Link as Buttons with Background Image (SOLVED)

The important part to note in the CSS below is the right margin on the <a> link tag - it's -20px. That beings in the right side so the :hover's work correctly.

When that is done another way the mouse over on one of the ends doesn't work and you get the background image shifting correctly on the end but not under the text. This way makes the link tag cover the entire span tag so both are always triggered on the native :hover state.


THE HTML:

<div class="button-container">
    <span class="button-wrapper">
        <a href="/fr/snapdragon-mobile-processor">Start</a>
    </span>
</div>


THE CSS:

#block-views-training-module-listing-block-2 .views-field-nid .field-content {
    background: url("images/trainmod-start-blank-wide-sprite.png") no-repeat scroll 0 0 transparent;
    display: block;
    float: left;
    height: 30px;
    position: relative;
    /*width: 82px;*/
}
#block-views-training-module-listing-block-2 .views-field-nid a {
    background: url("images/trainmod-start-blank-wide-sprite.png") no-repeat scroll 100% 0 transparent;
    color: #666666;
    display: block;
    font-size: 14px;
    font-weight: 600;
    height: 30px;
    line-height: 30px;
    margin: 0 -20px 0 0;
    padding: 0 30px 0 15px;
    position: relative;
    text-decoration: none;
    /*width: 82px;*/
}
#block-views-training-module-listing-block-2 .views-field-nid .field-content:hover {
    background-position: 0 100%;
}
#block-views-training-module-listing-block-2 .views-field-nid a:hover {
    background-position: 100% 100%;
}


THE BACKGROUND IMAGE:





Thursday, December 8, 2011

Update to Ubuntu Set Timezone Post

Just another reminder on how to quickly set the local timezone on Ubuntu Server.

I had blogged about this previously, but I didn't make it simple enough even for myself, so this is a do-over.


Find your timezone specific file in /usr/share/zoneinfo/America/.

Then run the following three commands:

$ cd /etc
$ mv localtime localtime_orig
$ ln -s /usr/share/zoneinfo/America/tzfilename localtime

Reboot and you're set. Now java defaults to this timezone.

Tuesday, November 29, 2011

Virtualbox - Mac Host - Ubuntu Guest - Networking

Messing with this half the day... It's so simple I overlooked it and went down strange Google paths.

This is the simple, straightforward answer to setting up networking for the Guest OS.

You set up two of the 4 possible network adapters before booting up the system. You can change the network settings while it's running and then run "sudo ifdown-a" and "sudo ifup-a", but that doesn't let you add a second adapter.

Set "Adapter 1" as "NAT" - this only gives the GUEST OS outside internet access through the HOST.

Set "Adapter 2" as "Host-only Adapter" - this only gives the HOST access to the

Together, we have what we want, we don't need anything fancy or custom, no bridgets, no scripts. But there is one tiny config setting that needs to be set to use the second adapter...


After you boot up the Ubuntu Linux server and log in you have to set up the second adapter in the interfaces config file because, by default, it only has one.

It will look like this:

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet dhcp


Now add this to the bottom:

# The primary network interface
auto eth1
iface eth1 inet dhcp

Now reboot.

Now when you run "ifconfig" you should see an ip address under "eth1". That is the IP address you can SSH to from the HOST machine.

YES!   IT'S REALLY THAT SIMPLE!


Saturday, November 26, 2011

Note to self: Railo Mail Server Gmail SMTP setup

When setting up the Railo Administrator Mail server to use Gmail, remember these settings so you don't waste time trying different arrangements:


Server (SMTP): smtp.gmail.com
Username: myaccount@gmail.com
Password: strongpassword
Port: 587
TLS: YES (checkbox checked)
SSL: NO (checkbox blank)


This link was somewhat helpful: http://mail.google.com/support/bin/answer.py?answer=13287


-Garrett

Sunday, November 20, 2011

MySQL to JSON - this is cool!

I've used MySQL's amazing "GROUP_CONCAT()" function many times, it's an absolute life saver in very specific situations, and it's supa-fast. I've attempted to use it to essentially store sub-query data in a string. This usually makes the resulting code less than ideal when attempting to parse the string back into an iterate-able data set. Today I needed this once again and I wasn't looking forward to it.

Recently I've dealt a lot more with JSON data sets with AJAX features and I've fallen in love with JSON. I love how universal it has become to pass data between programming languages, be that client side Javascript to/from server-side or between server-side languages in web services, whatever. It's always great. So I was thinking to my self, 'What if I could get by multidimensional data from the database into a JSON string?'. So I started googling "SQL to JSON" and I found this guys blog post: http://www.thomasfrank.se/mysql_to_json.html. (Thank you Tomas Frank! Wow, nearly 5 years ago. Ha!)  It was great. And all the comments were helpful as well. So I wrote my own in similar fashion. See my pseudo-sql below:

select f.fileid, f.parentfileid, f.filename, f.filesize, f.onloadon, f.uploadby, u.firstname, u.lastname,
    IFNULL((select CONCAT('[',
                    GROUP_CONCAT(
                        CONCAT('{"fileid":"', f2.fileid, '","filename":"', f2.filename, '","filesize":"', f2.filesize, '","onloadon":"', f2.onloadon, '","uploadby":"', f2.uploadby, '","firstname":"', u2.firstname, '","lastname":"', u2.lastname, '"}')
                    SEPARATOR ','),
                 ']')
            from filestable f2 LEFT OUTER JOIN userstable u2 ON u2.userid = f2.uploadby
            where f2.parentfileid = f.fileid
            and f2.deleted = 0
            order by f2.uploadon ASC),
    '[]')  as versions
from filestable f
  LEFT OUTER JOIN userstable u ON u.userid = f.uploadby
where f.parentfileid = 0
and f.deleted = 0


Essentially I'm querying for files and getting any past versions of each file packed into a JSON formatted string.

Then in the Coldfusion code you call: DeserializeJSON(myquery.versions) and you have an ARRAY of STRUCTURES in Coldfusion, each struct is a subquery row of data containing old file servsions. This is how we get 3 dimensional data from a 2 dimentional database query.

*** I hope the single and double quotes are easily readable in the code sample above. SQL strings are in single quotes and the JSON keys and values are all in double quotes.

*** It's important to notice the IFNULL() function around the sub-query because without that, if there are no records, it returns a NULL value. In Coldfusion that becomes an empty string. That's bad when we were expecting an array. I learned that the hard way when it was erroring out on my ArrayLen(variables.filevs) code, see below.

*** Another important note is to sort the sub-query Ascending by date. The reason for this specification is so that we can more easily loop over the array backwards to display the most recent versions at the top and the oldest at the bottom.

This is how the resulting Coldfusion code might look:

<cfloop query="variables.myquery">
    <!--- html here to display each file (current version) --->
    <cfset variables.filevs = DeserializeJSON(variables.myquery.versions) />
    <cfloop from="#ArrayLen(variables.filevs)#" to="1" step="-1" index="variables.LLfilev">
        <cfset variables.filevdata = variables.filevs[variables.LLfilev] />
        <!--- html here to display the data of each old-versions of each file --->
    </cfloop>
</cfloop>


Clean and simple. You've gotta love that. Fast too! Much better then getting all files, parent and old-versions, and then running a few query-of-query's in our server-side code to first get the parent records (current vertsions) and then get the old-versions with a query inside each loop. Without this, QoQ may have been the only solution. This new solution is *SO* much better, faster, and cleaner.


Friday, November 18, 2011

CFExecute with Multiple Bash Commands Inline && Getting the latest GIT short hash && custom CSS/JS caching solution - OH MY!

This one was hard. I knew it was possible so it was only a matter of time, googling, and testing. I got it.

Here is the code. Here I'm using the command "git rev-parse --short HEAD" to get the short hash of the latest GIT commit. But, in order for that to work we need to get into the right directory and CFExecute *starts* in the user directory of whatever user the Coldfusion server is running in. If you haven't set one the it's probably "/root".

So we first need to change directories to the current web root, then we grab the short GIT log hash, like this:

<cfexecute name="/bin/bash" arguments="-c 'cd -P #ExpandPath('/')#; git rev-parse --short HEAD'" variable="variables.test1" timeout="1" />

LOVE IT!

But a note on the results. If you output the above <cfoutput>[#ariables.test1#]</cfoutput> with brackets around it you will see there is an extra space on the end. That annoys me but I couldn't shake it off. My only solution was to trim itself afterwards with a <cfset variables.test1 = TRIM(variables.test1) />. Lame.

So, why am I wanting the latest short GIT log hash? I'm glad you asked.

I'm using it in my CSS and Javascript file tag query strings to prevent improper caching of old CSS and Javascript files so that users will always have the latest changes without having to clear their cache.

Example:

<link href="/css/global.css?v=<cfoutput>#server.codeversion#</cfoutput>" type="text/css" rel="stylesheet" />
<script src="/javascript/jquery.prod.min.js?v=<cfoutput>#server.codeversion#</cfoutput>"></script>



Yup. I LOVE IT!

Sunday, November 6, 2011

Railo Coldfusion & Less CSS (java implementation)

I just spent the last 4 hours figuring this out. I had to blog this to help someone - and my future self.

I wanted to start using Less and I want to compile it server side only when I need to. I have some url parameters, which can only be run from the admin login, that I use to reset certain caches and things. In this case I want it to recompile my less css only when I want to. So I need to set up a script to trigger and run the less css compiler. Railo is the BEST server wide web engine and it can tap into java like it's butter. I discovered that java has a server-side javascript engine called Rhino. A lot of trendy groups are there are implementing server-side javascript. I don't tend to get trendy, but I love the idea for very specific application uses. Anyway. With this Rhino we can implement the original Less.js compiler server-side. Sweet! Not so fast... People have tried to do this with Coldfusion and I can't get them to work (4 hours worth of attempts).

I finally figure out my own implementation - thanks to railo's native java loader - TWO LINES OF CODE!!!

<cfset variables.javajs = createObject("java","org.mozilla.javascript.tools.shell.Main","/jars/js.jar")>
<cfset variables.javaless = createObject("java","com.asual.lesscss.LessEngine","/jars/lesscss-engine-1.1.4.jar")>

I'm going to try to retrace my steps...

From https://github.com/cloudhead/less.js you can get the source and compile your own. Or you can use what thus guy put together http://www.asual.com/blog/lesscss/2009/11/05/less-for-java.html. That's what I did. Here is his Git repo: https://github.com/asual/lesscss-engine.

Actually, that's not right, I got it from this guys presentation notes here: http://dopefly.com/techblog/entry.cfm?entry=359
direct link: https://github.com/NathanStrutz/Write-LESS-CSS-Presentation-Material. That's where I got the "lesscss-engine-1.1.4.jar".

From even with the "js.jar" and the "lesscss-engine-1.1.4.jar" I couldn't get things to work. I had forgotten my Java schooling.

I hate the javaloader.JavaLoader crap. And it's old school. Railo can do it - natively. But I could scratch *how*. I googled and googled and I always thoguht it would be so simple. I finally googled and found the class to invoke. Railo's example code only gives you this:

<cfset object = createObject('java','path.to.package.classtoinvoke','/path/to/jar/file/on/system')>

and that didn't give me the name of the 'class to invoke'. But the Rhino site 'http://www.mozilla.org/rhino/scriptjava.html' did. And then from the code samples from Nathan Strutz presentation notes sample code I got the "com.asual.lesscss.LessEngine" class name for the 'js.jar'.


So now we're in business!

Here's how to compile the styles.less code into styles.css:

<!--- get your source styles.less from a cffile read or from in string, whatever, in a variable, say, 'variables.lessSource' --->
<cfset variables.outputcss = variables.javaless.compile(variables.lessSource) />
<!--- Then output the 'variables.outputcss' into <style></style> tags or do a cffile write to styles.css file and link the in the css file --->

That's it.



While I'm writing all this I get some other thoughts. You might even be able to pass in a source file path and write it right back to a cffile write -- but I haven't tested that yet. But in theory, maybe like this:

<cffile action="write" file="/path/to/css/styles.css" output="#variables.javaless.compile('/path/to/source/styles.less')#" />

UPDATE:
The above didn't work because it's expecting a java type file stream. This works:
<cffile action="write" file="#expandPath('/')#cssjs/test.css" output="#variables.javaless.compile(CreateObject("java", "java.io.File").init("#expandPath('/')#cssjs/less/test.less"))#" />

That would be slick - but again, just a theory, untested.

Now, while trying to retrace by steps over the last 4 hours I also discovered from a final note from the dopyfly.com blog post mentioned above that there is a low level C implementation of the LESS compiler int he git repo, "lessc". There might had been a simpler implementation via the cfexecute tag to process styles.less files into styles.css files. I'll give that try another day.

UPDATE:
This is way more complicated than I expected. It requires nodejs to be installed. I actually tried it and ran into dependency issues. If someone gets this command line lessc to work on ubuntu command line, please drop a comment.


That's a nice wrap! From bloated implementations with tricky dependancies I got it down to three lines of code! Haha!
Here it is again (excluding code to get the less source and write the output css file):

<cfset variables.javajs = createObject("java","org.mozilla.javascript.tools.shell.Main","/jars/js.jar")>
<cfset variables.javaless = createObject("java","com.asual.lesscss.LessEngine","/jars/lesscss-engine-1.1.4.jar")>
<cfset variables.outputcss = variables.javaless.compile(variables.lessSource) />


This is proof of concept which I have working successfully.

Friday, June 10, 2011

Default Method for component cfc - SOLVED!

I've been wanting this functionality for a *really* long time. Build a single cfc with all of the functionality for re-useability within the one file.

I am happy to day I have solved this dilemma. Look no further.

Required: Application.cfc.   (This will not work with traditional Application.cfm applications.)


First, how I came upon this solution. I discovered that when a CFC is run the Application.cfc the onRequestStart and onRequestEnd functions (methods) are processed but the actual onRequest function/method is NOT processed as it is with cfm pages. This was what prompted a small modification to the onRequestStart function processing.

In this example I have to pre-set the default method named "init". You could name it "default" or whatever you prefer, but this current implementation requires a hard-coded pre-set name. I'm curious if you can dig into an object's data and pull out a default method name. But that's for another day.

<cffunction name="onRequestStart" returntype="void" access="public" output="No">
        <cfargument name="targetpage" type="any" required="true">
        <cfif (LCASE(RIGHT(arguments.targetpage,3)) IS "cfc") AND (!structkeyexists(URL,"method"))><!--- only attempt default if no method specified --->
            <CFTRY>
                <cfinvoke component="#REPLACE(REPLACENOCASE(arguments.targetpage,'.cfc',''),'/','.','ALL')#" method="init" />
                <cfabort />
                <CFCATCH type="any"><!--- FAILED<cfdump var="#cfcatch#" /> ---></CFCATCH>
            </CFTRY>
        </cfif>

        <cfreturn />
</cffunction>

This is running on Railo. This works if a method exists in the cfc named "init" and no url method=useother exists. If the "init" method doesn't exist then the cfml engine displays the public and remote methods of the cfc as normal. No existing functionality is altered or interrupted. That is the greatest part of this implementation.

This works wonders and possibly paves the way for a mini framework if you will for self contained multi-functional pages. Ajax requests and ajax posts and processing could all be in a single cfc container file.

This was an amazing discovery and a fun implementation. This will transform my application development style.


Thoughts?



Tuesday, April 19, 2011

Work-around for "You can't specify target table 'XYZ' for update in FROM clause"

MySQL is awesome. I *love* sql in general. I know many of you just cringed - to each his/her own. However, I really like all of the unique functionality MySQL provides. And id many cases you can utilize it's tools to overcome it's own shortcomings.

Quite some time ago I discovered a valuable work-around for situations when you want to update a table using a subquery in the where statement. I never posted it. Today I needed to do this again and I've never seen this on the net, so I felt it was an over-due posting.

Lets assume we have a table 'XYZ' with a date field and we want to update a few records that have date A and update them to date B.

update XYZ
set datefield = '2011-04-19'
where id IN (select id from XYZ where datefield = '2011-04-18')

MySQL will yell at us because this is not allowed: "You can't specify target table 'XYZ' for update in FROM clause"

Are you familiar with 'Derived Queries'? They are my best friend. And yours now too.

Check this out:

update XYZ
set datefield = '2011-04-19'
where id IN (select id from (select id from XYZ where datefield = '2011-04-18') d)

No yelling, IT WORKED!

Why?

Derived queries are basically temporary tables populated on the fly, used, and then dropped without any additional work from you. So, the query above, by using a derived query, and therefore a temporary table, is no longer querying itself, so it performs the update.

You can use derived queries outside of update statements to do all sorts of things that might otherwise be difficult in normal unions and joins. They are powerful and fast.

Notice the "d" following the derived query - that's an alias. If you don't give your derived query an alias (basically, naming your temporary table) MySQL will yell at you saying "Every derived table must have its own alias".


Neat-o new best friend, eh?

Viewer, meet Derived - Derived, meet Viewer. Please, get to know each other, have a good time. Best of luck!

Monday, March 14, 2011

Solved: Mac Finder Crashes Upon Opening A Certain Folder Repeatedly

I experience this today. I had never heard of it before. It blew my mind at first. I thought my whole system was crashing down. Alas, it's a minor issue.

After googling some I wasn't able to find an absolute cause or solution. After some tests I discovered the cause, and a solid solution.

The cause: unreadable or corrupted extended attributes in one of the files or folders which prevents Finder from properly handling and displaying the folder contents.

The solution - remove the extended attributes on the the folder contents. I didn't know which file or folder in the affected directory was the cause, so I removed all extended attributes on all items and the problem was solved.

To do this:

1. Open terminal and go to the affected folder.
2. ls -al@e  to show the extended attributes on the folder contents.

Copy one of the attribute names and remove it from all items, for example 'com.apple.FinderInfo'

3. xattr -d com.apple.FinderInfo *  will remove this attribute from any items that have it.

Repeat step 3 for all attributes, one at a time. For example, I had to run:
xattr -d com.apple.ResourceFork *
xattr -d com.apple.quarantine *
xattr -d com.macromates.caret *
xattr -d com.apple.metadata:kMDItemWhereFroms *

That was it. Then my Finder displayed all items properly and stopped crashing.

Other responses from Google results recommended deleting .DS_store files or restoring the directory from a TimeMachine backup. Don't do any of that. It doesn't fix this issue. Only removing the extended attributes will solve this issue.





Saturday, March 12, 2011

Javascript Goodie - Smart Load JS/CSS Linked Files on First Ajax Request Only - Not on Subsequest Requests.

I've experienced an issue on many occasions where a feature of a website needs to load some advanced ui functionality via ajax onto a page and link additional css and/or js files with the ajax request in order to accomplish it. This feature may be requested numerous times while completing some sort of set-up, whatever. The repeated loading of the same css or js files is an unnecessary bandwidth hog and may slow the user experience considerably, as pop-up modals are expected to be snappy. In some cases this repeated reloading of the same linked files might possibly cause javascript errors as the repeated overloading of javascript functions overwriting the previous instance in the browser memory each time the js file is reloaded with the ajax request.

This is my solution. I had googled this issue on random occasions and found a couple hints here and there in the direction of what I wanted to accomplish, but no solid solutions presented themselves. So, I wrote my own solution. It was a lot simpler than I originally expected.

This example relies somewhat on jQuery, but it could be rewritten without it.


    function smartLoad(flist){
        if(flist.length==0){return false;}
        if(!window.smartLoadList)(window.smartLoadList="");
        var flistArray = flist.split(',');
        //console.log('Start');
        for(i in flistArray) {
            var f = $.trim(flistArray[i]);
            if(window.smartLoadList.indexOf(f)==-1) {
                if(f.substr(f.length-2,2).toLowerCase()=='js') {
                    $("head").append('<scr'+'ipt src="'+f+'" type="text/javascript"></scr'+'ipt>');
                } else if(f.substr(f.length-3,3).toLowerCase()=='css') {
                    $("head").append('<li'+'nk rel="stylesheet" type="text/css" href="'+f+'" />');
                } else {
                    continue;
                }
                window.smartLoadList = window.smartLoadList + "," + f;
            }
        }
    }
    $(document).ready(function() {
        smartLoad("/css/custom.css, /javascript/c1.js, /javascript/c2.js");
    });



That's a wrap!

Blog Archive