The latest version of Super Tables is out. I decided to call it version 0.30 instead of version 0.26 because I feel like it has earned the bigger jump speedwise. Enjoy!
Version 0.30 Change Log:
Have a look, it's now much faster.
Read more...I ran across an issue the other week where an onScroll JavaScript function was being called too often and I needed to figure out a way to execute it only when needed. Knowing that the code was mainly intended for post-scrolling execution, I came up with this idea* of setting and resetting a timeout again and again until the actual event finished and the set timeout fired the real code. So far it seems to be working great so I thought I'd share.
The following code will execute the intended onWhatever function once the user stops resizing, scrolling or moving the mouse ( depending on how it's used ). Please check out the demo pages to see the simulated events in action.
This script was successfully tested in Windows versions of Internet Explorer 5.5 - 7, Firefox 1.5 - 3, Opera 9 and Safari 3.
var whateverEndFunc = function () {
var delay = 50; // milliseconds
var whateverTimeout;
return function () {
if (whateverTimeout) {
clearTimeout(whateverTimeout);
}
whateverTimeout = setTimeout(function () {
// YOUR [onResize, onScroll or onMousemove] CODE HERE
}, delay);
};
}();
If you decrease the variable delay the code inside of the timeout will be called more often and vice versa. To use this code, call it just like you would onResize, onScroll or onMousemove. Some basic examples:
window.onresize = function () {
whateverEndFunc();
}
window.onscroll = function () {
whateverEndFunc();
}
document.onmousemove = function () {
whateverEndFunc();
}
* inspired by Ari Karp - who needs to make a damn blog : )
Read more...One of the more useful methods found in Mozilla browsers is the getComputedStyle method. This method, when called on an element, can return the computed runtime value of a specified style property using the getPropertyValue method.
While each Mozilla browser has its own quirks, the basic implementations are similiar. For example, if for an element you call getComputedStyle with the intent to find its width; it will return a length in pixels regardless of whether or not the style property was specified in pixels or at all on the element. As you may tell, this information is most useful for javascript functions that need to know the size of elements as they actually are on the screen.
Unfortunately Microsoft did not put this method into Internet Explorer 7 and below. This has left developers with the task of finding workarounds to their problems that would otherwise be easily solved had they the method. Fortunately, I may have found a satisfactory solution to IE's lacking support. - At least, for retrieving dimension sizes on block elements...
The following javascript object can return, in pixels ( or as possibly auto ), the computed width, height, padding, border width and more for block elements. The object relies on a code snippet I used in my width and height getter functions post about a month ago. The snippet is fairly straightforward, in which styleEl is the element we're looking at:
The argument "length" can be any sort of style value length such as 50px, 50em, 50pt, 50%, auto, etc. It will create a temporary DIV that will be placed in the same parent container as the element being called upon. This way relativity is maintained. The width is extracted and viola! - we have what we need.
One question you may be asking yourself is: why set the width every time and not the height? This is because even vertically-oriented styles such as margin-top, padding-top and border-top-width are based off of the horizontal. If you have a browser screen resolution of 800 x 600 and for an element, with parent element BODY with margin 0px, said that you wanted the padding-top to be 10%, it would be drawn 80px deep and not 60px. ( note: this does NOT apply to the height style )
Posted below is the full source code for the IE_computedStyle object. Please see the script's comments for usage. A demo is also available. ( please note that it was made for IE only and will return undefined purposefully in other browsers )
Read more...While each major browser has its own scripts and plugins for viewing the generated source code, there's nothing really universal except for the innerHTML/outerHTML method (from what I've found online).
The following bit of code is that very method presented in an easy to use way. It's CSS/HTML code that you can throw in and out of your page while developing. The code will allow you to view, select and copy the generated source code in IE, Firefox, Safari and Opera.
One note: After you click on 'View Source' a text area will appear. Press CTRL + A to select all of the text or just scroll through it. To close the text area, click anywhere on the page. (to bring it back, press the 'View Source' button again)
<style type="text/css">
textarea#doc_source { position:fixed;z-index:1000;bottom:10px;right:20px;width:600px;height:300px;display:none;overflow:scroll; }
input#doc_button { position:fixed;z-index:1000;top:10px;right:20px;width:120px; }
</style>
<!--[if lte IE 6]> <style type="text/css"> textarea#doc_source { position:absolute; } input#doc_button { position: absolute; } </style> <![endif]-->
<textarea id="doc_source" onblur="this.style.display='none';"></textarea>
<input id="doc_button" type="button" onclick="document.getElementById('doc_source').style.display='block';document.getElementById('doc_source').value='';document.getElementById('doc_source').value=document.documentElement.innerHTML;document.getElementById('doc_source').focus();" value="View Source" />
I should mention that in IE6 and below the button and text area do not follow you as you scroll down the page due to IE6's fixed position bug. Bleh.
Read more...Updated on 7/13/2008.
The following are two similiar functions you may find useful. When called on an element, they can return (in pixels) either:
The functions work on any(?) block element, regardless of whether or not it has a predefined width/height. They have been successfully tested in Windows versions of Internet Explorer 6 - 7, Firefox 1.5 - 3, Opera 9 and Safari 3.
Below this function is a small demo and here you can find the test page (with an additional dynamic style change test).
getWidth(), getHeight()://///////////////////////////////////////////////////////////////////////////////////////////////// // USED FOR GETTING THE COMPUTED WIDTH OF AN ELEMENT IN PIXELS /////////////////////////////////////////////////////////////////////////////////////////////////// var getWidth = function (/* Object */ el, /* boolean */ includePadding, /* boolean */ includeBorder) { var width; el = (typeof(el) === "string") ? document.getElementById(el) : el; if (window.getComputedStyle) { /* FF, Safari, Opera */ var style = document.defaultView.getComputedStyle(el, null); if (style.getPropertyValue("display") === "none") return 0; width = parseInt(style.getPropertyValue("width")); if (window.opera && !document.getElementsByClassName) { /* Opera 9.25 includes the padding and border when reporting the width/height - subtract that out */ width -= parseInt(style.getPropertyValue("padding-left")); width -= parseInt(style.getPropertyValue("padding-right")); width -= parseInt(style.getPropertyValue("border-left-width")); width -= parseInt(style.getPropertyValue("border-right-width")); } if (includePadding) { width += parseInt(style.getPropertyValue("padding-left")); width += parseInt(style.getPropertyValue("padding-right")); } if (includeBorder) { width += parseInt(style.getPropertyValue("border-left-width")); width += parseInt(style.getPropertyValue("border-right-width")); } } else { /* IE */ if (el.currentStyle["display"] === "none") return 0; var bRegex = /thin|medium|thick/; /* Regex for css border width keywords */ width = el.offsetWidth; /* Currently the width including padding + border */ if (!includeBorder) { var borderLeftCSS = el.currentStyle["borderLeftWidth"]; var borderRightCSS = el.currentStyle["borderRightWidth"]; var temp = document.createElement("DIV"); if (el.offsetWidth > el.clientWidth && el.currentStyle["borderLeftStyle"] !== "none") { if (!bRegex.test(borderLeftCSS)) { temp.style.width = borderLeftCSS; el.parentNode.appendChild(temp); width -= temp.offsetWidth; el.parentNode.removeChild(temp); } else if (bRegex.test(borderLeftCSS)) { temp.style.width = "10px"; temp.style.border = borderLeftCSS + " " + el.currentStyle["borderLeftStyle"] + " #000000"; el.parentNode.appendChild(temp); width -= Math.round((temp.offsetWidth-10)/2); el.parentNode.removeChild(temp); } } if (el.offsetWidth > el.clientWidth && el.currentStyle["borderRightStyle"] !== "none") { if (!bRegex.test(borderRightCSS)) { temp.style.width = borderRightCSS; el.parentNode.appendChild(temp); width -= temp.offsetWidth; el.parentNode.removeChild(temp); } else if (bRegex.test(borderRightCSS)) { temp.style.width = "10px"; temp.style.border = borderRightCSS + " " + el.currentStyle["borderRightStyle"] + " #000000"; el.parentNode.appendChild(temp); width -= Math.round((temp.offsetWidth-10)/2); el.parentNode.removeChild(temp); } } } if (!includePadding) { var paddingLeftCSS = el.currentStyle["paddingLeft"]; var paddingRightCSS = el.currentStyle["paddingRight"]; var temp = document.createElement("DIV"); temp.style.width = paddingLeftCSS; el.parentNode.appendChild(temp); width -= temp.offsetWidth; temp.style.width = paddingRightCSS; width -= temp.offsetWidth; el.parentNode.removeChild(temp); } } return width; }; /////////////////////////////////////////////////////////////////////////////////////////////////// // USED FOR GETTING THE COMPUTED HEIGHT OF AN ELEMENT IN PIXELS /////////////////////////////////////////////////////////////////////////////////////////////////// var getHeight = function (/* Object */ el, /* boolean */ includePadding, /* boolean */ includeBorder) { var height; el = (typeof(el) === "string") ? document.getElementById(el) : el; if (window.getComputedStyle) { /* FF, Safari, Opera */ var style = document.defaultView.getComputedStyle(el, null); if (style.getPropertyValue("display") === "none") return 0; height = parseInt(style.getPropertyValue("height")); if (window.opera && !document.getElementsByClassName) { /* Opera 9.25 includes the padding and border when reporting the width/height - subtract that out */ height -= parseInt(style.getPropertyValue("padding-top")); height -= parseInt(style.getPropertyValue("padding-bottom")); height -= parseInt(style.getPropertyValue("border-top-width")); height -= parseInt(style.getPropertyValue("border-bottom-width")); } if (includePadding) { height += parseInt(style.getPropertyValue("padding-top")); height += parseInt(style.getPropertyValue("padding-bottom")); } if (includeBorder) { height += parseInt(style.getPropertyValue("border-top-width")); height += parseInt(style.getPropertyValue("border-bottom-width")); } } else { /* IE */ if (el.currentStyle["display"] === "none") return 0; var bRegex = /thin|medium|thick/; /* Regex for css border width keywords */ height = el.offsetHeight; /* Currently the height including padding + border */ if (!includeBorder) { var borderTopCSS = el.currentStyle["borderTopWidth"]; var borderBottomCSS = el.currentStyle["borderBottomWidth"]; var temp = document.createElement("DIV"); if (el.offsetHeight > el.clientHeight && el.currentStyle["borderTopStyle"] !== "none") { if (!bRegex.test(borderTopCSS)) { temp.style.width = borderTopCSS; el.parentNode.appendChild(temp); height -= temp.offsetWidth; el.parentNode.removeChild(temp); } else if (bRegex.test(borderTopCSS)) { temp.style.width = "10px"; temp.style.border = borderTopCSS + " " + el.currentStyle["borderTopStyle"] + " #000000"; el.parentNode.appendChild(temp); height -= Math.round((temp.offsetWidth-10)/2); el.parentNode.removeChild(temp); } } if (el.offsetHeight > el.clientHeight && el.currentStyle["borderBottomStyle"] !== "none") { if (!bRegex.test(borderBottomCSS)) { temp.style.width = borderBottomCSS; el.parentNode.appendChild(temp); height -= temp.offsetWidth; el.parentNode.removeChild(temp); } else if (bRegex.test(borderBottomCSS)) { temp.style.width = "10px"; temp.style.border = borderBottomCSS + " " + el.currentStyle["borderBottomStyle"] + " #000000"; el.parentNode.appendChild(temp); height -= Math.round((temp.offsetWidth-10)/2); el.parentNode.removeChild(temp); } } } if (!includePadding) { var paddingTopCSS = el.currentStyle["paddingTop"]; var paddingBottomCSS = el.currentStyle["paddingBottom"]; var temp = document.createElement("DIV"); temp.style.width = paddingTopCSS; el.parentNode.appendChild(temp); height -= temp.offsetWidth; temp.style.width = paddingBottomCSS; height -= temp.offsetWidth; el.parentNode.removeChild(temp); } } return height; };Read more...
Updated on 7/13/2008.
Here is a function that when called on a particular HTML element will auto-select all of its inner text. The function works on elements such as INPUT (text), TEXTAREA, DIV, SPAN, TD, and PRE. It is also cross browser compatible.
Below this code is a working demo.
autoSelect(el):
var autoSelect = function (el) {
if(el.tagName === "TEXTAREA" || (el.tagName === "INPUT" && el.type === "text")) {
el.select();
return;
}
if (window.getSelection) { // FF, Safari, Opera
var sel = window.getSelection();
var range = document.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
} else if (document.selection) { // IE
document.selection.empty();
var range = document.body.createTextRange();
range.moveToElementText(el);
range.select();
}
};
Example function call: autoSelect(document.getElementById("myDiv"));
Read more...Rather than rewrite what is already on many websites such as this one, I'm simply going to post some regular expressions that you may find useful for things such as form validation and file parsing.
You may notice that some of these are really long. This is because they are rather strict when matching valid values. To see why by example, select a tab in the demo below.
Read more...Something that's not really that super yet but may be someday. Super Tables are large HTML tables enhanced with cross-browser fixed vertical and horizontal scrolling headers with custom skins and features.
Using a small (10kb uncompressed) javascript file and an equally small (4kb) CSS skin file, a rendered HTML table is taken by the superTables.js script and is turned into a Super Table using only a single line of javascript code.
You might need them if you have one or more large tables on your website and/or application and wish to:
After scouring the Internet for any useful DHTML/DOM events I could find, I have finally compiled what hopefully is a complete list of current javascript events. More of a reference than anything else, I've listed each event with some links providing more information and specification.
Please take note that many of these events are only supported in either IE or Mozilla and not both -- however one good indicator of cross browser support is whether or not the event is a W3C standard. Keep in mind that one browser may implement a particular event differently from the next browser.
First, some good general resources:
Web developer? Smart thinkin'. Here are some tips you should know if you don't already:
Well that's it - a quick read - hopefully you've learned something new!
Also, if you think I'm missing a good tip, please let me and everyone else know and comment below (and hey - it''ll be some good free SEO if you have a web development website.)
Read more...Updated on 6/8/2008.
It's not pretty, but the following function is a safe, bug free (to the best of my knowledge) hack for changing the name attribute as well as adding a name attribute on existing DOM elements in IE 5.5+. This function will also work with Firefox, Opera and Safari.
Below this code is a working demo.
renameEl(el, newName):
var renameEl = function (el, newName) {
el = (typeof el === "string") ? document.getElementById(el) : el;
el.name = newName;
if (/*@cc_on!@*/0) { // Internet Explorer
el.removeAttribute("name");
attributeEl = document.createElement("INPUT");
attributeEl.setAttribute("Name", newName);
holder = document.createElement("DIV");
holder.appendChild(attributeEl);
document.body.appendChild(holder);
holder.innerHTML = holder.innerHTML;
attributeEl = holder.firstChild;
el.mergeAttributes(attributeEl, false);
holder.parentNode.removeChild(holder);
}
};
Explanation: The function first removes the name attribute from the target element. It then creates a new temporary element with the desired name using a case-sensitive setAttribute 'Name' hack. The temporary element must be redrawn on the page in order for the name attribute to appear and function correctly, which is where the innerHTML comes in. In order to avoid the quirks innerHTML carries, the temporary element is isolated inside a temporary holder div. Once the temporary element has been redrawn and has successfully set a name attribute, it can be merged into the target element cleanly (thus leaving the target element alone during most of the process). Oh and for non-IE browsers just set the name attribute.
-- One of the main reasons most of the work is isolated from the rest of the page is because manipulating innerHTML removes events, and we certainly don't want that.
Updated on 7/13/2008.
If you're an aspiring javascript developer, a truly powerful object worth familiarizing yourself with is the event object. Capable of capturing and controlling almost any form of communication between an internet surfer and your website, the event object can turn your static HTML page into one powerful app.
To demonstrate some of the cool features that you can create with the event object, here's a script/demo that gives HTML elements the ability to be dragged around the page with your mouse. Feel free to try it out yourself by clicking on one of the elements/panes below and moving it around:
Please keep in mind that these are the simpler draggable panes as the entire area within the pane can be clicked on for dragging. Things get a little more interesting if you have a pane where only certain areas are designated as the points where you can click and drag the pane around. To see these kinds of panes in action, please visit the test page linked to below. The source code of the demo page is also available for viewing further in this article. Read more...
Luckily, hiding and removing DOM elements with javascript is a lot less hard, and a lot less buggy, than adding them. Let's start with hiding elements:
There are two basic ways to hide an element while still keeping it in the DOM (See Document Object Model). The first way is by changing the element's CSS display style to 'none' and the second is by changing the element's CSS visibility style to 'hidden'. Whenever either style property is set, the element will not be shown visibly on the page, however unlike removing an element completely, the semantic structure will remain within the page's DOM -- allowing you to still modify and work with it.
To bring an element back from invisibility, set display to 'block' or visibility to 'visible'. Below are some examples of what you would put inside a DOM element if you want that element hidden whenever a person clicks on it:
onclick="this.style.display='none';"The difference between display='none' and visibility='hidden' has to do with the flow of the page. When you set an element to display='none', the space that that element takes up on the page is removed and replaced by other elements on the page -- changing the page flow. When you set an element to visibility='none', that element's dimensions are kept in the page space and thus page flow. See the demo below for a visual example.
As there is no removeElement() function in javascript, one has to traverse up the DOM tree to the parent element, referred to in javascript as the parentNode -- and then call the removeChild(target) function at the targeted child element. Below is an example of what you would put inside an element if you want that element removed whenever a person clicks on it:
onclick="this.parentNode.removeChild(this);" Read more...For those of you looking to generate HTML tables dynamically, you may be interested to know that there are numerous ways to do so - each with their own pros and cons. The following are two heavily used approaches:
The left button uses standards compliant DOM methods such as createElement, createTextNode and appendChild to generate the HTML table. The use of these DOM methods guarantees that the function will work in just about every current browser as well as any future browsers. The downside however is that these methods are slow when compared to the alternative approach - that of generating long HTML strings.
Though not standards compliant, this faster version also works in just about every current browser. As such, until the DOM methods have caught up with the alternatives, I would recommend avoiding them unless the tables you plan on generating are consistently small.
This script was successfully tested in Windows versions of Internet Explorer 5.01 - 7, Firefox 1.5 - 3, Opera 9 and Safari 3.
Read more...Updated on 7/13/2008.
For those of you who have ever been given the task of making a javascript function that generates DOM elements on the fly, you may very well have run into technical issues with none other than (drum roll please) ... IE.
Below is a demo that will create a form using the createElement() function and submit an ajax request using this new form. Please note: this script was successfully tested in Windows versions of Internet Explorer 5.5 - 7, Firefox 1.5 - 3, Opera 9 and Safari 3.
Below this demo is the source code.
|
Form goes in here.
|
Ajax response goes in here.
|
In case you've never heard of the phrase 'content is king' when it comes to search engine optimization, here's a quick example as to why.
If you search for the keyword phrase "search engine optimization" on Google, you'll probably find that the top 15 sites rank similiar to this:
| Rank | Address | Approx. Word Count | PageRank | Approx. Creation Date |
|---|---|---|---|---|
| 1 | Google News Search | - | - | - |
| 2, 3 | en.wikipedia.org/wiki/Search_eng... | 3,780 | 7 | Jul-01 |
| 4 | www.seochat.com | 1,976 | 4 | Feb-03 |
| 5 | www.submitexpress.com | 684 | 6 | Jan-99 |
| 6, 7 | www.bruceclay.com/web_rank.htm | 8,467 | 6 | Jan-98 |
| 8 | www.inteliture.com | 390 | 5 | Mar-03 |
| 9, 10 | www.seoinc.com | 777 | 5 | Aug-02 |
| 11 | www.submitawebsite.com | 681 | 7 | Apr-99 |
| 12 | www.customermagnetism.com | 1,489 | 6 | Feb-01 |
| 13 | www.addme.com | 605 | 5 | Apr-97 |
| 14, 15 | searchenginewatch.com/showPage.h... | 459 | 6 | Dec-97 |
| Average: | 1,931 | 6 | Apr-00 | |
Strong results that content is indeed king when it comes to search engine optimization. 1,931 words are on the average top ranking website (1,204 if you take out bruceclay.com -- which is still quite a lot).
Also not too suprising is the fact that the youngest website ranked is from March of 2003. Google really likes the dinosaur websites, with the average age being 7 years, 8 months old.
One site that was somewhat out of place and hence a bit more interesting was www.inteliture.com. With a significantly less word count and a relatively new startup date, one has to wonder how it is ranking so high.
Titles may be obvious when it comes to making them unique for each page, but don't forget about the meta description and keyword tags. They can be unique for each page too you know! If you've got a dynamic website with generated content, it's even easer.
For example, if your site has forums, try putting the forum topic title as the title and meta description for that page. That way, users who happen to search for the right phrase online won't see a bland title such as "XX Forums", but will instead see a much more descriptive title and then some, as it will give them a preview of what they're about to see, which is the whole point anyways.
For all you RoR developers out there, here's what I do with every page on my site: <meta name="description" content="<% if @description == nil %>A blog on web development topics. Covering technologies such as Ruby on Rails, Javascript, AJAX, CSS and DHTML.<% else %><%= @description %><% end %>" /> Where the @description variable I specify in the controller. I do the same thing for the meta keywords too except with a @keywords variable.
Try this out: Google for 'search engine optimization' - you'll soon find that the majority of the top 10 ranked pages have an essay's worth or more of text on their front page. This stands to argue that the more words you have on your page, the better - so long as it's all relevant information. Just think about the sheer multitude of keywords and buzzwords that are in 2000 words over a meager 200 words. You'll get more organic search hits simply because you'll have more keywords and phrases than the next site. It's a no brainer.
Make it basic, just with links. This improves your ranking, plus it helps the search bots get around on your site.
More popular pages get crawled more often by search bots than their less popular peers. If you've got a new website, put a link to it on a popular page so the search bots will find it faster and thus index it quicker. If you don't have a web page that can help you out, post a link in the forums or comment sections of popular websites with similar content as your new site. Also, make sure to submit your sitemap.xml file as soon as your site is online to Google's webmaster tools.
Read more...If you're looking to add powerful, dynamic, customizable charts and graphs to your Ruby on Rails app, consider using the ZiYa plugin for XML/SWF Charts. It's quite easy to install and best of all it's free. All it requires is a simple script/plugin install from Rubyforge followed by a couple of require/include lines in your controller and that's it.
Some of the nicest features of the ZiYa plugin are support for dynamic data (on the fly rendering) and fully customizable look and feel skins that you can create in xml. For the app I am currently using these graphs on, I created session variables that the chart action (ie rails action) would read in and from that create a graph with a customizable skin I had made to fit the look and feel of my site. All in all, it took less than a few hours for me to figure everything out and have a page load with exactly what I wanted. Thanks in part to ZiYa's website which showcases a training page that has a dynamic xml stylesheet that you can edit and see exactly how your edits change the graph's look. If I wanted to add a graph nowadays, it would take almost no time at all. And this isn't because I'm some sort of genius, ZiYa just makes it that simple!
Read more...In its infinite wisdom, Microsoft decided when developing Internet Explorer that the idea of following standards was out of the question. It never occurred to them that one - not everyone uses their browser, and two - that by making their own standards, they would be giving webmasters years worth of frustration. And in such tradition, I present to you, fellow frustrated webmasters, a snippet of code that will allow you to make IE-read-only cascading style sheets.
Read more...Whether you're new to the Rails development community or are a seasoned veteran, here's a list of seven great tools any developer should have in their arsenal.
Simply put, a must have. This tool gives you the ability to view the generated source code on a rendered page, it allows you to disable CSS styling, view the document size, clear session and cookie data (great when working with that kind of stuff), and a ton more. You can download it at Firefox's add-ons page here.
This is a great tool for search engine optimizers which these days every successful web designer must become. This little plugin lets you view Google's Pagerank rating on any website you desire. It also relays for you a bunch of other nifty details such as the age of a site, an estimated inbound link count, a site's Alexa / Compete.com rank, and more. Grab it here at Aaron Wall's SEO site.
Another great tool, this program lets you install Internet Explorer 3.0, 4.01, 5.01, 5.5, and 6.0 all on the same pc! Though these days 5.5 and down are pretty much obsolete, it nevertheless allows you to have both IE6 and IE7 installed and running at once for all your testing needs. Multiple IE can be downloaded on TredoSoft's website for free.
Read more...We all know about the onfocus event but what about the onfocusin and onfocusout events? Sure there's the onunload event, but what of the onbeforeunload event? For those you who have never heard of these before, now you can. Below is a full list of javascript events courtesy of the MSDN library.
It's also worth noting that the majority of these events only work in Internet Explorer. If you see a W3C Standard note next to an event, however, it means that just about all major browsers support this event.