Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Tuesday 27 November 2012

Interesting thing coming in ECMAScript 6

Javascript always has been the poor cousin to all that whizz-bangery that happens on a server and as a result anything new coming down the pipe line kinda gets lost in the news-stream of super-duper server improvements.

I try were possible to keep up to speed with what's about to come along and it was with this in mind I I was casting my eye over Juriy Zaytsev's EMCAScript 6 compatibility chart and I started to notice green's appear. Some of the current or beta versions of the browsers are starting to support the new V6 changes so it shouldn't be that long until we start to see them in the wild and can start to use them in anger.
(if you are interested in the EMCAScript 6 Draft Doc you can download it here)

Of the changes coming I am piqued by the idea of

1. Modules

While there are some JS libraries that do something very similar ES6 will provide support for modules, the rational behind this is to provide for:
  • Standardized mechanism for creating libraries.
  • In-language loading of external modules (non-blocking, direct style).
  • Portability between different host environments.
  • Future-proof mechanism for platforms to introduce experimental libraries without collision.
  • No installation/registration code within modules.
As Modules are static by default (but can be dynamically reflected) this makes them far more compatible with static scoping. Modules are loaded from the filesystem or network in direct style instead of by callbacks and this means the main thread of execution is not blocked by the load.

It is hoped that Modules will be used for scoping and their implementation preserves and promote static, lexical scoping, thus avoiding the many problems of dynamic scope: programming pitfalls, malicious scope injection, poor performance and  lack of modularity. Static scoping is also necessary for checking for unbound variables at compile time.

A simple module would look like this

module orders {
export function ASP(qty,val) { return val/qty; }
export var dollar = "$";
export var pound = "£";
}


This module would then be accessed in your JS code like this :

import orders( ASP ,  pound) from orders;
alert( pound+" "+ASP(ThisOrder.Quantity,ThisOrder.Value) );


I can see instances where this will be very useful!

More details on Modules can be found here

2. Object.Observe
Object.Observe gives us the ability to watch Javascript objects and report back changes to the application, changes like properties being added, updated, removed or reconfigured. When I am building a UI frameworks I often want to provide an ability to data-bind objects in a data-model to UI elements. A key component of data-binding is to track changes to the object being bound. Today, JavaScript frameworks which provide data-binding typically create objects wrapping the real data, or require objects being data-bound to be modified to buy in to data-binding. The first case leads to increased working set and more complex user model, and the second leads to siloing of data-binding frameworks. ES6 will get around this by providing a run-time capability to observe changes to an object. Here is interesting discussion on this soon to be available new feature

3 Default Parameter Values

Default parameter values allow us to initialize parameters if they are not explicitly supplied, so you can do things like


function dspInputPanel(footer = "Steve McDonagh")
{
       ... build inputPanel Object..
       footer.innerHTML = footer;

}

So when I call dspInputPanel() with no parameters the footer object will contain Steve McDonagh
if I call dspInputPanel("Anne Other") then the footer object will contain Anne Other

4. Block Scoping
There will be 2 new declarations available for scoping data in a single block

let which is similar to the var declaration but allows you to redefine a var in the let's block scope without changing the orginal var in the scope of the function

function doInterestingStuff()
{
         var x = 5;
         var y = 6;
         let (x = x*2,y =y*3) { alert( x+y ); }     // pops up 28
         alert(x+y)                                            // pops up 11
}


const is the other declaration and is like let but is used for read-only constant declarations

5. Maps
Arrays of Name - Value pairs have been around a long time in JS and ES 6 will introduce the new Map() object with it's functions SET(), HAS(), GET() and DELETE() that makes using them even easier

var myDogs = new Map();
myDogs.set("Fido","Poodle")
myDogs.set("Rover","Collie")
myDogs.has("Fido")                                 // Returns true
myDogs.get("Fido")                                 // Returns "Poodle"
myDogs.delete("Fido")                             // Returns true when deleted
myDogs.has("Fido")                                //  Now returns false


6. Sets
SETs are basically arrays and there is a new object creator Set() with associated methods HAS(), ADD() and DELETE()

var myCustomers = new Set( ["IBM","DELL","APPLE"] )
myCustomers.has("IBM")                   // returns true
myCustomers.add("ASUS")               // adds "ASUS" to the set
myCustomer.delete("IBM")                // Removes IBM from the set
myCustomer.has("IBM")                   // now returns false

This will allow array filtering to be so much easier, consider the following where I have an Array of customer names that I want to ensure is unique this new method is much much much easier to read.

function unique( customers )
{
       var ucust = new Set();
       return customers.filter(item) {
                                     if(!ucust.has(item)) { ucust.add(item) }
                                     return true;
                                     } 
}



There are loads more changes and improvements in the spec and it seems that ES6 is targeting a 2013 full spec release but as always some browsers are already implementing individual features and it's only a matter of time before their availability is widespread.

JS it seems may be coming out of the closet in the next 6 months and may soon be considered a "proper" language :-)

Sunday 4 November 2012

Alternates to the evil EVAL() in javascript

I am interrupting the Design Series of post for a quick JavaScript post that comes out of a question asked on the JavaScript forum on LinkedIn about alternates to the eval() function in JavaScript.

The most pertinent reasons for not using eval() are:-

