Tagged JavaScript

On Safari Mobile for iOS 5, event.pageY is the new event.clientY

safari-logo-lg

We have some tooltips running at my work that are used to render sharing buttons when a user clicks or taps on them. When the recent upgrade to iOS came around, the tooltips stopped being rendered properly in iOS 5.

After running into a few problems with jQuery Tools and the iPad, I came up with a solution for getting the tooltips to appear next to the anchor element like they were supposed to. By using the event.clientY value from the touch event, I was able to detect where in the DOM the touch had happened, and simply position the tooltip right next to it, with something like this:

$('#tooltip').css('position', 'absolute !important').css('top', event.clientY);

In iOS 4.3, event.clientY was reporting the absolute position of the touch event relative to the entire document. In iOS 5, I discovered that it was reporting the position of the touch event relative to the window. So, if you tapped a tooltip way down on the page, but near the top of the current viewport window, the tooltip would appear right near the top of the document, completely off screen.

A little digging on Google yielded this page on the Apple site. The reference to an event.pageY property made me think that maybe that would do the trick, and it seems to work.

$('#tooltip').css('position', 'absolute !important').css('top', event.pageY);

Now, with iOS 5, the touch event was properly setting the tooltip’s top value to the position of the touch event within the entire DOM, not just the viewport. I’m not exactly sure what’s changed between iOS 4.3 and 5, but at least now I have something that works for both.

Lazy-load a LinkedIn Sharing button after the JavaScript window.load event

Adding social networking sharing buttons to your site has become almost a ubiquitous step in Web development, to the point when some designers have stopped thinking about the performance impact of rendering multiple buttons via JavaScript while a page is still loading. The delay might not be noticeable for, say, 1 or 2 buttons, but when you’re rendering multiple buttons per page (when you have a button to share individual Tweets on a page, for example), it can get out of hand (turns out JavaScript crashing the browser creates a user-unfriendly experience for most people).

The solution is to lazy-load the buttons when you need them, either when a user clicks to expose a previously hidden div, or at the very least after the window.load JavaScript event, to prevent slowing your pageload times down. Here’s an example of a simple way to lazy-load a LinkedIn Share button on window.load:

First, include the necessary scripts (LinkedIn’s in.js and jQuery). You can do this in the footer if you want…after all, you’re not doing anything with them until much later in JavaScript-time:



Next, add some jQuery in a script tag that looks for any script tag with a type of ‘unparsed-IN/Share’ (the name doesn’t matter, as long as it’s NOT IN/Share, since the whole point here is you don’t want the in.js script to parse the tag). Depending on the size of your DOM, you may want to be more specific with your jQuery selector…a div or a section of content is fine, and you can bind to a click event, a scroll event, or whatever else you’d like to initiate the parsing of your LinkedIn buttons:

 jQuery(window).load(function(){
    jQuery('body').find('script[type="unparsed-IN/Share"]').each(function(){
      jQuery(this).attr('type', 'IN/Share');
      IN.parse(document); //you can also use getElementById('id') in place of document here
    });
  });

