# Thread: Function Library

1. ## Function Library

Similar to my Prototype Function Collection thread: Here are 2 prototype-functions I created.
This thread is the place to share your cross-browser and reusable functions. If your function is a prototype-function, post it in the above link instead. If you don't even know what a prototype-function is, chances are your function isn't one and it should be posted here.

Index

Last edited by Ultimater; 09-18-2006 at 09:06 PM.

2. Because a layer can be inside another layer, a layer's style.left and style.top can both be 0px but the layer can be 500 pixels away from the margin.
These functions return the true offset:
Code:
```function getPositionLeft(This){
var el = This;var pL = 0;
while(el){pL+=el.offsetLeft;el=el.offsetParent;}
return pL
}```
Code:
```function getPositionTop(This){
var el = This;var pT = 0;
while(el){pT+=el.offsetTop;el=el.offsetParent;}
return pT
}```
Last edited by Ultimater; 06-07-2005 at 10:59 AM.

3. Moving rainbow happiness...

4. Artarmon Zealand
Join Date
Feb 2005
Location
USA
Posts
1,534
Compare Arrays

In JavaScript, if you try to compare two Arrays it will always return false, even this simple comparison: ([3]==[3]). So to see if two arrays are actually identical you can use this function, I could have made it accept more than two arrays but thought it was nice and simple as it was. It can take multi-dimensional arrays.

Code:
```function compareArrays(a, b){
if (a.constructor!=Array || b.constructor!=Array || a.length!=b.length) return false;
var L=a.length,i;
while (i<L) {
if (a[i]==b[i] || compareArrays(a[i],b[i])) i++;
else return false;
}
return true;
}```

5. The function isTopWindow() returns either true or false and accepts no arguments.
Code:
```function isTopWindow(){
var isTop=false
if(typeof top.stringToCheck!="undefined")
var tmp1=top.stringToCheck
if(typeof stringToCheck!="undefined")
var tmp2=stringToCheck
top.stringToCheck="tmp"
stringToCheck="3.1415926535897932384626433832795028841971693993751058209749445923"
if(top.stringToCheck==stringToCheck)
isTop=true
if(typeof tmp1!="undefined")
top.stringToCheck=tmp1
if(typeof tmp2!="undefined")
stringToCheck=tmp2
return isTop
}```
edit:
Forget it, it seems this function is the same as:
Code:
```function isTopWindow(){
return (top==window)
}```
Last edited by Ultimater; 08-17-2005 at 07:42 AM.

6. Artarmon Zealand
Join Date
Feb 2005
Location
USA
Posts
1,534
queryObject()

Send it an argument as a URL string or it will presume the windows location.
Builds an object of the query string:

Code:
```function queryObject(){
var s=arguments[0] || window.location.href, m=s.indexOf('?')+1, i=0, t;
this.toString=function(){return s}
if (m) {
m=s.substring(m,s.length).split("&");
while (i<m.length)
this[m[i].substring(0,t=m[i].indexOf("="))]=m[i].substring(t+1,m[i++].length);
}
}```
Example:
Code:
```var query=new queryObject("http://www.google.com.au/search?hl=en&q=lemurs&btnG=Search&meta=");

for (var i in query) alert(i+" = "+query[i]);```
Last edited by BigMoosie; 08-27-2005 at 12:17 AM.

7. ...
Last edited by Ultimater; 09-23-2005 at 06:04 PM.

The defining code is in royalblue:
Code:
```<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr" lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title></title>
<script type="text/javascript"><!--
//--></script>
<script type="text/JavaScript"><!--
function blah1(){
var e=document.getElementById("el1");
if(!e)alert("el1 cound\'t be found, please wait until the onload event")
}
function blah2(){
var e=document.getElementById("el2");
if(!e)alert("el2 cound\'t be found, please wait until the onload event")
}

blah1()
blah2()
//--></script>
<body>
<p>
<input type="text" value="valueof el1" id="el1">
<input type="text" value="valueof el2" id="el2">
</body>
</html>```
note: In the case of multiple external JS files that all will need to append to the onload event and you don't want to define the addFunctionToOnload function twice, use this code in each JS extneral file to define the function:
Code:
```if(typeof onloadString=="undefined"){
}```
It checks to see if it is already defined, then if it is undefined, then defines it. Then simply proceed in your JS file with the addFunctionToOnload defined as usual. Do make sure to put the defining code at the very top of your JS file so no futher code in it will require it's usage prior to it's defination.
Last edited by Ultimater; 10-02-2005 at 11:36 AM.

