unobtrusive javascript – Grey Panthers Savannah https://grey-panther.net Just another WordPress site Tue, 19 Dec 2006 07:13:00 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 206299117 What you don’t need javascript for – part 2 https://grey-panther.net/2006/12/what-you-dont-need-javascript-for-part-2.html https://grey-panther.net/2006/12/what-you-dont-need-javascript-for-part-2.html#comments Tue, 19 Dec 2006 07:13:00 +0000 https://grey-panther.net/?p=961 Read part 1 of my rant

There is a saying in Hungarian: Don’t look at the teeth of a horse you received as a gift. It refers to the fact that you shouldn’t criticize something if you get it for free. However from time to time I feel the need to raise my voice about things which could be better done. Example:

Via Global Nerdy I found a site called JS-Kit which allows you to add dynamic functionality to your own site. After doing a little googling, I found out that supposedly it was created by a Cisco Security Engineer. My comments are: is this the Cisco trust us, we know what’s best for you mentality or is this guy just inexperienced in the area of web security? Does he really think that I will include a script from his site that will run in the context of my page? And because the script is on his server, he can change it any time or even do sneaky things like only serve up the modified version when a referrer from my site is detected! An example of somebody getting it (partially) right is Widgetboy. You have to trust their javascript code, but after that they host every widget in an iframe, so that it can’t interact with your site.

My other problem is: why do you need javascript to submit a comment? Bulletin boards existed for ages without javascript! What about disabled users who use screen readers?

Here is the way it should be implemented IMHO:

  • The user should insert a single line of HTML in the page: <a href="http://js-kit.com/comment?[page url]>Comment on this<a>, the page url being optional (although recommended, see below)
  • When the user clicks on this link, s/he is redirected to the js-kit website, where a script takes the referrer url (which is activated in 99.9% of the browsers) to find out the page the comment should be placed on. If no referred url is available, it can fall back to the url passed as parameter. If none of these two is available, it gives an error message and terminates.
  • Now it redirects to a page which is divided in two frames: one which displays the original site and one which display the comments. The comments page should contain a prominent close link which redirects the top frame back to the original page, eliminating the comment frame.
  • The comment area can be used to place comments. There is no need to use javascript, plain old forms can do it, however you can use the principle of progressive enhancement to add visual effects with something like script.aculo.us, however the form should be usable without javascript.

The advantages would be:

  • Gives almost the same experience
  • There is no need to trust any third party javascript (no offense)
  • It works on a wide variety of browsers (event lynx knows frames)
  • It should work on speech browsers
]]>
https://grey-panther.net/2006/12/what-you-dont-need-javascript-for-part-2.html/feed 4 961
My time https://grey-panther.net/2006/12/my-time.html https://grey-panther.net/2006/12/my-time.html#respond Fri, 08 Dec 2006 07:04:00 +0000 https://grey-panther.net/?p=977 Update: you can find a simpler to use solution here.

From time to time I find myself reading a blog post which makes a reference to a give date / time (for example when a live stream will be activated). However the problem is that most of the time this reference is not given in my time-zone. So I’ve put together a little widget which you can see in the side-bar which displays the time in my time-zone (assuming that the clock and the timezone is correctly set on the viewers computer). It is also able to convert time references in the post to the time-zone of the reader (again, assuming that the reader has the correct date/time and timezone set and javascript activated), like the date / time when I’m writing this post (click on it to see the converted version – you must have javascript enabled and viewing this from my blog – not from the RSS feed).

Now for the main thing: how can you use it on your own blog? The easiest way is to go to the Widgetbox version (even more so if you are already using other widgets from the site), however that code has two limitations (because of the security model used by the site): (a) no clickable links will be generated for the date/time references (b) there is no iframe fallback support for browsers which have javascript disabled (because the site itself uses javascript to install the widgets in the blog, there would be no point in trying to create a no-javascript version).