1. Security - it leaves your code open to a JS injection attack which is never a good thing
2. Debugging - no line numbers which is a PITA
3. Optimization -  as until the code to be executed is unknown, it cannot be optimized.

Sadly EVAL is way to easy to use and as a result we see it all to often in places we shouldn't really see it and this can leave the door open to some nere-do-well making a mockery of the rest of your obviously wonderful code.

So what to do to avoid using eval()? Well alternates to the the 3 main areas I have used EVAL in the past are listed below.

1. When working out a bit of an object to change for example something like this

eval('document.'+IdName+'.style.display="none"');

Now I am not suggesting anyone WOULD do this given the tools available but I have come across code like this in older applications written by people just starting out in the wonderful world of JS.

document[IdName].style.display= 'none';

or

document.getElementById(IdName).style.display='none';

are both much safer and a lot faster.

2. Getting JSON that has been returned by AJAX calls to the server into the DOM, like this snippet of jQuery is doing.

$.ajax({ url: "getdata?openagent&key=SMCD-98LJM",

              success: function(data) { eval(data),
                                        doSomethingInteresting()
                                      }
        })

This will work but a more satisfactory way would be to use the JSON data type in the ajax call

$.ajax({
  url: url,
  dataType: 'json',
  data: data,
  success: *callback*
});

alternately use the $.getJSON() jQuery shorthand function.

If you don't use jQuery (or dojo which has an equivalent) you can use the powerful JavaScript JSON object.

var myJSONData = JSON.parse(data, reviver);

Where DATA is the the JSON data string and REVIVER is an optional function that will be called for every KEY and VALUE at every level of the final resulting object. Each value will be replaced by the result of the REVIVER function. For example this can be used to change strings in the JSON text into JS Date() objects.

3. The thorny and potentially very insecure loading and execution of Code Blocks, probably the most common use of eval() function in Javascript. Anywhere you allow code as text to be passed and run in the browser is prone to attack, it is much better where possible not to do this. When you absolutely have to do it then I would say using the Function constructor is less risky than a bold eval() call.

var myCode = "... your JS code ..."
var doSomething = new Function(myCode)
doSomething.call()


This will have the same effect as EVAL() but is less prone to being found as an avenue of attack for the forces of chaos on the internet. ** Note** you can also use the constructor format below to pass parms to the code block.

var doSomething = new Function("..var1name..","..var2name..", etc .. "..myCodeString..")

On a side note but related note, when you create a normal JS function construct, the definition does not have to appear at the start of the script (though it is usually best to do so for the sake of clarity). It can even be defined after the the code that calls it. In most cases, no matter where you choose to define your function, the JavaScript engine will create the function at the start of the current scope. BUT and it is an all caps BUT if you need to construct a code block conditioned on an IF, like this
if( someThingIsTrue )
 {
 function doSomeThingWonderful.call() { .... }
 }


Mozilla based browsers will allow it, but most others do not as they will always evaluate the function, even if the condition evaluates to false. So do not try to declare functions in the way noted above. Declaring functions inside these statements is possible in all current browsers using assigned anonymous functions, so it is better to do it this way.

var doSomeThingWonderful;
if( someThingIsTrure ) {
  doSomeThingWonderful = function () { --CodeBlock A--};
} else {
  doSomeThingWonderful = function () { --CodeBlock B--};
}
doSomeThingWonderful.call()

There are other reasons you need to evaluate objects or code  but generally there are ways around most of them that whilst potential slower to process are more secure and sensible.



     

Sunday 14 February 2010

Access the clipboard in Javascript

Now here is a wee something I fell over the other day whislt trying to figure out a way of copy and pasting a text stream from a Turd© document to a text area on a form. It would be really useful to grab the clipboard contents .. do some RegExp replaces on it and then import it into the text area.

Well after a moment or two's research you can be done in IE and you have to tweak Moz browsers see here to allow it to work and on Chrome it doesn't work

function clipboardHack ()
{
     var content = clipboardData.getData("Text");
     alert(content);
}

You can also push any changes back using clipboardData.setData("Text",[changedtext]);

Wednesday 16 September 2009

A JS/CSS based star rating system for web pages

I was working on a project tonight that needed a "star" rating system and I had one from a while ago that you may find useful.

It works like this.

I have an image that is 20px wide and 40px deep
In the top 20x20px I have an empty star
In the bottom 20x20px I have a selected star like this




If I place this image as a background in a block type element sized 20x20px with a CSS style of background-position: left top; the user will be presented with the empty star. If on the other hand I position it with the CSS of background-position: left bottom; you will see the selected star.

So all I need to do now is create an HTML
(1) that has a hidden field for me to store the value that will relate to the number of stars selected
(2) that has a table were each cell is sized to be 20x20px
(3) where each cell has CSS with a background-image of my star picture
(4) where each cell as an onmouseover event that changes the css so that the background image's css is changed to be the bottom portion of the background image.

If it all works you will get something like this (sorry it is off site.. but blogger wouldnt play ball with the JS)

The code for the page in the link above looks like this . feel free to take and use as you see fit.. however if you do drop me a comment.. I like to feel i am being useful ;-)

