Posts Tagged ‘JavaScript’

Compiling with ruby and closure

Tuesday, November 1st, 2011

Here's some code to call closure (which is renamed closure.jar) from a ruby script:

def optimize_js(target)
#get all files in this folder, recurse over them
filecounter = 0
modifiedcounter = 0
Dir.glob(target + '*.js').each do|f|
puts "Processing #{f}"
filecounter += 1
my_js = `java -jar closure.jar –charset iso-8859-1 –js #{f}`
File.open(f, "w"){|con_file|
con_file.write(my_js)
}
end

puts "\n\t # JS Optimization: Done. Modified #{filecounter} files."
end

This code will overwrite the js files, so please be sure to operate on a copy of your files!

It is a function which takes a directory (target) and processes all files with the ending .js, replacing them in place with the optimized JS output. You need to put closure.jar in the same directory as the ruby script.

Note, that I also use the –charset iso-8859-1 option. This option ensures that closure reads the file in that iso charset, instead of assuming UTF-8. UTF-8 as default will work ok, until you have special characters from foreign languages, i.e. ä ö ü ß or á or whatever. Think Spanisch, French, German.

Redirection with Concrete 5

Wednesday, September 14th, 2011

URL Shortening is all the rage now. Sometimes you want to give people ridiculously long URLs, which might also be subject to change.

So you want to do it with C5, don't you?

Great, you think – there's the "add external link" menu option in Concrete's sitemap. Unfortunately it does not work the way you expect it to – it just adds the link to the Navigation, but no page alias to point to the external page (i.e. http://www.synapse-redaktion.de/FaceBook won't work after adding a "FaceBook" external link).

What to do to solve this dilemma?

My suggestion is to use both: add a (hidden) page "FaceBook" which does header JavaScript forwarding to the other page, so you can give out the links to the people, and a "real external link" so you don't have to rely on JavaScript for most of your visitors.

The SiteMap will look like this:

sitemap

Adding custom attributes: (Header Extra Content, Exclude from Page List, Exclude from Nav)

header extra content

The page's setup:

setup

The script is easy:

<script type="text/javascript">
<!–
window.location = "http://www.surfnext.com"
//–>
</script>

with surfnext.com being the URL you are forwarding to.

If you have the time, you might want to add a static link or icon to the page (/*comment*/ the window.location = … part to be able to edit the page!) in case some person has their JavaScript turned off.

Head.js working unreliably

Monday, August 8th, 2011

What is head.js

From the same author as the fabulous JQuery Tools libraryhead.js is "the only script in your head". You include it in your HTML output, and write code for it to include and run other JS files. It also offers some extensions for CSS, for instance you can optimize for different screen resolutions or fix glitches in different browsers.

Why should you include your files via head.js?

Well, the browser will load in a blocking manner – that is, it will load the resources it encounters first, and then continue loading the other resources. If you have a bunch of JS files, they might take a while to load (think of the HTTP request overhead, and of network latency!), thus blocking images, CSS files and other content on your site.

Head.js is only one (small) JS file to include, which will take care of loading your JS files asynchronously and simultaneously in the background. Once they are ready, you can execute code using the head.ready() method.

The result is – your webpage display significantly faster!

Problem

Sometimes, the scripts you load via head.js will work, sometimes they won't – i.e. features of the site additionally coded by you will not show up constantly and predictably.

Solution

The problem may be a race condition. Head.js loads the scripts asynchronously, so sometimes the other code on your site gets executed before the JS files included via head.js are executed, and sometimes afterwards.

Example: you are passing some information to your script via a variable which differs from page to page.

Your code is something like this (actually I moved the call to head.js() to the head.min.js file itself, which may contribute to the problem!):

<script language = "JavaScript" src="includes/head.min.js"></script>
<script type="text/javascript">
head.js('includes/jquery.tools.min.js','includes/custom-script.js');

… lots of code inbetween …

var variable_to_pass = 'some value';
</script>

and in your custom-script.js you rely on variable_to_pass like this:

var i_rely = variable_to_pass;

Sometimes your variable_to_pass will get set up before head.js has loaded your custom-script, and sometimes not. In the first case, all will go well, in the latter case, your code will fail. In Google Chrome, for instance, silently, unless you activate the JavaScript console to see the error stated.

This is called a race condition. The solution to this condition is to rely on external variables only once the whole page has loaded and is scriptable, which you have to test for, extra.

For instance you could use JQuery's $(function() {]); method for this, setting up the dependent variable or using the passed variable inside the function.

Another possibility is to check if the variable is as of yet undefined, and to give it a default value.

if (typeof(variable_to_pass) === 'undefined') {
variable_to_pass = 'some default value';

}

(not writing var before the variable will make it global).

Enable and fix Lectora titles for the Opera browser

Friday, June 17th, 2011

Problem: If you publish a title with Lectora, and try to view it from Opera, instead of the title you see an error message

Your browser does not support dynamic html. Please download a current version of either Microsoft'" DESIGNTIMESP=18189>Microsoft Internet Explorer or Mozilla'" DESIGNTIMESP=18192>Mozilla Firefox and try visiting our site again. Thank You.

Solution: You have to modify trivantis.js in line 353 and line 355. The modifications are displayed in bold

this.ns = (name=="ns" && this.v>=4)||(navigator.userAgent.indexOf("Opera")!=-1)
this.ns4 = (this.ns && this.v==4)
this.ns5 = (this.ns && this.v==5)||(navigator.userAgent.indexOf("Opera")!=-1)

IMPORTANT: WordPress fucks up the quotation marks above, fix them by hand!!!

This tells Lectora's code to treat Opera like Netscape Navigator and its derivates. For the title we are developing for the WHO (ICF eLearning tool) it works flawlessly.

This fix is taken from this Lectora forum message, posted by ssneg.

(ssneg also explains why it is not possible to override this.min and set it to true – because Lectora only includes code for IE or NS to display the title contents, like buttons, later on. Thus we need for Opera to "pretend" that it is Navigator. The code works.)

Do you know any other browsers incompatible with Lectora? Please post a comment, and we might find a solution :-)!

 