The more complicated way would be to do a manual install. You will need some basic knowledge, access to your blog templates and to a host which can serve up PHP content (if you want to use the iframe fallback mechanism). In this case the steps would be the following:

  1. Upload PHP file to your host. You can see the source code below, or download it from here.
  2. Upload the javascript or you can directly include it in the page (between <script></script> tags of course). The source code can be seen below:

    Edit the last line (where it says .init(2);) so that in place of 2 you put your own time zone (offset from GMT)

  3. Finally insert the following code where you wish to show the clock:
    <!-- The url in the SRC attribute should poin where you updated the PHP file -->
    <!-- The offset is the time zone offset from GMT, the color the background color of the fallback IFRAME -->
    <!-- This can be ignored if you don't want an IFRAME fallback mechanism -->
    <iframe frameborder="0" marginheight="0" marginwidth="0" src="http://cdman83.byethost9.com/dateTime.php?offset=2&bgcolor=dfffbf" id="staticDisplayTime" style="width: 12em; height: 5em; border: none;" scrolling="no"
    ></iframe>

    <!-- This is where the javascript will display the date/time. Style it accordingly-->
    <div style="text-align: center; width: 10em;">
    <div id="displayAuthorsTime" style="font-size: xx-large;"></div>
    <div id="displayAuthorsDate" style=""></div>
    </div>

    <!-- The script. You can use an external file or include the script directly -->
    <script src="http://hype.free.googlepages.com/dateTime.js"></script>

  4. To insert an date element, format it like the following code: <span class="date"><!--Dec 08 2006 14:34:15-->click here to get the date/time written in the comment</span>
]]>
https://grey-panther.net/2006/12/my-time.html/feed 0 977
What you don’t need javascript for https://grey-panther.net/2006/12/what-you-dont-need-javascript-for.html https://grey-panther.net/2006/12/what-you-dont-need-javascript-for.html#comments Sun, 03 Dec 2006 16:20:00 +0000 https://grey-panther.net/?p=982 With all this Web 2.0 craze people start assuming that we all have javascript. I have a message for those people: you can have forms without javascript. I know that all those fading and stuff is cool, but if you use the standards more people can use it.

Example (I don’t mean to pick on anybody, this is just one example I know of): the guys over at the F-Secure blog started using some service for creating polls. Now for their polls to work you have to enable javascript from two sources: from pollmonkey (because they give you a script to include in your page) and from the originating page (because you have to activate the script). To give you a better idea, here is a direct code snippet from their site:


<script src="http://www.pollmonkey.com/s.asp?c=53753826&u=2619733987"></script>
<script language=javascript>DisplayVote33987();</script>

Because this is embedded on the F-Secure page, you have to allow script execution from both the pollmonkey website (for the included script to work) and from the F-Secure domain for the initialization code to execute. While javascript is one of the easiest techniques to use in this case (using iframes for example would mean to play around with the size), there is no need for the embedding site to call the initialization script, it can be done directly in the included script file.

They aren’t the only culprits, other well known examples include Google (with their Google Analytics / Urchin tracking code) and Digg (with their code which displays the number of diggs for a given article)

An other bad example would be Zoomerang. They claim 70+ Fortune 100 clients and other similar things. Even with this much money, they created a system which not only is based entirely on javascript (even though you can style forms entirely with CSS), but it also doesn’t give any warnings about the fact that you don’t have it activated. Arguably you would know if you disabled javascript, but even so it would be nice to get a warning.

The conclusion, if any, is the fact that managers (who buy the services of these sites) mostly have no idea about the real quality of service they are getting. While in some cases it may be reasonable for them not be an expert in the respective domain, they should at least ask an independent party who can accurately evaluate the service for them. But this is the topic for an other rant…

