Category Archives: Javascript

How to remove absolute image srcs in WordPress

I use WordPress for this site but to be honest, I absolutely hate WordPress.

Comment spam, Malware hacks, hostname is part of the config, answer to everything is a plugin, etc, etc, yuk, yuk, yuk.

I use it because all I want to do is make posts, and for that, it is fine. A lot of other people use it for Content Management on complex websites, and that’s where it starts to fall apart.

For instance, lets say you have a pretty important website, where you want changes to be verified by the site owner before they go live. So you do the sensible thing, and create a staging environment (staging.mysite.com), and promote code and DB changes to your live site (www.mysite.com) directly from your staging site, rather than manually updating your live site.

That’s the way things are done in the grown up Internet, but if you try to do this with WordPress, you’ve entered a world of pain.

When you use WordPress’s Media Library to put an image in a post, WordPress insists on creating an absolute src attribute for the image, including the protocol and the hostname.

eg

<img src="" src="http://staging.mysite.com/wp-content/upload/catpic.jpg" />

when ideally it should be using an absolute URL without the protocol and hostname

ie

 <img src="" src="/wp-content/upload/catpic.jpg" />

This means that you can’t port your site directing from staging to live, as your live site will contain images that are being pulled from your staging site. The same problem applies if you are changing your site to a completely different domain name.

Consulting the WP forums you will find all manner of solutions to this, ranging from (yes, you’ve guessed it) plugins, to running MySQL queries every time you want to update you site.

A much simpler way to do this is to user JQuery, which you insert into your code once (in script tags in the footer of your theme), and then never worry about again.

The necessary JQuery is as follows:


jQuery('img').each(function () {
       var curSrc = jQuery(this).attr('src');
       if (curSrc.substring(0, curSrc.indexOf('/', 4)) == 'http:') {
          var baseURL = curSrc.substring(0, curSrc.indexOf('/', 14));
          jQuery(this).attr("src",curSrc.replace(baseURL,""));
       }
});

What this does:

Each time your page loads, JQuery will cycle through all the images on that page. If it finds an image src that includes the protocol specifier ‘http:’, it will check what the base URL of your page is, and remove that value from the src of the image.

This will leave you with a page on which all the images are loaded relative to the root of your web server, rather than a Fully Qualified Domain Name.

How to use custom element attributes in JQuery

Have a look at the following snippet of very basic HTML.

<input type="button" class="my_button" value="Submit" product_id="1234">

You’ll recognise this as a FORM button, with a value of “Submit” and a DOM element class of “my_button”.

Nothing strange in that. But what’s this 3rd attribute in the element, “product_id”? That’s not a valid HTML attribute, is it?

No, its not. Its a custom attribute that I’ve added. It could be anything, and it will have no impact on the output of the button in the browser.

So why add it?

Custom HTML attributes, blended with a Javascript Framework like JQuery, are an excellent way to develop fluid UIs in web applications.

Let’s use the above example. Let’s say we have a list of products in a shopping cart application, and we want to give the user the option to add products to a cart, but we want to do this with AJAX, so we don’t have to refresh the page each time.

Our web application renders the list of products, each with a Submit button that has a custom HTML attribute “product_id” with a value of the product’s catalogue ID.

So, in our Javascript, we use JQuery to trigger our required Javascript when the document loads. Standard stuff.

$(document).ready(js_Init);

In our initialisation function, we then attach another function, js_addToCart(), to the Click event on any element with class, “my_button”.

function js_Init() {
	$(".my_button").live("click", function(event) {
                  js_addToCart($(this).attr("product_id"));
        });
}

Now, notice the argument that we pass to this function.

Its a JQuery object first and foremost, that is, the element on which the Click event occurred. The argument we want is the value of the attribute of that element called “product_id”.

Our js_addToCart() function now has the catalogue ID of the product the user wants to add to their cart, which we can process with JQuery without ever having to do a FORM submission.

You can add as many custom attributes to an element as you wish, and pass as many of this back to JQuery as you wish, which means you should never really have to use a HTML form again.

Facebook Page Tabs and Access Tokens

