this is all my new public_html git repo for CS department at least
[tues-crep.git] / p / delicious-yebyen_files / lib.js
blobf5f2d7b27b7a9efc0456ce9ed20e363407700f37
1 function emptyFunc(){}
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() }}
8 function prevent(e) {
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()
16 f()
17 return (new Date().getTime() - then)
20 function extend(dest, src){
21 if(!src) return dest
22 for(var k in src) dest[k] = src[k]
23 return dest
25 function niceExtend(dest, src){
26 if(!src) return dest
27 if(src.html) { dest.innerHTML = src.html; delete src.html }
28 if(src.css) { dest.className = src.css; delete src.css }
29 if(src.attr) {
30 var s = src.attr
31 for(var k in s) dest.setAttribute(k, s[k])
32 delete src.attr
34 if(src.style) {
35 var d = dest.style, s = src.style
36 for(var k in s) d[k] = s[k]
37 delete src.style
39 for(var k in src) dest[k] = src[k]
40 return dest
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={'&lt;':'<','&gt;':'>','&amp;':'&','&quot;':'"'},t=this; for(i in e) t=t.replace(new RegExp(i,'g'),e[i]); return t },
51 escHtml: function(){ var i,e={'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'},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){
56 var n = this
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
65 return r
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]
72 return r
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) )
78 else this.push(o)
79 return this
81 Array.prototype.each = function(f){
82 var l = this.length
83 for(var i = 0; i < l; i++) f(this[i], i)
84 return this
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))
89 return r
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))
95 return r
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||'')
109 else {
110 var e = document.createElement(o)
111 if (t) {
112 if (typeof t == 'string') e.innerHTML = t
113 else niceExtend(e, t)
115 return e
118 // todo: make this decent
119 function ROW(a, options) {
120 options = options || {}
121 var tr = create('tr')
122 var first = true
123 a.each(function(o) {
124 var td = create('td', options)
125 if(isArray(o)) o.each(function(item){ td.appendChild(item) })
126 else {
127 if(!o.nodeName) o = create('label', {html: o})
128 td.appendChild(o)
130 if(first) { td.className = 'first'; first = false }
131 tr.appendChild(td)
133 return tr
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)
143 return table
146 // styling functions
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)
163 return div
165 function getTextSize(text, o){
166 o.innerHTML = text.escHtml().replace(/ /g, '&nbsp;')
167 return o.offsetWidth
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, '&nbsp;')})
172 appendTo.appendChild(div)
173 var w = div.offsetWidth
174 remove(div)
175 return w
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]
189 var elements = []
190 o.each( function(e){
191 var children = $tags(t||'*', e)
192 children.each( function(child){ if(isA(child,c)) elements.push(child) } )
194 return elements
197 function previousElement(o) {
198 do o = o.previousSibling; while(o && o.nodeType != 1)
199 return o
202 function nextElement(o) {
203 do o = o.nextSibling; while(o && o.nodeType != 1)
204 return o
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)) }
211 // get window size
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 }
221 return y
223 function getX(o){ var x = 0
224 if (o.offsetParent) while (o.offsetParent) { x += o.offsetLeft; o = o.offsetParent }
225 return x
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
232 return false
235 function makeFocusFunc(obj, selectFrom){ return function(){
236 var focusRange = obj.createTextRange()
237 obj.focus()
238 focusRange.collapse(false)
239 focusRange.select()
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
249 obj.select()
250 obj.setSelectionRange(selectFrom, selectFrom)
251 } else { //safari
252 if(safariSelect) obj.select()
253 obj.blur()
254 obj.focus()
256 // obj.scrollTop = selectFrom
259 // the following two functions ganked from prototype (http://prototype.conio.net)
260 // (c) 2005 sam stephenson
261 var Class = {
262 create: function() {
263 return function() { this.initialize.apply(this, arguments) }
265 Function.prototype.bind = function(o) {
266 var __method = this
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)) }
275 function $ize(a) {
276 return extend(a, {
277 $: function(txt) {
278 var r = []
279 for(var i=0, o; o=this[i]; i++) {
280 var f = find(txt, o)
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]
285 return $ize(r)
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)
299 var t = t.substr(1)
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))
305 if (o) return [o]
306 else return []
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
313 var fx = {}
314 fx.Base = function(){}
315 fx.Base.prototype = {
316 setOptions: function(options) {
317 this.options = { duration: 500, onComplete: '' }
318 extend(this.options, options)
320 go: function() {
321 this.duration = this.options.duration
322 this.startTime = (new Date).getTime()
323 this.timer = setInterval (this.step.bind(this), 13)
325 step: function() {
326 var time = (new Date).getTime()
327 var Tpos = (time - this.startTime) / (this.duration)
328 if (time >= this.duration+this.startTime) {
329 this.now = this.to
330 clearInterval (this.timer)
331 this.timer = null
332 if (this.options.onComplete) setTimeout(this.options.onComplete.bind(this), 10)
334 else {
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
338 this.increase()
340 custom: function(from, to) {
341 if (this.timer != null) return
342 this.from = from
343 this.to = to
344 this.go()
346 hide: function() { this.now = 0; this.increase() },
347 clearTimer: function() { clearInterval(this.timer); this.timer = null }
350 //stretchers
351 fx.Layout = Class.create()
352 fx.Layout.prototype = extend(new fx.Base(), {
353 initialize: function(el, options) {
354 this.el = $id(el)
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" },
365 toggle: function() {
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" },
374 toggle: function(){
375 if (this.el.offsetWidth > 0) this.custom(this.el.offsetWidth, 0)
376 else this.custom(0, this.el.iniWidth)
380 //fader
381 fx.Opacity = Class.create()
382 fx.Opacity.prototype = extend(new fx.Base(), {
383 initialize: function(el, options) {
384 this.el = $id(el)
385 this.now = 1
386 this.increase()
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
396 toggle: function() {
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) {
406 this.el = $id(el)
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)
412 toggle: function() {
413 this.el.o.toggle()
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()
419 hide: function(){
420 this.el.o.hide()
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();
427 Ajax.prototype = {
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) {
449 if (this.onComplete)
450 setTimeout(function(){this.onComplete(this.transport)}.bind(this), 10)
451 if (this.update)
452 setTimeout(function(){this.update.innerHTML = this.transport.responseText}.bind(this), 10)
453 } else {
454 if (this.onError)
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()
463 else return false
467 Mini MochiKit
470 function forEach(list, fn) {
471 for (var i=0; i<list.length; i++) fn(list[i]);
474 function filter(fn, list) {
475 var rv = [];
476 for (var i=0; i<list.length; i++)
477 if (fn(list[i]))
478 rv[rv.length] = list[i];
479 return rv;
482 function map(fn, list) {
483 var rv = [];
484 for (var i=0; i<list.length; i++) rv[rv.length] = fn(list[i]);
485 return rv;
488 function appendChildNodes(parent, nodes) {
489 for (var i=0; i<nodes.length; i++) {
490 var node = nodes[i];
491 if (node.nodeType)
492 parent.appendChild(node);
493 else if ( (typeof(node) == 'object') && node.length)
494 appendChildNodes(parent, node);
495 else
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) {
503 var v = attrs[k];
505 if (k.substring(0, 2) == "on") {
506 if (typeof(v) == "string") {
507 v = new Function(v);
509 elem[k] = v;
510 } else {
511 elem.setAttribute(k, v);
514 switch(k) {
515 // MSIE seems to want this.
516 case 'class': elem.className = v; break;
519 if (nodes) appendChildNodes(elem, nodes);
520 return elem;
523 function createDOMFunc(name) {
524 return function(attrs) {
525 var nodes = [];
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)
533 forEach([
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); });