PS. If you are interested in building better forms, go listen to episode 41 of the boagworld.com podcast.

]]>
https://grey-panther.net/2006/12/what-you-dont-need-javascript-for.html/feed 3 982
How to publish a good looking code on Blogger? – take 2 https://grey-panther.net/2006/12/how-to-publish-a-good-looking-code-on-blogger-take-2.html https://grey-panther.net/2006/12/how-to-publish-a-good-looking-code-on-blogger-take-2.html#comments Sun, 03 Dec 2006 06:58:00 +0000 https://grey-panther.net/?p=987 Update – there seem to be some issues with iframe-s and google reader (in the sense that its not displaying them 🙁 ). I’ll investigate the issue further shortly and hopefully can post a solution.

Hello all! First of all I would like to apologize to all of you who in the last couple days tried to access my random password generator or my password combinator. I was in the process of moving them from my free host to a google pages account. There were no major problems with it, but Google seems more reliable and also doesn’t put any ads in your content. Of course you don’t get any server side code execution possibilities (Perl, PHP, SSI), but currently I don’t need them. To sum up: both of my scripts are available:

And I also updated the bookmarklet so that it points to the new location.

Now for the main feature: from this point I’ll be using a new method to publish syntax highlighted code on the blog. My problem with the old method was that it inserted a blob of CSS in every post. The new way used is formed from an IFRAME, an HTML document which contains the highlighted source code and a small JS source which adds the expand / collapse link to the code. Here is the procedure step by step:

  1. Install jEdit. You will have to have Java installed. I recommend that you download the latest (development) version. If you use the Java based installer, it doesn’t create shortcuts in the start menu or on your desktop, so you have to start it manually by issuing the command c:Program FilesjEdit 4.3pre8jedit.jar (unless you have installed it in an other directory).
  2. Start jEdit, and go to Plugins -> Plugin Manager. Press the Download Options button and select an other mirror. Restart jEdit.
  3. Go to the plugin manager again, and in the install tab (you’ll have to be patient until the list of plugins gets downloaded) check Code2HTML (the current version is 0.5 for the development version of jEdit and 0.3.5 for the stable one) and click install.
  4. Now upen up the code you want to highlight. Make sure that the file it’s saved in has the appropriate extension so that jEdit can highlight it properly (as an added bonus, jEdit correctly highlights the different languages which may be present in the same file – for example PHP, CSS, HTML and Javascript). Now go to Plugins -> Code2HTML -> HTMLize current buffer
  5. Tweak the resulting HTML code. For example I add the style body { margin: 0px; } to the stylesheet to avoid wasting screen realestate. I also add the snippet which is the google analytics tracking code.
  6. Save the HTML file and upload it (as mentioned earlier I use google pages to host them).
  7. Now in the page you wish to insert the sample code, enter the following: <iframe src="...link to the highlighted source code..." class="source_code" style="width: 100%; height: 20em;"></iframe>. Of course you can change the styling so that it blends nicely with your blogger template
  8. If you link to the javascript code show below (with a <script> tag), you will get an expand / collapse link before each iframe if the client has javascript activated
  9. Enjoy!
]]>
https://grey-panther.net/2006/12/how-to-publish-a-good-looking-code-on-blogger-take-2.html/feed 8 987
Graceful degradation people! https://grey-panther.net/2006/11/graceful-degradation-people.html https://grey-panther.net/2006/11/graceful-degradation-people.html#respond Wed, 29 Nov 2006 20:04:00 +0000 https://grey-panther.net/?p=990 I went to check out Less Accounting (because I saw it at the Web 2.0 show). Here are two screenshots, one with javascript enabled and the other with it disabled:

Do I really need javascript to submit a simple form? Really? As for the server running the given website, its version number isn’t too reassuring either.

]]>
https://grey-panther.net/2006/11/graceful-degradation-people.html/feed 0 990
How to publish a good looking code on Blogger? https://grey-panther.net/2006/10/how-to-publish-a-good-looking-code-on-blogger.html https://grey-panther.net/2006/10/how-to-publish-a-good-looking-code-on-blogger.html#comments Thu, 12 Oct 2006 17:05:00 +0000 https://grey-panther.net/?p=1042 This article is considered obsolete. Please read the followup post.

