Archive for the ‘JavaScript’ Category

⚃ Rolling Dice with JS and Unicode ⚂

Wednesday, January 6th, 2010

I recently discovered the unicode xscreensaver hack, and have had it running on my secondary monitor for the heck of it. I found out that there are dice face symbols, and I was inspired to do something with them.

So, I made a simple Unicode-dice roller in JavaScript. I know the same thing could be done in JS, but this way you can roll some numbers to paste into Twitter or something, if you feel like it.

Enter number of Dice to roll:

Result:  

The code is extremely simple, calling Math.floor on the result of Math.random n times, then using a small table of the codepoints from U+2680 to U+2685 to build a string.

Here is the code for anyone interested:

<script type="text/javascript">
function roll(n) {
    var dice = ['\u2680', '\u2681', '\u2682', '\u2683', '\u2684', '\u2685'];
    var results = '';
    for (var i=0; i<n; i++) {
        results += dice[Math.floor(Math.random()*6)] + ' ';
    }
    return results;
}
 
function doRoll(countElem, resultElem) {
    document.getElementById(resultElem).innerHTML = 
        roll(parseInt(document.getElementById(countElem).value));
}
</script>
 
Enter number of Dice to roll:<br><input type="text" id="dice-roll-number" />
<input type="button" onclick="doRoll('dice-roll-number', 'dice-roll-result')" value="Roll!" />
 
Result: <span style="font-size: 64px; line-height: normal" id="dice-roll-result"></span>

A save your place bookmarklet

Tuesday, December 1st, 2009
saveplace

I read a lot of web comics, and one of the things that happens when reading through the archives of a comic is that I lose my place in the history, so when I come back, I have to spend a lot of time searching to find where I left off.

I wrote this simple set of bookmarklets to help me in this situation. The “save place” bookmarklet stuffs the current URL into a cookie (cookies are per site, so there will be one cookie for each site you use this on), and the “restore place” bookmarklet takes the URL out of the cookie (if it exists) and loads that page. The “clear place” bookmarklet clears the cookie.

To use them, just drag the bookmarklets to your bookmark toolbar, or right-click on them and select “bookmark this link”.

Save Place | Restore Place | Clear Place

For those who are interested, here’s the code in function form:

function savePlace() {
    var date = new Date();
    document.cookie='ppdc_saved_location='+escape(document.location)
        +'; expires='+date.setTime(date.getTime()+22896000000)+'; path=/';
}
 
function restorePlace() {
    document.location = (function() {
         var ca = document.cookie.split(';');
         for(var i=0;i<ca.length;i++) {
             var c=ca[i];
             while (c.charAt(0)==' ') c = c.substring(1,c.length);
             if (c.indexOf('ppdc_saved_location=') == 0) 
                 return unescape(c.substring(20,c.length));
         }
         return document.location;
    })();
}
 
function clearPlace() {
    document.cookie='ppdc_saved_location=; expires=-1; path=/';
}

I based my code off the createCookie and readCookie functions from QuirksMode

Fun with bookmarklets and CSS3 transforms

Thursday, November 26th, 2009

Transform!

I recently read about the CSS transform property, and I was inspired to give it a try in a fun and mostly useless way.

After a bit of fidding, I present to you the “Rotate!” bookmarklet (click it several times if it doesn’t work the first time):

Rotate!

Simply drag the above link to your bookmarks toolbar, and whenever you get bored with a webpage, click that link, and see what happens!

The code is pretty simple. It just gets a list of all the divs on the page, picks one of them at random, and starts rotating it. Click it multiple times, and it will rotate multiple times.

Here’s the code, formatted for your viewing pleasure:

(function() {
  var ds = document.getElementsByTagName('div');
  var d = ds[Math.round(Math.random()*ds.length)];
  function rotateHeaders(r) {
    d.style['WebkitTransform'] = d.style['MozTransform'] = 'rotate(' + r + 'deg)';
    setTimeout(function() {rotateHeaders(++r % 360);}, 100);
  }
  rotateHeaders(1);
})()

Unfortuneately, this only works in Firefox and Webkit-based browsers at the moment..wait, no, that’s pretty much ok. You IE folks out there are used to things not working in your browser by now.

With a couple small changes, you can make it scale instead: Scale!

IE7 Requires type=”submit” for <button> elements

Friday, October 30th, 2009

If you don’t specify type=”submit” for a <button> element, IE7 (and probably IE6, too) will do nothing when that button is clicked (well, unless you have an onclick handler on that element, of course).