This is a tricky little issue that has tripped me up a few times and for which I’ve finally found an answer.

If you design a Facebook application, and a Facebook user grants permission to your application to access your data, you can do all sorts of nice things with their friend lists, events, interests, birthday etc.

Your application is allowed obtain that user data on the basis of an access token, which is obtained as follows:

  • You direct the Facebook user to a Facebook URL that describes what data you want access to
  • The Facebook user clicks a link on that Facebook URL to indicate their approval
  • The Facebook user is then redirected back to you application, using a URL that contains a “code” parameter in the GET Request
  • Your application collects that code, sends it back to Facebook, and Facebook responds with a string which is the access token for that user

In this way, Facebook knows that the user in question has allowed your application to access particular data about them.

Now, here’s where it gets a bit more complex.

Facebook allows you to host applications in one of two ways: on a Canvas, or in a Page Tab. Regardless of which you choose, Facebook provides you with a dedicated link for your application as it is presented in either a Canvas or a Page Tab. It is to this URL that the user is generally redirected when Facebook needs to send your application the “code” parameter that your application needs to  request an access token.

However, in the case of both the Canvas and the Page Tab, your application is presented in an IFRAME within the general Facebook skin.

Here, an important difference occurs.

In the case of an application hosted on a Canvas, Facebook will pass on the “code” parameter to the source URL for your application, which is what Facebook uses as the src for the IFRAME. Your application can then pick this up and request the access token.

In the case of an application hosted on a Page Tab, Facebook will not pass on the “code” parameter to the source URL for your application, which means your application cannot request an access token, which means it can’t make requests for user data.

To have your Page Tab hosted application interact with the Facebook API, you need to obtain your access token in a different way.

When Facebook loads your application in the IFRAME, it sends you application a Signed Request, or in other words and encrypted string contain data about the user who is viewing your Page Tab. This tells you thinks like their Facebook ID, if they are an admin of the Page hosting the Page Tab and if they have Liked the Page.

This also contains value named “oauth_token”. Is it this value that you use as your access token when making requests for data for the user who is viewing your application.

Note: to use this, the user still has to have authorised your application to access your data, so you still need to use the Facebook application authorisation process.

You can read more about authentication and Page Tabs at this link, which also links you to a page that tells you how to decode the Signed Request:

https://developers.facebook.com/docs/authentication/pagetab/

Design a Simple Tab Based Widget

Widgets appear all over web sites these days. Little boxes of context that you can unwrap to reveal all sorts of wonderful information.

As a web developer, you will often be asked to provide them, and there are various ways of doing this.

Here is my recipe. It doesn’t use any graphics, and relies instead entirely on CSS and JQuery, which makes it really light and easy to use.

Facebook Apps and the Same Origin Policy

Over recent months, Facebook have become a lot stricter in relation to the use of secure URLs for applications presented in the App Canvas and on Page Tabs.

The bottom line in this is that you need to serve your Facebook application content from a secure (https) URL. You can have your app set up to serve on both http and https, but if  you don’t have this https set up correctly, any Facebook user who has Secure Browsing switched on will not be able to use your application.

My reaction to this was to convert all my applications to use https for all connectivity, so as to remove any uncertainty in this regard.

I figured that the users browser would just communicate with my web server over https, regardless of whether the Facebook use was using Secure Browsing or not.

However, there is a big problem with this if you use AJAX calls in your application.

I had set up all my AJAX calls to use https, but if the viewing Facebook user isn’t using Secure Browsing (ie they are connecting to your application over http), you are going to fall foul of Browser restrictions arising from the Same Origin Policy.

This policy is designed to prevent XSS attacks, in that it prevents Javascript from making calls to URLs domains that are not the same as the URL domain the user is viewing. Crucially, this includes the protocol which is used.

That means that if your Facebook user is connecting to http://facebook.nightbluefruit.com for general application content, and the application makes an AJAX call to https://facebook.nightbluefruit.com, the browser will send the request but will refuse to receive the response.

To overcome this, you should really set up your AJAX URLs based on the protocol used to connect to your application. You can use the $_SERVER['HTTPS'] special variable to do this.