9. I don't normally revive threads like this, but this time I figured, why not? I've found myself using this a couple of times already - it's a function to get the contents of an XML element and convert it to text. Like innerHTML, only using the DOM and without the entities. Found myself needing this for AJAX type applications, when it's neccessary to send back the contents of an element (all of them) to the server without always knowing just what would be there.

It takes as an argument the node you want Text-isized

Code:
```function getXML(aNode)
{
var out = '';
if(aNode.nodeType == Node.ELEMENT_NODE)
{
out = '<'+aNode.nodeName;
if(aNode.hasAttributes())
{
var atts = aNode.attributes;
for(var x=0;x<atts.length;x++)
{
out +=' '+atts[x].nodeName+'="'+atts[x].nodeValue+'"';
}
}

if(aNode.hasChildNodes())
{
out += '>';
var kids = aNode.childNodes;
for(var x=0;x<kids.length;x++)
{
switch(kids[x].nodeType)
{
case Node.ELEMENT_NODE:
out += getXML(kids[x]);
break;
case Node.TEXT_NODE:
out += kids[x].nodeValue;
break;
case Node.COMMENT_NODE:
out += '<!--'+kids[x].nodeValue+'-->';
break;
case Node.CDATA_SECTION_NODE:
out += '<'+'![CDATA['+kids[x].nodeValue+']'+']>';
break;
}
}
out += '</'+aNode.nodeName+'>';
} else {
out += '/>';
}
}
return out;
}```
It's been a while since I've done much Javascript (well, until lately at least) but it's been working out fine for me.

10. Registered User
Join Date
Nov 2002
Location
England
Posts
693

## Meh, spent some time on this so thought I'd share

Someone wanted to change the order of dynamically assigned event handlers and as seen as there is no guarantee of which fires first I set about writing a program that would handle it, however I got no response so I thought I'd see if anybody else has a use for it.

It's still a little off of a finished product but I can see it has its' uses. There is no support for arguments in the functions that are called as of yet and no support for capturing and bubbling but what the hell:

Check the bottom of the program for usage... I might add support for event capturing and bubbling if anybody is interested.