From time to time I would like to publish a post in which I can show code snippets. However the standard <code> or <pre> tags look way too boring. Something with color stands much more out. I was thinking: if I had my own server and would host my blog there, I could add automatic syntax highlighting in no-time using GeSHi (Generic Syntax Highlighter). Then it hit me: why not use the demo hosted by them and copy the output over as HTML? It’s not as elegant or simple as having a server-side script taking care of it, but it’s better than the standard look. So here are the steps:

  1. Head over to the GeSHi demo page and plug your source in. Play around with the settings until you get a satisfying result.
  2. Save the resulting page (it would easier to use view source, but since this is a dynamically generated page using parameters passed with the POST method – rather than GET – it doesn’t work).
  3. Open it in a text editor (like gedit or notepad) and find the style section where it says <style type=”text/css”>/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */ and copy it over to the blog post
  4. Find the start of the code (you can do this easily by searching for style="border: 1px dotted and copy it over until the end of the code. This you can recognize by the sequence </div></li></ol>
  5. Add a final </div> after the part you just copied.
  6. Because I use a Blogger template which styles list items in a special way and also restricts the width of the part where the post is displayed, I have to add the following lines to the style sheet:
    div.code { overflow: auto; width: 100%; }
    div.code li {
     list-style: decimal outside;
      padding-left: 0px;
      margin-bottom: 0px;
      background: none;
    }   
    

    and also add the code class to the starting div (to do this go to the start of the part you copied and where it says class="[something]" add code, so that it looks like this: class="[something] code"

  7. Enjoy 🙂

There are a few problems with this approach: (a) the biggest is that it’s a multi-step fairly complicated procedure (b) If you have multiple post with source code on your page you will have duplicate style-sheet information in your page (c) It is not recommended to include style information in-line or in the main body (the style tags you copy will end up in the body instad of the header where they should be put) (d) While copying the code you might have some weird characters appear (e) GeSHi is not perfect (for example in the code below it gets confused by the embedded javascript), but it’s the best I’ve found so far. It is a beta solution and if any of you have ideas on how to improve it, please take the time to write a comment. As a bonus you find below the source code for my Javascript random password generator (not that you couldn’t do a view source until now, but this is more accessible).

]]>
https://grey-panther.net/2006/10/how-to-publish-a-good-looking-code-on-blogger.html/feed 8 1042
Pimping my blog #2 https://grey-panther.net/2006/10/pimping-my-blog-2.html https://grey-panther.net/2006/10/pimping-my-blog-2.html#respond Thu, 12 Oct 2006 05:33:00 +0000 https://grey-panther.net/?p=1043 After observing that most of my visitors (45% currently) use Internet Explorer, I’ve made a little modification so that they to can enjoy the <q> tag. A more detailed discussion and other solutions can be found at the List Apart site. I’ll only present in short my version.

My version consists of two parts: a style using the underscore hack to make the contents of the tag italic for the security conscious users (those who don’t have Javascript enabled) and then a script written in unobtrusive style which (a) adds a " before and after each tag and (b) disables the italic style. You can find the sources below.

GeSHi © 2004, Nigel McNie
  1. <style type=“text/css”><!–
  2.   Q { _font-style: italic; }
  3. –></style>
