]> Joshua Wise's Git repositories - patchfork.git/blob - std/playlist.js
Update support for Amazon coverart grabbing (patch from Václav Nováček <waclaw66...
[patchfork.git] / std / playlist.js
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
21 var playlist_element = null;
22
23
24 function 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
85 function 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
95 function get_plid(node) {
96         return node.id.substring(7);
97 }
98
99 function get_plpos(node) {
100         return node.getAttribute("plpos");
101 }
102
103 function set_pl_position(node, new_pos) {
104         node.childNodes[0].childNodes[0].nodeValue = (new_pos+1);
105         node.setAttribute("plpos", new_pos);
106 }
107
108 function 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
115 function 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) */
122 function 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 */
145 function 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
156 function 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 */
174 function 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
198 function 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 */
268 function cclass_for_konqueror() {
269         playlist_element.className  = "";
270 }
271
272 function 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
279 function 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
458 function 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
480 function 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*/
497 function 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 */
525 function 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
545 function pagination_fetch_current_page() {
546         playing.pl_version = -1; 
547         pagination.need_update = true;
548         reschedule_update_now();
549 }
550
551 function 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
567 function 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
590 function 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
601 function 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
611 function pagination_set_following(follow) {
612         setting_set("follow_playing", (follow?"1":"0"));
613         pagination.following = follow;
614         pagination_update_follow();
615 }
616
617 function pagination_toggle_following() {
618         pagination_set_following(!pagination_is_following());
619 }
620
621 function 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 */
635 function 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
655 function 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 */
672 function 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 */
677 function 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
696 function 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
714 function 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
760 function 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
768 function 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
777 function 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 */
787 function 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
821 function 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
849 function 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
865 function 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
880 function 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
889 function 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
896 function playlist_add_close(e) {
897         if(e)
898                 stop_event(e);
899         if(playlist_add_popup)
900                 playlist_add_popup.hide();
901 }
902 function 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.121884 seconds and 4 git commands to generate.