Concrete 5 behaving weirdly

Sunday, May 8th, 2011

The problem

Suddenly you can't edit your content blocks anymore – Concrete 5 shows them in HTML. Also you can't save properly, and page content becomes disordered, some blocks are missing after saving. This seems to happen in several browsers.

The solution

You may have a proxy server software or something similar which blocks some JS scripts Concrete needs to process the page correctly. In my case, Privoxy was the problem. After I turned off the proxy settings in my Firefox, I could edit the page normally. Of course I had Privoxy enabled in the other browsers I was testing the site with, too.

Btw, Privoxy is a great and free software to reduce the "noise level" while browsing by blocking "unnecessary" third-party content on webpages (read advertisements. I know, it's a philosophical question for some other time.)

Lectoras external HTML object and z-index

Sunday, February 20th, 2011

Given the limited flexibility of Lectora, in some cases you need to include custom scripted HTML objects.

For instance you want to build an overlay for a login dialog, which would communicate directly with the server using AJAX.

After positioning your external HTML object on the page and building the HTML you want to include (by i.e. a PHP "include" call), sometimes you will find Lectora is putting other things on top of your HTML object's contents.

The first possibility to fix this would be modifying Lectora's "Layering" option of your object: "Bring to Front".

The second possibility comes in handy, if you do not want to modify the Lectora project itself: on-the fly z-index – updating.

I use the JS library JQuery to efficiently work on the DOM across browsers. Using it, you can set the z-index during runtime (i.e. reacting to a mouseclick on an icon):

$('#object-name').css('z-index','1000');

You can find out the name of the DIV Lectora creates for your external HTML object using Firebug, or looking up the object name property in Lectora (double click your object to see the settings dialogue).

Creating DIVs inside your Lectora object and setting their z-indices to higher values, i.e. by CSS, does not work. You need to alter the z-index of the wrapper DIV provided by Lectora. It is created during run-time using this code:

object-name = new ObjInline('object-name',null,0,580,900,40,1,15,null,'div')
object-name.build()

The Lectora code sets the z-index! Thus, your z-index from the CSS would be ignored, and you need to update it during runtime, as I have described above.

jQuery AJAX & Internet Explorer

Wednesday, May 26th, 2010

Internet Explorer getJSON trouble

This piece of code initially did not work for me on IE:

$.getJSON("../inc/exercise_ajax.php?" + $(this).serialize(), function(json)

FireFox worked without problems.

The reason is that my JSON code was not well-formed. It had a comma (',') too much.

Here's the code which I use in PHP to create my JSON (braces omitted):

foreach($answers as $question => $answer){
$outstr .= '"q'.$question.'": ';
if (isset($_GET[$question])){
if ($_GET[$question] == $answer) $outstr .= 'true';
else $outstr .= 'false';
} else $outstr .= 'null';
$outstr .= ',';
}
echo chop($outstr,',');

You have to chop off the trailing comma – if you don't, IE will choke on it and your callback function won't be executed.

Internet Explorer & AJAX caching

Yes, Internet Explorer caches your requests. You've got to empty the browser cache before testing the fix I mentioned. Also, you should append a unique parameter to suppress caching, i.e. the current timestamp. Example:

var now = new Date();
// submit with AJAX
$.getJSON("../inc/exercise_ajax.php?ts=" + now.getTime() + '&' + $(this).serialize(), function(json)