]> Joshua Wise's Git repositories - patchfork.git/blame - std/playlist.js
Update support for Amazon coverart grabbing (patch from Václav Nováček <waclaw66...
[patchfork.git] / std / playlist.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/* this file contains anything pertaining to playlist management */
20
21var playlist_element = null;
22
23
24function playlist_init() {
25 show_status_bar(LANG.WAIT_LOADING, true);
26 var http = new XMLHttpRequest();
27 http.open("GET", "command.php?ping");
28 remove_children(playlist_element);
29
30 var c = create_node("tr");
31 function ctws(size) {
32 var tmp = create_node("td");
33 tmp.style.width = size + "px";
34 c.appendChild(tmp);
35 }
36 ctws(23); // pos
37 for(var i=1; i< pl_entries.length-1; i++) {
38 if(pl_entries[i]=="Track") {
39 ctws(50);
40 }
41 else {
42 ctws(200);
43 }
44 }
45 ctws(30); // time
46 c.className = "playlist";
47 pl_entry_clone = c;
48
49 http.onreadystatechange = function() {
50 if(http.readyState==4) {
51 var resp = null;
52 if(!http.responseText||!(resp = evaluate_json(http.responseText))) {
53 show_status_bar(LANG.E_INVALID_RESPONSE);
54 throw("Init failed");
55 }
56 else if(http.status==200) {
57 if(resp['connection']&&resp['connection']=="failed") {
58 show_status_bar(LANG.E_CONNECT);
59 throw(LANG.E_CONNECT);
60 }
61
62 /* for pagination to work properly we need to know some values in forehand */
63 if(resp.status) {
64 var s = resp.status;
65 if(typeof(s.song)!='undefined')
66 playing.pos = parseInt(s.song);
67 }
68
69 if(pagination_is_following())
70 playlist_scroll_to_playing();
71
72 hide_status_bar(1);
73 dirlist_init();
74 setTimeout(need_update,10);
75 }
76 else {
77 show_status_bar(LANG.E_INIT_PL);
78 throw("init failed");
79 }
80 }
81 }
82 http.send(null);
83}
84
85function create_lazy_pl_row(info, id) {
86 var tr = null;
87 var pos = parseInt(info["cpos"]);
88 tr = pl_entry_clone.cloneNode(true);
89 tr.firstChild.appendChild(create_txt(parseInt(pos)+1));
90 tr.setAttribute("plpos", pos);
91 tr.id = id;
92 return tr;
93}
94
95function get_plid(node) {
96 return node.id.substring(7);
97}
98
99function get_plpos(node) {
100 return node.getAttribute("plpos");
101}
102
103function set_pl_position(node, new_pos) {
104 node.childNodes[0].childNodes[0].nodeValue = (new_pos+1);
105 node.setAttribute("plpos", new_pos);
106}
107
108function moved_plitem(stat) {
109 if(stat!="ok") {
110 show_status_bar(LANG.E_PL_MOVE);
111 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
112 }
113}
114
115function playlist_get_move_txt() {
116 /* todo */
117 return "Moving selection..";
118}
119
120/* a note on this... if to is null then it was put first in the list */
121/* if move is null then it's a multi-move (which it always will be for now) */
122function playlist_move(move, to) {
123
124 if(move==null) {
125 var range = get_pl_selection_range(false);
126 to = get_plpos(to);
127 send_command("rangemove=" + encodeURIComponent(to) + "&elems=" + encodeURIComponent(range));
128 return;
129 }
130
131 if(to==move) {
132 debug("trying to move to same, you should never see this");
133 return;
134 }
135
136 var from = get_plid(move);
137 var topos = get_plpos(to);
138 if(from<0 || topos == null || topos == "" ) {
139 debug("Missing id on to or from!");
140 }
141 send_command("playlist=move&from=" + from + "&to=" + topos, moved_plitem);
142}
143
144/* cut's of elements at the end of playlist */
145function playlist_resize(size) {
146 if(pagination.max>0&&pagination.pages>1) {
147 if(pagination.page==pagination.pages-1 && size%pagination.max!=0 ) {
148 remove_children_after(playlist_element, size%pagination.max);
149 }
150 }
151 else {
152 remove_children_after(playlist_element, size);
153 }
154}
155
156function select_playing_song() {
157 var new_p = document.getElementById("plitem_" + playing.id);
158 if(playing.show_node) {
159 if(playing.show_node==new_p) // same node
160 return;
161 apply_border_style_to_children(playing.show_node, "none");
162 playing.show_node.removeAttribute("playing");
163 playing.show_node = null;
164 }
165 if(new_p) {
166 apply_border_style_to_children(new_p, PLAYLIST_PLAYING_STYLE);
167 new_p.setAttribute("playing", "i");
168 playing.show_node = new_p;
169 }
170
171}
172
173/* not really lazy, but it needs a name */
174function get_lazy_info(need_info) {
175 var ids = "";
176 var start_id=-1, last_id=-1, id;
177 for(id in need_info) {
178 if(start_id<0) {
179 start_id = last_id = id;
180 }
181 else if(last_id==id-1) {
182 last_id = id;
183 }
184 else {
185 ids = add_range(ids, start_id, (start_id==last_id?false:last_id));
186 start_id = last_id = id;
187 }
188 }
189 ids = add_range(ids, start_id, (start_id==last_id?false:last_id));
190
191 if(ids.length>0) {
192 need_info_arr = need_info;
193 /* get missing info and don't get plchanges */
194 send_command("playlist=info", get_lazy_info_cb, LANG.WAIT_UPDATING_PL, true, "ids=" + encodeURIComponent(ids), true);
195 }
196}
197
198function get_lazy_info_cb(res) {
199
200 var node,id,info;
201 var ple = pl_entries;
202
203 var need_info = need_info_arr;
204 need_info_arr = null;
205 if(need_info==null) {
206 //debug("get lazy info cb called, but no need_info array available");
207 /* FIXME: we have a potential race condition here
208 (may get several results, but only one of them is the one we need and or can use) */
209 return;
210 }
211
212 if(!res) {
213 show_status_bar(LANG.E_INVALID_RESULT);
214 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
215 return;
216 }
217 show_status_bar(LANG.WAIT_UPDATING_PL);
218
219 /* todo: hide when more than 500 changes */
220 var length = res.length;
221 var plength = ple.length;
222 for(var i=0; i<length; i++) {
223 info = res[i];
224 var res_id = info.Id;
225 id = false;
226 node = need_info[res_id];
227 if(node) {
228 info = res[i];
229 for(var j=1; j<plength;j++) {
230 var val = info[ple[j]];
231
232 if(val) {
233 if(ple[j]=="Time")
234 val = convert_minsec(val);
235 }
236 else {
237 if(ple[j]=="Title") {
238 val = info["file"];
239 val = val.substring(val.lastIndexOf(DIR_SEPARATOR)+1);
240 }
241 else {
242 val = "";
243 }
244 }
245 if(val.length>29) {
246 node.childNodes[j].title = val;
247 val = val.substring(0,27) + "..";
248 }
249 else if(node.childNodes[j].title) {
250 node.childNodes[j].removeAttribute("title");
251 }
252
253 if(node.childNodes[j].hasChildNodes())
254 node.childNodes[j].childNodes[0].nodeValue = val;
255 else node.childNodes[j].appendChild(create_txt(val));
256 }
257 }
258 }
259 hide_status_bar();
260
261 if(browser_is_konqueror()) {
262 playlist_element.className = "pltemp";
263 setTimeout(cclass_for_konqueror, 1);
264 }
265}
266
267/* see bug #46 */
268function cclass_for_konqueror() {
269 playlist_element.className = "";
270}
271
272function pl_selection_changed(sel) {
273 if(sel!=last_pl_selected) {
274 last_pl_selected = sel;
275 document.getElementById('crop_items_button').title = sel?LANG.CROP_SELECTION:LANG.CLEAR_PLAYLIST;
276 }
277}
278
279function plchanges_handler3(list, size) {
280 if(!list||!list.length||list.length<=0)
281 return;
282 var cont = playlist_element;
283 var df = create_fragment(); // temporary storage until we end
284 var buf = create_fragment(); // for appending
285 var i=0;
286 var id;
287 var plid;
288 var pointer = null; // working point in playlist
289 var cursor = null; // temporary point in playlist to make get from doc more effective
290 var need_info = new Array();
291 var count = 0;
292
293 /* returns the id of the next item in the list */
294 function _gn_id() {
295 if(i+1<list.length)
296 return "plitem_" + list[i+1]["Id"];
297 else return null;
298 }
299 /* checks if it is in cache */
300 function _get_from_df(id) {
301 var cf = df.childNodes;
302 for (var j=0; j<cf.length; j++) {
303 if(cf[j].id&&cf[j].id==id) {
304 return df.removeChild(cf[j]);
305 }
306 }
307 return null;
308 }
309
310 function _get_from_doc(id) {
311 /* document.getElementById seems slow on large lists,
312 and there are a few assumptions we can make.. */
313 if(!cursor)
314 cursor = pointer.nextSibling;
315 var start_point = cursor;
316 var stop_at = false;
317 while(cursor) {
318 if(cursor.id == id) {
319 var ret = cursor;
320 cursor = cursor.nextSibling;
321 return cont.removeChild(ret);
322 }
323 cursor = cursor.nextSibling;
324 if(!cursor&&start_point) {
325 if(start_point!=pointer.nextSibling) {
326 stop_at = start_point;
327 start_point = false;
328 cursor = pointer.nextSibling;
329 }
330 }
331 if(stop_at == cursor)
332 break;
333 }
334 return null;
335 }
336
337 /* create a row */
338 function _create_row(id) {
339 /* wow, what a mess.... */
340 n = create_lazy_pl_row(list[i], "plitem_" + id);
341 need_info[id] = n;
342 return n;
343 }
344
345 function _update_current_row(id) {
346 pointer.id = "plitem_" + id;
347 need_info[id] = pointer;
348 }
349
350 function _get_from_df_or_create(id) {
351 var n = _get_from_df("plitem_" + id);
352 if(!n) n = _create_row(id);
353 return n;
354 }
355
356 var changes_length = list.length;
357 var changes_start = parseInt(list[0]["cpos"]);
358 var changes_end = parseInt(list[list.length-1]['cpos']);
359 var pagination_start = pagination.max * pagination.page;
360 var pagination_end = pagination.max + pagination_start;
361 var start_pos = 0;
362
363 var pagination_switched_page = pagination.need_update;
364
365 if(pagination.max==0) {
366 start_pos = changes_start;
367 }
368 else if(changes_start<=pagination_start&&changes_end>=pagination_start) {
369 i = pagination_start - changes_start;
370 }
371 else if(changes_start<pagination_end) {
372 i = 0;
373 start_pos = changes_start - pagination_start;
374 }
375 else { // outside range
376 return; // let's hope we can just return...
377 }
378
379 if(start_pos<cont.childNodes.length&&start_pos>=0) {
380 pointer = cont.childNodes[start_pos];
381 }
382 else if(pointer==null) {
383 pointer = _create_row(list[0]["Id"]);
384 cont.appendChild(pointer);
385 }
386
387 if(start_pos==0) { // make sure there are no-one before us...
388 if(pointer.previousSibling) {
389 // todo obviously (if needed)
390 debug("let me know if you ever see this message (NTS, plchanges_handler)");
391 }
392 }
393
394 var append = false;
395 var length = list.length;
396 var n, nid;
397 var max = pagination.max || Number.MAX_VALUE;
398
399 var _insert_before = insert_before;
400 var _replace_node = replace_node;
401
402 for(; i < length && start_pos++ < max; i++) {
403 id = list[i]["Id"];
404 if(append) {
405 n = _get_from_df_or_create(id)
406 buf.appendChild(n);
407 continue;
408 }
409 plid = "plitem_" + id;
410
411 // if it's a page switch everything will have to be updated
412 if(pagination_switched_page) {
413 _update_current_row(id);
414 }
415 else if(pointer.id!=plid) {
416 nid = _gn_id();
417 n = _get_from_df(plid);
418 /* if n is found in df it has been removed, but wants back in */
419 if(n||nid==null||pointer.id==nid) {
420 if(!n)
421 n = _get_from_doc(plid);
422 if(!n)
423 n = _create_row(id);
424 _insert_before(n, pointer);
425 //debug("insert");
426 }
427 else {
428 if(!n)
429 n = _get_from_doc(plid);
430 if(!n)
431 n = _create_row(id);
432 _replace_node(n,pointer);
433 df.appendChild(pointer);
434 //debug("replace");
435 }
436 pointer = n;
437 }
438 if(pointer.nextSibling)
439 pointer = pointer.nextSibling;
440 else
441 append = true;
442 }
443
444 if(buf.hasChildNodes())
445 cont.appendChild(buf);
446 if(need_info.length>0)
447 get_lazy_info(need_info);
448
449 playlist_resize(size);
450 update_node_positions2(cont);
451 select_playing_song();
452
453 // must be called last
454 if(pagination_switched_page)
455 pagination_post_pageswitch();
456}
457
458function update_node_positions2(container) {
459 var node = container.firstChild;
460 var found_diff = false;
461 var i = pagination.max * pagination.page;
462 while(node) {
463 if(found_diff) {
464 set_pl_position(node, i++);
465 node = node.nextSibling;
466 }
467 else {
468 if(get_plpos(node)==i) {
469 node = node.nextSibling;
470 i++;
471 }
472 else {
473 found_diff = true;
474 }
475 }
476 }
477 return i;
478}
479
480function pagination_init() {
481
482 pagination.following = null; // set to true/false in pagination_is_following
483
484 /* these values shouldn't be hard-coded, but they are */
485 pagination.left = 50;
486 pagination.width = 680;
487
488 pagination.scroll_id = false;
489 pagination.scroll_left = false;
490
491 pagination.follow_button = document.getElementById("pagination_follow_current");
492 pagination.scroll_to_pos_after_switch = false;
493 pagination_update_follow();
494}
495
496/* should only be called when the size of the list has been changed and pages no longer fit*/
497function pagination_update_list(size) {
498 if(pagination.max<=0)
499 return;
500 var l = pagination.list;
501 var npages = Math.ceil(size/pagination.max); // number of pages
502 var cpages = pagination.pages; // current number of pages
503 var cpage = pagination.page;
504
505 while(npages>cpages) {
506 var n = add_li(l, cpages+1);
507 n.setAttribute("page", cpages++);
508 }
509 while(npages<cpages) {
510 remove_node(l.lastChild);
511 cpages--;
512 }
513
514 pagination.container.style.display = cpages>1?"block":"";
515
516 pagination.pages = cpages;
517 /* if we have switched page it needs update */
518 if(cpage>=cpages) {
519 cpage = cpages - 1;
520 }
521 pagination_update_current_page(cpage);
522}
523
524/* c: new page number */
525function pagination_update_current_page(c) {
526 if(pagination.max<=0)
527 return;
528 var p = pagination.list.firstChild;
529
530 if(pagination.cpage&&pagination.cpage.hasAttribute("cpage"))
531 pagination.cpage.removeAttribute("cpage");
532
533 while(p) {
534 if(p.getAttribute("page")==c) {
535 scrollIntoView(p);
536 p.setAttribute("cpage", "1");
537 break;
538 }
539 p = p.nextSibling;
540 }
541 pagination.cpage = p;
542 pagination.page = c;
543}
544
545function pagination_fetch_current_page() {
546 playing.pl_version = -1;
547 pagination.need_update = true;
548 reschedule_update_now();
549}
550
551function pagination_change_page(e, page) {
552 if(e!=null&&e.target.hasAttribute("page")) {
553 pagination.page = parseInt(e.target.getAttribute("page"));
554 }
555 else if(typeof(page)!='undefined') {
556 pagination.page = page;
557 }
558 else {
559 return;
560 }
561
562 pagination_update_current_page(pagination.page);
563 pagination_fetch_current_page();
564 unselect_all_nodes(playlist_element);
565}
566
567function pagination_scroll_view(e) {
568 var x = e.pageX - pagination.left;
569 var left = false;
570 var abort = true;
571
572 if(x>pagination.width-20) {
573 abort = false;
574 }
575 else if(x<20&&pagination.list.scrollLeft>0) {
576 abort = false;
577 left = true;
578 }
579
580 if(!pagination.scroll_id&&!abort) {
581 pagination_scroll_real(left);
582 }
583 else if(pagination.scroll_id&&abort) {
584 pagination_scroll_stop();
585 }
586
587 stop_event(e);
588}
589
590function pagination_scroll_stop(e) {
591
592 if(e && e.relatedTarget && (e.relatedTarget.id=="pagination_list"||e.relatedTarget.parentNode.id=="pagination_list"||typeof(e.relatedTarget.page)!='undefined'))
593 return;
594
595 if(pagination.scroll_id) {
596 clearTimeout(pagination.scroll_id);
597 pagination.scroll_id = false;
598 }
599}
600
601function pagination_is_following() {
602 if(pagination.following == null) {
603 var f = setting_get("follow_playing");
604 if(f&&parseInt(f))
605 pagination.following = true;
606 else pagination.following = false;
607 }
608 return pagination.following;
609}
610
611function pagination_set_following(follow) {
612 setting_set("follow_playing", (follow?"1":"0"));
613 pagination.following = follow;
614 pagination_update_follow();
615}
616
617function pagination_toggle_following() {
618 pagination_set_following(!pagination_is_following());
619}
620
621function pagination_update_follow() {
622 if(!pagination.follow_button)
623 return;
624 if(pagination_is_following()) {
625 pagination.follow_button.src = IMAGE.PAGINATION_FOLLOW;
626 pagination.follow_button.title = LANG.PAGINATION_FOLLOW;
627 }
628 else {
629 pagination.follow_button.src = IMAGE.PAGINATION_NOFOLLOW;
630 pagination.follow_button.title =LANG.PAGINATION_NOFOLLOW;
631 }
632}
633
634/** left or right */
635function pagination_scroll_real(left) {
636 var l = pagination.list;
637 var adjust = 0;
638
639 if(left) {
640 if(l.scrollLeft>0)
641 adjust = -10;
642 else return;
643 }
644 else {
645 adjust = 10;
646 }
647 try {
648 l.scrollLeft += adjust;
649 if(pagination.scroll_id)
650 clearTimeout(pagination.scroll_id);
651 pagination.scroll_id = setTimeout(pagination_scroll_real, 50, left);
652 }catch(e) {debug(e.message);}
653}
654
655function pagination_post_pageswitch() {
656 pagination.need_update = false;
657 if(pagination.scroll_to_pos_after_switch!=false) {
658 var n = playlist_scroll_to_pos_real(pagination.scroll_to_pos_after_switch);
659 pagination.scroll_to_pos_after_switch = false;
660 if(n) {
661 unselect_all_nodes(playlist_element);
662 select_node(n);
663 }
664 }
665 else if(pagination_is_following()&&playing.show_node) {
666 playlist_scroll_to_pos_real(playing.pos);
667 }
668}
669
670
671/* Returns false if have to switch page, true otherwise */
672function playlist_scroll_to_playing() {
673 return playlist_scroll_to_pos(playing.pos);
674}
675
676/* set select to true if all other nodes should be unselected and the right node selected */
677function playlist_scroll_to_pos(pos, select) {
678 if(pagination.max>0) {
679 if(pos<0) pos = 0;
680 var page = Math.floor(pos/pagination.max);
681 if(page!=pagination.page) {
682 pagination_change_page(null, page);
683 if(select)
684 pagination.scroll_to_pos_after_switch = pos;
685 return false; // selecting handled in pagination_post_pageswitch
686 }
687 }
688 var n = playlist_scroll_to_pos_real(pos);
689 if(select) {
690 unselect_all_nodes(playlist_element);
691 select_node(n);
692 }
693 return true;
694}
695
696function playlist_scroll_to_pos_real(pos) {
697 if(pagination.max>0) {
698 pos = pos%pagination.max
699 }
700
701 if(pos<0) {
702 }
703 else if(pos<playlist_element.childNodes.length) {
704 var n = playlist_element.childNodes[pos];
705 window.scrollTo(0,n.offsetTop -20);
706 return n;
707 }
708 else if(playlist_element.childNodes.length) {//if something in playlist, nag about it
709 debug("scroll to node request outside range");
710 }
711 return null;
712}
713
714function get_pl_selection_range(invert) {
715 var c = playlist_element.childNodes;
716 var sel = "";
717 var pagination_add = invert&&pagination.max>0;
718
719 /* if we have pagination and not on page one, we need to add everything up until this page first */
720 if(pagination_add&&pagination.page>0) {
721 sel = add_range(sel, 0, pagination.max * pagination.page -1);
722 }
723
724 var tmp_start = null;
725 var tmp_stop = null;
726 var length = c.length;
727 for(var i=0; i<length; i++) {
728 var selected = is_node_selected(c[i]);
729 if(invert)
730 selected = !selected;
731 if(selected) {
732 if(!tmp_start)
733 tmp_start = c[i];
734 else tmp_stop = c[i];
735 }
736 else if(tmp_start) {
737 tmp_start = get_plpos(tmp_start);
738 if(tmp_stop)
739 tmp_stop = get_plpos(tmp_stop);
740 sel = add_range(sel, tmp_start, tmp_stop);
741 tmp_start = null;
742 tmp_stop = null;
743 }
744 }
745 if(tmp_start) {
746 tmp_start = get_plpos(tmp_start);
747 // todo: what if not proper last node
748 if(tmp_stop)
749 tmp_stop = get_plpos(tmp_stop);
750 sel = add_range(sel, tmp_start, tmp_stop);
751 }
752
753 // add after this page
754 if(pagination_add&&pagination.page+1<pagination.pages) {
755 sel = add_range(sel, (pagination.page+1)*pagination.max, playing.pl_size-1);
756 }
757 return sel;
758}
759
760function playlist_dblclick(elem, e) {
761 var id = get_plid(elem);
762 if(id>=0) {
763 var cmd = "act=play&id=" + get_plid(elem);
764 send_command(cmd);
765 }
766}
767
768function playlist_add_button(e) {
769 if(!playlist_add_popup) {
770 playlist_add_popup = playlist_add_create_content(
771 document.getElementById("playlist_add"));
772 }
773 stop_event(e);
774 playlist_add_popup.show();
775}
776
777function playlist_save_button(e) {
778 if(!playlist_save_popup) {
779 playlist_save_popup = playlist_save_create_content(
780 document.getElementById("playlist_save"));
781 }
782 stop_event(e);
783 playlist_save_popup.show();
784}
785
786/* these functions should be merged somehow */
787function playlist_add_create_content(padd) {
788 var cats = new Array(LANG.BY_URL); //, "From file", "Text");
789 var c = create_fragment();
790 var ul = create_node("ul");
791 ul.className = "playlist_popup";
792 c.appendChild(ul);
793 var li;
794 for(var i=0; i < cats.length; i++) {
795 li = add_li(ul, cats[i]);
796 li.className = "playlist_popup";
797 }
798 li = add_li(ul, LANG.CLOSE);
799 li.className = "playlist_popup";
800 add_listener(li, "click", playlist_add_close);
801 var d = create_node("div");
802 c.appendChild(d);
803
804 var tmp = create_node("input", "playlist_add_url");
805 add_listener(tmp, "keydown", playlist_add_by_url);
806 d.appendChild(tmp);
807
808 tmp = create_node("span");
809 d.appendChild(tmp);
810 tmp.className = "playlist_popup";
811 tmp.appendChild(create_txt(" Add"));
812 add_listener(tmp, "click", playlist_add_by_url);
813
814 var pop = new Popup(padd, c);
815 pop.popup.style.marginLeft = "-140px";
816 /* don't let the click get anywhere else either */
817 add_listener(pop.popup, "click", stop_event);
818 return pop;
819}
820
821function playlist_save_create_content(psave) {
822 var c = create_fragment();
823 var tmp = create_node("p");
824 tmp.className = "nomargin";
825 tmp.appendChild(create_txt(LANG.PL_SAVE_AS));
826 var close = create_node("span");
827 add_listener(close, "click", playlist_save_close);
828 close.appendChild(create_txt(LANG.CLOSE));
829 close.className = "playlist_popup";
830 tmp.appendChild(close);
831 tmp.appendChild(create_node("br"));
832 c.appendChild(tmp);
833 tmp = create_node("input", "playlist_save_box");
834 add_listener(tmp, "keydown", playlist_save_listener);
835 c.appendChild(tmp);
836 tmp = create_node("span");
837 tmp.appendChild(create_txt(" " + LANG.SAVE));
838 tmp.className = "playlist_popup";
839 add_listener(tmp, "click", playlist_save_listener);
840 c.appendChild(tmp);
841
842 var pop = new Popup(psave, c);
843 pop.popup.style.marginLeft = "-140px";
844 /* don't let the click get anywhere else either */
845 add_listener(pop.popup, "click", stop_event);
846 return pop;
847}
848
849function playlist_add_by_url(e) {
850 stop_propagation(e);
851 if((e.type=="keydown"&&e.keyCode==RETURN_KEY_CODE)||e.type=="click") {
852 stop_event(e);
853 var p = document.getElementById("playlist_add_url");
854 var url = p.value;
855 url = url.trim();
856 if(url.length>6) {
857 send_command("playlist_add_url=" + encodeURIComponent(url),
858 playlist_add_by_url_cb, LANG.WAIT_ADDING_PL);
859 p.value = "";
860 playlist_add_close();
861 }
862 }
863}
864
865function playlist_save_listener(e) {
866 stop_propagation(e);
867 if((e.type=="keydown"&&e.keyCode==RETURN_KEY_CODE)||e.type=="click") {
868 stop_event(e);
869 var p = document.getElementById("playlist_save_box");
870 var name = p.value;
871 name = name.trim();
872 if(name.length>0) {
873 send_command("playlist_save=" + encodeURIComponent(name), playlist_save_cb, LANG.PL_SAVING);
874 p.value = "";
875 playlist_save_popup.hide();
876 }
877 }
878}
879
880function playlist_add_by_url_cb(result) {
881 if(result=="failed") {
882 show_status_bar(LANG.E_FAILED_ADD_PL);
883 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
884 }
885 else {
886 }
887}
888
889function playlist_save_cb(result) {
890 if(result=="failed") {
891 show_status_bar(LANG.E_FAILED_SAVE_PL);
892 hide_status_bar(STATUS_DEFAULT_TIMEOUT);
893 }
894}
895
896function playlist_add_close(e) {
897 if(e)
898 stop_event(e);
899 if(playlist_add_popup)
900 playlist_add_popup.hide();
901}
902function playlist_save_close(e) {
903 if(e)
904 stop_event(e);
905 if(playlist_save_popup)
906 playlist_save_popup.hide();
907}
This page took 0.115816 seconds and 4 git commands to generate.