The W3C HTML standard states that the default for a <button> element should be “submit”, but if you want it to work with IE7 or earlier, you’ll have to be explicit about it.

I lost some precious time on this fun bug. I was doing some form validation via the great jQuery Validation plugin and for some reason, the form wasn’t validation in any IE earlier than IE 8.

Of course, since it’s such a pain to debug IE, I had a heckuva time figuring out the source of the bug, because I just assumed it was some weird JavaScript quirk, and didn’t even consider that it could be something as simple as a “missing” element attribute.

Ah well. Hopefully this will help somebody else avoid the same problem.

Failed half-hour project

Thursday, June 25th, 2009

My attempt at a half-hour project before going to sleep failed. It took a little more than a half-hour, and my input of the following:

      version proto

      character paul
        image paul.png
      end

      character angie
        image angie.png
      end

      angie says I thought you were going to bed!
      paul say But I really wanted to try and write a comic markup language prototype.
      angie says What? What the heck is wrong with you? Go to sleep.
      paul says Just give me a half hour.
      angie says Ok, fine, but only a half hour. Crazy person.

only resulted in the following output:

Unrecognized command at line 3: "character"

Ah well, there’s always tomorrow…

simple textarea auto-resizer

Friday, April 24th, 2009

Today I was having issues with a textarea resizer (a hacked-up version of SmartArea) that I had been using for a while in a work project. It was working fine for textareas of a certain width, but it got less and less useful as the textareas got less wide, not wrapping lines until it already had scrollbars for a word or two.

It seemed to me that it needn’t be as complex as it was, so I decided to try and write my own, and here’s what I came up with:

function growTextArea(e) {
    if (!this.rows || this.rows < 1) this.rows = 1;
    while (this.clientHeight >= this.scrollHeight && this.rows > 1) this.rows -= 1;
    while (this.clientHeight < this.scrollHeight) this.rows += 1;
}

A working example, embedded using jQuery:

$('#example-resizing-textarea')
    .keyup(growTextArea).keyup();

Type some text in here:

Compatibility

This works for me in Firefox, IE6, IE7, Chrome and Chromium, Safari (for Windows, testing in a Windows VM along with the IEs and Chrome), and Opera 9.62. As you may have noticed I’ve avoided using any JS-library or browser-specific code, so this should work equally well with jQuery, Prototype, or with no library at all.

IE actually gives incorrect values for scrollHeight, but that is easily made up for by using “this.clientHeight >= this.scrollHeight” in the first while loop rather than “this.clientHeight == this.scrollHeight”

Minimum and Maximum rows

If you want to set a minimum and maximum height, it takes a little more work:

function sizeTextArea(min, max) {
    return function(e) {
        if (!this.rows || this.rows < min) this.rows = min;
        while ((this.clientHeight >= this.scrollHeight 
                && this.rows > 1 && this.rows <= max) 
               || this.rows > max) this.rows -= 1;
        while ((this.clientHeight < this.scrollHeight 
                || this.rows < min) 
               && this.rows < max) this.rows += 1;
        if (this.rows == max
            && this.clientHeight < this.scrollHeight) this.style.overflow = 'auto';
        else this.style.overflow = 'hidden';
    }
}

Another example, limited to having between 4 and 8 rows:

var sizer48 = sizeTextArea(4, 8);
$('#example-resizing-textarea')
    .keyup(sizer48).keyup();

Type some text in here, too:

Possible modifications could include using pixel sizes instead of changing the “row” attribute and animating the resizing.

This could easily be packaged into a plugin for jQuery or Prototype, and I might just do that, but right now it’s getting late, so I’m going to sleep instead.

return false; it’s good for you.

Sunday, November 25th, 2007

Today I was looking around for blogs about JavaScript when I stumbled upon The Strange Zen of JavaScript by Scott Andrew LePera (Hacker/Singer/Songwriter), which looks to be quite informative, though sadly it seems as though it has been in hibernation since July.

I was relieved to see in reading The Mark Of The n00b that I’m not a n00b (at least according to that particular metric). Though I suppose I should point it out to others so they can avoid being n00bs as well:

use href=”#” and return false from your onclick event handlers to avoid jumping! (Ironically there were comments asking how to avoid the jumping scrollbars in the Mark of the n00b post, which was posted immediately after the return false post. Whoops.) Hopefully adding yet another post about this will help people googling for solutions to this frustrating problem to be more likely to find it.

More about returning false