Code:
```<div id="text">

Some text
<br />
Goes here

</div>

<script>
var cache = document.getElementById;
var isIE = 0;

if(navigator.appName == "Microsoft Internet Explorer"){
isIE=1;
}

document.getElementById = function(id){ // Override the document.getElementById function to add the addEventListener function

this.getId = cache; // Copy the native document.getElementById into this objects getId variable
this.domObject = this.getId(id); // Assign this.domObject to the object that you are getting by id

this.domObject.addListenerObject = function(){ // Add the addListenerObject method to the document.getElementById method

return new listenerObject(id);

}

return this.domObject;
}

function listenerObject(id){

this.id = id;
this.listeners = new Array(); // Array of event listeners
this.eventHandler = myEventHandler;
this.add = addListener; // Method to add an event listener
this.remove = removeListener; // Method to remove an event listener
this.push = pushListener; // Method to increase the listeners precedence
this.shift = shiftListener; // Method to decrease listeners precedence
this.move = moveListener; // Method to move a listener to a specific index
this.swap = switchListeners; // Method to switch the position of two listeners
this.list = list; // Method to retrieve the event handlers i array format
this.eventHandler = myEventHandler // Event Handling method

return this;
}

function addListener(type, func, bool, index){ // Method for adding event listeners

with(this);

if(isIE){

type = "on" + type; // Append on to the event type, IE handles events differently to mozilla

}

if(!this.listeners[type]){  // If there hasn't been an array defined for the event type
this.listeners[type] = new Array(); // Create one

if(!index){ // If the index argument has been ommited
index = this.listeners[type].length; // add the listener object to the end
}

this.listeners[type][index] = func; // Add an event listener to the events list

var thisEventListener = this; // Reference this so the anonymous function can access it

var eventHandler = function(ev){ // Capture the events

thisEventListener.eventHandler(ev.type.toString(), thisEventListener.listeners); // Pass events to the event handler

}

if(isIE){

document.getElementById(this.id).attachEvent(type, eventHandler); // Add the event listener to the element

}else{

document.getElementById(this.id).addEventListener(type, eventHandler, bool); // Add the event listener to the element

}

}else{

if(!index){ // If the index argument has been ommited
index = this.listeners[type].length; // add the listener object to the end
}

this.listeners[type][index] = func; // Add an event listener to the events list

}

return this;
}

function removeListener(ev, func){ // Method for removing an event listener

with(this);

if(isIE){

ev = "on" + ev;

}

var tempArray = new Array(); // Create a temporary array to store the listeners

for(var i=0; i<this.listeners[ev].length; i++){ // Iterate through the listeners

if(this.listeners[ev][i] != func){

tempArray[tempArray.length] = this.listeners[ev][i]; // Store the data from the listener array in a temporary array (I had to do it this way as I was getting unexpected results with splice)

}

}

this.listeners[ev] = tempArray; // Update the listeners array

return this;

}

function pushListener(ev, func){ // Function still in progress

with(this);

if(isIE){

ev = "on" + ev;

}

var index;
var tempValue;

if(this.listeners[ev][0] != func){ // Make sure we aren't trying to push the listener off of the end of the array

for(var i=this.listeners[ev].length-1; i>0; i--){ // Iterate through the array

if(this.listeners[ev][i] == func){ // If we have found the function

index = i; // Make a note of it's index

}

}

tempValue = this.listeners[ev][index-1]; // Store the listener to be shifted

this.listeners[ev][index-1] = this.listeners[ev][index]; // Switch
this.listeners[ev][index] = tempValue;                   // the values at the index

return this;

}

}

function shiftListener(ev, func){ // Function to decrease the listeners index

with(this);

if(isIE){

ev = "on" + ev;

}

var tempArray = new Array(); // Define a temporary array to store the new listeners array

if(this.listeners[ev][this.listeners[ev].length-1] != func){ // Make sure we aren't trying to shift the listener off of the end of the array

for(var i=0; i<this.listeners[ev].length; i++){ // Iterate through the array

if(this.listeners[ev][i] == func){ // If we have found the function

tempArray[i] = this.listeners[ev][i+1]; // Switch
tempArray[i+1] = this.listeners[ev][i]; // the listeners
i++;

}else{

tempArray[i] = this.listeners[ev][i];

}

}

this.listeners[ev] = tempArray; // Overwrite the listeners array

return this;

}

}

function moveListener(ev, func, index){ // Method to move a listener to a specific location

with(this);

if(isIE){

ev = "on" + ev;

}

if(index > -1 && index < this.listeners[ev].length){ // Don't allow listeners to be moved from the extremeties of the array

var functionIndex;
var found = false;
var tempArray = new Array();

for(var i=0; i<this.listeners[ev].length; i++){ // Iterate through the array

if(!found){ // If we have not yet found the listener index in the listeners array

if(this.listeners[ev][i] == func){ // Check to see if we are at the index of the listener

found = true; // Set the flag telling the loop that we have found the funtion's index
// Notice how we ignore the listener, it does not get copied

}else{

tempArray[i] = this.listeners[ev][i]; // Copy the function into the temporary array

}

}else{

tempArray[i-1] = this.listeners[ev][i]; // Shift the rest of the listeners up in the array

}

}

var finalArray = new Array(); // Define an array to store our final listeners list
var isIndex = false; // Flag that determines if we are at the desired index

for(var k=0; k<this.listeners[ev].length-1; k++){ // Iterate through the array

if(!isIndex){ // If we have not yet passed the listener index

if(k == index){ // Check to see if we are at the index of the listener

isIndex = true; // Set the flag telling the loop that we have passed the index
finalArray[k] = func; // Add the function to the array at the index point
finalArray[k+1] = tempArray[k]; // Shift the next listener up

}else{

finalArray[k] = tempArray[k]; // Copy the listener into the new array

}

}else{

finalArray[k+1] = tempArray[k]; // Shift the rest of the listeners up

}

}

this.listeners[ev] = finalArray; // Overwrite the listeners array

return this;

}

}

function myEventHandler(ev, listeners){

if(isIE){

ev = "on" + ev;

}

for(var i=0; i<listeners[ev].length; i++){

eval(listeners[ev][i] + "()");

}

}

function switchListeners(ev, func1, func2){

with(this);

if(isIE){

ev = "on" + ev;

}

var index1;
var index2;

for(var i=0; i<this.listeners[ev].length; i++){

if(this.listeners[ev][i] == func1){

index1 = i;

}

if(this.listeners[ev][i] == func2){

index2 = i;

}

}

this.listeners[ev][index2] = func1;
this.listeners[ev][index1] = func2;

return this;

}

function list(type){

with(this);

if(isIE){

type = "on" + type; // Append on to the event type, IE handles events differently to mozilla

}

return this.listeners[type]; // return the listeners array

}

function click1(){
}

function click2(){
}

function click3(){
}

function click4(){
}

function click5(){
}

var myListener = document.getElementById("text").addListenerObject();

myListener.swap("click","click2","click5");

myListener.remove("click","click1");

myListener.push("click","click4");

myListener.shift("click","click3");

myListener.move("click","click2", 1);

</script>```