<html>
<head>
<style>
.star
{
background-image: url(star_rating.gif);
background-position: top left;
width: 20px;
height: 20px;
cursor: pointer;
}
</style>
<script = 'javascript'>
function star(a)
{
// reset all stars to blank
for(var t=1;t<=5;t++)
{
document.getElementById(t+"star").style.backgroundPosition="left top";
}
// Set new value in hidden field
document.forms[0].likeem.value=a;
// Set new value for display
for(var t=1;t<=parseInt(a);t++)
{
document.getElementById(t+"star").style.backgroundPosition="left bottom";
}
}
</script>
</head>
<body onload="star(3)">
<form>
This field below normaly be hidden <br>
<input type='text' id='likeem' name='likeem' value=""><br>
Now move your mouse over the stars below</br>

<table cellspacing='0' cellpadding='0' border='0'>
<tr>
<td id='1star' class='star' onmouseover= "star(1)"></td>
<td id='2star' class='star' onmouseover= "star(2)"></td>
<td id='3star' class='star' onmouseover= "star(3)"></td>
<td id='4star' class='star' onmouseover= "star(4)"></td>
<td id='5star' class='star' onmouseover= "star(5)"></td>
</tr>
</table>

</form>
</body>
</html>

Tuesday 15 September 2009

FireBug 1.4.2 in Firefox 3.5.3 suddenly stopped working - END OF WORLD!

Just a quickie ("Ding Dong Matron![twirl moustache & wink laciviously]")
Found out after much headless chicken panicking if Firefox is set to "Not remember History" (Options / Privacy / History) Firebug suddenly stops working.. makes sense when you think about it but BOY did it give me a turn!

Thursday 4 June 2009

An Alternate way of embedding a configurable Video player in an NSF

I recently came across a nice open source video player that is dead easy to build into your Notes Applications. The player is called FLOWPLAYER and has been released under a GPL license. There are commercial and multi-domain versions which you have to pay for, but the base app is free to build into your apps.

You can download it here and once you have the zip file unzipped you have two SWFs and an example directory. I embedded it in my app like this.

01. I embedded FlowPlayer-3.1.1.swf into the RESOURCES / FILES section of the nsf

02. I embedded FlowPlayer.controls-3.1.1.swf into the RESOURCES / FILES Section of the nsf

03. I embedded the Flowplayer-3.1.1.min.js inot the RESOURCES / FILES section of the nsf

04. I added the flowplayer-3.1.1.min.js as an external JS file to the form I wanted the player to be on

05. I added a RT field into which a Video file could be attached

06. I added this code to the form
<a href="'http://www.unseenuni.com:81/flowplay.nsf/new/[ComputedText1]/$File/[ComputedText2]?openelement' style='display:block;width:400px;height:300px' id='player'></a>

<script language="'javascript'"> flowplayer("player","http://www.unseenuni.com:81/flowplay.nsf/fp311.swf?openfileresource")</script></pre>


[ComputedText1] = @documentUniqueID and
[ComputedText2] = @attachmentnames

07. I created the form .. attached an MP4 opened it in the browser and it worked like a charm and looked like this



So if you have a need for a very clean, easy to use adaptable player for free (we like for free) then you can't go far wrong with Flowplayer ... check it out here

Saturday 25 April 2009

Sharing my Javascript toolbox - tiplets

In addition to my last post here are two more tiplets from my JS toolbox

First additions to the String object that allow you to use left(x) and right(x) just like in LS

// ****************************************
String.prototype.left = function(n){
if (n <= 0)
return "";
else if (n > this.length)
return this;
else
return this.substring(0,n);
}
// ****************************************
String.prototype.right= function(n){
if (n <= 0)
return "";
else if (n > this.length)
return this;
else {
var iLen = this.length;
return this.substring(iLen, iLen - n);
}
}
// *****************************************


and another String function setCharAt(x,y) which will replace the character at postion x with character y. BTW x starts at 0 as the first character!
for example

myString = "My Dog has no nose"
myString.setChar(3,"G")

would result in myString being equal to "My God has no nose"


String.prototype.setCharAt = function(index,chr) {
if(index > this.length-1) return str;
return this.substr(0,index) + chr + this.substr(index+1);
}


Finally for today and extension to the number object Number.padZero(x) that will return any number as string x long with left padded zeros.
For example
var myNumber = 12
var myPad = myNumber.padZero(4)
would return myNumber = "0012"
This function is useful if you are populating the DOM with objects based on a FOR loop and you want the object.id's to be a set number of characters long.

Number.prototype.padZero = function(cnt)
{
var retvar = this.toString();
cnt=cnt-retvar.length
if(cnt>0)
{
for(var x=1;x<=cnt;x++)
{
retvar = "0"+retvar;
}
}
return retvar;
}

Sunday 19 April 2009

Sharing my Javascript toolbox - Date Formatting

I was sorting out my Javascript Utilities into some semblance of order over the weekend and I found an extension to the date object that you might find useful. This is one of those things that I use on a daily basis and kinda forget that it is not standard and that other people may find it useful.

Basically what I got pissed off having to recode date formatting routines and having to remember things like how to work out the week number in the year given a data. So I extended the native Date Object with a new method called format which if you supply it with a date format string will return the date in the format you require. Rather like the format() LS command. However being a bit of a PHP nut I used the PHP format string structure as my starting point, because it makes more sense (well to me anyway... and i am very odd)