Multiple JPlayers on the same page

JPlayer is a very nice Javascript library that allows you to create HTML5 media players in your HTML pages.

http://www.jplayer.org/

The site creates pretty decent documentation and examples, but I recently came to a dead halt when I had to create multiple audio players on the same page.

The JPlayer site provides an example of this, but it isn’t exactly clear how it works. This post explains exactly what you have to do.

First thing to understand:

In HTML5, when you want to create a media player, you either use the default interface or create a custom interface. If you want to create a custom interface, you have to create separate HTML for the interface. The default JPlayer installation includes a custom interface, so if you want to create multiple players, you have to create multiple interfaces, each of which must be carefully constructed from the point of view of the DOM and CSS.

Each of your interfaces will have a DOM Element ID, which of course must be unique. That ID determines which players activates when a control in that interface is clicked (play, stop, pause etc). If you don’t have this correctly set up, either multiple players will start at once, or nothing will happen at all.

If you only create one player on a page, the default Interface Element ID that JPlayer looks for is “#jp_interface_1″.

If you want to create multiple players, you need to tell each JPlayer instance which interface it is associated with.

To do this, you specify the cssSelectorAncestor property for each player instance you create:

eg

function js_audioPlayer(file,location) {
	jQuery("#jquery_jplayer_" + location).jPlayer( {
	    ready: function () {
	      jQuery(this).jPlayer("setMedia", {
		mp3: file
	      });
	    },
	    cssSelectorAncestor: "#jp_interface_" + location,
	    swfPath: "/swf"
	  });
return;
}

In this example, I’m passing a file and location variable into a wrapper function, which then constructs the player.

In my script, I dynamically create Player DIVs with IDs:

jquery_jplayer_1
jquery_jplayer_2
jquery_jplayer_3
etc

and Interface DIVs with IDs:

jp_interface_1
jp_interface_2
jp_interface_3
etc

and then run the js_audioPlayer() javascript function as many times as I want players:

js_audioPlayer(‘file1.mp3′,1);
js_audioPlayer(‘file2.mp3′,2);
js_audioPlayer(‘file3.mp3′,3);
etc

More: http://www.jplayer.org/latest/developer-guide/#jPlayer-predefined-css-selectors

Building a Video Library with FFMPEG

The video above is imported from http://www.centerforclinicalexcellence.com, for whom I’ve recently constructed a Buddypress Video Library using FFMPEG and the JW Player.

The owners of the site had originally wanted to use a third party like Vimeo or Twistage for this solution, but I persuaded them that they’d achieve a lot more flexibility and functionality if they went with a bespoke solution.

This would allow them to integrate seamlessly with their Buddypress User Database, which was not something that was going to happen very easily with a third party API.

I’m pretty happy with the finished product. Users can upload video, rate videos, comment on videos, embed videos in other sites, and linkback to videos through Facebook and Twitter.

FFMPEG isn’t for the faint hearted, however. It generally doesn’t come installed on hosting platforms, and has a long list of dependencies about which it is very particular when installing.

Normally, you can overcome this by installing through a package manager like yum on CentOS, which I have used before, but the current version of FFMPEG uses a version of libmp3lame (3.98.2, which is used for encoding audio) that contains a nasty little bug that prevents the duration of a clip being embeded in Flash encoded videos.

This in turn plays havoc with Flash players, who don’t know who long the video they are playing will run.

Unfortunately, there is no easy way in yum to specify the version of dependencies you want to use, so you have to go through all of FFMPEG’s dependencies and install them manually, just so you can install a downgraded version of libmp3lame (3.97) which doesn’t contain the bug.

You then need to comile FFMPEG from source.

This is a tricky process, but thankfully I found this article which gives a pretty good summary of what you have to do (there are one or two typos in it, but you’ll catch them as you proceed; and install lame 3.97, not 3.982 as listed). You also need to pay close attention re. the linking of libraries as described, and be sure to run ldconfig.

You can also leave 1 or 2 of the slightly less common codecs if they are giving your errors. The ones you really need are lame, faad, faac and vorbis.