11. Registered User
Join Date
Mar 2003
Posts
575

## Function to multiply numbers in base ten

function mul() {
// multiplies two numbers given in string form (in base ten)
// decimals OK, negative numbers and scientific notation not OK
// returns answer as a string
if (arguments.length!=2) return false;
var figsi=new Array(); var figsw=new Array();
var fdp=false; var places=0; var point='.';
// if your country writes decimals with a comma
// then uncomment the following line:
// point=',';
var wa=0; var ts=''; var posn=0; var tc='';
for (wa=0; wa<2; wa++) {
fdp=false; ts=arguments[wa]; figsi[wa]=new Array();
if (typeof(ts)!='string') return false;
if (ts=='' || ts==point) return false;
for (posn=0; posn<ts.length; posn++) {
tc=ts.charAt(posn);
if (tc>='0' && tc<='9') {
figsi[wa][figsi[wa].length]=tc-0; if (fdp) places++; }
else if (tc==point && fdp==false) fdp=true;
else return false; }
figsw[wa]=figsi[wa].reverse();}
var i=0; var j=0; var ansa=new Array();
for (i=0; i<=figsw[0].length+figsw[1].length; i++) ansa[i]=0;
for (i=0; i<figsw[0].length; i++)
for (j=0; j<figsw[1].length; j++)
ansa[i+j]+=(figsw[0][i]*figsw[1][j]);
// now meld
for (i=0; i<ansa.length-1; i++) {
ansa[i+1]+=Math.round((ansa[i]-(ansa[i]%10))/10); ansa[i]%=10; }
ansa[places]+=point;
var ans=ansa.reverse().join('');
// clean up
while (ans.charAt(0)=='0' && ans.length>1 && ans.charAt(1)!='.')
ans=ans.substring(1,ans.length);
fdp=false;
while (fdp==false && (ans.charAt(ans.length-1)=='0' ||
ans.charAt(ans.length-1)==point)) {
if (ans.charAt(ans.length-1)==point) fdp=true;
ans=ans.substring(0,ans.length-1); }
return ans; }

12. Registered User
Join Date
Mar 2003
Posts
575

