2 function falseFunc(){ return false }
4 function addLoadEvent(f
) { var old
= window
.onload
5 if (typeof old
!= 'function') window
.onload
= f
6 else { window
.onload = function() { old(); f() }}
9 if (window
.event
) window
.event
.returnValue
= false
10 else e
.preventDefault()
13 // return the time it takes to run a function in millisecs
14 function funcTimer(f
){
15 var then
= new Date().getTime()
17 return (new Date().getTime() - then
)
20 function extend(dest
, src
){
22 for(var k
in src
) dest
[k
] = src
[k
]
25 function niceExtend(dest
, src
){
27 if(src
.html
) { dest
.innerHTML
= src
.html
; delete src
.html
}
28 if(src
.css
) { dest
.className
= src
.css
; delete src
.css
}
31 for(var k
in s
) dest
.setAttribute(k
, s
[k
])
35 var d
= dest
.style
, s
= src
.style
36 for(var k
in s
) d
[k
] = s
[k
]
39 for(var k
in src
) dest
[k
] = src
[k
]
43 function isArray(o
) { if(o
&& typeof o
== 'object' && o
.constructor == Array
) return true; return false }
45 extend( String
.prototype, {
46 include: function(t
) { return this.indexOf(t
) >= 0 ? true : false },
47 trim: function(){ return this.replace(/^\s+|\s+$/g,'') },
48 splitrim: function(t
){ return this.trim().split(new RegExp('\\s*'+t
+'\\s*')) },
49 encodeTag: function() { return encodeURIComponent(this).replace(/%2F/g, '/') },
50 unescHtml: function(){ var i
,e
={'<':'<','>':'>','&':'&','"':'"'},t
=this; for(i
in e
) t
=t
.replace(new RegExp(i
,'g'),e
[i
]); return t
},
51 escHtml: function(){ var i
,e
={'&':'&','<':'<','>':'>','"':'"'},t
=this; for(i
in e
) t
=t
.replace(new RegExp(i
,'g'),e
[i
]); return t
},
52 escRegExp: function(){ return this.replace(/[\\$*+?()=!|,{}\[\]\.^]/g,'\\$&') }
55 Number
.prototype.times = function(f
){
57 while(n
> 0) { f(); n
-- }
60 // make a cheep hash from an array
61 Object
.fromArray = function(src
, value
){
62 if(typeof(value
) == 'undefined') value
= true
63 var r
= {}, l
= src
.length
64 for (var i
= 0; i
< l
; i
++) r
[src
[i
]] = value
68 // copy an arraylike obj to an actual array
69 Array
.from = function(src
){
70 var l
= src
.length
, r
= []
71 for (var i
=0; i
<l
; i
++) r
[i
] = src
[i
]
74 // push/collapse. needs a better name
75 Array
.prototype.pushc = function(o
){
76 if (o
=== null || typeof(o
) == 'undefined') return this
77 else if (o
.each
) o
.each( function(i
){ this.pushc(i
) }.bind(this) )
81 Array
.prototype.each = function(f
){
83 for(var i
= 0; i
< l
; i
++) f(this[i
], i
)
86 Array
.prototype.map = function(f
){
87 var r
= [], l
= this.length
88 for (var i
= 0; i
< l
; i
++) r
.push(f(this[i
], i
))
91 // map/collapse. needs a better name
92 Array
.prototype.mapc = function(f
){
93 var r
= [], l
= this.length
94 for (var i
= 0; i
< l
; i
++) r
.pushc(f(this[i
], i
))
97 Array
.prototype.random = function(){ return this[Math
.floor(Math
.random() * this.length
)] }
98 // array.get(0) is like array[0] except doesn't go out of bounds
99 // Array.prototype.get = function(n){ return this.splice(n,n+1) }
101 //function visible(o){ return o.style.display != 'none' }
102 function toggle(o
){ if (visible(o
)) hide(o
); else show(o
) }
103 function invisible(o
) { o
.style
.visibility
= 'hidden' }
104 function hide(o
){ o
.style
.display
= 'none'; }
105 function show(o
){ o
.style
.display
= ''; o
.style
.visibility
= '' }
106 function remove(){ for(var i
=0, o
; o
=arguments
[i
]; i
++) if(o
&& o
.parentNode
) o
.parentNode
.removeChild(o
) }
107 function create(o
,t
){
108 if (o
== 'text') return document
.createTextNode(t
||'')
110 var e
= document
.createElement(o
)
112 if (typeof t
== 'string') e
.innerHTML
= t
113 else niceExtend(e
, t
)
118 // todo: make this decent
119 function ROW(a
, options
) {
120 options
= options
|| {}
121 var tr
= create('tr')
124 var td
= create('td', options
)
125 if(isArray(o
)) o
.each(function(item
){ td
.appendChild(item
) })
127 if(!o
.nodeName
) o
= create('label', {html
: o
})
130 if(first
) { td
.className
= 'first'; first
= false }
136 function TABLE(a
, options
) {
137 options
= options
|| {}
138 var table
= create('table', options
), tbody
= create('tbody')
139 table
.appendChild(tbody
)
140 a
.each(function(tr
) {
141 tbody
.appendChild(tr
)
147 function isA(o
,klass
){ if(!o
.className
) return false; return new RegExp('\\b'+klass
+'\\b').test(o
.className
) }
148 function addClass(o
,klass
){ if(!isA(o
,klass
)) o
.className
+= ' ' + klass
}
149 function rmClass(o
,klass
){ o
.className
= o
.className
.replace(new RegExp('\\s*\\b'+klass
+'\\b'),'') }
150 function swapClass(o
,klass
,klass2
){ var swap
= isA(o
,klass
) ? [klass
,klass2
] : [klass2
,klass
]; rmClass(o
,swap
[0]); addClass(o
,swap
[1]) }
151 function getStyle(o
,s
) {
152 if (document
.defaultView
&& document
.defaultView
.getComputedStyle
) return document
.defaultView
.getComputedStyle(o
,null).getPropertyValue(s
)
153 else if (o
.currentStyle
) { return o
.currentStyle
[s
.replace(/-([^-])/g, function(a
,b
){return b
.toUpperCase()})] }
156 function getTextStyle(o
){
157 return { fontSize
: getStyle(o
, 'font-size'), fontFamily
: getStyle(o
, 'font-family'), fontWeight
: getStyle(o
, 'font-weight') }
159 function makeTextSize(style
, appendTo
){
160 style
= extend({zborder
: '1px solid red', visibility
: 'hidden', position
: 'absolute', top
: 0, left
: 0}, style
)
161 var div
= create('div', {style
: style
})
162 appendTo
.appendChild(div
)
165 function getTextSize(text
, o
){
166 o
.innerHTML
= text
.escHtml().replace(/ /g
, ' ')
169 function getTextWidth(text
, style
, appendTo
){
170 style
= extend({border
: '1px solid red', zvisibility
: 'hidden', position
: 'absolute', top
: 0, left
: 0}, style
)
171 var div
= create('div', {style
: style
, html
: text
.escHtml().replace(/ /g
, ' ')})
172 appendTo
.appendChild(div
)
173 var w
= div
.offsetWidth
178 function $id(id
){ if (typeof id
== 'string') return document
.getElementById(id
); return id
}
179 function $tags(t
,o
){ o
=o
||document
180 if (!o
.getElementsByTagName
) return []
181 return Array
.from(o
.getElementsByTagName(t
))
183 function $tag(t
,o
,i
){ o
=o
||document
; return o
.getElementsByTagName(t
)[i
||0] }
184 // get all elements of class c starting at object o that are of tag t
185 // o + t are optional, and o can be an array of objects
186 // eg: $c('post', document, 'li')
187 function $c(c
,o
,t
){ o
=o
||document
188 if (!isArray(o
)) o
= [o
]
191 var children
= $tags(t
||'*', e
)
192 children
.each( function(child
){ if(isA(child
,c
)) elements
.push(child
) } )
197 function previousElement(o
) {
198 do o
= o
.previousSibling
; while(o
&& o
.nodeType
!= 1)
202 function nextElement(o
) {
203 do o
= o
.nextSibling
; while(o
&& o
.nodeType
!= 1)
207 // get mouse pointer position
208 function pointerX(e
) { return e
.pageX
|| (e
.clientX
+ (document
.documentElement
.scrollLeft
|| document
.body
.scrollLeft
)) }
209 function pointerY(e
) { return e
.pageY
|| (e
.clientY
+ (document
.documentElement
.scrollTop
|| document
.body
.scrollTop
)) }
212 function windowHeight() { return self
.innerHeight
|| document
.documentElement
.clientHeight
|| document
.body
.clientHeight
|| 0 }
213 function windowWidth() { return self
.innerWidth
|| document
.documentElement
.clientWidth
|| document
.body
.clientWidth
|| 0 }
215 function pageScrollY() { return self
.pageYOffset
|| document
.documentElement
.scrollTop
|| document
.body
.scrollTop
|| 0 }
216 function pageScrollX() { return self
.pageXOffset
|| document
.documentElement
.scrollLeft
|| document
.body
.scrollLeft
|| 0 }
218 // get pixel position of an object
219 function getY(o
){ var y
= 0
220 if (o
.offsetParent
) while (o
.offsetParent
) { y
+= o
.offsetTop
; o
= o
.offsetParent
}
223 function getX(o
){ var x
= 0
224 if (o
.offsetParent
) while (o
.offsetParent
) { x
+= o
.offsetLeft
; o
= o
.offsetParent
}
227 function setX(o
, n
){ o
.style
.left
= n
+ 'px' }
228 function setY(o
, n
){ o
.style
.top
= n
+ 'px' }
230 function getRadioValue(o
) {
231 for(var i
= 0, r
; r
= o
[i
]; i
++) if (r
.checked
&& r
.value
) return r
.value
235 function makeFocusFunc(obj
, selectFrom
){ return function(){
236 var focusRange
= obj
.createTextRange()
238 focusRange
.collapse(false)
242 // focus the caret to end of a form input
243 // should work in all four browsers now! woo
244 function focusTo(obj
, safariSelect
) {
245 var selectFrom
= obj
.value
.length
246 if(obj
.createTextRange
){ //ie + opera
247 setTimeout(makeFocusFunc(obj
, selectFrom
), 10)
248 } else if (obj
.setSelectionRange
){ //ff
250 obj
.setSelectionRange(selectFrom
, selectFrom
)
252 if(safariSelect
) obj
.select()
256 // obj.scrollTop = selectFrom
259 // the following two functions ganked from prototype (http://prototype.conio.net)
260 // (c) 2005 sam stephenson
263 return function() { this.initialize
.apply(this, arguments
) }
265 Function
.prototype.bind = function(o
) {
267 return function() { return __method
.apply(o
, arguments
) }
270 // the following chunk inspired by jquery (http://jquery.com)
271 // by john resig (http://ejohn.org)
273 function $(txt
, context
) { return $ize(find(txt
, context
)) }
279 for(var i
=0, o
; o
=this[i
]; i
++) {
281 if (f
.length
) r
= r
.concat(f
)
283 if (this.stack
) { r
.stack
= this.stack
; r
.stack
.push(this) }
284 else r
.stack
= [this]
287 addClass: function(c
) { return this.each(function(o
){ addClass(o
, c
) }) },
288 rmClass: function(c
) { return this.each(function(o
){ rmClass(o
, c
) }) },
289 end: function(){ return this.stack
.pop() }
293 find = function( t
, context
) {
294 context
= context
|| document
295 var token
= t
.charAt(0)
296 if (token
== '.') return ($c(t
.substr(1), context
) || [])
297 else if (token
== '@' ) {
298 var a
= $tags('*', context
)
300 return a
.mapc( function(o
){
301 if (o
.getAttribute
&& o
.getAttribute(t
) != null) return o
; return null
303 } else if (token
== '#' ) {
304 var o
= $id(t
.substr(1))
307 } else return ($tags(t
, context
) || [])
310 // the following code is a slightly mangled moo.fx (http://moofx.mad4milk.net)
311 // by valerio proietti (http://mad4milk.net)
312 // 10/24/2005 v(1.0.2) under mit-style license
314 fx
.Base = function(){}
315 fx
.Base
.prototype = {
316 setOptions: function(options
) {
317 this.options
= { duration
: 500, onComplete
: '' }
318 extend(this.options
, options
)
321 this.duration
= this.options
.duration
322 this.startTime
= (new Date
).getTime()
323 this.timer
= setInterval (this.step
.bind(this), 13)
326 var time
= (new Date
).getTime()
327 var Tpos
= (time
- this.startTime
) / (this.duration
)
328 if (time
>= this.duration
+this.startTime
) {
330 clearInterval (this.timer
)
332 if (this.options
.onComplete
) setTimeout(this.options
.onComplete
.bind(this), 10)
335 this.now
= ((-Math
.cos(Tpos
*Math
.PI
)/2) + 0.5) * (this.to
-this.from) + this.from
336 //this time-position, sinoidal transition thing is from script.aculo.us
340 custom: function(from, to
) {
341 if (this.timer
!= null) return
346 hide: function() { this.now
= 0; this.increase() },
347 clearTimer: function() { clearInterval(this.timer
); this.timer
= null }
351 fx
.Layout
= Class
.create()
352 fx
.Layout
.prototype = extend(new fx
.Base(), {
353 initialize: function(el
, options
) {
355 this.el
.style
.overflow
= "hidden"
356 this.el
.iniWidth
= this.el
.offsetWidth
357 this.el
.iniHeight
= this.el
.offsetHeight
358 this.setOptions(options
)
362 fx
.Height
= Class
.create()
363 extend(extend(fx
.Height
.prototype, fx
.Layout
.prototype), {
364 increase: function() { this.el
.style
.height
= this.now
+ "px" },
366 if (this.el
.offsetHeight
> 0) this.custom(this.el
.offsetHeight
, 0)
367 else this.custom(0, this.el
.scrollHeight
)
371 fx
.Width
= Class
.create()
372 extend(extend(fx
.Width
.prototype, fx
.Layout
.prototype), {
373 increase: function() { this.el
.style
.width
= this.now
+ "px" },
375 if (this.el
.offsetWidth
> 0) this.custom(this.el
.offsetWidth
, 0)
376 else this.custom(0, this.el
.iniWidth
)
381 fx
.Opacity
= Class
.create()
382 fx
.Opacity
.prototype = extend(new fx
.Base(), {
383 initialize: function(el
, options
) {
387 this.setOptions(options
)
389 increase: function() {
390 if (this.now
== 1) this.now
= 0.9999
391 if (this.now
> 0 && this.el
.style
.visibility
== "hidden") this.el
.style
.visibility
= "visible"
392 if (this.now
== 0) this.el
.style
.visibility
= "hidden"
393 if (window
.ActiveXObject
) this.el
.style
.filter
= "alpha(opacity=" + this.now
*100 + ")"
394 this.el
.style
.opacity
= this.now
397 if (this.now
> 0) this.custom(1, 0)
398 else this.custom(0, 1)
402 //composition effect, calls Opacity and (Width and/or Height) alltogether
403 fx
.FadeSize
= Class
.create()
404 fx
.FadeSize
.prototype = {
405 initialize: function(el
, options
) {
407 this.el
.o
= new fx
.Opacity(el
, options
)
408 if (options
) options
.onComplete
= null
409 this.el
.h
= new fx
.Height(el
, options
)
410 this.el
.w
= new fx
.Width(el
, options
)
414 for (var i
= 0; i
< arguments
.length
; i
++) {
415 if (arguments
[i
] == 'height') this.el
.h
.toggle()
416 if (arguments
[i
] == 'width') this.el
.w
.toggle()
421 for (var i
= 0; i
< arguments
.length
; i
++) {
422 if (arguments
[i
] == 'height') this.el
.h
.hide()
423 if (arguments
[i
] == 'width') this.el
.w
.hide()
426 Ajax
= Class
.create();
428 initialize: function(options
){
429 this.transport
= this.getTransport();
430 this.postBody
= options
.postBody
|| '';
431 this.method
= options
.method
|| 'POST';
432 this.onComplete
= options
.onComplete
|| null;
433 this.onError
= options
.onError
|| null;
434 this.update
= $id(options
.update
) || null;
435 this.request(options
.url
);
437 request: function(url
){
438 this.transport
.open(this.method
, url
, true)
439 this.transport
.onreadystatechange
= this.onStateChange
.bind(this)
440 if (this.method
!= 'GET') {
441 this.transport
.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
442 if (this.transport
.overrideMimeType
) this.transport
.setRequestHeader('Connection', 'close')
444 this.transport
.send(this.postBody
)
446 onStateChange: function(){
447 if (this.transport
.readyState
== 4) {
448 if (this.transport
.status
== 200) {
450 setTimeout(function(){this.onComplete(this.transport
)}.bind(this), 10)
452 setTimeout(function(){this.update
.innerHTML
= this.transport
.responseText
}.bind(this), 10)
455 setTimeout(function(){this.onError(this.transport
)}.bind(this), 10);
457 this.transport
.onreadystatechange
= emptyFunc
460 getTransport: function(){
461 if (window
.ActiveXObject
) return new ActiveXObject('Microsoft.XMLHTTP')
462 else if (window
.XMLHttpRequest
) return new XMLHttpRequest()
470 function forEach(list
, fn
) {
471 for (var i
=0; i
<list
.length
; i
++) fn(list
[i
]);
474 function filter(fn
, list
) {
476 for (var i
=0; i
<list
.length
; i
++)
478 rv
[rv
.length
] = list
[i
];
482 function map(fn
, list
) {
484 for (var i
=0; i
<list
.length
; i
++) rv
[rv
.length
] = fn(list
[i
]);
488 function appendChildNodes(parent
, nodes
) {
489 for (var i
=0; i
<nodes
.length
; i
++) {
492 parent
.appendChild(node
);
493 else if ( (typeof(node
) == 'object') && node
.length
)
494 appendChildNodes(parent
, node
);
496 parent
.appendChild(document
.createTextNode(''+node
));
500 function createDOM(name
, attrs
, nodes
) {
501 var elem
= document
.createElement(name
);
502 if (attrs
) for (k
in attrs
) {
505 if (k
.substring(0, 2) == "on") {
506 if (typeof(v
) == "string") {
511 elem
.setAttribute(k
, v
);
515 // MSIE seems to want this.
516 case 'class': elem
.className
= v
; break;
519 if (nodes
) appendChildNodes(elem
, nodes
);
523 function createDOMFunc(name
) {
524 return function(attrs
) {
526 for (var i
=1; i
<arguments
.length
; i
++)
527 nodes
[nodes
.length
] = arguments
[i
];
528 return createDOM(name
, attrs
, nodes
);
532 // Create $TAG() functions for commonly used HTML tags. (Yes, this is ugly)
534 'A', 'BUTTON', 'BR', 'CANVAS', 'DIV', 'FIELDSET', 'FORM',
535 'H1', 'H2', 'H3', 'HR', 'IMG', 'INPUT', 'LABEL', 'LEGEND', 'LI', 'OL',
536 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SELECT', 'SPAN', 'STRONG', 'TABLE', 'TBODY',
537 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TR', 'TT', 'UL', 'DL', 'DT', 'DD'
538 ], function(n
) { window
['$'+n
] = createDOMFunc(n
); });