]>
Commit | Line | Data |
---|---|---|
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 | ||
28 | var moveables = new Array(); | |
29 | var move_idx = -1; | |
30 | ||
31 | var sliders = new Array(); | |
32 | var slider_idx = -1; | |
33 | ||
34 | var overlay = new Array(); | |
35 | var overlay_adjust = 100; // px | |
36 | var open_overlay_idx = -1; | |
37 | var overlay_time = 5; | |
38 | var overlay_hide_on_resize = true; // hide content on resize? | |
39 | ||
40 | var xpath_queries; | |
41 | ||
42 | function 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 | ||
66 | function get_time() { | |
67 | var d = new Date(); | |
68 | return d.getTime(); | |
69 | } | |
70 | ||
71 | /* evaluates json response and returns object containing information */ | |
72 | function evaluate_json(txt) { | |
73 | var obj = new Object(); | |
74 | ||
75 | /* limit context */ | |
76 | obj = eval(txt, obj); | |
77 | return obj; | |
78 | } | |
79 | ||
80 | function browser_is_opera() { | |
81 | return window.opera?true:false; | |
82 | } | |
83 | function browser_is_konqueror() { | |
84 | if(navigator.vendor=="KDE") | |
85 | return true; | |
86 | return false; | |
87 | } | |
88 | ||
89 | // replaces rem with ins | |
90 | function replace_node(ins, rem) { | |
91 | return rem.parentNode.replaceChild(ins, rem); | |
92 | } | |
93 | // removes this nodes children | |
94 | function 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 | ||
103 | function remove_node(what) { | |
104 | if(what) | |
105 | return what.parentNode.removeChild(what); | |
106 | return null; | |
107 | } | |
108 | ||
109 | function 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' */ | |
123 | function insert_first(node, at) { | |
124 | if(at.hasChildNodes()) | |
125 | at.insertBefore(node, at.firstChild); | |
126 | else at.appendChild(node); | |
127 | } | |
128 | ||
129 | function insert_before(what, before) { | |
130 | before.parentNode.insertBefore(what, before); | |
131 | } | |
132 | ||
133 | function 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 | ||
140 | function 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 | */ | |
164 | function 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 | ||
173 | function 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 | |
184 | function get_absolute_height(node) { | |
185 | return node.offsetTop + get_absolute_top(node); | |
186 | } | |
187 | ||
188 | function 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 | ||
199 | function EventListener(to, type, func) { | |
200 | this.to = to; | |
201 | this.type = type; | |
202 | this.func = func; | |
203 | } | |
204 | ||
205 | EventListener.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 | ||
215 | EventListener.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 | */ | |
228 | function add_listener(to, event_s, func) { | |
229 | var el = new EventListener(to, event_s,func); | |
230 | el.register(); | |
231 | return el; | |
232 | } | |
233 | ||
234 | function 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 */ | |
246 | function 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 | ||
256 | function 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 | |
271 | function 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 | ||
286 | function create_txt(txt) { | |
287 | return document.createTextNode(txt); | |
288 | } | |
289 | ||
290 | function create_fragment() { | |
291 | return document.createDocumentFragment(); | |
292 | } | |
293 | ||
294 | // creates an empty table row with id and | |
295 | // returns it | |
296 | function create_tr(id) { | |
297 | return create_node("tr", id, null); | |
298 | } | |
299 | ||
300 | function 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 | |
308 | function add_td(tr, content, id) { | |
309 | var n = create_node("td", id, content); | |
310 | tr.appendChild(n); | |
311 | return n; | |
312 | } | |
313 | ||
314 | function add_li(list, content, id) { | |
315 | var n = create_node("li", id, content); | |
316 | list.appendChild(n); | |
317 | return n; | |
318 | } | |
319 | ||
320 | function add_txt(node, txt) { | |
321 | node.appendChild(create_txt(txt)); | |
322 | } | |
323 | ||
324 | function 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 | ||
334 | function 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 | ||
358 | function 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 | ||
371 | function add_move_doubleclick(id, func) { | |
372 | moveables[id].double_click_cb = func; | |
373 | } | |
374 | ||
375 | function set_moveable(id, moveable) { | |
376 | moveables[id].can_move = moveable; | |
377 | } | |
378 | ||
379 | function set_selection_change_handler(id, func) { | |
380 | moveables[id].selection_change_cb = func; | |
381 | } | |
382 | ||
383 | /* NodeSelection _ find out if a node is selected */ | |
384 | function is_node_selected(node) { | |
385 | return node.hasAttribute&&node.hasAttribute("selected"); | |
386 | } | |
387 | ||
388 | /* NodeSelection - set whether a node is selectable or not */ | |
389 | function 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 */ | |
397 | function 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 | ||
407 | function unselect_node(node) { | |
408 | if(node.hasAttribute("selected")) { | |
409 | node.removeAttribute("selected"); | |
410 | } | |
411 | } | |
412 | ||
413 | function unselect_all_nodes(container) { | |
414 | if(xpath_ok()) { | |
11c37741 | 415 | var nodes = xpath_query(container, ".//*[@selected]"); |
964dd0bc JW |
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 */ | |
436 | function selection_anything_selected(container) { | |
437 | if(xpath_ok()) { | |
11c37741 | 438 | var x = xpath_query(container, ".//*[@selected]", XPathResult.ANY_UNORDERED_NODE_TYPE); |
964dd0bc JW |
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 | */ | |
455 | function find_first_selected_node(container, needle) { | |
456 | if(xpath_ok()&&!needle) { | |
11c37741 | 457 | var x = xpath_query(container, ".//*[@selected]", XPathResult.FIRST_ORDERED_NODE_TYPE); |
964dd0bc JW |
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 */ | |
475 | function 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 */ | |
485 | function 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 | ||
497 | function 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 | ||
566 | function 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 */ | |
585 | function 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 */ | |
623 | function 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 | ||
686 | function 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 | ||
703 | function 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 | ||
716 | function 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 | */ | |
738 | function 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 | ||
763 | function 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 | ||
770 | function 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 */ | |
781 | function 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 | ||
805 | function 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 | ||
817 | Slider.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 | } | |
823 | Slider.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 */ | |
836 | function 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 | ||
859 | function get_slider_txt(sid) { | |
860 | return sliders[sid].text_area; | |
861 | } | |
862 | ||
863 | function slider_send_callback(sid) { | |
864 | if(sliders[sid].change_call) | |
865 | sliders[sid].change_call(sliders[sid].value); | |
866 | } | |
867 | ||
868 | function 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 | ||
899 | function get_slider_pos(sid) { | |
900 | return sliders[sid].value; | |
901 | } | |
902 | ||
903 | function 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 | ||
927 | function 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 | ||
940 | function 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 | ||
956 | function 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 | ||
965 | function 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 */ | |
975 | function 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 | ||
996 | function 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 | ||
1005 | function 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 | ||
1043 | function 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 | ||
1087 | function 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 | ||
1126 | function 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 | } | |
1135 | function 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 | ||
1148 | function stop_propagation(e) { | |
1149 | if(e.stopPropagation) | |
1150 | e.stopPropagation(); | |
1151 | } | |
1152 | ||
1153 | function 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 | */ | |
1169 | function 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 | ||
1178 | function 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 | ||
1194 | function 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 | } | |
1208 | function setCaretToEnd (input) { | |
1209 | setSelectionRange(input, input.value.length, input.value.length); | |
1210 | } | |
1211 | function setCaretToBegin (input) { | |
1212 | setSelectionRange(input, 0, 0); | |
1213 | } | |
1214 | function setCaretToPos (input, pos) { | |
1215 | setSelectionRange(input, pos, pos); | |
1216 | } | |
1217 | ||
1218 | ||
1219 | ||
1220 | String.prototype.trim = function() { | |
1221 | return this.replace(/^\s+|\s+$/g,''); | |
1222 | } | |
1223 | ||
1224 | function 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 | ||
1233 | function 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 */ | |
1260 | function 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 */ | |
1275 | function 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 | ||
1285 | Popup.prototype.show = function() { | |
1286 | this.popup.style.display = "block"; | |
1287 | } | |
1288 | Popup.prototype.hide = function() { | |
1289 | this.popup.style.display = ""; | |
1290 | } | |
1291 | Popup.prototype.destroy = function() { | |
1292 | remove_node(this.popup); | |
1293 | this.popup = null; | |
1294 | this.point = null; | |
1295 | this.content = null; | |
1296 | } | |
1297 | ||
1298 | /* xpath */ | |
1299 | function xpath_init() { | |
1300 | xpath_queries = new Hashtable(); | |
1301 | } | |
1302 | ||
1303 | /* checks if xpath is available */ | |
1304 | function xpath_ok() { | |
1305 | return document.evaluate?true:false; | |
1306 | } | |
1307 | ||
1308 | // remember to check with xpath_ok first when using this function | |
1309 | function 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 | ||
1325 | function 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 | ||
1336 | function 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 | } | |
1345 | function 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 | } | |
1355 | function 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/ | |
1360 | function 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 | ||
1410 | function 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 | ||
1440 | function 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 | } |