## Easter computus

Code:
```function easter(year) {

// function to calculate the date of Easter Sunday
// as given by the Gregorian calendar reform of 1582
// Note: this function returns a Date object
// with its time set to NOON local time

// function by Juuitchan

if (typeof(year)!='number') return false;
if (year%1!=0) return false;
if (year<1582) return false;

var ccpass=Math.floor(year/100)-15;
// Century changes since the calendar reform

var gsnum=year%19;
// Used in a table lookup

// Calculate the seed for the table
var seed=22; // it was initialized to this in 1582
seed+=(ccpass-Math.ceil(ccpass/4)); // Solar Equation
seed-=(8*Math.floor(ccpass/25)+Math.floor((ccpass%25)/3));
// the line above is the Lunar Equation
seed%=30; // seed is restricted to range 0-29

var moontable=new Array();
var wheel=seed; var finger=0; var p29=-1; var p28=-1;
for (finger=0; finger<19; finger++) {
moontable[finger]=wheel;
if (wheel==29) p29=finger; // gets special treatment
if (wheel==28) p28=finger; // might get special treatment
wheel-=11; if (wheel<0) wheel+=30; }
if (p29>=0 && p28>=0) moontable[p28]=27;
if (p29>=0) moontable[p29]=28;

var pfmoffset=moontable[gsnum];
// Paschal Full Moon is this many days past March 21

var work=new Date(year,3-1,21+pfmoffset,12,0,0);
// work is set to date of Paschal Full Moon
// (time is set to noon to avoid a problem
// with JS Date objects near midnight)

work.setDate(work.getDate()+(7-work.getDay()));
// this sets the date to the following Sunday

return work;

// Ash Wednesday = Easter Sunday - 46 days
// (Sundays are not counted in the 40 days of Lent)
// Palm Sunday = Easter Sunday - 7 days
// Good Friday = Easter Sunday - 2 days
// Pentecost = Easter Sunday + 49 days

}```
Last edited by Juuitchan; 10-26-2006 at 03:09 AM.

13. Ever want to add a StyleSheet to your document using the full CSS without having to use a load of addRules and insertRules?
Although this is non-standard it is a pretty niffy approach that I'm sure can be expanded upon.

The addNewStyleSheetByFullCSS function accepts one argument, the full CSS to be used within the styleSheet, and the new StyleSheet is appended to the DOM Tree automatically.
Code:
```<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html dir="ltr" lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<title></title>
<script type="text/javascript">
var newStyleSheet=document.createElement("style");
newStyleSheet.type="text/css";
h[0].appendChild(newStyleSheet);
try{
newStyleSheet.styleSheet.cssText=innerCSS;
}catch(e){try{
newStyleSheet.appendChild(document.createTextNode(innerCSS));
newStyleSheet.innerHTML=innerCSS;//Just in case it helps some browser out there
}catch(e){}}

}
</script>
<script type="text/javascript">
var fullCSS=''+
'\nbody { margin: 20px 10px 10px 10px; padding: 0; background-color: #FFFFFF; color: #000000;'+
'\nfont-family:serif; font-size:medium;'+
'\n}'+
'\ntr { vertical-align: top;  }'+
'\n.fieldframe { background-color: #F1F2F6; color: #929BAB; border: 1px solid #929BAB; padding: 5px }'+
'\n.buttonframe { background-color: #F1F2F6; color: #929BAB; margin-top: 10px; border: 1px solid #929BAB; padding: 5px }'+
'\n.field { background-color: #E3E4EA; color: #000000; border: 1px solid #929BAB;}'+
'\n.label { background-color: #E3E4EA; color: #000000; font-weight: bold; vertical-align: top;'+
'\nwidth:180px;border:1px solid #929BAB;'+
'\n}'+
'\n.input { background-color: #F1F2F6; color: #5D636E; vertical-align: top;'+
'\nwidth: 80px; border:1px solid #929BAB; padding:2px;'+
'\n}'+
'\n.input input{'+
'\nbackground-color: white; color: black; border:0 none;'+
'\n}'+
'\n.button { background-color: #E3E4EA; color: #5D636E; border: 1px solid #929BAB; margin: 1px;  }'+
'\n.button:hover { background-color: #F4F4F6; color: #5D636E; border: 1px solid #929BAB; margin: 1px;  }'+
'\ndiv.field{'+
'\n}\n'

</script>
<body>
<div class="label">I am styling!</div>
</body>
</html>```
Tested in IE, Firefox, and Opera.
Last edited by Ultimater; 09-19-2006 at 03:25 PM.