Finally, you just need to add LinkedIn sharing tags in the following manner. The key here is to change the JS script type from IN/Share to unparsed-IN/Share (or whatever you chose in the jQuery above), which will cause the tag not to be rendered when in.js is loaded, allowing you to control with the JS when the tag is actually parsed, using IN.parse (which can be applied to the document as a whole, or an element as retrieved by the built-in JS document.getElementById method.


Update: As Howard points out in the comment section, if you don’t need to load the in.js script to render any LinkedIn buttons or content earlier, you can always accomplish lazy-loading by simply deferring the script load until you want to render the buttons. This allows you to avoid parsing and replacing the ‘type’ on each JavaScript snippet. If you need LinkedIn content to render both before the onload event as well as after, though, you’ll still need to do the replacement.

WordPress blogging software administration on the Blackberry

The Blackberry: Sweet, juicy….Internet.
Blackberries

As PDAs and similar handheld devices continue to advance, it becomes more and more realistic to consider them in one’s site design, in order to reach the widest audience possible. Since I happen to have a Blackberry right now, I’ve been trying various sites in order to see what’s compatible and what fails miserably.

The usual suspects, such as Google and Gmail, performed flawlessly, as expected. The folks over at Google seem to a have a special little spot in their hearts for the mobile user, and their most popular offerings don’t disappoint in this regard.

Once I was sure that I’d maxed out my PDA’s capability to process client-side markup and scripting (you have to manually add JavaScript, Cascading Style Sheets (CSS), and XML support, otherwise you’re basically running Internet Explorer 4.0 on a teeny-tiny screen–a browsing experience that would make even the most desperate bsuite-hound run for the nearest Mennonite community), I headed over to this blog.

The front page loaded flawlessly, though it takes quite a while, and the Blackberry’s status bar indicates a laborious process of running scripts and proccessing CSS at what is, relatively, a snail’s pace. What surprised me the most was the appearance of a photo that went with one of the stories, nicely formatted and filling the screen. It’s easy to scroll through and read posts, click on related articles, and do pretty much anything else you’d want.

With the front page test complete, I tried logging in to the admin section. Navigating to /wp-admin yielded a standard userID/password dialog, and within 30 seconds, I was on the admin dashboard, free to click on any tab, change any options I wanted, and even post an article. As far as I can tell, WP works with the Blackberry, or rather, the Blackberry has no problems handling WordPress. It’s a far cry from the cell-phone internet I’m used to.

I plan to continue trying out sites to see where the Blackberry might get stuck. I’ll post if I find anything, and update this entry if I find any more significant sites or webapps that work.

UPDATE: I found a page with a really nice intro to CSS and web development on the Blackberry. Read about it here.

Editing WordPress QuickTags to automatically create captioned images

Filler Bunny: He takes up space
Filler Bunny

One of the best ways to add life to your blog posts is to include images with the text–your reader’s eye is naturally drawn to the large visual well before the text itself, and the addition of a picture can bring an element or realism to your post that would normally be missed. Many templates available on the web, however, fail to include a simple way to add captions to your images, limiting what you can do with them. For example, anyone posting a picture of, say, two dogs would be hard-pressed to indicate which was Rover and which Fido without the aid of a caption. The easiest solution is to place the image in a table with a caption, of course, but this adds several ungainly lines of code which you must type in by hand in order to add a single captioned image. Even copying and pasting, this method of posting captioned images is a serious pain at best.

Thanks to WordPressQuickTags (the row of buttons directly above the post content itself on the Write page), however, it’s relatively simple to edit the ‘img’ button to create custom captioned images.

First, replace the function edInsertImage in /wp-includes/js/quicktags.js with the following javascript:

function edInsertImage(myField) {
var myValue = prompt(‘Enter the URL of the image’, ‘http://’);
if (myValue) {
myValue = ‘<img src="’
+ myValue
+ ‘" alt="’ + prompt(‘Enter a description of the image’, ”)
+ ‘" />’;
myValue = ‘<table class="alignright" width="’
+ prompt(‘Enter the image width’, ‘250’)
+ ‘" border="’
+ prompt(‘Border size:’, ‘0’)
+ ‘" cellspacing="0" cellpadding="0">’
+ ‘<caption align="bottom"><b>’
+ prompt(‘Caption:’, ”)
+ ‘</b></caption><tr><td>’
+ myValue
+ ‘</tr></td></table>’;
edInsertContent(myField, myValue);
}
}

Now, at this point, once you’ve replaced your current quicktags.js, the ‘img’ button on the write page may or may not do what you want it to do. Chances are that you’ll have to add to your CSS as well before you can reap the benefits of the modified ‘img’ button, though. If so, place the following in your template’s CSS sheet:

table.alignright {
padding: 4px;
margin: 0 0 2px 7px;
display: inline;
}

table.alignleft {
padding: 4px;
margin: 0 7px 2px 0;
display: inline;
}

That should do it. Now whenever you go to add an image with the quicktags img button, it will prompt you for all the appropriate parameters to create a nicely captioned image like the one above. Should you wish, you can add other elements to the javascript, such as the ability to choose the color of the photo’s border.

UPDATE: Make sure you refresh the ‘Write Post’ page of WordPress after you modifiy your quicktags.js file. Otherwise, the cached (unmodified) version will continue to be used.

Importing Macromedia Fireworks HTML into WordPress 2.0

To create the previous post, I obviously needed to incorporate some Fireworks HTML into WordPress 2.0‘s post editor in order to show the example. Having long since given up on the WYSIWYG editor that shipped with this new release, I started by trying various methods to get the image into the post by cutting and pasting various bits of HTML and JavaScript from the fireworks .html source file. The most important thing to remember is that you need to include Macromedia’s JS functions in the header of your theme, as high up in the code as possible, but at least before the CSS. What you’ll need looks like this:

<script language="JavaScript">

function MM_findObj(n, d) { //v4.01
var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i

So, with functions firmly in place, I began cutting and pasting some more. The main issues with this approach which quickly made themselves apparent were:

  1. By default, the ‘post’ lives on the blog‘s root level directory, but the billions and billions of tiny .jpgs which make up the actual Fireworks-produced rollover image live in whatever directory you put them. Updating the links does nothing, since the rollover behavior is governed by JavaScript, and a simple find/replace can’t help you there.
  2. Even when you decide you’re willing to dump billions and billions of tiny images into your root blog directory, the image shows up waaaaay down the post, for no apparent reason.

In light of these problems, I finally threw up my hands and decided I’d insert the image into a simple Dreamweaver html page, put it to the server, load the page in a browser, select all, and paste the whole mess into the WordPress editor, only this time with the WYSIWYG turned on. Lo and behold, it works perfectly, rollovers and all (assuming the page with the image you create is in the same directory as the Fireworks HTML and images, and that you’ve added Macromedia’s JavaScript to your header). The fact that the html looks exactly the same as it does when you painstakingly insert it into the html post editor by cut and paste notwithstanding, none of the spacing issues remain. Simple and easy, and finally, a justification (at least for me) for the WYSIWYG (which is back off for this post).

Hide your JavaScript with PHP sessions

Hiding JavaScript so that visitors can’t see it might not seem like a necessary precaution to take in most web programming situations. After all, a server-side language like PHP automatically prevents users from seeing your source code, and increasing functionality is quickly rendering the client-side advantages of JavaScript less significant by the day. However, there are many practical reasons to take the PHP-hidden-JavaScript approach, especially if you have long and complicated scripts that already exist and are in use, which would take a significant time commitment to revamp in PHP.
The key to this approach is to encapsulate your JavaScript in a separate PHP file, and to use a PHP session to restrict access to those scripts except when you want it to be explicitly permitted (i.e. when you want to run them from a specific page). To accomplish this, we first create a PHP session on the page from which we want to run the JavaScript.

< ?php session_cache_limiter('none'); session_start(); if(!$_SESSION['allow_script']) { $_SESSION['allow_script'] = true; } ?>

Placing this PHP at the top of your page opens a session and registers the variable ‘allow_script’ to that session, with a value of ‘true.’
The next step is to move whatever JavaScript you want to execute over to another file called ‘script.php’ This file should contain your JavaScript wrapped in a PHP tag, along these lines:


< ?php if(!$_GET['allow_script']) { session_start(); //restart the session from the previous page } if($_SESSION['allow_script']) //execute the javascript only if the variable is passed { header("Content-type: text/javascript"); ?>
alert("Hello World! JavaScript executed.");

< ?php } ?>


This portion of the PHP guarantees that the JavaScript generated by it does not appear to the end user, even if they navigate directly to script.php. The $_GET['allow_script'] check insures that the user is not trying to do an end-around by passing the allow_script variable with a value of ‘true’ directly to the script.php page, which would obviously allow them to view the JavaScript source.
Finally, you need to unregister the variable and close the session:


< ?php $allow_script = false; session_unregister('allow_script'); //delete the variable from the session session_unset(); //make the session inactive session_destroy(); //and toast it for IE } ?>

NB: session_destroy() is not necessary for Firefox or Internet Explorer 6 or better, but leaving it out means that IE 5 users will be unable to reuse the script.php page without closing and re-opening the browser.
The end result of this simple process is a nicely hidden, encapsulated JavaScript that can be called with the simple line:

<script language="JavaScript" src="script.php">

Now your existing JavaScript (with all its client-side capability) can be easily referenced within your code, without leaving it vulnerable to the malicious efforts of prying eyes.