]> Joshua Wise's Git repositories - patchfork.git/blame - std/toolkit.js
Add patch support notice.
[patchfork.git] / std / toolkit.js
CommitLineData
964dd0bc
JW
1/*
2 Pitchfork Music Player Daemon Client
3 Copyright (C) 2007 Roger Bystrøm
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17*/
18
19
20/**
21 * Why reinvent the wheel when you can make a hexadecagon instead -- Me
22 *
23 * -- OR --
24 *
25 * Reinventing the wheel to run myself over -- FOB
26 */
27
28var moveables = new Array();
29var move_idx = -1;
30
31var sliders = new Array();
32var slider_idx = -1;
33
34var overlay = new Array();
35var overlay_adjust = 100; // px
36var open_overlay_idx = -1;
37var overlay_time = 5;
38var overlay_hide_on_resize = true; // hide content on resize?
39
40var xpath_queries;
41
42function debug(str, force) {
43
44 /* switch && false to true on release */
45 if(typeof(force)=="undefined" && true) {
46 return;
47 }
48
49 var d = document.getElementById('debugbox');
50 if(d==null) {
51 d = create_node("div");
52 d.id = "debugbox";
53 document.body.appendChild(d);
54 }
55
56 var n = create_node("p", null, str);
57 n.style.padding = "0px";
58 n.style.margin = "0px";
59 d.appendChild(n);
60 try {
61 scrollIntoView(d.lastChild);
62 }
63 catch (e) {}
64}
65
66function get_time() {
67 var d = new Date();
68 return d.getTime();
69}
70
71/* evaluates json response and returns object containing information */
72function evaluate_json(txt) {
73 var obj = new Object();
74
75 /* limit context */
76 obj = eval(txt, obj);
77 return obj;
78}
79
80function browser_is_opera() {
81 return window.opera?true:false;
82}
83function browser_is_konqueror() {
84 if(navigator.vendor=="KDE")
85 return true;
86 return false;
87}
88
89// replaces rem with ins
90function replace_node(ins, rem) {
91 return rem.parentNode.replaceChild(ins, rem);
92}
93// removes this nodes children
94function remove_children(what) {
95 if(!what.hasChildNodes)
96 return null;
97 var buf = create_fragment();
98 while(what.hasChildNodes())
99 buf.appendChild(what.removeChild(what.firstChild));
100 return buf;
101}
102
103function remove_node(what) {
104 if(what)
105 return what.parentNode.removeChild(what);
106 return null;
107}
108
109function remove_children_after(container, after) {
110 /* removing elements outside list */
111 var c = container.childNodes;
112 if(after>=c.length)
113 return;
114 var node = c[parseInt(after)];
115 while(node) {
116 var t = node.nextSibling;
117 container.removeChild(node);
118 node = t;
119 }
120}
121
122/* insert 'node' first on 'at' */
123function insert_first(node, at) {
124 if(at.hasChildNodes())
125 at.insertBefore(node, at.firstChild);
126 else at.appendChild(node);
127}
128
129function insert_before(what, before) {
130 before.parentNode.insertBefore(what, before);
131}
132
133function insert_after(what, after) {
134 var p = after.parentNode;
135 if(after.nextSibling)
136 p.insertBefore(what, after.nextSibling);
137 else p.appendChild(what);
138}
139
140function get_node_content(node) {
141
142 if(node.hasChildNodes && node.hasChildNodes())
143 node = node.childNodes[0];
144
145 if(node.nodeValue) {
146 return node.nodeValue;
147 }
148 else if(node.textContent) {
149 return node.textContent;
150 }
151 else if(node.textValue) {
152 return node.textValue;
153 }
154 else if(node.text) {
155 return node.text;
156 }
157 else {
158 return node;
159 }
160}
161
162/*Returns content of first node with specified tag
163 */
164function get_tag(item, tag) {
165 if(item.getElementsByTagName) {
166 var tmp = item.getElementsByTagName(tag)[0];
167 if(tmp!=null)
168 return get_node_content(tmp);
169 }
170 return null;
171}
172
173function get_absolute_top(node) {
174 var height = 0;
175 while(node.offsetParent != null) {
176 node = node.offsetParent;
177 if(node.offsetTop)
178 height += node.offsetTop;
179 }
180 return height;
181}
182
183// returns the absolute distance to start of page
184function get_absolute_height(node) {
185 return node.offsetTop + get_absolute_top(node);
186}
187
188function get_absolute_left(node) {
189 var left = node.offsetLeft;
190 while(node.offsetParent != null) {
191 node = node.offsetParent;
192 if(node.offsetLeft) {
193 left += node.offsetLeft;
194 }
195 }
196 return left;
197}
198
199function EventListener(to, type, func) {
200 this.to = to;
201 this.type = type;
202 this.func = func;
203}
204
205EventListener.prototype.register = function() {
206 if( this.to.addEventListener ) {
207 this.to.addEventListener(this.type, this.func, false);
208 }
209 else if(this.to.attachEvent) {
210 this.to.attachEvent(this.type, this.func);
211 }
212 else debug("unable to add listener");
213}
214
215EventListener.prototype.unregister = function() {
216 if(this.to.removeEventListener) {
217 this.to.removeEventListener(this.type, this.func, false);
218 }
219 else if(to.detachEvent) {
220 this.to.detachEvent(this.type, this.func);
221 }
222 else debug("unable to detach event");
223}
224
225/**
226 * Creates a new event listener, register it and return it
227 */
228function add_listener(to, event_s, func) {
229 var el = new EventListener(to, event_s,func);
230 el.register();
231 return el;
232}
233
234function remove_listener(to, event_s, func) {
235 if(to.removeEventListener) {
236 to.removeEventListener(event_s, func, false);
237 }
238 else if(to.detachEvent) {
239 to.detachEvent(event_s, func);
240 }
241 else debug("unable to detach event");
242}
243
244/* Get's first real child (e.g. one with an id
245 * from the element specified */
246function get_first_real_child(from) {
247 from = from.firstChild;
248 while(from.nextSibling) {
249 if(from.id)
250 return from;
251 from = from.nextSibling;
252 }
253 return null;
254}
255
256function get_last_real_child(from) {
257 var children = from.childNodes;
258 for(var i=children.length-1; i>=0; i++) {
259 if(children[i].id)
260 return children[i];
261 }
262 return null;
263}
264
265
266/*
267 * Operations for creating elements
268 */
269// creates node of type type with id id and content content
270// returns the node created
271function create_node(type, id, content) {
272 var node = document.createElement(type);
273 if(id&&id!=null) {
274 node.id = id;
275 node.name = id;
276 }
277 if(content&&content!=null) {
278 if(document.createTextNode)
279 node.appendChild(document.createTextNode(content));
280 else
281 node.innerHTML = content;
282 }
283 return node;
284}
285
286function create_txt(txt) {
287 return document.createTextNode(txt);
288}
289
290function create_fragment() {
291 return document.createDocumentFragment();
292}
293
294// creates an empty table row with id and
295// returns it
296function create_tr(id) {
297 return create_node("tr", id, null);
298}
299
300function create_param(name, value) {
301 var p = create_node("param");
302 p.name = name;
303 p.value = value;
304 return p;
305}
306
307// add a new TD with id id and content to a tr
308function add_td(tr, content, id) {
309 var n = create_node("td", id, content);
310 tr.appendChild(n);
311 return n;
312}
313
314function add_li(list, content, id) {
315 var n = create_node("li", id, content);
316 list.appendChild(n);
317 return n;
318}
319
320function add_txt(node, txt) {
321 node.appendChild(create_txt(txt));
322}
323
324function apply_border_style_to_children(who, style) {
325 var c = who.childNodes;
326 for(var i=0; i<c.length; i++) {
327 if(c[i].style) {
328 c[i].style.borderBottom = style;
329 c[i].style.borderTop = style;
330 }
331 }
332}
333
334function MoveObject(container, on_change, multi_move) {
335 // container, moving, element that's moving, initial position, element that's simulating movement,
336 // function to call if something has been moved and a variable to know if mouse key is down,
337 // if we should be able to move thigns around, optional doubleclick handler, optional selection change handler,
338 // if we *think* something is selected or not
339 this.container = container; // container for the elements
340 this.on_change = on_change; // function to call if something has been moved
341 this.moving = false; // if we are moving something
342 this.moving_elem = null; // the elemnt that is moving
343 this.moving_init_pos = null; // initial position of moving element (pagex,pagey)
344 this.moving_clone = null; // the clone that is actually moving
345 /* this is for interaction between mousemoving and mousedown */
346 this.possible_move_node = null; // the node the user might try moving
347 this.can_move = true; // if we are allowed to move anything at all
348 this.double_click_cb = null; // function to call on doubleclick
349 this.selection_change_cb = null;// function to call when the selection changes (with true or false
350 this.select_if_no_move = false; // if nothing has moved the node should be selected
351 this.multi_move = multi_move; // if allow for multiple move we won't do any of the moving and this function should
352 // return text that should be placed on the "moving" object
353 this.something_selected = false; // whether something currently is selected
354}
355
356/* visual effects 0> moving */
357
358function setup_node_move(container, on_change, multi_move) {
359 var id = moveables.length;
360 add_listener(container, "mousedown", mouse_down_node);
361 add_listener(container, "mouseup", mouse_up_node);
362 add_listener(container, "mousemove", move_node);
363 container.setAttribute("move_id", id);
364 if(!multi_move)
365 multi_move = false;
366
367 moveables[id] = new MoveObject(container, on_change, multi_move);
368 return id;
369}
370
371function add_move_doubleclick(id, func) {
372 moveables[id].double_click_cb = func;
373}
374
375function set_moveable(id, moveable) {
376 moveables[id].can_move = moveable;
377}
378
379function set_selection_change_handler(id, func) {
380 moveables[id].selection_change_cb = func;
381}
382
383/* NodeSelection _ find out if a node is selected */
384function is_node_selected(node) {
385 return node.hasAttribute&&node.hasAttribute("selected");
386}
387
388/* NodeSelection - set whether a node is selectable or not */
389function set_node_selectable(node, val) {
390 if(val&&node.hasAttribute&&node.hasAttribute("noselect")) {
391 node.removeAttribute("noselect");
392 }
393 else node.setAttribute("noselect", "true");
394}
395
396/* NodeSelection - select node */
397function select_node(node) {
398 if(node.hasAttribute("noselect"))
399 return false;
400 if(node.hasAttribute("selected"))
401 return true;
402
403 node.setAttribute("selected", "1");
404 return true;
405}
406
407function unselect_node(node) {
408 if(node.hasAttribute("selected")) {
409 node.removeAttribute("selected");
410 }
411}
412
413function unselect_all_nodes(container) {
414 if(xpath_ok()) {
415 var nodes = xpath_query(container, ".//.[@selected]");
416 var n;
417 var elems = new Array();
418 while((n = nodes.iterateNext())) {
419 elems[elems.length] = n;
420 }
421 for(var i=0; i<elems.length; i++)
422 unselect_node(elems[i]);
423 }
424 else {
425 var node = container.childNodes
426 if(!node)
427 return;
428 for(var i=0; i < node.length; i++) {
429 if(node[i].hasAttribute("selected"))
430 unselect_node(node[i]);
431 }
432 }
433}
434
435/* will check if anything is selected */
436function selection_anything_selected(container) {
437 if(xpath_ok()) {
438 var x = xpath_query(container, ".//.[@selected]", XPathResult.ANY_UNORDERED_NODE_TYPE);
439 return x.singleNodeValue?true:false;
440 }
441 else {
442 var nodes = container.childNodes
443 for(var i=0; i < nodes.length; i++) {
444 if(node.hasAttribute("selected"))
445 return true;
446 }
447 return false;
448 }
449
450}
451
452/* Will find the first selected node and set attribute needle
453 * in needle if it is found before it returns
454 */
455function find_first_selected_node(container, needle) {
456 if(xpath_ok()&&!needle) {
457 var x = xpath_query(container, ".//.[@selected]", XPathResult.FIRST_ORDERED_NODE_TYPE);
458 return x.singleNodeValue;
459 }
460 else {
461 var nodes = container.childNodes
462 var length = nodes.length;
463 for(var i=0; i < length; i++) {
464 var node = nodes[i];
465 if(needle&&needle==node)
466 needle.setAttribute("needle", "found");
467 if(node.hasAttribute&&node.hasAttribute("selected"))
468 return node;
469 }
470 return null;
471 }
472}
473
474/* selects all nodes between the two */
475function select_range(from, to) {
476 var node = from;
477 select_node(from);
478 while(node != null && node!=to) {
479 node = node.nextSibling;
480 select_node(node);
481 }
482}
483
484/* will return an array of selected elements attribute in container */
485function get_attribute_from_selected_elems(container, attribute) {
486 var c = container.childNodes;
487 var ret = new Array();
488 var l = c.length;
489 for(var i=0; i<l; i++) {
490 if(is_node_selected(c[i]) && c[i].hasAttribute(attribute)) {
491 ret[ret.length] = c[i].getAttribute(attribute);
492 }
493 }
494 return ret;
495}
496
497function mouse_down_node(e) {
498 if(e.button!=0&&e.button!=1)
499 return;
500
501 move_idx = get_target_id(e.target);
502
503 if(move_idx<0)
504 return;
505 stop_event(e);
506
507 var m = moveables[move_idx];
508 var elem = find_target_node(e.target);
509 if(elem==null)
510 return;
511 /* move_node will toggle this if true and call start_node_move to initiate moving*/
512 // do not move if it specified not to move
513 if(m.can_move) {
514 m.moving_init_pos = new Array(e.pageX, e.pageY);
515 m.possible_move_node = elem;
516 }
517 var something_selected = true;
518 if(e.detail>1) { // we were just here, don't do the other stuff again..
519 /* double click */
520 if(m.double_click_cb&&e.detail==2)
521 m.double_click_cb(elem, e);
522 }
523 else if(e.ctrlKey||e.metaKey) {
524 if(is_node_selected(elem)) {
525 unselect_node(elem);
526 if(m.selection_change_cb&&m.something_selected)
527 something_selected = selection_anything_selected(m.container);
528 }
529 else {
530 select_node(elem);
531 }
532 }
533 else if (e.shiftKey) {
534 var sel_node = null;
535
536 sel_node = find_first_selected_node(m.container, elem);
537 if(sel_node==null) {
538 select_node(elem);
539 }
540 else {
541 if(elem.hasAttribute("needle")) {
542 select_range(elem, sel_node);
543 elem.removeAttribute("needle");
544 }
545 else {
546 select_range(sel_node, elem);
547 }
548 }
549 }
550 else {
551 if(!is_node_selected(elem)) {
552 unselect_all_nodes(m.container);
553 select_node(elem);
554 }
555 else {
556 m.select_if_no_move = true;
557 }
558 }
559 /* something selected */
560 if(m.selection_change_cb) {
561 m.selection_change_cb(something_selected);
562 m.something_selected = something_selected;
563 }
564}
565
566function mouse_up_node(e) {
567 if(move_idx<0)
568 return;
569 var m = moveables[move_idx];
570 if(m.moving) {
571 stop_node_move(e);
572 }
573 else if(m.select_if_no_move) {
574 var elem = find_target_node(e.target);
575 unselect_all_nodes(m.container);
576 select_node(elem);
577 }
578 m.select_if_no_move = false;
579 m.possible_move_node = null;
580 // safari workaround
581 m.container.className = m.container.className;
582}
583
584/* todo; rework to use elem instead of event */
585function start_node_move(e, elem) {
586 stop_event(e);
587
588 move_idx = get_target_id(e.target);
589
590 if(move_idx<0)
591 return;
592 if(!moveables[move_idx].can_move)
593 return;
594
595 var m = moveables[move_idx];
596 var move = find_target_node(e.target);
597 var container = m.container;
598 if(move!=null) {
599 m.moving = true; // moving
600 m.moving_elem = find_target_node(m.possible_move_node); // what
601 move = m.moving_elem;
602 m.possible_move_node = null;
603 var txt = "Moving";
604 if(m.multi_move)
605 txt = m.multi_move();
606 else if(move.childNodes[1])
607 txt = move.childNodes[1].textContent;
608 else txt = move.childNodes[0].textConten;
609
610 m.moving_clone = detach_node(move, txt);
611 set_node_offset(e, m.moving_clone);
612
613 add_listener(document.body, "mouseup", stop_node_move);
614 add_listener(document.body, "mousemove", move_node);
615
616 container.style.cursor = "move";
617 }
618 else move_idx = -1;
619}
620
621
622/* basically the reverse of start */
623function stop_node_move(e) {
624 if(move_idx<0||!moveables[move_idx].moving)
625 return;
626
627 var m = moveables[move_idx];
628 m.moving = false;
629 var move = m.moving_elem;
630 var container = m.container;
631 var target = find_target_node(e.target);
632
633 if(m.multi_move) {
634 /* don't move it if we are moving on top of selection */
635 if(target&&!is_node_selected(target)) {
636 m.on_change(null,target);
637 }
638 reattach_node(move, null, m.moving_clone, 4); // remove moving node
639 }
640 else if(target!=null&&target!=move) {
641 /* if first in list or above the one beeing moved, move it up */
642 var to = null;
643 if(target==get_first_real_child(container)||target.nextSibling==move) {
644 to = target;
645 reattach_node(move, target, m.moving_clone, 1);
646 }
647 else if(target.nextSibling!=null) {
648 /* normally default action */
649 var attach_at;
650 to = target;
651 if(is_moving_up(container, move, target)) {
652 attach_at = target;
653 }
654 else {
655 attach_at = target.nextSibling;
656 }
657 reattach_node(move, attach_at, m.moving_clone, 1);
658 }
659 else {
660 /* basically this means we don't know any better */
661 /* should not happen unless target actually is last in list */
662 /*to = get_last_real_child(container);
663 reattach_node(move, container, m[4], 2);*/
664 to = target;
665 reattach_node(move, container, m.moving_clone, 2);
666 }
667
668 // say we changed
669 m.on_change(null, to);
670 }
671 else {
672 reattach_node(move, null, m.moving_clone, 4); // don't move it
673 }
674
675 container.style.cursor = "default";
676
677 remove_listener(document.body, "mouseup", stop_node_move);
678 remove_listener(document.body, "mousemove", move_node);
679
680 m.moving_elem = null;
681 m.moving_init_pos = null;
682 m.moving_clone = null;
683 move_idx = -1;
684}
685
686function move_node(e) {
687 var id = window.move_idx || -1;
688 var o = 4; // required offset
689 if(id&&id>=0) {
690 if(moveables[id].possible_move_node!=null) {
691 var p = moveables[id].moving_init_pos;
692 if(Math.abs(p[0]-e.pageX)>=o||Math.abs(p[1]-e.pageY)>o)
693 start_node_move(e);
694 }
695 if(!moveables[id].moving)
696 return;
697
698 stop_event(e);
699 set_node_offset(e, moveables[id].moving_clone);
700 }
701}
702
703function is_moving_up(container, move, target) {
704 var c = container.childNodes;
705 for(var i=0; i<c.length; i++) {
706 if(move==c[i])
707 return false;
708 if(target==c[i])
709 return true;
710 }
711 debug("Wops, not moving up or down!")
712 return false;
713}
714
715
716function detach_node(d, txt) {
717 var rep = create_node("div");
718
719 rep.style.width = d.offsetWidth/4 + "px";
720 rep.className = "moving_box";
721
722 txt = create_node("p", null, txt);
723 txt.className = "nomargin";
724 rep.appendChild(txt);
725
726 d.setAttribute("old_class", d.className);
727 d.className = "moving";
728
729 document.body.appendChild(rep);
730 return rep;
731}
732 /* reattach node at specified position (at) with action
733 * 1 => insertBefore
734 * 2 => appendChild
735 * 3 => replaceChild
736 * 4 => dont move
737 */
738function reattach_node(node, at, clone, action) {
739 node.style.width ="";
740 node.style.top = "";
741 node.style.position = "";
742 node.className = node.getAttribute("old_class");
743 if(action==1) {
744 remove_node(node);
745 at.parentNode.insertBefore(node, at);
746 }
747 else if(action == 2) {
748 remove_node(node);
749 at.appendChild(node);
750 }
751 else if(action == 3) {
752 remove_node(node);
753 replace_node(node, at);
754 }
755 else if(action==4) {
756 }
757 else {
758 debug("invalid action in reattach_node");
759 }
760 remove_node(clone);
761}
762
763function get_target_id(target) {
764 var t = find_target_node(target);
765 if(t!=null&&t.parentNode&&t.parentNode!=null)
766 return t.parentNode.getAttribute("move_id");
767 else return -1;
768}
769
770function find_target_node(target) {
771 while(target != null && target.parentNode&&target.parentNode != null) {
772 for(var i=0; i<moveables.length; i++)
773 if(moveables[i].container==target.parentNode)
774 return target;
775 target = target.parentNode;
776 }
777 return null;
778}
779
780/* set's this node to the position in event */
781function set_node_offset(ev, node) {
782 /* relative positioning:*/
783 var ot = 0;
784 var ol = 0;
785 if(node.hasAttribute("ot")&&node.hasAttribute("ol")) {
786 ot = node.getAttribute("ot");
787 ol = node.getAttribute("ol");
788 }
789 else {
790 ot = node.offsetTop;
791 ol = node.offsetLeft - 10;
792 node.setAttribute("ot", ot);
793 node.setAttribute("ol", ol);
794 }
795 var h = ev.pageY - ot;
796 var l = ev.pageX - ol;
797 /* absolute:
798 var h = ev.pageY - (node.offsetHeight/2);
799 var l = ev.pageX + 10;*/
800 node.style.top = h + "px";
801 node.style.left = l + "px";
802 return h;
803}
804
805function Slider(sid, main_slider, change, text_area) {
806 this.main_slider = main_slider;
807 this.change_call = change;
808 this.text_area = text_area;
809 this.value = 0;
810 this.moving_pos = 0;
811 this.user_moving = false;
812 this.timer = null;
813 this.timer_last_pos = null;
814 this.sid = sid;
815}
816
817Slider.prototype.setup_timer = function() {
818 if(this.timer!=null)
819 clearTimeout(this.timer);
820 this.timer_last_pos = this.moving_pos;
821 this.timer = setTimeout(this.timer_cb, 250);
822}
823Slider.prototype.timer_cb = function() {
824 // user has managed to hold mousepoitner stil
825 if(this.timer_last_pos==this.moving_pos) {
826 // omg...
827 var idx = window.slider_idx;
828 window.slider_send_callback(idx);
829 }
830 else if(this.user_moving) {
831 this.setup_timer();
832 }
833}
834
835/* should be a div */
836function setup_slider(slider, callback, txt) {
837 var sid = sliders.length;
838 if(txt!=null) {
839 txt = create_node("p", "slider_txt_" + sid, txt);
840 txt.className = "slider_txt";
841 slider.appendChild(txt);
842 }
843 var s = create_node("div");
844 s.className = "slider_main";
845 s.id = "slider_main" + sid;
846 slider.appendChild(s);
847 var pointer = create_node("div", " ");
848 pointer.className = "slider_pointer";
849 pointer.id = "slider_pointer" + sid;
850 s.setAttribute("sliderid", sid);
851 add_listener(s, "mousedown", mouse_down_slider);
852 pointer.style.height = (s.offsetHeight) + "px";
853 s.appendChild(pointer);
854 sliders[sid] = new Slider(sid, slider, callback, txt);
855 set_slider_pos(sid, 0);
856 return sid;
857}
858
859function get_slider_txt(sid) {
860 return sliders[sid].text_area;
861}
862
863function slider_send_callback(sid) {
864 if(sliders[sid].change_call)
865 sliders[sid].change_call(sliders[sid].value);
866}
867
868function set_slider_pos(sid, pos, force) {
869 var pointer = document.getElementById("slider_pointer" + sid);
870 var s = document.getElementById("slider_main" + sid);
871 if(!force)
872 force = false;
873 if(pointer==null||s==null) {
874 debug("no slider pointer||main");
875 return;
876 }
877
878 if(sliders[sid].user_moving&&!force)
879 return;
880
881 if(pos>100)
882 pos=100;
883 if(pos<0)
884 pos=0;
885
886 if(pos==sliders[sid].value) {
887 return;
888 }
889
890 sliders[sid].value = pos;
891
892 var dist = (s.offsetWidth * pos) /100
893 if(isNaN(dist)||dist=="NaN")
894 dist = 0;
895
896 pointer.style.left = dist+ "px";
897}
898
899function get_slider_pos(sid) {
900 return sliders[sid].value;
901}
902
903function mouse_down_slider(e) {
904 var targ = e.target;
905 /* TODO: rewrite test */
906 if(!targ||!targ.hasAttribute||!targ.hasAttribute("sliderid")) {
907 if(targ)
908 targ = targ.parentNode;
909 // *umpf*
910 if(!targ||!targ.hasAttribute||!targ.hasAttribute("sliderid"))
911 return;
912 }
913
914 slider_idx = targ.getAttribute("sliderid");
915
916 add_listener(document.body, "mousemove", mouse_move_slider);
917 add_listener(document.body, "mouseup", mouse_up_slider);
918
919 sliders[slider_idx].user_moving = true;
920 sliders[slider_idx].main_slider.setAttribute("slider_moving", "yeahitis");
921
922 mouse_move_slider(e); // lazy
923 //e.stopPropagation();
924
925}
926
927function mouse_move_slider(e) {
928 if(slider_idx<0) {
929 debug("mouse_move_slider should not be called now");
930 mouse_up_slider(e);
931 return;
932 }
933 stop_event(e);
934 var left = slider_get_left(e, slider_idx)
935 set_slider_pos(slider_idx, left, true);
936 sliders[slider_idx].moving_pos = left;
937 sliders[slider_idx].setup_timer(sliders[slider_idx].change_call);
938}
939
940function mouse_up_slider(e) {
941 if(slider_idx<0)
942 return;
943
944 // prolly not necessary though
945 clearTimeout(sliders[slider_idx].timer);
946 sliders[slider_idx].timer = null;
947
948 remove_listener(document.body, "mousemove", mouse_move_slider);
949 remove_listener(document.body, "mouseup", mouse_up_slider);
950 sliders[slider_idx].user_moving = false;
951 sliders[slider_idx].main_slider.removeAttribute("slider_moving");
952 slider_send_callback(slider_idx);
953 slider_idx = -1;
954}
955
956function slider_get_left(e, sid) {
957 var x = e.pageX - get_absolute_left(sliders[sid].main_slider);
958 x = (x*100)/sliders[sid].main_slider.offsetWidth;
959 x-=3;
960 if(x<0)
961 x = 0;
962 return x;
963}
964
965function OverlayObject(back, sizes, open_callback, close_callback) {
966 this.back = back; // element to put overlay over
967 this.sizes = sizes; // minimum sizes [top, left, min-height, min-width ]
968 this.open_callback = open_callback;
969 this.close_callback = close_callback;
970 this.overlay = null; // the overlay element
971 this.write = null; // write area
972}
973
974/* overlay */
975function setup_overlay(back, sizes, open_callback, close_callback) {
976 var oid = overlay.length;
977 overlay[oid] = new OverlayObject(back, sizes, open_callback, close_callback);
978 var t = create_node("div", "overlay_" + oid);
979 overlay[oid].overlay = t;
980 t.className = "overlay";
981 t.style.height = overlay_adjust + "px";
982 var img = create_node("img", "overlay_close_" + oid);
983 img.src = IMAGE.CLOSE;
984 img.setAttribute("oid", oid);
985 img.className = "close fakelink";
986 img.title = "Close [Ctrl+Shift+X]";
987 add_listener(img, "click", close_overlay_cb);
988
989 t.appendChild(img);
990
991 document.body.appendChild(t);
992
993 return oid;
994}
995
996function get_overlay_write_area(oid) {
997 if(overlay[oid].write==null) {
998 overlay[oid].write = create_node("div", "overlay_write_area_" + oid);
999 overlay[oid].overlay.appendChild(overlay[oid].write);
1000
1001 }
1002 return overlay[oid].write;
1003}
1004
1005function open_overlay(oid) {
1006 var sizes = overlay[oid].sizes;
1007 var o = overlay[oid].back;
1008 var top = get_absolute_top(o);
1009 if(top<sizes[0])
1010 top = sizes[0];
1011 var left = get_absolute_left(o);
1012 if(left<sizes[1])
1013 left = sizes[1];
1014 var height = o.offsetHeight;
1015 if(height<sizes[2])
1016 height = sizes[2];
1017 var width = o.offsetWidth;
1018 if(width<sizes[3])
1019 width = sizes[3];
1020
1021 if(overlay_hide_on_resize&&overlay[oid].write)
1022 overlay[oid].write.style.display = "none";
1023
1024 var op = overlay[oid].overlay;
1025 open_overlay_idx = oid;
1026 op.style.left = left + "px";
1027 op.style.top = top + "px";
1028 op.style.width = overlay_adjust + "px";
1029 op.style.height = overlay_adjust + "px";
1030
1031 op.style.display = "block";
1032 var hx = 1, wx =1;
1033 if(width>height)
1034 wx = width/height;
1035 else
1036 hx = height/width;
1037
1038 overlay[oid].close_key = keyboard_register_listener(close_overlay_cb, "x", KEYBOARD_CTRL_KEY|KEYBOARD_SHIFT_KEY, true);
1039
1040 setTimeout(adjust_overlay_size, overlay_time, oid, new Array(overlay_adjust, overlay_adjust), new Array(height, width, hx, wx));
1041}
1042
1043function open_overlay_fixed(oid) {
1044 // TODO: find another way to determine these heights
1045 var sizes = new Array(106, 56, 800, 500);
1046
1047 var height = sizes[3];
1048 var width = sizes[2];
1049 var op = overlay[oid].overlay;
1050 open_overlay_idx = oid;
1051 if(overlay_hide_on_resize&&overlay[oid].write)
1052 overlay[oid].write.style.display = "none";
1053
1054 op.style.position = "fixed";
1055
1056 op.style.left = sizes[1] + "px";
1057 op.style.top = sizes[0] + "px";
1058 op.style.width = overlay_adjust + "px";
1059 op.style.height = overlay_adjust + "px";
1060
1061 op.style.display = "block";
1062
1063 /* adjust to browser window */
1064 var x_o = 30;
1065 var w_h = window.innerHeight;
1066 var w_w = window.innerWidth;
1067
1068 /* ignore it if unreasonable values.. */
1069 if(w_h&&w_w&&w_h>100&&w_w>100) {
1070 if(height+sizes[0]+x_o>w_h)
1071 height = w_h - sizes[0] - x_o;
1072 if(width+sizes[1]+x_o>w_w)
1073 width = w_w - sizes[1] - x_o;
1074 }
1075
1076 var hx = 1, wx =1;
1077 if(width>height)
1078 wx = width/height;
1079 else
1080 hx = height/width;
1081
1082 overlay[oid].close_key = keyboard_register_listener(close_overlay_cb, "x", KEYBOARD_CTRL_KEY|KEYBOARD_SHIFT_KEY, true);
1083
1084 setTimeout(adjust_overlay_size, overlay_time, oid, new Array(overlay_adjust, overlay_adjust), new Array(height, width, hx, wx));
1085}
1086
1087function adjust_overlay_size(oid, current, dest) {
1088 var h = current[0] = current[0] + (dest[2]*overlay_adjust);
1089 var w = current[1] = current[1] + (dest[3]*overlay_adjust);
1090 var adjusted = false;
1091
1092 if(h<dest[0]) {
1093 adjusted = true;
1094 }
1095 else {
1096 h = dest[0];
1097 }
1098 if(w<dest[1]) {
1099 adjusted = true
1100 }
1101 else {
1102 w = dest[1];
1103 }
1104 h = parseInt(h);
1105 w = parseInt(w);
1106 overlay[oid].overlay.style.height = h + "px";
1107 overlay[oid].overlay.style.width = w + "px";
1108 //debug("h: " + h + ", w: " + w);
1109
1110 if(adjusted) {
1111 //debug("setting timeout");
1112 setTimeout(adjust_overlay_size, overlay_time, oid, current, dest);
1113 }
1114 else {
1115 var height = (overlay[oid].overlay.offsetHeight-20);
1116 if(overlay[oid].write) {
1117 if(overlay_hide_on_resize) {
1118 overlay[oid].write.style.display = "block"; // kiss
1119 }
1120 }
1121 if(overlay[oid].open_callback)
1122 overlay[oid].open_callback(height);
1123 }
1124}
1125
1126function close_overlay(oid) {
1127 var o = overlay[oid].overlay;
1128 open_overlay_idx = -1;
1129 o.style.display = "none";
1130 if(overlay[oid].close_key)
1131 overlay[oid].close_key = keyboard_remove_listener(overlay[oid].close_key);
1132 if(overlay[oid].close_callback)
1133 overlay[oid].close_callback();
1134}
1135function close_overlay_cb(e) {
1136 var t = e.target;
1137 if(t&&t.hasAttribute&&t.hasAttribute("oid")) {
1138 close_overlay(t.getAttribute("oid"));
1139 stop_event(e);
1140 }
1141 else if(open_overlay_idx>=0) {
1142 close_overlay(open_overlay_idx);
1143 stop_event(e);
1144 }
1145
1146}
1147
1148function stop_propagation(e) {
1149 if(e.stopPropagation)
1150 e.stopPropagation();
1151}
1152
1153function stop_event(e) {
1154 if(e) {
1155 if(e.preventDefault)
1156 e.preventDefault();
1157 if(e.stopPropagation)
1158 e.stopPropagation();
1159 if(e.returnValue)
1160 e.returnValue = false;
1161 }
1162}
1163
1164/* range selection (to put ranges in a "list" */
1165/* txt: excisting range:
1166 * from: from what number
1167 * to: optional to argument
1168 */
1169function add_range(txt, from, to) {
1170 if(txt.length>0)
1171 txt+=";";
1172 txt+=from;
1173 if(to)
1174 txt+="-" + to;
1175 return txt;
1176}
1177
1178function scrollIntoView(elem, top) {
1179 if(!top)
1180 top = false;
1181 /* seriously though, if you don't support it, don't claim you do!*/
1182 //if(elem.scrollIntoView) {
1183 if(navigator.product&&navigator.product=="Gecko") {
1184 elem.scrollIntoView(top);
1185 }
1186 else if(elem.parentNode) {
1187 // TODO: top
1188 try {
1189 elem.parentNode.scrollTop=elem.offsetTop - (top?elem.offsetHeight*2:elem.parentNode.offsetHeight);
1190 } catch (e) { }
1191 }
1192}
1193
1194function setSelectionRange(input, selectionStart, selectionEnd) {
1195 if (input.setSelectionRange) {
1196 input.focus();
1197 input.setSelectionRange(selectionStart, selectionEnd);
1198 }
1199 else if (input.createTextRange) {
1200 var range = input.createTextRange();
1201 range.collapse(true);
1202 range.moveEnd('character', selectionEnd);
1203 range.moveStart('character', selectionStart);
1204 range.select();
1205 range.detach();
1206 }
1207}
1208function setCaretToEnd (input) {
1209 setSelectionRange(input, input.value.length, input.value.length);
1210}
1211function setCaretToBegin (input) {
1212 setSelectionRange(input, 0, 0);
1213}
1214function setCaretToPos (input, pos) {
1215 setSelectionRange(input, pos, pos);
1216}
1217
1218
1219
1220String.prototype.trim = function() {
1221 return this.replace(/^\s+|\s+$/g,'');
1222}
1223
1224function add_string_with_br(to, str) {
1225 str = str.replace("\r", "").split('\n');
1226 for(var i=0; i<str.length; i++) {
1227 if(str[i].length>0)
1228 to.appendChild(create_txt(str[i]));
1229 to.appendChild(create_node("br"));
1230 }
1231}
1232
1233function adjust_opacity_timer(node, current_opacity, dest_opacity, last_time) {
1234 var now = get_time();
1235 var time = now;
1236 if(last_time)
1237 time -= last_time;
1238 else time = 0;
1239
1240 time = 100-time;
1241 //debug("time: " + time);
1242 if(time<0) {
1243 time = 0;
1244 current_opacity+=0.2;
1245 }
1246 else {
1247 current_opacity+=0.1;
1248 }
1249
1250 if(current_opacity<dest_opacity) {
1251 node.style.opacity = current_opacity ;
1252 setTimeout(adjust_opacity_timer, time, node, current_opacity, dest_opacity, now);
1253 }
1254 else {
1255 node.style.opacity = dest_opacity ;
1256 }
1257}
1258
1259/* what to blink, what color and count, two first arguments are required */
1260function blink_node(what, color, count) {
1261 if(typeof(count)=='undefined') {
1262 count = 3;
1263 }
1264 if(count%2==1)
1265 what.style.backgroundColor = color;
1266 else
1267 what.style.backgroundColor = "";
1268 if(count>0) {
1269 setTimeout(blink_node, 350, what, color, --count);
1270 }
1271}
1272
1273/* popup */
1274/* if content is null, we'll use tabs */
1275function Popup(point, content) {
1276 this.point = point;
1277 this.content = content;
1278 this.popup = create_node("div");
1279 if(content)
1280 this.popup.appendChild(content);
1281 this.popup.className = "popup";
1282 this.point.appendChild(this.popup);
1283}
1284
1285Popup.prototype.show = function() {
1286 this.popup.style.display = "block";
1287}
1288Popup.prototype.hide = function() {
1289 this.popup.style.display = "";
1290}
1291Popup.prototype.destroy = function() {
1292 remove_node(this.popup);
1293 this.popup = null;
1294 this.point = null;
1295 this.content = null;
1296}
1297
1298/* xpath */
1299function xpath_init() {
1300 xpath_queries = new Hashtable();
1301}
1302
1303/* checks if xpath is available */
1304function xpath_ok() {
1305 return document.evaluate?true:false;
1306}
1307
1308// remember to check with xpath_ok first when using this function
1309function xpath_query(container, expression, resulttype, nocache_query) {
1310 if(!resulttype)
1311 resulttype = XPathResult.ANY_TYPE;
1312 if(nocache_query) {
1313 return document.evaluate(expression, container, null, resulttype, null);
1314 }
1315 else {
1316 var e = xpath_queries.get(expression);
1317 if(!e) {
1318 e = document.createExpression(expression, null);
1319 xpath_queries.put(expression, e);
1320 }
1321 return e.evaluate(container, resulttype, null);
1322 }
1323}
1324
1325function opera_quirk_set_display_none(element, cleanup) {
1326 if(cleanup) {
1327 element.style.display = "none";
1328 element.style.visibility = "";
1329 }
1330 else {
1331 setTimeout(opera_quirk_set_display_none, 10, element, true);
1332 element.style.visibility = "hidden";
1333 }
1334}
1335
1336function createCookie(name,value,days) {
1337 if (days) {
1338 var date = new Date();
1339 date.setTime(date.getTime()+(days*24*60*60*1000));
1340 var expires = "; expires="+date.toGMTString();
1341 }
1342 else var expires = "";
1343 document.cookie = name+"="+value+expires+"; path=/";
1344}
1345function readCookie(name) {
1346 var nameEQ = name + "=";
1347 var ca = document.cookie.split(';');
1348 for(var i=0;i < ca.length;i++) {
1349 var c = ca[i];
1350 while (c.charAt(0)==' ') c = c.substring(1,c.length);
1351 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
1352 }
1353 return null;
1354}
1355function eraseCookie(name) {
1356 createCookie(name,"",-1);
1357}
1358
1359// This function is in the public domain. Feel free to link back to http://jan.moesen.nu/
1360function sprintf() {
1361 if (!arguments || arguments.length < 1 || !RegExp) {
1362 return "";
1363 }
1364 var str = arguments[0];
1365 var re = /([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X)(.*)/;
1366 var a = b = [], numSubstitutions = 0, numMatches = 0;
1367 while ((a = re.exec(str))) {
1368 var leftpart = a[1], pPad = a[2], pJustify = a[3], pMinLength = a[4];
1369 var pPrecision = a[5], pType = a[6], rightPart = a[7];
1370
1371 //alert(a + '\n' + [a[0], leftpart, pPad, pJustify, pMinLength, pPrecision);
1372
1373 numMatches++;
1374 if (pType == '%') {
1375 subst = '%';
1376 }
1377 else {
1378 numSubstitutions++;
1379 if (numSubstitutions >= arguments.length) {
1380 alert('Error! Not enough function arguments (' + (arguments.length - 1) + ', excluding the string)\nfor the number of substitution parameters in string (' + numSubstitutions + ' so far).');
1381 }
1382 var param = arguments[numSubstitutions];
1383 var pad = '';
1384 if (pPad && pPad.substr(0,1) == "'") pad = leftpart.substr(1,1);
1385 else if (pPad) pad = pPad;
1386 var justifyRight = true;
1387 if (pJustify && pJustify === "-") justifyRight = false;
1388 var minLength = -1;
1389 if (pMinLength) minLength = parseInt(pMinLength);
1390 var precision = -1;
1391 if (pPrecision && pType == 'f') precision = parseInt(pPrecision.substring(1));
1392 var subst = param;
1393 if (pType == 'b') subst = parseInt(param).toString(2);
1394 else if (pType == 'c') subst = String.fromCharCode(parseInt(param));
1395 else if (pType == 'd') subst = parseInt(param) ? parseInt(param) : 0;
1396 else if (pType == 'u') subst = Math.abs(param);
1397 else if (pType == 'f') subst = (precision > -1) ? Math.round(parseFloat(param) * Math.pow(10, precision)) / Math.pow(10, precision): parseFloat(param);
1398 else if (pType == 'o') subst = parseInt(param).toString(8);
1399 else if (pType == 's') subst = param;
1400 else if (pType == 'x') subst = ('' + parseInt(param).toString(16)).toLowerCase();
1401 else if (pType == 'X') subst = ('' + parseInt(param).toString(16)).toUpperCase();
1402 }
1403 str = leftpart + subst + rightPart;
1404 }
1405 return str;
1406}
1407
1408/* settings */
1409
1410function setting_set(name, value) {
1411 var s = readCookie("pf_conf");
1412
1413 var ns = "";
1414 var set = false;
1415 if(s) {
1416 s = s.split(":");
1417 for(var i=0; i< s.length; i++) {
1418 var tmp = s[i].split("-");
1419 if(!tmp[0].length)
1420 continue;
1421
1422 if(tmp[0]==name) {
1423 ns+=name + "-" + value;
1424 set = true;
1425 }
1426 else {
1427 ns+=s[i];
1428 }
1429 ns+=":";
1430 }
1431 }
1432 if(!set)
1433 ns+=name + "-" +value + ":";
1434
1435 createCookie("pf_conf", ns, 200);
1436
1437 return true;
1438}
1439
1440function setting_get(name) {
1441 var val = readCookie("pf_conf");
1442
1443 if(!val||!val.length)
1444 return null;
1445
1446 val = val.split(":");
1447 for(var i=0; i < val.length; i++) {
1448 var t = val[i].split("-");
1449 if(t[0]==name)
1450 return t[1];
1451 }
1452 return null;
1453}
This page took 0.22175 seconds and 4 git commands to generate.