The format string you use can be made up of the following characters.
All other characters and spaces in your string will be considered as constants., but be careful of including words like "and" which will be resolved as "a", "n", "d"


When you add my code to your web pages/forms all you need to do is instansiate your date and then use the new method format([format string],[locale code]) and the date stored in your Date object will be returned in the format you requested For example
myDate = new Date();
xxx =myDate.format("d/m/Y","EN")
Will result in xxx containing 19/04/2009 or
myDate = new Date();
xxx = myDate.format("D dS, F Y","EN")
will result in xxx containing Sunday 19th, April 2009

Localisation

I have provided 3 Locale's English =EN, French =FR, and German = DE however it is really easy to add others if you need them. In the code find the definition for

daysL = Names of Days Long
daysS = Names of Days Short
monthL = Names of Months Long
monthS = Names of Months Short
daySuf = Suffices for Day numbers (st,nd,rd and th)

and add the values that you want in the format that the other countries are in.

You can get the JS source code DateExt.js here feel free to use and if you find anything odd, wrong or additions that you find useful please let me know ... enjoy ;-)

Tuesday 7 April 2009

Javascript Sorting

OK this came up today in a skype chat about browser side sorting of array's returned by AJAX, prior to display on the page. particularly useful if you want the user to have the ability to sort the date in a variety of ways without going back to the server to get it done. The great thing is there is a built in JS method on the ARRAY object that allows you to sort the contents in all sorts of interesting ways.

It is relatively simple to do but there are a few GOTCHAs to remember the main one of these being that sort() sorts lexicographically! So....
myArray = ["Bob","Anna","Zeebedee","George"]
myArray.sort()
...will result in myArray contents = ["Anna","Bob","George","Zeebeedee"]

Thats all fine and dandy however what happens when you do this?
myArray = [12,400,3,25]
myArray.sort()
You will get myArray = [12,25,3,400]!
Why???WTF??? I hear you cry.. this happens because it a lexicographic sort and lexicographically 3 is bigger than 25 ...go figure! But all is not lost to get arround this you would pass a function to the sort() method.

When such a function is passed into array.sort(), the array elements are sorted based on the relationship between each pair of elements "a" and "b" and the function's return value. The three possible return numbers are: less than 0, 0, or greater than 0

  • Less than 0: Sort "a" to be a lower index than "b"
  • Zero: "a" and "b" should be considered equal, and no sorting performed.
  • Greater than 0: Sort "b" to be a lower index than "a".

So to sort an array numerically and ascending for example, the body of your function would look like this:

myArray = [12,400,3,25]
myArray.sort(sortMyNumbersAsc)

function sortMyNumbersAsc(a,b) { return (a-b) }

This works the way it does because whenever "a" is less than "b", a negative value is returned, which results in the smaller elements always appearing to the left of the larger ones, in other words, ascending.

Sort an array numerically but descending isn't much different, and just requires reversing the two operands "a" and "b" into this

myArray = [12,400,3,25]
myArray.sort(sortMyNumbersDsc)

function sortMyNumbersAsc(a,b) { return (b-a) }

You can also have fun shuffling the contents of your array by randomising the entries, i don't actually test "a" and "b" I just return a value of less than 0, 0, or greater than 0

var myarray=[1996, "Duck", 28.445, "Gertrude's Lemon Corporation"]
myarray.sort(scrambleMe)

function scrambleMe(a.b) { return (0.5 - Math.random()) }
So that is what you do when you have flat single dimension arrays, what happens when I have a multiple dimension array -- can I still sort? Yes you can and here is how... conside this array
var myArray = new Array();
myArray.push( ["one",1]);
myArray.push( ["three",3]);
myArray.push( ["four",4]);
myArray.push( ["two",2]);
myArray.sort(sortMe);
Now when you pass a and b to the function the entire dimension is passed so you can refer to the index value to do the sort, like this is we want to sort ascending on the second numeric dimension
function sortMe(a,b)
{
x = a[1];
y= b[1];
return (x-y)
}
This will return the array sorted like this

["one",1]
["two",2]
["three",3]
["four",4]

Simple ;-)

Enjoy!

Monday 16 March 2009

Some regex for the new to the Web programmer

I was asked today how on a web form you could check to see if an email address was correctly formatted before the form was submitted. Well with the advent of Xpages and the pervasiveness of AJAX frameworks, web pages in the Domino World, like any web faced back end are not exempt from the double requirement of being shiny sexy things that users love AND having functions that can stop users doing the stupid things they always do.

The question was posed by a RPG programmer new to the world of the web and when I said "och that's a piece of piss, use a RegEx" they looked at me like I had grown an extra head (which i do do on occasions for extra effect when I am being flash)

RegEx is short for Regular Expression
and is a string that describes a search pattern. *.txt is a RegEx that will be familiar to everyone. But proper RegEx is like that but on steroids, human growth hormone and crack cocaine.

There are loads of web sites that go into great detail about how to correctly form a RegEx and I will let you go find them yourself .. there is thing called Google and it is really useful ;-)

However how to use RegEx and a RegEx pattern to test an email address?