I hate to just link to a post without adding something to the discussion, so I’ll throw in a bit of extra information about JavaScript event handler return values.

Return values are handy in most any event handler, not just onclick. Returning false prevents the event from “bubbling” up to the browser

Here are some suggestions for ways in which to use event handler return values:

  • onsubmit

    Add an onsubmit handler to a form using onsubmit=”return validate_form()”, if the form input is valid, return true, allowing the form to be submitted. If it is not valid, return false, preventing it from being submitted, then let the user know why.

  • onmousemove

    When using onmousedown and onmousemove to make an element drag-n-drop-able, then you will probably want to return false from the onmousemove handler to prevent any text on the page from being selected.

  • onmousedown, onmouseup

    Say you want to respond to a right click on a link, but you want to leave alone regular left clicks. Register an onmouseup event handler (which takes a parameter e) for that link, check the value of e.button. If it is 0, return true and the link is followed. If it is 2, do your thing (pop up a context menu, perhaps?), then return false so that the browser doesn’t pop up its own context menu. This is the technique used by those annoying scripts that “prevent” you from downloading images from their sites.

For an enormous amount of more information, check out the DOM Event Compatibility Tables over at Quirksmode

Fun With Bookmarklets

Saturday, November 24th, 2007

I’ve got a project planned for the near future which will require some sort of interaction with webpages other than my own. There are two ways I’m considering doing this: browser plugin, or bookmarklet(s). The problem with doing a browser plugin is that I’d have to write a separate plugin for each browser or, worse, only support a single browser. So I’m leaning toward bookmarklets to begin with. As with most things, I figured I’d get a bit of experience with bookmarklets before trying to do anything too complicated.

My first bookmarklet

According to this page on bookmarklets, the longest I can make a bookmarklet and have it still run in every browser (read: IE6) is 488 characters. That’s hardly enough to do any sort of cool Web2.0 stuff, so I need to load in an external script. Despite what the previously linked site says, it is indeed possible to insert script tags into the header of more than just IE, so that’s what I’ll do:

(function() {
    var head = document.getElementsByTagName('head')[0];
    var newscript = document.createElement('script');
    newscript.type='text/javascript';
    newscript.src='http://probablyprogramming.com/files/bm/js/google.js';
    head.appendChild(newscript);
})()

There, only 250 characters when I take out all the whitespace and add “javascript:” to the beginning. Notice that everything is wrapped in anonymous functions; this avoids putting unnecessary stuff into global namespace, which should prevent this code from conflicting with any code already on the page it’s being inserted into. The one thing that I do put into the global namespace is the blogpaulbonsercomclosegoogle_box() function, which I named to avoid conflicts.

google.js:

function blog_paulbonser_com_close_google_box() {
    var gb = document.getElementById('blog_paulbonser_com_google_box');
    gb.parentNode.removeChild(gb);    
}
 
(function() {
    var body = document.getElementsByTagName('body')[0];
    var head = document.getElementsByTagName('head')[0];
 
    var newstyle = document.createElement('link');
    newstyle.href = "http://probablyprogramming.com/files/bm/css/google.css";
    newstyle.rel="stylesheet";
    head.appendChild(newstyle);
 
    body.innerHTML += '<div id="blog_paulbonser_com_google_box"><div><a href="#" onclick="blog_paulbonser_com_close_google_box(); return false;">Close</a></div><iframe src="http://google.com"></iframe></div>';
})();

Go ahead, give it a try.

Example Bookmarklet: open an iframe

There you go, google popping up in the middle of my page. The real power of this, however, is that it should work on any page (except for pages with frames, since they don’t have a top-level body element). If you drag the link up to your bookmark toolbar, or rightclick and select “Bookmark this link”, etc, you will then be able to go to any page, click on that bookmark, and have a google search page pop up right in the middle.

My first “useful” bookmarklet

That’s a good start, but how about something that might actually be useful? Here’s an attempt at just that.

Lightboxify Bookmarklet: lightboxify page

This bookmarklet, plus a slightly modified version of the wonderful Lightbox plugin by Lokesh Dhakar, will take any links to images on the current page and “lightboxify” them. Give it a try on this page with the links below (some random images pulled from my computer). Before running the bookmarklet, it will navigate away from this page to the image. After running it: instant fancy image gallery. (Okay, there are still no thumbnails, but that would require a bit of extra work.)

If you feel so inclined, you can also drag this bookmarklet to your bookmarks toolbar, go to the Apache-generated directory listing, and give it a whirl there, as well.

1 2 3 4 5 6 7 8