The weekend just past was my first that I’ve had to work since I left Tesco. Not an entirely unpleasant experience, although I would have much rather had my weekend.
The reason we had to work the weekend was down to us launching (re-launching actually) a product for the Swift Group’s extranet, something that a lot of people had been rather worried about. Mainly because, apparently, the previous time this product was launched it corrupted important data for six months without anyone noticing. Wonderful.
Something I wasn’t too happy about when I first inherited this project is that it was my sole responsibility. Slowly I came around to the idea though, it would be all my fault if everything went wrong, true, but it’d also be all down to me if everything went well; looks pretty good being responsible for a whole project only 10 months into a job.
Anyway, this is now day 1 of the launch at an end and a few niggling things aside, everything went swimmingly. No show stopping bugs at all, only minor things that took barely more than a minute to fix. I can safely say I’m in the good books.
Here’s to day 2 going as well as day 1.
Download: domnavigation-1.1.js
As I said I would be in my previous post, I’ve been working on improving getNextElement. I’ve improved the overall performance of the function and also created a few others with similar purpose; including the sister function getPrevious element. I outline all the functions and their uses below; you can find the download link at the top and bottom of this post.
Any bugs anyone finds don’t fret to email me or post a comment here, i’ll work on fixing them asap.
The Functions
getNextElement & getPreviousElement
Basically this function is a more advanced, flexible version of the “element.nextSibling” and “element.previousSibling” properties. Features include the ability to specify the next element you’e looking for explicitly, so you can return the next list-item in a list (even if it happens to be a child of the current element) or the next matching node type. Also recursion is toggleable.
getFirstChild & getLastChild
A core part of getNextElement/getPreviousElement, this function recursively searches an elements child nodes for a matching element. Can be used stand alone to only return from within an elements child structure; recursively parses the childNode structures of all child elements.
getNextParent & getPreviousParent
Gets the next node in the DOM tree after the current nodes parent; this walks the DOM tree backwards until it finds a parent of the current node with a nextSibling/previousSibling present.
isType
Detects whether a specified element is of correct type; compares against a numerical value (nodeType) or a string value (tagName).
The Examples
Note: All functions that require an element as a parameter can either take a direct reference or a string ID value.
getNextElement & getPreviousElement
Both functions take exactly the same parameters and are used in the same way, so I’ll only provide examples for one.
Note: These functions also walk up the DOM tree, so if you have two lists and call getNextElement on the last list-item in the first list it will return the first item of the second list.
getNextElement(id);
Returns the next element, regardless of type, after id.
getNextElement(id, 'li');
Returns the next list item, after id; could potentially be a child of id.
getNextElement(id, 1);
Returns the next element with a nodeType of 1.
getNextElement(id, 'li', false);
Returns the next list-item that resides on the same level, or higher, as id; no child nodes are searched.
Practical example:
<div id="popup">
<h1>This is a popup</h1>
<p id="paragraph">Below are some options:</p>
<ul id="list">
<li>Your first choice</li>
<li id="secondItem">Your second choice</li>
</ul>
</div>
getNextElement('popup');
Would most likely return whitespace.
getNextElement('popup', 1);
Would return the H1 tag.
getNextElement('paragraph', 'li');
Would return the first list-item, “Your first choice”.
getPreviousElement('secondItem', 'ul');
Would return the UL element.
getPreviousElement('paragraph', 1);
Would return the paragraph element.
getFirstChild & getLastChild
Once again, both these functions take the same parameters and behave the same way so I’ll only provide examples for one.
getFirstChild(id);
Returns the first child of id, regardless of type.
getFirstChild(id, 'li');
Returns the first child of id that is a list-item.
getFirstChild(id, 1);
Returns the first child of id that has a nodeType of 1.
Practical example:
<div id="popup">
<h1>This is a popup</h1>
<p>Below are some options:</p>
<ul>
<li>Your first choice</li>
<li>Your second choice</li>
</ul>
</div>
getFirstChild('popup');
Would most likely return a Text node with some whitespace.
getFirstChild('popup', 1);
Would return the H1 element.
getFirstChild('popup', 'li');
Would return the first list-item, “Your first choice”.
getLastChild('popup');
Once again, probably whitespace.
getLastChild('popup', 1);
Would return the UL element.
getLastChild('popup', 'li');
Would return the last list-item, “Your second choice”.
getNextParent & getPreviousParent
Again, both these functions take the same parameters, so I’ll only show one.
getNextParent(id);
Returns the node next to the parent of id.
Practical example:
<ul>
<li id="first">Item One</li>
</ul>
<ul>
<li id="second">Item Two</li>
</ul>
getNextParent('first');
Would return the second UL element.
getPreviousParent('second');
Would return the first UL element.
isType
isType(id, 'li');
Returns true if id has a tagName of ‘li’.
isType(id, 3);
Returns true if id has a nodeType of 3.
Download: domnavigation-1.1.js
I’ve been creating a content management system over the past few weeks with all the bells and whistles you’d expect from a new web project. One thing that has caught my eye is the potential security risk when using AJAX.
For said project I’ve been using the Ajax.Net library which, like most others, outputs wrapped calls to a server-side functions in javascript.
With that in mind then, surely anyone can open up the rendered source, see your methods and then execute them at will, potentially causing havoc. Initially I was using Ajax for most of my interaction with the server - something which seems pointless in hindsight. This meant that I had a create user function exposed to the public, potentially anyone could create themselfs an account within the system by using the Javascript. This isn’t much of a problem from within the context of this project, because you can only ever view the page with the javascript when you’re authorised to create users; so it doesn’t make any difference. If this was public though, it could be a serious security risk. An example could be a comment form on a blog post, if you expose the method of creating a new comment through javascript then someone, with a little bit of work, could use the javascript to post automated comments.
Once again, nothing major but I think it is definetly something you should bare in mind when creating your pages. I guess the moral of this little story is don’t use Ajax for the sake of it and if you do use it make sure that the functions you are calling are harmless. Anything dealing with security should be left to post-backs but user experience improving features are fine - auto complete text boxes for example.
(…)
Download: prototype-extensions.js.
I’ve been playing with the prototype framework for a while now and am very impressed, the file size is a bit of a down point but that aside it’s excellent.
The one thing that has slightly irritated me (and others it seems) is that there isn’t a stop function built into the PeriodicalExecuter object. Seems something strangly simple to miss out, especially as the Ajax.PeriodicalUpdater has one built in. With that in mind I’ve made an extension my self to perform this function.
I’ve simply placed the following code in a prototype-extensions.js file and referenced it wherever needed.
PeriodicalExecuter.prototype.registerCallback = function() {
this.intervalID = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
}
PeriodicalExecuter.prototype.stop = function() {
clearInterval(this.intervalID);
}
There’s really nothing much going on in this code, all it does is take the current registerCallback function (which creates the actual timer) and stores its returned interval ID which we then use in the new stop function with the native clearInterval method.
Here’s an example implementation where I fire the PeriodicalExecuter when a key is released in a text box and then stop it once the call completes, this was the main reason I created this extension, my aim was to have a waiting period of a few seconds before a ajax lookup is performed; mainly to cut down on server calls. Each time the textbox changes the PeriodicalExecuter gets reset and started again which means the function will only ever fire once the countdown is complete.
<input type="text" id="changer" />
<script type="text/javascript">
var pe;
$('changer').onkeyup = function() {
if (pe) pe.stop();
pe = new PeriodicalExecuter(textChange, 5);
}
function textChange() {
alert('check textbox content against database here');
pe.stop();
}
</script>
I’m sure this method of extension is probably frowned upon from within the community and changes are expected to be submitted for the actual library, but I needed a fix asap and I’m sure a few other people might too.