OK lets say you have this HTML on a form
Email Address <input type='text' name='email' value=''>
I am going to use this is a JS function that will return true or false if the email address entered is valid
function emailOK()
{
myRegEx = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
if (document.forms[0].email.value.search(myRegEx) != -1)
{
return true;
else
return false;
}
}
You will notice that I do NOT use a string literal surrounded by a pair of ""s for the myRegExp. Why? Because in a string literal \ is special (as in new line \n) so the RegEx expression \w+ would become "\\w+" in a sting literal which makes something that is very hard to read even harder to read. JS allows you to delimit RegEx's like this /pattern/ which makes things much nicer!

I pass this RegEx to the SEARCH method of the JS String object (which is what the .value of an input field is BTW) and it returns -1 is the pattern does not match or a positive integer if it does match. Which is all very simple BUT ... what does all that gooble-de-gook mean.. if you don't care .. then far enough, copy and paste the code and use it in your own app ;-) if you are curious here is what it means:

1. it begins with a / and the matching / is the very last character these act as the "" would in a normal string

2. The ^ symbol, means start matching at the absolute beginning of the string.

3. \w+ matches one or more alphanumeric characters.

4. This is where this gets interesting :-)
((-\w+)|(\.\w+))*
First, note that the whole thing is surrounded by (...)* which means that we want to match zero or more of whatever is inside.

Inside the ()* parentheses, we have (-\w+) and (\.\w+) separated by the | character This means it with match EITHER -\w+ OR \.\w+

The first one indicates that we should have a match if we find a hyphen followed immediately by a set of alphanumeric characters. The second part matches if we find a period followed immediately by a set of alphanumeric characters.

(NOTE . by itself is a special character so we must delimit it by placing a backslash in front of it.)

So far we have a pattern that will match [some alphanumerics]-[some alphanumerics] or [some aphanumerics].[some aphanumerics]

5. After this match, comes an \@ sign (once again i use \ to override any special meaning @ may have in RegEx

6. Immediately following the @ is [A-Za-z0-9]+ which matches a set of alphanumeric characters of either upper or lower case. I don't use \w+ because this would allow characters like _ and - ... OK?

7. next up is ((\.|-)[A-Za-z0-9]+)*

8. Note that the search is surround by ( ... )* this means we are matching one or none of a match to the pattern inside the ( ... )

9. So take them away and we are left with (\.|-)[A-Za-z0-9]+

10 First (\.|-) This is trying to match the first character as a . or a -

11. Then comes [A-Za-z0-9]+, the match only works if the period or hyphen is followed by a set of alphanumeric characters. This effectively represents an email address that contains a (possible) set of .something or -something sections. Because the * is used, the pattern works if they are present and also if they aren't.

12. Finally the \.[A-Za-z0-9]+ pattern matches a . followed by a set of alphanumerics. Because it is the last part of the regular expression, it represents the final part of the email address, which is the .com .co.uk bit.

13. The $ symbol ensures that the previous bit only matchs the END of the string.

14. The last character (the /) closes the first /

Simple .. init? ;-)

Tip of the Day- A JS way to create inline images to display from attachments in a Rich Text Field

Here is a wee Domino related JS tip.

Say you have a RT field into which users can attach files, these will in the natural schemem of things appear as a list of attachments with nice icons to click on. But what if you want to display them but couldn't be arsed coding in the domino bit of the form to get them to display as inline images.

01. Put a DIV tag around your RT field and give it an ID


<div id='imageRT'>[DominoRTField]</div>


03. Create an empty target [div] to display them in


<div id='imageDsp'></div>


04. Create a JS function in the form or page like this

function dspLinks()
{
target = document.getElementById("imageDsp");
imgLinks = document.getElementById("imageRT").getElementsByTagName("a")
for(t=0;t<imgLinks.length;t++)
{
imgLink = imgLinks[t].href;
img = document.createElement("img");
img.src = imgLink;
target.appendChild(img)
}
}


04. Put your dspLinks() function in the onload of the form and voila you have all the images in your RichText field displayed in the target div as well as the normal link icons you get from a RT Field's attachments.

Wednesday 21 January 2009

My First V8.5.0 project - Getting a decent floating layout

I have been fiddling with a variety of layouts of late and I really wanted a fluid 2 column plus header and footer arrangment, like the one on the left (but not in those colours) And I did not want to involve tables. So I tried I floated things left and right, up and down, in and out, but could not get it just the way I wanted it without going all position: absolute. the main problem being floating the footer to the bottom.

It seemed that the only way to do this was with absolute positioning, which I wanted to avoid if at all possible!

Then I came across this article by Shaun Inman and my problem was solved! He describes the solution much better than I can so I advise you to go have a look see if such things make you moist.

He has a really simple CSS and JS resolution to the problem so I copied it down and into a NSF page to see if it would work and it does!! Wonderfully fluid centered [div]s with a header at the top and a footer at the bottom ..(see below) ... Yippee ... Just what I wanted. Now if I can just get it to work in xPages which is being somewhat of a puzzle, but I shall continue on regardless. More tomorrow.

Posted by Picasa

Monday 15 December 2008

Loading an external JS or CSS file on the fly.

OK all you dev's out there are prob used to loading JS or CSS somewhere in your HTML this is generally hard coded and is something like this
[head]
[script type='text/javascript'm src='loadofstuff.js'][/script]
[/head]