14. Ultimater,

I was looking to post this function over at JavaScript Source and was wondering why you didn't just add the two scripts together? Are you just trying to show the actual function separate?

15. Correct, just keeping the function separate and the example usage in another SCRIPT tag. -- Just my way of organizing. Feel free to concentrate the two as you fancy.

Hey, for the Contributor URL can you place a link to http://invisionfree.com/forums/Black_Forest_Boards/ this time instead of to http://ultimiacian.tripod.com/? Thanks. You can leave the other script's Contributor URLs to the old link.
Last edited by Ultimater; 09-19-2006 at 03:41 PM.

##### Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

"

"

## X vBulletin 4.2.2 Debug Information

• Page Generation 0.14607 seconds
• Memory Usage 3,097KB
• Queries Executed 15 (?)
Template Usage (36):
• (13)bbcode_code
• (1)footer
• (1)forumjump
• (1)forumrules
• (1)gobutton
• (15)memberaction_dropdown
• (1)navbar
• (1)navbar_moderation
• (1)navbar_noticebit
• (1)navbar_tabs
• (2)option
• (1)pagenav
• (1)pagenav_curpage
• (15)postbit
• (15)postbit_onlinestatus
• (15)postbit_wrapper
• (1)spacer_close
• (1)spacer_open
• (1)tagbit_wrapper

Phrase Groups Available (6):
• global
• inlinemod
• postbit
• posting
• reputationlevel
Included Files (26):
• ./global.php
• ./includes/class_bootstrap.php
• ./includes/init.php
• ./includes/class_core.php
• ./includes/config.php
• ./includes/functions.php
• ./includes/class_friendly_url.php
• ./includes/class_hook.php
• ./includes/class_bootstrap_framework.php
• ./vb/vb.php
• ./vb/phrase.php
• ./includes/functions_calendar.php
• ./includes/functions_bigthree.php
• ./includes/class_postbit.php
• ./includes/class_bbcode.php
• ./includes/functions_reputation.php
• ./includes/functions_notice.php
• ./packages/vbattach/attach.php
• ./vb/types.php
• ./vb/cache.php
• ./vb/cache/db.php
• ./vb/cache/observer/db.php
• ./vb/cache/observer.php

Hooks Called (74):
• init_startup
• friendlyurl_resolve_class
• init_startup_session_setup_start
• database_pre_fetch_array
• database_post_fetch_array
• init_startup_session_setup_complete
• global_bootstrap_init_start
• global_bootstrap_init_complete
• cache_permissions
• fetch_postinfo_query
• fetch_postinfo
• fetch_foruminfo
• global_state_check
• global_bootstrap_complete
• global_start
• style_fetch
• global_setup_complete
• strip_bbcode
• friendlyurl_clean_fragment
• friendlyurl_geturl
• forumjump
• cache_templates
• cache_templates_process
• template_register_var
• template_render_output
• fetch_template_start
• fetch_template_complete
• parse_templates
• notices_check_start
• notices_noticebit
• process_templates_complete
• friendlyurl_redirect_canonical
• bbcode_fetch_tags
• bbcode_create
• postbit_factory
• postbit_display_start
• bbcode_parse_start
• postbit_imicons
• bbcode_parse_complete_precache
• bbcode_parse_complete
• postbit_display_complete
• memberaction_dropdown
• pagenav_page
• pagenav_complete
• tag_fetchbit_complete
• forumrules
• navbits
• navbits_complete