JW Player by comparison is a breeze to install. The license and FB and Twitter plugins were purchased for the very reasonable sum of €77. Its a great player, and I’d recommend it to anyone.

Google Maps and Dynamic IFRAMEs

I recently created an application that displayed a Google Map in an IFRAME in the main page.

The IFRAME itself was created by running a small piece of javascript to populate innerHTML in a specific DIV container.

For some reason, several of the tiles were missing from the page when it first rendered.

After tricking around with this for ages, I eventually came up a solution.

When you insert a Google Map in a page, either in a standard page or in an IFRAME, the map will display according to the geometry of the page. For standard page, the geometry is straightforward, and you generally won’t encounter any problems.

In a page containing an IFRAME things are a little different, particularly when you create the IFRAME on the fly.

Consider this:

A page starts to render. Its a long page, and half way down, some javascript runs to create an IFRAME. This IFRAME then goes off and pulls down a Google Map, but this process starts before the parent page is fully rendered.

Result: Google Map is wonky.

So what’s the solution?

Basically, you just need to insert a little delay into your Javascript to allow the parent page fully render before the Google Map create begins:

eg

setTimeout(js_viewGoogleMap,1000);

If you need to pass co-ords to your map rendering function, just
create an inner function in your primary function:

eg

function js_viewGoogleMap(x,y) {

function loadMap() {

load(x,y);

}

setTimeout(loadMap,1000);

}

Hope this helps.

Variables in Javascript Nested Functions

Like many programming/scripting languages, Javscript provides the ability to nest one function inside another function, a bit like this:

function outside () {

function inside() {

window.alert(‘Hello World’);

}

}

This behaviour is most commonly seen when a developer needs to assign a function to an event that is created inside another function, for instance:

function outside () {

var menu =document.createElement(‘SELECT’);

menu.onchange = function () {

window.alert(‘Hello World’);

}

}

One of the difficulties that can arise here is that quite often it is necessary to pass a variable to the inner function. Say for instance, you want to create a 3 SELECTs, each having an onChange event which displays an alert unique to that SELECT. Would this work?

function outside () {

for (i=1;i<4;i++) {

var menu =document.createElement(‘SELECT’);

menu.id = i;

menu.onchange = function (i) {

window.alert(‘Menu’ + document.getElementById(i).id);

}

}

}

The simple answer is that no, it won’t.

What this execution will do is run the inner function at the same time as the outer function and assign the return value of the inner function to the ‘onchange’ property of the SELECT object, even if nothing is returned.

This isn’t what we want. What we want is for the inner function to be assigned to the onChange event of the SELECT.

There are couple of ways to do this, 3 of which are very well explained in this article.

Here’s one of them. What we do in this case is create a new property for the SELECT object, to which we assign the necessary variables, which we can then reference with the this object reference.

function outside () {

for (i=1;i<4;i++) {

var menu =document.createElement(‘SELECT’);

menu.menuid = i;

menu.onchange = function () {

window.alert(‘Menu’ + this.menuid);

}

}

}

This method isn’t without its problems either, but it will work in the majority of cases. If you want the Gold Standard solution, check out the referenced article above, preferably from a quiet, well-aired room with a nice view of distant snow-capped mountains (ie its a little complicated…)

The Scriptalizer

Given the extended use of Javascript in today’s web applications, one of the best ways to improve site performance is to obfuscate your javascript before it is loaded into the browser.

Trimming white space and new lines can shave as much as 50% from your script file sizes, which can make as significant difference to the initial load delay of your site.

http://www.scriptalizer.com is as good a solution as I have found for this acheter cialis sans ordonnance en pharmacie.

You upload your files, hit the button, and wham, all your beautifully formed javascript is compressed into a congealed, but wonderfully efficient, blob in a single file.

Only thing is that you have to insert a bit of logic into your code to load your human readable files in development and the single obfuscated file in Production, because you don’t wanted to have to repeat the obfuscation process every time you want to test a new piece of code, and you certainly don’t want to try and edit the obfuscated file by hand.