However there may come a time when you want to bring in a JS file based on some criteria or process that is only resolvable at runtime. Localization for example, you want to bring in a JS file that has your lovely code rendered in glorious Polish or Tagalog or you need to change the CSS to facilitate Hebrew right to left alignment.

To do this you need to have some insertion fun with the DOM. Nothing like a good insertion if it is done well I always say!

For JS you would create a "script" element and for CSS you would create a "link" element .. yes it is that simple ... here is some code


function insertMyFile(whatIsIt,whatsTheFile)
{
if(whatIsIt == "js")
{
externalFile = document.createElement("script");
externalFile.setAttribute("type","text/javascript")
externalFile.setAttribute("src",whatsTheFile)
} else if(whatIsIt == "css")
{
externalFile = document.createElement("link");
externalFile.setAttribute("rel", "stylesheet")
externalFile.setAttribute("type", "text/css")
externalFile.setAttribute("href", whatsTheFile)
} else {
alert("You knob! Pass a file type please");
}
if (typeof externalFile!="undefined")
{
document.getElementsByTagName("head")[0].appendChild(externalFile);
} else {
alert("Bollox something nasty has happened");
}
}


Then all you need to do at some point in your code is go...
insertMyFile("js","myPolishCode.js")
or
inserMyFile("css","myHebrewCss.css")

Okey Dokey?

Thursday 11 December 2008

Javascript and Christmas Queues

Gentle reader , another JS pearl of wisdom.

Today I was writing some code and i needed to use a "stack" to take values in and feed them out one at a time using the "Last In First Out" or LIFO paradigm. Now you could should the urge overtake you go down the C++ or Java route and build all sorts of interesting data structures to do this. However there is an easy way using Arrays, let me explain

The javascript array object comes with a couple of interesting methods, namely push(), pop(), shift() and unshift() .

[array object].push([value]) appends a value to the bottom of an array

[array object].unshift([value]) does the same as the .push() method and appends a value to an array.

[array object].pop() removes the top most value from an array (index = 0)

[array object].shift() removes the bottom most value from an array (index array.length-1)

Using push() and pop() for LIFOing an array

var pileOfData = new Array();
// ** So we now have an empty array
pileOfData.push("Roast Turkey");
// ** The array has 1 element containing the string "Roast Turkey"
pileOfData.push("Christmas Pudding");
// ** The array now has 2 elements "Roast Turkey" and "Christmas Pudding"
var whatWasLastIn = pileOfData.pop();
// the pop() method gets the element at index 0 and removes it
// Now the array has one element "Christmas Pudding"
// and the variable whatWasLastIn contains "Roast Turkey"
Using push() and shift() for FIFOing an array
var pileOfData = new Array();
// ** So we now have an empty array
pileOfData.push("Roast Turkey");
// ** The array has 1 element containing the string "Roast Turkey"
pileOfData.push("Christmas Pudding");
// ** The array now has 2 elements "Roast Turkey" and "Christmas Pudding"
var whatWasLastIn = pileOfData.shift();
// the pop() method zips down to the bottom of the array and removes the element it finds there and removes it
// Now the array has one element "Roast Turkey"
// and the variable whatWasLastIn contains "Christmas Pudding"
I used the top method to queue AJAX requests and then release them to the server in a timely manner once the previous request had completed.

Wednesday 10 December 2008

Making javascript remember things

OK Geek Post Alert!

If you have been following my JS posts you will know that I quite like it as a language .. now there comes a time in most coder's life when they get to a point in some code where they need a global variable and they have that "DUH!" moment and have to scoot back up to the top of their code to define a var in a place that will define it as global... well here is a way around that.

There is a global object in JS ... i'm waiting ... that's right Edgerton-Smythe the window object and can we use it? YES WE CAN ! Paulson PUT Bigglesworth down this instant or I SHALL send you to the padre!

Lets say we want to tweak a value the user has entered and come back to it later say in the form submission JS. I would use this bit of JS that I keep in my "tool box" javascript library.

function dontforget(theValueToRemember,theNameIWillCallIt)
{
      window[theNameIWillCallIt] = theValueToRemember;
}
For example I want to remember the pearson's age in years that I have calculated from their birthday which they entered in date format but I dont have a global variable to hold the age defined in my code so I use this :

      dontForget(56,"theirAge");

Then I go off do other things, slip out of the function I was in and come back to the value I memorized at any time by simply looking in window.theirAge or window["theirAge"].

Please be aware I am not advocating the fullscale use of this .. you should declare all your vars and scope them correctly, but if you have to write quick code for whatever reason and find yourself needing a global var, this is a method you can use.

Tuesday 11 November 2008

Coding for the Mouse Wheel in Javascript

This is quite an esoteric post for those JS heads out there ... how do you code for the user using the mouse wheel?