GeSHi © 2004, Nigel McNie
  1.   var quoteResolver = {
  2.     addEvent : function (obj, evType, fn) {
  3.       //taken from: http://www.scottandrew.com/weblog/articles/cbs-events
  4.       if (obj.addEventListener){
  5.         obj.addEventListener(evType, fn, false);
  6.         return true;
  7.       } else if (obj.attachEvent){
  8.         var r = obj.attachEvent(“on”+evType, fn);
  9.         return r;
  10.       } else {
  11.         return false;
  12.       }  
  13.     },
  14.    
  15.     doWork: function () {
  16.       //add a ” before and after each q
  17.       var qs = document.getElementsByTagName(‘q’);
  18.       for (var i = 0; i < qs.length; i++) {
  19.         var before = document.createTextNode(‘”‘);
  20.         var after = document.createTextNode(‘”‘);
  21.         qs[i].parentNode.insertBefore(before, qs[i]);
  22.         qs[i].parentNode.insertBefore(after, qs[i].nextSibling);
  23.       }
  24.      
  25.       //deactivate the font-style: italic rule     
  26.       for (var i = 0; i < document.styleSheets.length; i++) {
  27.         //the standard would be cssRules, but IE uses rules
  28.         //and we are targeting IE only
  29.         var ruleList = document.styleSheets[i].rules;
  30.         for (var j = 0; j < ruleList.length; j++)
  31.           if (‘Q’ == ruleList[j].selectorText && ‘italic’ == ruleList[j].style.fontStyle) {
  32.             //this is the style we wish to disable
  33.             ruleList[j].style.fontStyle = ;
  34.             break;      
  35.           }
  36.       }         
  37.     },
  38.    
  39.     init : function () {
  40.       //try to determine if this is an IE browser
  41.       var userAgent = /MSIE/; var nonUserAgent = /Opera/; var os = /Windows/;
  42.       if ( userAgent.exec(navigator.userAgent) && !nonUserAgent.exec(navigator.userAgent) && os.exec(navigator.userAgent) ) { 
  43.         //register a function to do the work after we finish loading
  44.         this.addEvent(window, ‘load’, this.doWork);
  45.       }
  46.     }
  47.   }.init();
]]>
https://grey-panther.net/2006/10/pimping-my-blog-2.html/feed 0 1043
Delaying the loading of elements in a web page https://grey-panther.net/2006/10/delaying-the-loading-of-elements-in-a-web-page.html https://grey-panther.net/2006/10/delaying-the-loading-of-elements-in-a-web-page.html#respond Wed, 11 Oct 2006 15:17:00 +0000 https://grey-panther.net/?p=1044 After listening to the latest Practical Webdesign Magazine podcast (I listen to every one of them as well as the Boagworld podcast, both being great podcasts), I felt the urge to write this post :). When you include many third party things in your webpage, the loading of it can be slowed down considerably if the client doesn’t have a good connection or the given service has outages. The solution I came up with is to delay the inclusion of the content until the webpage (or at least the part loading from your server) has finished loading. To accomplish this I’ve created the little javascript below. What it does is to schedule a given function to be executed a given number of milliseconds after the page has been loaded. If you set this low (the default is 100 milliseconds for example), the users won’t notice an interruption in the loading (if the other services that you rely on can deliver content fast enough) or at least will see the parts of your page which is loaded from your server until the other parts load (if they have a slow connection to the third party source). To use this, use the following type of call: delayedLoader.scheduleAfterLoad(function() { alert("Hello World!"); });.

An other feature of this script is that it simplifies the cases when you have to include HTML from third party sites (an IFRAME for example). To use this feature create a placeholder div or span in which you should include the temporary content (the content which should be displayed while the third party content is loading), give it a class of "to_replace" and immediately after create a comment in which you should include the text witch which the temporary content should be replaced. Probably looking at the example below this becomes much clearer than after reading my babbling.

GeSHi © 2004, Nigel McNie
  1. <div class=“to_replace”>This needs to be replaced!</div>
  2. <!– This is the <em>replacement</em> –>

The source code:

GeSHi © 2004, Nigel McNie
  1.   var delayedLoader = {
  2.     addEvent : function (obj, evType, fn) {
  3.       //taken from: http://www.scottandrew.com/weblog/articles/cbs-events
  4.       if (obj.addEventListener){
  5.         obj.addEventListener(evType, fn, false);
  6.         return true;
  7.       } else if (obj.attachEvent){
  8.         var r = obj.attachEvent(“on”+evType, fn);
  9.         return r;
  10.       } else {
  11.         return false;
  12.       }  
  13.     },
  14.  
  15.     //schedules a given function to be invoked a given number of miliseconds
  16.     //after the loading of the document has finshed. the default number of
  17.     //miliseconds is 100
  18.     scheduleAfterLoad : function (fn, msecs) {
  19.       if (msecs <= 0) msecs = 100;
  20.       this.addEvent(window, ‘load’, function() { setTimeout(fn, msecs); });      
  21.     },
  22.        
  23.     replaceElements : function () {
  24.       var replaceElementArray = function (to_process) {
  25.         for (var i = 0; i < to_process.length; i++) {
  26.           if (to_process[i].className.indexOf(‘to_replace’) > -1) {
  27.             var element = to_process[i];
  28.             while (null != element && 8 != element.nodeType) element = element.nextSibling;
  29.             if (null != element && 8 == element.nodeType)
  30.               to_process[i].innerHTML = element.nodeValue
  31.           }
  32.         }        
  33.       };
  34.      
  35.       //process divs and spans
  36.       var to_process = document.getElementsByTagName(‘div’);
  37.       replaceElementArray(to_process);
  38.       to_process = document.getElementsByTagName(‘span’);
  39.       replaceElementArray(to_process);
  40.     },
  41.    
  42.     init : function () {
  43.       this.scheduleAfterLoad(this.replaceElements);
  44.       return this;     
  45.     }  
  46.   }.init();
  47.  

There is a potential problem with all this: the user might not have javascript enabled. This could be mitigated by repeating the content in a noscript tag (that was my original plan to use the content of the noscript tag to replace the content of the parent), however I’m pretty sure (although not 100%) that the user agent (the browser) would still load the stuff, event though it is invisible and slow the loading of the site down.

]]>
https://grey-panther.net/2006/10/delaying-the-loading-of-elements-in-a-web-page.html/feed 0 1044
(Yet an other) Javascript random password generator https://grey-panther.net/2006/10/yet-an-other-javascript-random-password-generator.html https://grey-panther.net/2006/10/yet-an-other-javascript-random-password-generator.html#comments Mon, 02 Oct 2006 09:03:00 +0000 https://grey-panther.net/?p=1061 Here is YARPG (Yet Another Random Password Generator). Why on earth would I do yet an other random password generator? Because I can :). Seriously: there are at least two random password generators out there that I’ve used, and I have some problems with them:

  • The one that Steve Gibson created can not be customized (I don’t always want ultra-long passwords)
  • The one at winguides.org does not by default use HTTPS (although you can convince it manually)
  • They both use a round-trip to the server and I must trust their server that it doesn’t keep logs about IP-passwords association for example. What makes it even worse in the case of the winguides.org website is the fact that they transmit all the options as GET parameters which are logged by default by the webservers (as opposed to POST parameters which are by default not logged). This means that they must make an extra effort to disable logging (at least for this part of their site), which I’m not sure they did.

My javascript offers 100% client-side generation and you can view its source code to make sure that it does what it claims it does. There is no need for HTTPS / SSL because no connection is made / no data is transmitted to the server.

Be safe and remember: password length beats password complexity most of the time.

Update: the script has been update so that it is more unobtrusive. Also I’ve published the source code for those who don’t want to search through a whole page in a copy paste ready format.

This password generator requires a javascript capable browser.

Update: you can now download the source as a zip file.

Update: Fixed the problem that not all generated passwords contained at least one character from each selected set. See the post announcing the update for details. Also, the new download location is my SVN repo: js_password_generator.html.

]]>
https://grey-panther.net/2006/10/yet-an-other-javascript-random-password-generator.html/feed 8 1061