News: Phentermine Online With Insurance No Prescription Cheapest Buy Phentermine Buy Phentermine Sat Delivery Cod Phentermine Without A Prescription Saturday Delivery Cheap Phentermine 37 5mg Phentermine Rxdrug Phentermine Order Cod Phentermine 37.5 Mg Tab Phentermine Prices Pharmacy Online Real Phentermine 37.5 Without Prescription Phentermine Overnight Phentermine Didrex Vs Phentermine Buy Phentermine Online No Scrip Cheap Phentermine Extra Cheap Phentermine Danger Phentermine Online Pharmacy Best Price Phentermine Vs Adipex Phentermine Ingestion By Pets

Reciprocal linking is a process to establish mutual link between two websites to ensure mutual benefit i.e. traffic, search engine enclosure. It is an important and crucial part of the SEO process because Search engines uses link popularity algorithm (depend upon the number of links that point to a particular page of a website and the title of the link) to rank websites for relevancy.

While doing reciprocal linking you have to be very careful about few particular things. Here we are listing few tips for running a successful reciprocal link building service:

1. Find relevant websites: You will be getting more value from search engines for linking to and from other websites which are relevant to your website. Reciprocal linking from other irrelevant website will not greatly help your websites standing with search engines.

2. Make sure that each inbound links are good: Be sure to have quality inbound links only. It had been recognized that 100 high quality relevant links is better them 1000 irrelevant low quality links. So try to get links from quality relevant websites only.

3. Do not Link to questionable sites which CAN hurt your ranking: Be aware of such sites that use questionable search engine optimization processes because such sites can harm your ranking. Before accepting any link check whether the page where your link will be posted is cached or not. Also we prefer to not to have any link which is not cached by Google within last 90 days.

4. Few facts to be followed: This is not possible to have all links from same quality sites. But still you have to set up some criteria for accepting links and have to follow them strictly. Don’t go for links which are not indexed by SE, don’t accept any links with no-follow tag or text links in JavaScript or redirected. These link will not pass any value to your site so better avoid them.

5. Organize the procedure: Be sure to manage your reciprocal link building campaign well organized. Try to keep all records of the URLs where your link is posted along with their link partnership email. Try to track each link periodically and if any links get dropped then try to contact the person and ask him to reestablish the link else delete the corresponding link from your website.

These are few facts that will ensure your rank improvement obvious in search engines. Also while doing reciprocal campaign we recommend you to run a simultaneous one way link campaign as well.

Introduction

Most auto-complete textboxes may have a reverse effect on end-users. Instead of helping them get things done faster, they get irritated by design flaws made by the programmer. (Admittedly, I’ve made such design flaws too.)

I got to learn this lesson when designing my first auto-complete edit control, found here[^]. Although it seemingly looks intuitive, I forgot to consider the fact that what if the end-user wanted to type just ‘ap’ but the ‘ple’ appears out of nowhere? This means that the end-user would then have to hunt for, and press the delete key.

After seeing how GMail made its auto-complete, I took the idea and implemented my own version of the auto-complete control.
How does it work?

The important event that will fire whenever the user press any key is onkeydown. The onkeydown event handles all the normal character input and is in charge of creating the auto-complete list. It also handles keys like ‘up’, ‘down’ and ‘enter’.

Using the JavaScript regexp() object, the script will run through the array containing the keywords and match them one by one. After which, a DIV will be created dynamically using document.createElement(). Finally, when the user presses the ‘Enter’ key, the DIV will be detached and the input box updated.

The user can also select the options using the mouse. This is done through three events: onmouseover, onmouseout, and onclick.
How do you implement it into your own textbox?

Firstly, include the .js file into your script:

Next, create an array (in JavaScript) containing the keywords:

customarray = new Array(’apple’,'pear’,'mango’,'pineapple’,
‘orange’,'banana’,'durian’, ‘jackfruit’,'etc’);

Apply the widget to your textbox using JavaScript:

actb(document.getElementById(’textbox_id’),customarray);

And you’re done!
Tweakability

This auto-complete edit control has some customizable features:

/* —- Variables —- */
// Autocomplete Timeout in ms (-1: autocomplete never time out)
this.actb_timeOut = -1;
// Number of elements autocomplete can show (-1: no limit)
this.actb_lim = 4;
// should the auto complete be limited to the beginning of keyword?
this.actb_firstText = false;
// Enable Mouse Support
this.actb_mouse = true;
// Delimiter for multiple autocomplete.
// Set it to empty array for single autocomplete
this.actb_delimiter = new Array(’ ‘,’,');
// Show widget only after this number of characters is typed in.
this.actb_startcheck = 1;
/* —- Variables —- */

/* — Styles — */
this.actb_bgColor = ‘#888888′;
this.actb_textColor = ‘#FFFFFF’;
this.actb_hColor = ‘#000000′;
this.actb_fFamily = ‘Verdana’;
this.actb_fSize = ‘11px’;
this.actb_hStyle = ‘text-decoration:underline;font-weight=”bold”‘;
/* — Styles — */

this.actb_keywords = new Array();

The styles are pretty self-explanatory; tweak the values for best results for your own website. Firstly, the variable actb_timeOut controls how long the auto-complete list’s timeout should be (i.e., after x ms, the list will disappear). By default, it is set to -1, which represents no timeout.

Next, the variable actb_lim limits the number of elements the list will show, to prevent over-spamming. If you do not want to set any limit, set it to -1.

Thirdly, the actb_firstText variable determines whether the match with the keywords-array should only start from the first character or if the match can be any arbitrary match within the keyword. For example, if firstText is set to true, then a given string “ello” will match with “hello”.

Also, the actb_mouse variable determines whether the control should respond to mouse events. Mouse support works when user clicks on the auto-complete list that appears.

The actb_delimiter variable allows for the much requested multiple auto-complete feature. Set a custom delimiter, or even multiple delimiters like semi-colon (;) or comma (,), and the engine will complete words separated by the given delimiter.

Lastly, actb_startcheck controls the number of characters that must be typed in before the textbox will display the control. Thanks to flyasfly for this suggestion.
Implementations

As of version 1.3, all of the above mentioned are public variables. This can be useful in emulating controls like Google Suggest. When you apply the control to your textbox using the actb function, it returns an object.

Changing the autocomplete list

obj = actb(document.getElementById(’textbox_id’),customarray);
// … after some time …
obj.actb_keyword = new Array(’this’,'is’,'a’,'new’,’set’,'of’,'keywords’);

Multiple auto-complete textboxes

obj = new actb(document.getElementById(’textbox_id’),customarray);
obj2 = new actb(document.getElementById(’textbox2_id’),customarray2);

Multiple textboxes (different options)

obj = new actb(document.getElementById(’textbox_id’),customarray);
obj.actb_mouse = false; // no mouse support
obj2 = new actb(document.getElementById(’textbox2_id’),customarray2);
obj2.actb_startcheck = 2; // start actb only after 2nd character

Todo

* Add second array (customarrayDesc) for display description in the list (ex => [an apple: it’s an apple] instead of [an apple]. Suggestion by angelo77).
* Many other features suggested by CPians, some of which might be beyond me at the moment but I’ll still try my best!

Tested browsers

* Internet Explorer 6.0.28
* Mozilla Firefox version 1.0.3

Finally…

Thank you to all of you who have supported, modified, and offered your suggestions to the control! I’m extremely apologetic for the inactiveness of this project because of schoolwork etc. However, I still try my best to work on it whenever anyone has a new feature request!

Introduction

If you have to implement a Web application that intensively uses JavaScript for some client side effects or some AJAX like features, and if you have to support more than Microsoft Internet Explorer 6.0, then you might find here a not widely known trick to make your programming easier by implementing a small compatibility layer.

Both browsers, Microsoft Internet Explorer and Mozilla/FireFox, do have a lot of functionalities as defined by the standards HTML, CSS and JavaScript, and some of them are really useful for implementing some functionality on the client. Because there are some extensibility features available on these different platforms, it is possible to extend one browser with methods and properties that are not available in the other one out of the box.
JavaScript Prototypes

The JavaScript language interpreters included in the browser platforms offer almost identical functionalities. There is no real need to use this feature to bring some missing functionalities to one of the platforms, but it is an interesting feature anyway and it gives you the chance of extending both platforms.

The object types of JavaScript, better called intrinsic objects of JavaScript (String, Number, Array, …) that are part of the JavaScript language have an extensibility mechanism by using the available prototype property.

By attaching new functions to the prototype, you make this method available to all objects that derive from that type.

The following sample adds a trim() method to all string objects that eliminates all leading and trailing blanks and returns a new string with the remaining characters (if any):

String.prototype.trim =      function() {
return (this.replace(/^[\s\xA0]+/, “”).replace(/[\s\xA0]+$/, “”));
}

To use this function, you will use the following syntax:

var s = “    Hello World      “;
var txt = s.trim(); // returns only “Hello World”

You can use this extensibility feature in Internet Explorer and Mozilla/FireFox to add new methods and (readonly) properties to the intrinsic objects, but there is no cross browser way to capture the access to properties of those objects.

You might think that it is also possible to add a global method trim(s) that uses a parameter and the return value to do the same thing, but you might get in conflict with other variables or methods from different libraries using the same name. You can also add a trim method to the Array object that handles array items, without getting a conflict.

Some general information about the prototype property can be found at: MSDN.
JavaScript Prototypes in Mozilla/FireFox

The Mozilla/FireFox platform also offers a proprietary but very useful extension model that allows to also implement properties on the JavaScript intrinsic objects. Here I added a weight property that returns the sum of the char codes of a string:

String.prototype.__defineGetter__(”weight”,
function () {
var w = 0;
for (var n = 0; n < this.length; n++)
w += this.charCodeAt(n);
return w;
}
);

You can use this property on any string:

var s = "ABC";
var n = s.weight; // will return 198

Remember:

The __defineGetter__ and __defineSetter__ are unique features to Mozilla/FireFox and you can find some (still few) samples on the internet by searching through Google for these keywords.
Prototypes with HTML objects

JavaScript objects and HTML objects are completely different kinds of objects when using the Microsoft Internet Explorer but with Mozilla/FireFox, these objects share a common implementation. So, the feature we look at now is only available in Mozilla/FireFox.

The Internet Explorer, for example, supports a innerText property on many HTML objects like span, div, p, … that can be used to safely access and set the text of an HTML object.

Mozilla/Firefox, in contrary, uses the textContent property that is part of the newer DOM Level 3 standard to do the same thing.

Now you can use the extensibility features of Mozilla/FireFox to emulate an innerText property on all HTML objects and you can eliminate all conditional scripting across your JavaScript programs:

var isIE = (window.navigator.userAgent.indexOf("MSIE") > 0);

if (! isIE) {
HTMLElement.prototype.__defineGetter__(”innerText”,
function () { return(this.textContent); });
HTMLElement.prototype.__defineSetter__(”innerText”,
function (txt) { this.textContent = txt; });
}

You just have to include this script in one of your common JavaScript include files.

Here are some more usable wrappers to Microsoft specific features:

innerText Gets and Sets the inner text of HTML nodes.
obj.children[] Returns the obj.childNodes[] collection. This is not a perfect emulation but probably helps making your code work.
XMLDocument Returns a XMLDocument object from the inner text that should be XML.
attachEvent Attach event handlers to HTML objects.
detachEvent Detach event handlers from HTML objects.
window.event Return the actual executing event object.
event.srcElement Return the target node of the executing event.
event.cancelBubble Stop the propagation of the current event.
event.returnValue Set the return value of the current event.
xmlobj.selectSingleNode Return a single node from an XML element by using an XPath expression.
xmlobj.text Return the inner text of an XML element.

Conclusion

If you ever thought that writing cross browser compatible JavaScript is hard to do, you now have a chance to build your layer of compatibility and make your script more readable and easier to maintain, and get rid of the conditional code fragments spread all over your web application.

This approach helps a lot but is not the definitive solution. A lot of people (including myself) hope that the current and upcoming standards will get implemented in all browsers. It’s better to use these features, when available on multiple platforms. There are also good samples of proprietary Microsoft Internet Explorer features that are so useful that Mozilla/Firefox did implement them. The most popular sample to this is the XMLHTTP object that allows AJAX like cross browser implementations.

Some good reading URLs for browser compatibility hints:

* QuirksMode
* Migrate apps from Internet Explorer to Mozilla
* Curious: this document contains a lot of important hints on how to implement cross browser compatible pages but is itself not cross browser compatible. IE shows a blank page. Read it using Firefox!
* A book on this topic.

Introduction

This article describes:

* How to display a horizontal scroll bar in a select box (HTML) or listbox (ASP.NET).
* On pressing up or down arrow keys, the functionality should also work as expected.

The Problem

There are some limitations in Internet Explorer (IE) while rendering some HTML controls. One of such controls is the combobox (HTML) or the ListBox (ASP.NET).

Again, there are a couple of limitations, while rendering a combobox or a listbox in IE:

* In a combo box, if width is specified and the length of the content is greater than the specified width, then a horizontal scrollbar won’t appear.
* Specifying the title attribute won’t display the tool tip.

I’ve gone through many articles from the net with respect to putting a horizontal scroll bar in a combobox or a listbox, but none looked good.

Finally, I got some articles which explained how to put a custom horizontal scrollbar for a combobox or a listbox. But again, there are some limitations in a custom scrollbar as up and down arrow keys won’t work as expected. We can achieve horizontal scroll bar in a combobox using a DIV tag by specifying the height and the width. Now, consider a scenario where the number of items in a combobox is greater than the specified height of the DIV element. Now, if we press down/up arrow keys, it won’t work as expected, i.e.,we can’t see the selected item.
The Solution

There are a couple of things we need to work out to overcome the horizontal scrollbar issue in a combobox.

* As we know, IE doesn’t support horizontal scrollbars in a combobox, so we have to go with the custom horizontal scroll bar. From the look and feel and user point of view, horizontal scrollbar will appear as a part of the combobox.
* Now we have added a DIV tag on top of the combobox. To overcome up/down arrow key issue, we need to apply some tricks, so that it should behave as expected.

Introduction

Note: this code requires internet explorer 5.5 or better.

Following up on a tree list control I made using JScript and ASP (article here), I have created a new one which requires no ASP at all. It is not very fast in adding a whole lot of nodes at once, but expanding and contracting a node is instantaneous. Hovering over text in a row will cause the node for that row to highlight, making it easier to determine which node you are looking at.
Usage:

Create an instance of the tree:

var myTree = new TreeListControl(”myUniqueID”);

Add the columns:

myTree.addColumn([column name], [width], [alignment]);

Create the tree, specifying the parent element:

myTree.createIn(document.body);

Add Nodes:

myTree.addNode([parent ID], [relative path to icon], [expand branch?],
[column text 1], …, [column text n]);

Delete a Node:

myTree.deleteNode([node ID]);

API
Methods:

TreeListControl ( strID )

Each instance of the tree must have its own unique identifier. This will become the .id property of the element, and is used in id assignment for all the nodes.

TreeListControl . addColumn ( strTitle[, [intWidth[, strAlign]]] )

Adds a column to the tree. This must be done before the createIn() method of TreeListControl is called.

TreeListControl . createIn ( objContainerElement )

This builds the main tree object and appends it to the object passed in.

TreeListControl . addNode ( intParentID, strIconSrc, boolExpandChildren, strColumnText1, …, strColumnTextN )

Used to add an entry in the tree. The return value is the integer ID value for that node, which can be used to reference that node later if desired. First supply the parent ID for the node you are adding (0 or null if there is no parent), then a path to the icon to be used, then true/false depending on whether you want this branch to be collapsed or expanded, then the text for each column. If you use the string [[id]] in the text for the columns, it will be replaced with the actual id number that node is assigned. Also, if a node is added, and the specified parent does not exist, it will be queued and added when the parent id is added to the tree.

TreeListControl . setText ( intNodeID, intColumnIndex, strText )

Changes a node’s text in the specified column. If you use the string [[id]] in the text for the columns, it will be replaced with the actual id number that node is assigned.

TreeListControl . deleteNode ( intNodeID )

Deletes the specified node and all its children.

TreeListControl . deleteAllChildren ( intNodeID )

Deletes all the children of the specified node, but not the node itself.

TreeListControl . redrawAllIcons ( )

Forces the tree to redraw all the line connection images that make the tree look correct. This must be called if nodes have been added while the property autoRedrawIcons was set to false.
Properties:

TreeListControl . autoRedrawIcons
When a new node is added, this determines whether or not to recalculate which line connector images to draw so that the tree looks correct. If you are adding a whole bunch of nodes at once, set this to false, add the nodes, then set it to true. This should speed up the operation.
Example usage

function addone(parentid) {
var opt = “[ Delete”;
opt += ” | Add Child ]”
var newid = xx.addNode(parentid,
xx.pathtoicons+”icon_folder.gif”, //the icon to use
true, //expand this node’s children?
s[Math.floor(Math.random()*s.length)], //value for column 1
s[Math.floor(Math.random()*s.length)], //value for column 2
s[Math.floor(Math.random()*s.length)], //value for column 3
s[Math.floor(Math.random()*s.length)], //value for column 4
opt); //value for column 4
}

xx = new TreeListControl(”tlc1″); //create an instance of the control
// and specify its unique identifier string
xx.autoRedrawIcons = false;       //don’t calculate the icons until we’ve added
// all the nodes (faster this way)
xx.pathtoicons = “treelistcontrol/treeicons/”; //specify the path to the tree
// icons
xx.addColumn(”Things”,250) //add some columns (label, width, alignment)
xx.addColumn(”More Things”,150)
xx.addColumn(”Interesting Things”,150)
xx.addColumn(”Other Things”,150)
xx.addColumn(”Options”,null,”right”) //the last column should not have a width

xx.createIn(document.body); // create the tree, passing in the container object
//to generate the tree inside

s = new Array(”yay”,”cool”,”wonderful”,”great”,”awesome”,”fluff”,
“green”,”beans”,”mean”,”machine”, “high”,”balloons”,
“flying”,”for”,”fun”,”great”,”happy”,
“apples and cherries”,”bump”); //make some random text values
for(var z=0; z<50; z++){
addone(Math.floor(Math.random()*z));
}

xx.autoRedrawIcons = true; //remember to set this back to true so that future
//nodes added will be drawn correctly
xx.redrawAllIcons(); //since no icons were drawn, redraw all of them

Introduction
This JavaScript code can be used to convert tables in ordinary HTML into scrollable ones. No additional coding is necessary. All you need to do is put header rows in TBODY and give your table an ID field, include the ScrollableTable.js file and call makeScrollableTable in your document’s onLoad method.




ColA ColBC ColDE ColF
ColB ColC ColD ColE
A B C D E F
A B C D E F
A B C D E F
A B C D E F
A B C D E F
A B C D E F
A BBBBBBBBBBBBBBBBBBBBBBBBB C D E F


Introduction

If you spend any time surfing the web you will find
list would allow us to type “No” and automatically get “North Carolina”. Mississippi and Arkansas are other good examples. A few lines of client side JavaScript can solve this nuisance. I’ve included examples of both types of
above records each keystroke in a hidden input tag and uses ALL keystrokes to search for a matching Option in the list. A few questions may come to mind, such as “How to you clear previously captured keystrokes?”. The onBlur() and onFocus() events clear previous keystrokes but what about starting a new search without moving focus from the

First, add selectKeyDown(), selectKeyPress(), and clr() javascript functions to your page as found in the source code download, or simply View->Source for this page.

Next, add onBlur(), onFocus(), onKeyPress(), and onKeyDown() event handlers to your
tags will never be the same.
The Code

// Java Script to Handle AutoSearch
function selectKeyDown()
{
// Delete Key resets previous search keys
if(window.event.keyCode == 46)
clr();
}
function selectKeyPress()
{
// Notes:
//    1) previous keys are cleared onBlur/onFocus and with Delete key
//    2) if the search doesn’t find a match, this returns to normal 1 key
//        search setting returnValue = false below for ALL cases will
//        prevent default behavior

//TODO:
//    1) add Netscape handling

var sndr = window.event.srcElement;
var pre = this.document.all[”keys”].value;
var key = window.event.keyCode;
var char = String.fromCharCode(key);

// “i” -> ignoreCase
var re = new RegExp(”^” + pre + char, “i”);

for(var i=0; i {
if(re.test(sndr.options[i].text))
{
sndr.options[i].selected=true;
document.all[”keys”].value += char;
window.event.returnValue = false;
break;
}
}
}
function clr()
{
document.all[”keys”].value = “”;
}

Introduction

This is my third attempt at making a TreeListControl for Internet Explorer-based web applications. The first was very slow and required ASP to generate a tree. The second has lots of features, and even resizable columns, but, while it did not suffer from the freeze-up delays that occurred in the first one, was generally sluggish in operation if there were more than a few nodes on the screen. This latest version has tighter code and is generally more versatile all round. It doesn’t have resizable columns, but it shouldn’t be too hard to put them in. If I do that, I’ll upload the updated version here. The only other major limitation of this control is that it is fixed-width. That is, you have to specify the exact width of each column, and this determines the control width.

Features that version 3.0 has are:

* Enable/disable column headings
* Enable/disable root node
* The ability to choose which column the tree appears in
* Dynamic loading of branches via XML files
* Completely dynamic updating of the tree structure after it has been generated, including:
o remove nodes
o add new nodes
o remove nodes and re-add them somewhere else
o insert before or after a specified node
o expand/collapse branches
* optional row onclick action
* row highlights while being pointed at
* prevent specified columns from firing the row onclick event (e.g. for a column of checkboxes)

To use the control, simply include treelistcontrol.js and treelistcontrol.css in your html file, then, inside the element (body tag, div tag, or where ever) you want to render the tree inside, place a script tag and build the tree according to the API. A demo of how to do this is inside the included zip file.
Usage

See the API below for explanations of the tree’s objects, and the file demo.htm for an example of how to use the tree.

1. Create a tree control
2. Create and add the columns to the tree
3. Add all the initial nodes to the tree
4. document.write the tree object to the page

Tree List Control v3.0 API
TreeListControl

TreeListControl(strRootNodeLabel, strRootNodeIconSrc, boolHideColumnHeadings, boolHideRootNode)

* strRootNodeLabel: the label to use for the root node
* strRootNodeIconSrc: the path to the node’s icon
* boolHideColumnHeadings: don’t show the column headings
* boolHideRootNode: don’t show the root node

Properties

* showColumnHeadings: hide/show the column headings. The visibility of the column headings will automatically change depending on the state of this property.
* showRootNode: hide/show the root node. The visibility of the root node will automatically change depending on the state of this property.
* all: this is a collection (array) contain references to all the nodes that were assigned a non-null refKey when added to the tree. usage: mytree.all[’mynoderefKey’]
* allNodes: this is a collection containing references to every node in the tree, indexed by the node’s automatically assigned ID property.
* rootNode: a reference to the tree’s root node. This is of type TreeListControlNode.
* iconPath: the path to the location where the tree’s images are stored. The default is ‘tlcimages/’.

Methods

* addColumn( oColumnObject ): adds a column to the tree. Do not use this once the tree has been rendered to the page. Pass in a reference to a TreeListControlColumn object that defines the column’s parameters.
* add( oNodeObject ): appends a node to the children of the root node. Pass in a reference to a previously created node.

TreeListControlColumn

TreeListControlColumn (intWidth, strTitle, boolPreventRowClickEvents)

* intWidth: the width, in pixels, of the column.
* strTitle: the heading/title of the column. Use a zero-length string if no title is desired.
* boolPreventRowClickEvents: when a row is clicked, it fires the onclick event for that row. Setting this parameter to true will prevent clicks in this row from firing that event.

TreeListControlNode

TreeListControlNode (boolShowChildren, strIconSrc, strXMLSrc, strReferenceKey)

* boolShowChildren: this specifies the initial expand/collapse state for the node.
* strIconSrc: the path to the icon image to use.
* strXMLSrc: if the children of this node are to be loaded at run-time when the node is expanded, this parameter should contain the URL of the XML file. Set to null or ‘’ if not used.
* strReferenceKey: if you want to use your own identifiers for each node, instead of the automatically-assigned ID that each node has, specify the identifier here. It can be an integer or a string, and, once the node has been added to the tree, you can access the node via the all property of the TreeListControl object.

Properties

* onclick: the javascript to execute when the onclick event fires for that node. Only set this before the node has been added to the tree.

Methods

* expand: shows the node’s children.
* collapse: hides the node’s children.
* setText( strColumn1, strColumn2, …, strColumnN ): sets the node’s text in each column.
* setColumnText( intColumn, strText ): sets the text for the node in the specified column.
* add( oNodeObject ): appends a node object to this node’s children. DO NOT use this method if this node has not yet been added to the tree.
* insertBefore( oNodeObject ): inserts the supplied node immediately before this node.
* insertAfter( oNodeObject ): inserts the supplied node directly after this node.
* remove(): removes this node from the tree completely and returns a reference to the node so that it can be reinserted elsewhere if desired.

Introduction

I needed a JavaScript date format function such as the Visual Basic Format function, in which you can pass a format string; my first approach was to issue a series of consecutive and “destructive” replace calls, but upon discovering that the 5.5 (or higher) version of JScript supported the use of a function as the replaceText argument of the replace method, I got creative.

Here’s an example call of what I wanted:

SomeDiv.innerText = (new Date()).format(’dddd, mmmm dd, yyyy.’);

This would display:

Saturday, July 16, 2005

So in my first approach, I globally and case-insensitively replaced dddd with the corresponding string, which “destroyed” every occurrence, so that later in the code I could replace dd with the date number.

This worked just fine, but I knew that by inspecting the format specifier for a match, I could skip the search of every format specifier; say I only want the month and the date; well, by switching upon the format specifier (or rather “datepart” specifier), the year replacement will never be issued. Get it?

The fun part relies in the use of a function in the replaceText argument of the replace method; this way the $1 property as a function argument always represents the last match.

Other considerations include the format or “datepart” specifiers: none other than yyyy will be parsed as the year; months and days have the usual three flavors of fullname (mmmm), three-letter (mmm) or numeric (mm); hours (hh) can be rectified to the 12-hour format with the a/p specifier, and minutes (nn) and seconds (ss) may also be specified.
Implementation

WOFA, (Without Further Adou):

// a global month names array
var gsMonthNames = new Array(
‘January’,
‘February’,
‘March’,
‘April’,
‘May’,
‘June’,
‘July’,
‘August’,
‘September’,
‘October’,
‘November’,
‘December’
);

// a global day names array
var gsDayNames = new Array(
‘Sunday’,
‘Monday’,
‘Tuesday’,
‘Wednesday’,
‘Thursday’,
‘Friday’,
‘Saturday’
);

// the date format prototype
Date.prototype.format = function(f)
{
if (!this.valueOf())
return ‘ ’;

var d = this;

return f.replace(/(yyyy|mmmm|mmm|mm|dddd|ddd|dd|hh|nn|ss|a\/p)/gi,
function($1)
{
switch ($1.toLowerCase())
{
case ‘yyyy’: return d.getFullYear();
case ‘mmmm’: return gsMonthNames[d.getMonth()];
case ‘mmm’:  return gsMonthNames[d.getMonth()].substr(0, 3);
case ‘mm’:   return (d.getMonth() + 1).zf(2);
case ‘dddd’: return gsDayNames[d.getDay()];
case ‘ddd’:  return gsDayNames[d.getDay()].substr(0, 3);
case ‘dd’:   return d.getDate().zf(2);
case ‘hh’:   return ((h = d.getHours() % 12) ? h : 12).zf(2);
case ‘nn’:   return d.getMinutes().zf(2);
case ’ss’:   return d.getSeconds().zf(2);
case ‘a/p’:  return d.getHours() < 12 ? ‘a’ : ‘p’;
}
}
);
}

Notes

* A date with a value of 0 returns a non-breaking space.
* Notice how the d variable is available to the replacement function (but the this object is not).
* The zf number prototype (not shown) prefixes a number with zeroes the specified number of times, up to the number’s character length, i.e. 2 turns into 02, but 16 remains 16. Behave and I may supply the prototype.
* The regular expression looks for any of the bracketed pattern characters in a two+ sequence, or for the very specific a/p match.
* Defining names globally helps and serves other purposes, i.e. listing days in a calendar.

Enjoy.

Introduction

Once upon a time, not so long ago, pushing any significant processing to the client browser was considered a bad practice. Now with the rise in popularity of AJAX style development, it has suddenly become a hot new technology. Unfortunately, the most commonly used browser on the market is painfully slow at one of the most common tasks in programming — string concatenation.

The good news is that although IE is slow when it comes to string concatenation, it is quite fast with array operations. With this in mind, I decided to write a simple StringBuilder class that pushes individual strings into an array and then uses the join method to produce the concatenated output string. In tests I have run with 5,000 strings, it is 117 times faster than the equivalent string concatenation using the s1 += s2 syntax. With 10,000 strings, it is an amazing 261 times faster!
Using the code

The StringBuilder class only provides four methods: a constructor, an append method, a clear method, and a toString method. You can add more properties and methods if you need them, but I chose to keep it as simple as possible for this article.

Here is the entire script that defines the StringBuilder class:

// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
function StringBuilder(value)
{
this.strings = new Array(”");
this.append(value);
}

// Appends the given value to the end of this instance.
StringBuilder.prototype.append = function (value)
{
if (value)
{
this.strings.push(value);
}
}

// Clears the string buffer
StringBuilder.prototype.clear = function ()
{
this.strings.length = 1;
}

// Converts this instance to a String.
StringBuilder.prototype.toString = function ()
{
return this.strings.join(”");
}

The code is so simple and straightforward that it should be self-explanatory. Now here’s an example of how to use it:

// create a StringBuilder
var sb = new StringBuilder();

// append some text
sb.append(”Lorem ipsum dolor sit amet, consectetuer adipiscing elit, “);
sb.append(”sed diem nonummy nibh euismod tincidunt ut lacreet dolore “);
sb.append(”magna aliguam erat volutpat.”);

// get the full string value
var s = sb.toString();

Again, so simple and straightforward it shouldn’t require any further explanation. If you’ve ever used the StringBuilder in .NET, then you already know how to use this one.

If you download the demo project, you will find an HTML page that performs a side-by-side comparison of StringBuilder vs. string concatenation. You can use it to run your own tests to see the difference for yourself. On my machine, it takes IE over 14 seconds to concatenate 5,000 strings. The StringBuilder does it in 110 ms. With 10,000 strings, it takes IE a full minute to concatenate. The StringBuilder does it in 230 ms. More than a minute to less than a quarter of a second, that’s a fairly significant improvement!
Conclusion

The whole purpose of pushing processing to the client is to provide a richer, more responsive user experience. That means, it’s important to make sure the client-side code is as efficient as possible. I hope this article helps your client-side string building code really scream.

Next Page »