I was working on Name Picker V2.0.0 tonight and one of the "improvements" is that there will be both cursor key and mouse key support on the new format list (which is basically a vertical array of [div]s rather than a select object.

Most of the default form objects that support scroll bars will have mouse support. But what about [li] or some interesting nested [div]s or a [table] construct? With all this Web 2.0 stuff out there you may need to get to grips with doing something with the mouse wheel to allow the user to move to some element on your page. Here is how to do it ... (The O'Reilly Javascript Definitive Guide came in VERY handy for the event properties!)

Mozilla based browsers have a built in event called DOMMouseScroll YIPPEE! I hear you cry but guess what IE doesn't! Instead IE has onmousewheel on both the window and the document object. Browser compatibility don't you just LOVE it to bits!

Now I am going to get all Greek on you and talk about "Delta". Delta is the 4th letter of the greek alphabet and is used by math and other hard sum geeks as the symbol for some form of change. In this instance the change is the direction a user whizzes the mouse wheel and based on that direction the mouse wheel whizzing perform some wondrous code of your own devising.

OK there are some more gotchas for the JS coder.
IE stores delta in event.wheelDelta and positive values are UP negative are DOWN
Opera stores delta in event.wheelData and positive values are DOWN and negative are UP
Mozilla stores delta in event.detail and positve values are DOWN and negative are UP

Right first thing to do is write your handling code
function myWheelHandler(D)
{
  if(D<0)
  {
     ... do some DOWN code ...
  } else {
     ... do some UP code ...
  }
}

That's your bit done, now we have to bend the browsers to our will by writing some code to use instead of the default code
function myWheelFunction(event)
{
  var D = 0;
  // Catch the event for butter fingers IE
  // as it doesnt send event as an arg
  if(!event)
  {
    event = window.event
  }
  // if this is IE or OPERA delta is in wheelDelta
  if(event.wheelDelta)
   {
     D = event.wheelDelta
     // If we are in OPERA change the sign
     if(window.opera)
     {
     D = -D
     }
   } else {
   // OK I am going to assume Mozilla if not IE or OPERA
   // correct the signage to - is down and + up
    D = -event.detail
   }
  // Perform my fantastic wheel mouse code
  myWheelhandle(D)
   // Stop the default actions happening
   if(event.preventDefault)
   {
     event.preventDefault();
   }
   // needless to say IE needs this to cancel default actions
     event.returnValue = false;
   }
}

Right all that is left is to put some code somewhere in your code to override the default with your code.

// For Mozilla
  if(window.addEventListener)
  {
    window.addEventListener("DOMMouseScroll",myWheelFunction,false)
  }
  // For IE and Opera
  window.onmousewheel = document.onmousewheel = myWheelFunction


So there you go, you can now code loads of lovely things for your mouse wheel operations on your web pages.

Thursday 6 November 2008

Name Picker V2.0.0 started

I recently got two messages on OpenNTF informing me that there was a bug in the multiple selection section code of my AJAX Name Picker and after some checking indeed there is! I had made a fairly minor change in a bit of what I was "sure" was unrelated JS and managed to duplicate all the data in an array. So sure was I that it was fine I didn't test all 3 types of name picker ~hangs head in shame~ I really should know better!

Anyway, it was a bit of code I wrote back in 2006 and as such it is starting to look a wee bit tired (as well as buggy). So I have started tarting it up and foremost amongst the changes will be that it will be a JS class NP_object and you will need only to instantiate a Name Picker object on the form onload event to create a Name picker that can be used anywhere on the form by attaching it to a form object event.

This evening I wrote the "injection" mechanism that creates and adds the Name Picker objects to your form/page's DOM. The default picker (single selection popup) looks like this and is fully drag and dropable.
So to the 2 people that are waiting for my fix to Name Picker V1, please be patient rather than fix the bug in the current release. You will be getting a "fully" tested newer version hopefully with more features.

I hope to also release this as a Google Desktop widget to allow your users to be able to get vCard like information from your PAB without the need to have the notes client active, but more on that later.

Saturday 18 October 2008

Create a web based Drag and Drop Calendar

As part of my "spreading the domnio love" I have for the past year or so been a "yoda" to a Notes Developer who wanted to start branching out into more web based apps. Now in typical DYM form fate does not thrust me an apprentice with whom I can share the odd beer at the weekend. Oh NO! My "Luke Skywalker" does not live in Ireland! C'est la vie :-)

Anyway she asked me the other day how she could make one of her CRM calendar facilities a bit flashier and more modern and I like a fool said "why don't you do it in AJAX and while you are at it incorporate Drag and Drop?"
"Oh that would be good" she said "How would I do that?". My bluff was well and truly called! I said I would have a look at it this evening and send her an example over the weekend. After a certain amount of head scratching and asking myself "How would Chris Blatnick do it?" I fired up the DYM PC and started to code.

One of the problems with calendars and domino has been how absolutely SHITE they look on the web and building any sort of functionality into them was a labour of hercules which involved far to much futtering about with $ fields and the like. My non-domino alter ego PHPYouWillYouWill (tm) gave me a stout dig in the ribs and whispered in my ear, go on break the 11th commandment, use the domino server as a back end server and do nearly everything in JS. I know that this in some quarters sufficient for my domino woggle to be ceremonially crushed as LS. However in mitigation my design runs quite happily on servers V6 and above and the Domino Web Server way back then was a bit ... well it was a lot ... EUCK.

The premise of this example is simple, you have two forms Customer which stores customer data and Appt which stores an Appointment with a customer on a particular day. This data needs to be presented in a MONTH view to the user. The users need to be able to schedule a meeting with a customer on a particular day so they also need to be able to
a) Find a customer in the application
b) Drag the customer onto a date cell which will create an APPT form in the back end NSF

I am used to the YUI framework and one of these days I will get all DOJO but for the moment I know what I am doing with YUI and it has a nice easy D&D implementation.
You register the dragable object and target objects, define a couple of handler functions and Robert is your mothers brother.

Now please remember this is a simple app written as an example of "how I would start to" rather than an actual full functioning app and it was written in 3 hours this evening. Anyway it looks like this, (Click on image for a better look see)


A: Controls for moving the viewable month around.
B: Search Bar á la Google that allows typeahead look up of the customers.
C: Results from the search appear here.
D: An Item being dragged from the list to the calendar.
E: As the Customer passes over a calendar cell the cell is highlighted.
F: An existing Appointment in the calendar.

I used YUI 2.2.4. as the framework for the AJAX calls and DOM manipulation.

Like I said it looks kinda better than the ordinary one and isn't all that complicated at all (it took me 3 hours to code up from scratch!) and will run happily on a V6 onwards server you don't need any on the V8 fancy pants stuff and all the YUI stuff is contained in the NSF.

If anyone is interested an uncommented version of the file can be downloaded here.
Download it, Sign it, pop it on your server and goto crm.nsf/calendar.html

If you think it is useful let me know and I will definitely pop the commented version up on OpenNtf (once i have commented it that is!)

Friday 15 August 2008

Useful JS script to get around IE's inability to do getElementsByName properly

If you need to use the JS function getElementsName() which works perfectly in all other browsers except that f**king slough of programming despond that is IE. Try this.

It basically overrides the getElementsById() function with a new one that unlike the spew in IE, works!

if ( /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) )
{
document.getElementsByName=function(str)
{
str=new String(str);
var myMatches=new Array();
var allEls=document.getElementsByTagName("*"),l=allEls.length;
for(var i=0;i<l;i++)if(allEls[i].name==str || allEls[i].getAttribute("name")==str)myMatches[myMatches.length]=allEls[i];
return myMatches;
}
}


Sunday 27 July 2008

Getting intimate with Javascript objects part #7 - Really Useful Associative Arrays

Sorry about the delay getting this post to press. I have been a wee bit busy. However without further ado lets look at a javascript thingie I think is REALLY useful.

You will all be familiar now with the period operator that is used to access the properties of an object. for example myGirlFriend.hair = "Blond (Well the bits you can see)" but you cal also express this as myGirlFriend["hair"] = "Blond (well the bits you can see)".

In C,C++ and Java and object can only have a fixed number of properties that are defined at compile time. Since Javascript is "loosely" this rule is not enforced a program or function can access add or delete properties to any object. When you use the "." operator you have to use the name of the property. The text that follows the "." is not a data type so cannot be manipulated by the program.

[...Drum Roll...]

If we use the [] syntax the identifier is a string, now a string IS a javascript data type and we CAN manipulate strings ... YIPEE!

Say we had a HR data table which had an object like this
Person.Name1 = "Steve"
Person.Name2 = "John"
Person.Name3 = "Marshmallow"
Person.Name4 = "McDonagh"
and we wanted to combine all of this data into a single string for full name would do something like this
PersonFullName= Person.Name1+" "+Person.Name2+" "+Person.Name3+" "+Person.Name4
or we could do it like this

var PersonFullName="";f
or(t=1;t<5;t++)> {PersonFullName += Person["Name"+t]+" ";


This is perhaps a bit simple and not something you consider using in real life but it does demonstrate the use of the [] construct to get at information you may not know ahead of time.

Lets look at a slightly more complicated example. You have an ebusiness selling socks. You do not know ahead of each sale what size or colour or socks your users are going to buy that day.

Say a user comes along and asks for a pair scks that are Yellow and Adult size 9. You have no way using the "." operator to construct and get this information from your stock object which looks like this.

Stock.Yellow7 = 100;
Stock.Yellow8 = 15;
Stock.Yellow9 = 3;

But using the [] construct you can easily do this by concatenating the values entered by the user

alert(Stock["Yellow9"]) would result in an alert that has 3 in it.

When a object's properties are accessed in this way the object has ceased to be just an object it has become an associative array. Don't worry to much about this but you may hear the term used by some smart arse project leader like me and it pays to be up on the jargon we like to use. If you move on to PERL or PHP you will come across objects that can be accessed in this way. An PHP and PERL programmers are much nicer that those legends in their own lunchtimes Java programmers ;-)

Oh an before I forget.. like Lotusscript if you want you can use a For/In construct using the associative array method. Like this, if we wanted a total number of socks
in out Stock object.

var allsocks = 0;
for (Socks in Stock){ allsocks += Socks; }


Since we may add or delete Items from Stock, for example "Yellow Size 7" are just not selling so I give them to the charity shop and remove them from my inventory. If I use the for/in loop to get my total I do not have to change any code that may contain a line like this

allsocks = Stock.Yellow7+Stock.Yellow8+Stock.Yellow9

I use this particular trick nearly everyday and if you are going to be able to jump into the wider world of Javascript in the near future with things like xPages chances are so will you.

Next time (and hopefully very soon) I will post on the properties and methods that are inherited by ALL Javascript objects from the Object class. These methods and properties are often forgotten which is a pity because they can be quite useful!

Disqus for Domi-No-Yes-Maybe