spl.js 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521
  1. //--------------------------------------------------------------------------------------------------------------------------------
  2. // Playlist Functions
  3. //--------------------------------------------------------------------------------------------------------------------------------
  4. var AIRTIME = (function(AIRTIME){
  5. if (AIRTIME.playlist === undefined) {
  6. AIRTIME.playlist = {};
  7. }
  8. var mod = AIRTIME.playlist,
  9. viewport,
  10. $lib,
  11. $pl,
  12. $togglePl = $("<button id='pl_edit' class='btn btn-small' href='#' title='"+$.i18n._("Open Media Builder")+"'>"+$.i18n._("Open Media Builder")+"</button>"),
  13. widgetHeight,
  14. resizeTimeout,
  15. width;
  16. function isTimeValid(time) {
  17. //var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$");
  18. var regExpr = new RegExp("^\\d{2}[:]([0-5]){1}([0-9]){1}[:]([0-5]){1}([0-9]){1}([.]\\d{1})?$");
  19. return regExpr.test(time);
  20. }
  21. function isFadeValid(fade) {
  22. var regExpr = new RegExp("^\\d{1}(\\d{1})?([.]\\d{1})?$");
  23. return regExpr.test(fade);
  24. }
  25. function playlistError(json) {
  26. alert(json.error);
  27. openPlaylist(json);
  28. }
  29. function stopAudioPreview() {
  30. // stop any preview playing
  31. $('#jquery_jplayer_1').jPlayer('stop');
  32. }
  33. function highlightActive(el) {
  34. $(el).addClass("ui-state-active");
  35. }
  36. function unHighlightActive(el) {
  37. $(el).removeClass("ui-state-active");
  38. }
  39. function showError(el, error) {
  40. $(el).parent().next()
  41. .empty()
  42. .append(error)
  43. .show();
  44. }
  45. function hideError(el) {
  46. $(el).parent().next()
  47. .empty()
  48. .hide();
  49. }
  50. function changeCueIn(event) {
  51. event.stopPropagation();
  52. var span = $(this),
  53. id = span.parent().attr("id").split("_").pop(),
  54. url = baseUrl+"Playlist/set-cue",
  55. cueIn = $.trim(span.text()),
  56. li = span.parents("li"),
  57. unqid = li.attr("unqid"),
  58. lastMod = getModified(),
  59. type = $('#obj_type').val();
  60. if (!isTimeValid(cueIn)){
  61. showError(span, $.i18n._("please put in a time '00:00:00 (.0)'"));
  62. return;
  63. }
  64. $.post(url,
  65. {format: "json", cueIn: cueIn, id: id, modified: lastMod, type: type},
  66. function(json){
  67. if (json.error !== undefined){
  68. playlistError(json);
  69. return;
  70. }
  71. if (json.cue_error !== undefined) {
  72. showError(span, json.cue_error);
  73. return;
  74. }
  75. setPlaylistContent(json);
  76. li = $('#side_playlist li[unqid='+unqid+']');
  77. li.find(".cue-edit").toggle();
  78. highlightActive(li);
  79. highlightActive(li.find('.spl_cue'));
  80. });
  81. }
  82. function changeCueOut(event) {
  83. event.stopPropagation();
  84. var span = $(this),
  85. id = span.parent().attr("id").split("_").pop(),
  86. url = baseUrl+"Playlist/set-cue",
  87. cueOut = $.trim(span.text()),
  88. li = span.parents("li"),
  89. unqid = li.attr("unqid"),
  90. lastMod = getModified(),
  91. type = $('#obj_type').val();
  92. if (!isTimeValid(cueOut)){
  93. showError(span, $.i18n._("please put in a time '00:00:00 (.0)'"));
  94. return;
  95. }
  96. $.post(url,
  97. {format: "json", cueOut: cueOut, id: id, modified: lastMod, type: type},
  98. function(json){
  99. if (json.error !== undefined){
  100. playlistError(json);
  101. return;
  102. }
  103. if (json.cue_error !== undefined) {
  104. showError(span, json.cue_error);
  105. return;
  106. }
  107. setPlaylistContent(json);
  108. li = $('#side_playlist li[unqid='+unqid+']');
  109. li.find(".cue-edit").toggle();
  110. highlightActive(li);
  111. highlightActive(li.find('.spl_cue'));
  112. });
  113. }
  114. /* used from waveform pop-up */
  115. function changeCues($el, id, cueIn, cueOut) {
  116. var url = baseUrl+"Playlist/set-cue",
  117. lastMod = getModified(),
  118. type = $('#obj_type').val(),
  119. li,
  120. span;
  121. if (!isTimeValid(cueIn)){
  122. $el.find('.cue-in-error').val($.i18n._("please put in a time '00:00:00 (.0)'")).show();
  123. return;
  124. }
  125. else {
  126. $el.find('.cue-in-error').hide();
  127. }
  128. if (!isTimeValid(cueOut)){
  129. $el.find('.cue-out-error').val($.i18n._("please put in a time '00:00:00 (.0)'")).show();
  130. return;
  131. }
  132. else {
  133. $el.find('.cue-out-error').hide();
  134. }
  135. $.post(url,
  136. {format: "json", cueIn: cueIn, cueOut: cueOut, id: id, modified: lastMod, type: type},
  137. function(json){
  138. $el.dialog('destroy');
  139. $el.remove();
  140. if (json.error !== undefined){
  141. playlistError(json);
  142. return;
  143. }
  144. if (json.cue_error !== undefined) {
  145. li = $('#side_playlist li[unqid='+id+']');
  146. if (json.code === 0) {
  147. span = $('#spl_cue_in_'+id).find('span');
  148. showError(span, json.cue_error);
  149. span = $('#spl_cue_out_'+id).find('span');
  150. showError(span, json.cue_error);
  151. }
  152. else if (json.code === 1) {
  153. span = $('#spl_cue_in_'+id).find('span');
  154. showError(span, json.cue_error);
  155. }
  156. else if (json.code === 2) {
  157. span = $('#spl_cue_out_'+id).find('span');
  158. showError(span, json.cue_error);
  159. }
  160. return;
  161. }
  162. setPlaylistContent(json);
  163. li = $('#side_playlist li[unqid='+id+']');
  164. li.find(".cue-edit").toggle();
  165. highlightActive(li);
  166. highlightActive(li.find('.spl_cue'));
  167. });
  168. }
  169. /* used from waveform pop-up */
  170. function changeCrossfade($el, id1, id2, fadeIn, fadeOut, offset, id) {
  171. var url = baseUrl+"Playlist/set-crossfade",
  172. lastMod = getModified(),
  173. type = $('#obj_type').val();
  174. $.post(url,
  175. {format: "json", fadeIn: fadeIn, fadeOut: fadeOut, id1: id1, id2: id2, offset: offset, modified: lastMod, type: type},
  176. function(json){
  177. $el.dialog('destroy');
  178. $el.remove();
  179. if (json.error !== undefined){
  180. playlistError(json);
  181. return;
  182. }
  183. setPlaylistContent(json);
  184. $li = $('#side_playlist li[unqid='+id+']');
  185. $li.find('.crossfade').toggle();
  186. highlightActive($li.find('.spl_fade_control'));
  187. });
  188. }
  189. function changeFadeIn(event) {
  190. event.preventDefault();
  191. var span = $(this),
  192. id = span.parent().attr("id").split("_").pop(),
  193. url = baseUrl+"Playlist/set-fade",
  194. fadeIn = $.trim(span.text()),
  195. li = span.parents("li"),
  196. unqid = li.attr("unqid"),
  197. lastMod = getModified(),
  198. type = $('#obj_type').val();
  199. if (!isFadeValid(fadeIn)){
  200. showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
  201. return;
  202. }
  203. $.post(url,
  204. {format: "json", fadeIn: fadeIn, id: id, modified: lastMod, type: type},
  205. function(json){
  206. if (json.error !== undefined){
  207. playlistError(json);
  208. return;
  209. }
  210. if (json.fade_error !== undefined) {
  211. showError(span, json.fade_error);
  212. return;
  213. }
  214. setPlaylistContent(json);
  215. li = $('#side_playlist li[unqid='+unqid+']');
  216. li.find('.crossfade').toggle();
  217. highlightActive(li.find('.spl_fade_control'));
  218. });
  219. }
  220. function changeFadeOut(event) {
  221. event.stopPropagation();
  222. var span = $(this),
  223. id = span.parent().attr("id").split("_").pop(),
  224. url = baseUrl+"Playlist/set-fade",
  225. fadeOut = $.trim(span.text()),
  226. li = span.parents("li"),
  227. unqid = li.attr("unqid"),
  228. lastMod = getModified(),
  229. type = $('#obj_type').val();
  230. if (!isFadeValid(fadeOut)){
  231. showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
  232. return;
  233. }
  234. $.post(url,
  235. {format: "json", fadeOut: fadeOut, id: id, modified: lastMod, type: type},
  236. function(json){
  237. if (json.error !== undefined){
  238. playlistError(json);
  239. return;
  240. }
  241. if (json.fade_error !== undefined) {
  242. showError(span, json.fade_error);
  243. return;
  244. }
  245. setPlaylistContent(json);
  246. li = $('#side_playlist li[unqid='+unqid+']');
  247. li.find('.crossfade').toggle();
  248. highlightActive(li.find('.spl_fade_control'));
  249. });
  250. }
  251. function submitOnEnter(event) {
  252. //enter was pressed
  253. if(event.keyCode === 13) {
  254. event.preventDefault();
  255. $(this).blur();
  256. }
  257. }
  258. function openFadeEditor(event) {
  259. var li;
  260. event.stopPropagation();
  261. li = $(this).parents("li");
  262. li.find(".crossfade").toggle();
  263. if ($(this).hasClass("ui-state-active")) {
  264. unHighlightActive(this);
  265. }
  266. else {
  267. highlightActive(this);
  268. }
  269. }
  270. function openCueEditor(event) {
  271. var li, icon;
  272. event.stopPropagation();
  273. icon = $(this);
  274. li = $(this).parents("li");
  275. li.find(".cue-edit").toggle();
  276. if (li.hasClass("ui-state-active")) {
  277. unHighlightActive(li);
  278. unHighlightActive(icon);
  279. }
  280. else {
  281. highlightActive(li);
  282. highlightActive(icon);
  283. }
  284. }
  285. function editName() {
  286. var nameElement = $(this),
  287. lastMod = getModified(),
  288. type = $('#obj_type').val();
  289. //remove any newlines if user somehow snuck them in (easy to do if dragging/dropping text)
  290. nameElement.text(nameElement.text().replace("\n", ""));
  291. /* --until we decide whether Playlist name should autosave or not
  292. url = baseUrl+'Playlist/set-playlist-name';
  293. $.post(url,
  294. {format: "json", name: nameElement.text(), modified: lastMod, type: type},
  295. function(json){
  296. if (json.error !== undefined) {
  297. playlistError(json);
  298. }
  299. else {
  300. setModified(json.modified);
  301. nameElement.text(json.playlistName);
  302. redrawLib();
  303. }
  304. });
  305. */
  306. }
  307. function redrawLib() {
  308. var dt = $lib.find("#library_display").dataTable();
  309. dt.fnStandingRedraw();
  310. AIRTIME.library.redrawChosen();
  311. }
  312. function setPlaylistContent(json) {
  313. var $html = $(json.html);
  314. $('#spl_name > a')
  315. .empty()
  316. .append(json.name);
  317. $('#obj_length')
  318. .empty()
  319. .append(json.length);
  320. $('#fieldset-metadate_change textarea')
  321. .empty()
  322. .val(json.description);
  323. $('#spl_sortable').off('focusout keydown');
  324. $('#spl_sortable')
  325. .empty()
  326. .append($html);
  327. setCueEvents();
  328. setFadeEvents();
  329. setModified(json.modified);
  330. AIRTIME.playlist.validatePlaylistElements();
  331. redrawLib();
  332. }
  333. function setFadeIcon(){
  334. var contents = $("#spl_sortable");
  335. var show = contents.is(":visible");
  336. var empty = $(".spl_empty");
  337. if (!show || empty.length > 0) {
  338. $("#spl_crossfade").hide();
  339. } else {
  340. //get list of playlist contents
  341. var list = contents.children();
  342. //if first and last items are blocks, hide the fade icon
  343. var first = list.first();
  344. var last = list.last();
  345. if (first.find(':first-child').children().attr('blockid') !== undefined &&
  346. last.find(':first-child').children().attr('blockid') !== undefined) {
  347. $("#spl_crossfade").hide();
  348. } else {
  349. $("#spl_crossfade").show();
  350. }
  351. }
  352. }
  353. function getId() {
  354. return parseInt($("#obj_id").val(), 10);
  355. }
  356. function getModified() {
  357. return parseInt($("#obj_lastMod").val(), 10);
  358. }
  359. function setModified(modified) {
  360. $("#obj_lastMod").val(modified);
  361. }
  362. function openPlaylist(json) {
  363. $("#side_playlist")
  364. .empty()
  365. .append(json.html);
  366. setUpPlaylist();
  367. setCueEvents();
  368. setFadeEvents();
  369. // functions in smart_blockbuilder.js
  370. setupUI();
  371. appendAddButton();
  372. appendModAddButton();
  373. removeButtonCheck();
  374. }
  375. function openPlaylistPanel() {
  376. var screenWidth = Math.floor(viewport.width - 40);
  377. viewport = AIRTIME.utilities.findViewportDimensions();
  378. widgetHeight = viewport.height - 185;
  379. $lib.width(Math.floor(screenWidth * 0.53));
  380. $pl.show().width(Math.floor(screenWidth * 0.44));
  381. $pl.height(widgetHeight);
  382. $("#pl_edit").hide();
  383. }
  384. //Purpose of this function is to iterate over all playlist elements
  385. //and verify whether they can be previewed by the browser or not. If not
  386. //then the playlist element is greyed out
  387. mod.validatePlaylistElements = function(){
  388. $.each($("div .big_play"), function(index, value){
  389. if ($(value).attr('blockId') === undefined) {
  390. var mime = $(value).attr("data-mime-type");
  391. //If mime is undefined it is likely because the file was
  392. //deleted from the library. This case is handled in mod.onReady()
  393. if (mime !== undefined) {
  394. if (isAudioSupported(mime)) {
  395. $(value).bind("click", openAudioPreview);
  396. } else {
  397. $(value).attr("class", "big_play_disabled dark_class");
  398. $(value).qtip({
  399. content: $.i18n._("Your browser does not support playing this file type: ")+ mime,
  400. show: 'mouseover',
  401. hide: {
  402. delay: 500,
  403. fixed: true
  404. },
  405. style: {
  406. border: {
  407. width: 0,
  408. radius: 4
  409. },
  410. classes: "ui-tooltip-dark ui-tooltip-rounded"
  411. },
  412. position: {
  413. my: "left bottom",
  414. at: "right center"
  415. },
  416. })
  417. }
  418. }
  419. } else {
  420. if ($(value).attr('blocktype') === 'dynamic') {
  421. $(value).attr("class", "big_play_disabled dark_class");
  422. $(value).qtip({
  423. content: $.i18n._('Dynamic block is not previewable'),
  424. show: 'mouseover',
  425. hide: {
  426. delay: 500,
  427. fixed: true
  428. },
  429. style: {
  430. border: {
  431. width: 0,
  432. radius: 4
  433. },
  434. classes: "ui-tooltip-dark ui-tooltip-rounded"
  435. },
  436. position: {
  437. my: "left bottom",
  438. at: "right center"
  439. },
  440. })
  441. } else {
  442. $(value).bind("click", openAudioPreview);
  443. }
  444. }
  445. });
  446. }
  447. //sets events dynamically for playlist entries (each row in the playlist)
  448. function setPlaylistEntryEvents() {
  449. $pl.delegate("#spl_sortable .ui-icon-closethick",
  450. {"click": function(ev){
  451. var id;
  452. id = parseInt($(this).attr("id").split("_").pop(), 10);
  453. AIRTIME.playlist.fnDeleteItems([id]);
  454. }});
  455. $pl.delegate(".spl_fade_control",
  456. {"click": openFadeEditor});
  457. $pl.delegate(".spl_cue",
  458. {"click": openCueEditor});
  459. $pl.delegate(".spl_block_expand",
  460. {"click": function(ev){
  461. var id = parseInt($(this).attr("id").split("_").pop(), 10);
  462. var blockId = parseInt($(this).attr("blockId"), 10);
  463. if ($(this).hasClass('close')) {
  464. var sUrl = baseUrl+"playlist/get-block-info";
  465. mod.disableUI();
  466. $.post(sUrl, {format:"json", id:blockId}, function(data){
  467. $html = "";
  468. var isStatic = data.isStatic;
  469. delete data.type;
  470. if (isStatic) {
  471. $.each(data, function(index, ele){
  472. if (ele.track_title !== undefined) {
  473. if (ele.creator === null) {
  474. ele.creator = "";
  475. }
  476. if (ele.track_title === null) {
  477. ele.track_title = "";
  478. }
  479. $html += "<li>" +
  480. "<span class='block-item-title'>"+ele.track_title+" - </span>" +
  481. "<span class='block-item-author'>"+ele.creator+"</span>" +
  482. "<span class='block-item-time'>"+ele.length+"</span>" +
  483. "</li>";
  484. }
  485. })
  486. } else {
  487. for (var key in data.crit){
  488. $.each(data.crit[key], function(index, ele){
  489. var extra = (ele['extra']==null)?"":"- "+ele['extra'];
  490. $html += "<li>" +
  491. "<span class='block-item-title'>"+ele['display_name']+"</span>" +
  492. "<span class='block-item-criteria'>"+ele['display_modifier']+"</span>" +
  493. "<span class='block-item-criteria'>"+ele['value']+"</span>" +
  494. "<span class='block-item-criteria'>"+extra+"</span>" +
  495. "</li>";
  496. });
  497. }
  498. $html += "<li><br /><span class='block-item-title'>"+$.i18n._("Limit to: ")+data.limit.value+" "+data.limit.display_modifier+"</span></li>";
  499. }
  500. $pl.find("#block_"+id+"_info").html($html).show();
  501. mod.enableUI();
  502. });
  503. $(this).removeClass('close');
  504. } else {
  505. $pl.find("#block_"+id+"_info").html("").hide();
  506. $(this).addClass('close');
  507. }
  508. }});
  509. }
  510. //sets events dynamically for the cue editor.
  511. function setCueEvents() {
  512. var temp = $('#spl_sortable');
  513. temp.on("focusout", ".spl_cue_in span", changeCueIn);
  514. temp.on("keydown", ".spl_cue_in span", submitOnEnter);
  515. temp.on("focusout", ".spl_cue_out span", changeCueOut);
  516. temp.on("keydown", ".spl_cue_out span", submitOnEnter);
  517. //remove show waveform buttons since web audio api is not supported.
  518. if (!(window.AudioContext || window.webkitAudioContext)) {
  519. temp.find('.pl-waveform-cues-btn')
  520. .parent()
  521. .html($.i18n._("Waveform features are available in a browser supporting the Web Audio API"));
  522. }
  523. }
  524. //sets events dynamically for the fade editor.
  525. function setFadeEvents() {
  526. var temp = $('#spl_sortable');
  527. temp.on("focusout", ".spl_fade_in span", changeFadeIn);
  528. temp.on("keydown", ".spl_fade_in span", submitOnEnter);
  529. temp.on("focusout", ".spl_fade_out span", changeFadeOut);
  530. temp.on("keydown", ".spl_fade_out span", submitOnEnter);
  531. //remove show waveform buttons since web audio api is not supported.
  532. if (!(window.AudioContext || window.webkitAudioContext)) {
  533. temp.find('.pl-waveform-fades-btn')
  534. .parent()
  535. .html($.i18n._("Waveform features are available in a browser supporting the Web Audio API"));
  536. }
  537. }
  538. function initialEvents() {
  539. var cachedDescription;
  540. //main playlist fades events
  541. $pl.on("click", "#spl_crossfade", function() {
  542. var lastMod = getModified(),
  543. type = $('#obj_type').val();
  544. if ($(this).hasClass("ui-state-active")) {
  545. $(this).removeClass("ui-state-active");
  546. $pl.find("#crossfade_main").hide();
  547. }
  548. else {
  549. $(this).addClass("ui-state-active");
  550. var url = baseUrl+'Playlist/get-playlist-fades';
  551. $.post(url,
  552. {format: "json", modified: lastMod, type: type},
  553. function(json){
  554. if (json.error !== undefined){
  555. playlistError(json);
  556. }
  557. else {
  558. var fadeIn = $pl.find("span.spl_main_fade_in");
  559. var fadeOut = $pl.find("span.spl_main_fade_out");
  560. if (json.fadeIn == null) {
  561. fadeIn.parent().prev().hide();
  562. fadeIn.hide();
  563. } else {
  564. fadeIn.parent().prev().show();
  565. fadeIn.show();
  566. fadeIn.empty().append(json.fadeIn);
  567. }
  568. if (json.fadeOut == null) {
  569. fadeOut.parent().prev().hide();
  570. fadeOut.hide();
  571. } else {
  572. fadeOut.parent().prev().show();
  573. fadeOut.show();
  574. fadeOut.empty().append(json.fadeOut);
  575. }
  576. if (json.fadeIn != null || json.fadeOut != null) {
  577. $pl.find("#crossfade_main").show();
  578. }
  579. }
  580. });
  581. }
  582. });
  583. $pl.on("blur", "span.spl_main_fade_in", function(event){
  584. event.stopPropagation();
  585. var url = baseUrl+"Playlist/set-playlist-fades",
  586. span = $(this),
  587. fadeIn = $.trim(span.text()),
  588. lastMod = getModified(),
  589. type = $('#obj_type').val();
  590. if (!isFadeValid(fadeIn)){
  591. showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
  592. return;
  593. }
  594. $.post(url,
  595. {format: "json", fadeIn: fadeIn, modified: lastMod, type: type},
  596. function(json){
  597. hideError(span);
  598. if (json.modified !== undefined) {
  599. setModified(json.modified);
  600. }
  601. });
  602. });
  603. $pl.on("blur", "span.spl_main_fade_out", function(event){
  604. event.stopPropagation();
  605. var url = baseUrl+"Playlist/set-playlist-fades",
  606. span = $(this),
  607. fadeOut = $.trim(span.text()),
  608. lastMod = getModified(),
  609. type = $('#obj_type').val();
  610. if (!isFadeValid(fadeOut)){
  611. showError(span, $.i18n._("please put in a time in seconds '00 (.0)'"));
  612. return;
  613. }
  614. $.post(url,
  615. {format: "json", fadeOut: fadeOut, modified: lastMod, type: type},
  616. function(json){
  617. hideError(span);
  618. if (json.modified !== undefined) {
  619. setModified(json.modified);
  620. }
  621. });
  622. });
  623. $pl.on("keydown", "span.spl_main_fade_in, span.spl_main_fade_out", submitOnEnter);
  624. $pl.on("click", "#crossfade_main > .ui-icon-closethick", function(){
  625. $pl.find("#spl_crossfade").removeClass("ui-state-active");
  626. $pl.find("#crossfade_main").hide();
  627. });
  628. //end main playlist fades.
  629. //edit playlist name event
  630. $pl.on("keydown", "#playlist_name_display", submitOnEnter);
  631. $pl.on("blur", "#playlist_name_display", editName);
  632. //edit playlist description events
  633. $pl.on("click", "legend", function(){
  634. var $fs = $(this).parents("fieldset");
  635. if ($fs.hasClass("closed")) {
  636. cachedDescription = $fs.find("textarea").val();
  637. $fs.removeClass("closed");
  638. }
  639. else {
  640. $fs.addClass("closed");
  641. }
  642. });
  643. $pl.on("click", 'button[id="playlist_shuffle_button"]', function(){
  644. obj_id = $('input[id="obj_id"]').val();
  645. url = baseUrl+"Playlist/shuffle";
  646. enableLoadingIcon();
  647. $.post(url, {format: "json", obj_id: obj_id}, function(json){
  648. if (json.error !== undefined) {
  649. alert(json.error);
  650. }
  651. AIRTIME.playlist.fnOpenPlaylist(json);
  652. if (json.result == "0") {
  653. $pl.find('.success').text($.i18n._('Playlist shuffled'));
  654. $pl.find('.success').show();
  655. }
  656. disableLoadingIcon();
  657. setTimeout(removeSuccessMsg, 5000);
  658. });
  659. })
  660. $pl.on("click", "#webstream_save", function(){
  661. //get all fields and POST to server
  662. //description
  663. //stream url
  664. //default_length
  665. //playlist name
  666. var id = $pl.find("#obj_id").attr("value");
  667. var description = $pl.find("#description").val();
  668. var streamurl = $pl.find("#streamurl-element input").val();
  669. var length = $pl.find("#streamlength-element input").val();
  670. var name = $pl.find("#playlist_name_display").text();
  671. //hide any previous errors (if any)
  672. $("#side_playlist .errors").empty().hide();
  673. var url = baseUrl+'Webstream/save';
  674. $.post(url,
  675. {format: "json", id:id, description: description, url:streamurl, length: length, name: name},
  676. function(json){
  677. if (json.analysis){
  678. for (var s in json.analysis){
  679. var field = json.analysis[s];
  680. if (!field[0]) {
  681. var elemId = "#"+s+"-error";
  682. var $div = $("#side_playlist " + elemId).text(field[1]).show();
  683. }
  684. }
  685. } else {
  686. var $status = $("#side_playlist .status");
  687. $status.html(json.statusMessage);
  688. $status.show();
  689. setTimeout(function(){$status.fadeOut("slow", function(){$status.empty()})}, 5000);
  690. var $ws_id = $("#obj_id");
  691. $ws_id.attr("value", json.streamId);
  692. var $ws_id = $("#ws_delete");
  693. $ws_id.show();
  694. var length = $("#side_playlist #ws_length");
  695. length.text(json.length);
  696. //redraw the library to show the new webstream
  697. redrawLib();
  698. }
  699. });
  700. });
  701. $lib.on("click", "#pl_edit", function() {
  702. openPlaylistPanel();
  703. $.ajax( {
  704. url : baseUrl+"usersettings/set-library-screen-settings",
  705. type : "POST",
  706. data : {
  707. settings : {
  708. playlist : true
  709. },
  710. format : "json"
  711. },
  712. dataType : "json"
  713. });
  714. });
  715. $pl.on("click", "#lib_pl_close", function() {
  716. var screenWidth = Math.floor(viewport.width - 40);
  717. $pl.hide();
  718. $lib.width(screenWidth).find("#library_display_length").append($togglePl.show());
  719. $.ajax( {
  720. url : baseUrl+"usersettings/set-library-screen-settings",
  721. type : "POST",
  722. data : {
  723. settings : {
  724. playlist : false
  725. },
  726. format : "json"
  727. },
  728. dataType : "json"
  729. });
  730. });
  731. $('#save_button').live("click", function(event){
  732. /* Smart blocks: get name, description, and criteria
  733. * Playlists: get name, description
  734. */
  735. var criteria = $('form').serializeArray(),
  736. block_name = $('#playlist_name_display').text(),
  737. block_desc = $('textarea[name="description"]').val(),
  738. save_action = baseUrl+'Playlist/save',
  739. obj_id = $('input[id="obj_id"]').val(),
  740. obj_type = $('#obj_type').val(),
  741. lastMod = getModified(),
  742. dt = $('table[id="library_display"]').dataTable();
  743. enableLoadingIcon();
  744. $.post(save_action,
  745. {format: "json", data: criteria, name: block_name, description: block_desc, obj_id: obj_id, type: obj_type, modified: lastMod},
  746. function(json){
  747. if (json.error !== undefined) {
  748. alert(json.error);
  749. }
  750. if (json.html !== undefined) {
  751. AIRTIME.playlist.fnOpenPlaylist(json);
  752. }
  753. setModified(json.modified);
  754. if (obj_type == "block") {
  755. callback(json, "save");
  756. } else {
  757. $('.success').text($.i18n._('Playlist saved'));
  758. $('.success').show();
  759. setTimeout(removeSuccessMsg, 5000);
  760. dt.fnStandingRedraw();
  761. }
  762. setFadeIcon();
  763. disableLoadingIcon();
  764. }
  765. );
  766. });
  767. $("#pl-bl-clear-content").live("click", function(event) {
  768. var sUrl = baseUrl+"playlist/empty-content",
  769. oData = {};
  770. playlistRequest(sUrl, oData);
  771. });
  772. }
  773. function setUpPlaylist() {
  774. var sortableConf;
  775. sortableConf = (function(){
  776. var aReceiveItems,
  777. html,
  778. fnReceive,
  779. fnUpdate;
  780. fnReceive = function(event, ui) {
  781. var aItems = [],
  782. aSelected,
  783. i,
  784. length;
  785. AIRTIME.library.addToChosen(ui.item);
  786. //filter out anything that isn't an audiofile.
  787. aSelected = AIRTIME.library.getSelectedData();
  788. for (i = 0, length = aSelected.length; i < length; i++) {
  789. aItems.push(new Array(aSelected[i].id, aSelected[i].ftype));
  790. }
  791. aReceiveItems = aItems;
  792. html = ui.helper.html();
  793. AIRTIME.library.removeFromChosen(ui.item);
  794. };
  795. fnUpdate = function(event, ui) {
  796. var prev,
  797. aItems = [],
  798. iAfter,
  799. sAddType;
  800. prev = ui.item.prev();
  801. if (prev.hasClass("spl_empty") || prev.length === 0) {
  802. iAfter = undefined;
  803. sAddType = 'before';
  804. }
  805. else {
  806. iAfter = parseInt(prev.attr("id").split("_").pop(), 10);
  807. sAddType = 'after';
  808. }
  809. //item was dragged in from library datatable
  810. if (aReceiveItems !== undefined) {
  811. $pl.find("tr.ui-draggable")
  812. .after(html)
  813. .empty();
  814. aItems = aReceiveItems;
  815. aReceiveItems = undefined;
  816. AIRTIME.playlist.fnAddItems(aItems, iAfter, sAddType);
  817. }
  818. //item was reordered.
  819. else {
  820. aItems.push(parseInt(ui.item.attr("id").split("_").pop(), 10));
  821. AIRTIME.playlist.fnMoveItems(aItems, iAfter);
  822. }
  823. };
  824. return {
  825. items: 'li',
  826. //hack taken from
  827. //http://stackoverflow.com/questions/2150002/jquery-ui-sortable-how-can-i-change-the-appearance-of-the-placeholder-object
  828. placeholder: {
  829. element: function(currentItem) {
  830. return $('<li class="placeholder ui-state-highlight"></li>')[0];
  831. },
  832. update: function(container, p) {
  833. return;
  834. }
  835. },
  836. forcePlaceholderSize: true,
  837. handle: 'div.list-item-container',
  838. start: function(event, ui) {
  839. ui.placeholder.height(56);
  840. },
  841. receive: fnReceive,
  842. update: fnUpdate
  843. };
  844. }());
  845. $pl.find("#spl_sortable").sortable(sortableConf);
  846. AIRTIME.playlist.validatePlaylistElements();
  847. }
  848. mod.fnNew = function() {
  849. var url = baseUrl+'Playlist/new';
  850. stopAudioPreview();
  851. $.post(url,
  852. {format: "json", type: 'playlist'},
  853. function(json){
  854. openPlaylist(json);
  855. redrawLib();
  856. });
  857. };
  858. mod.fnWsNew = function() {
  859. var url = baseUrl+'Webstream/new';
  860. stopAudioPreview();
  861. $.post(url,
  862. {format: "json"},
  863. function(json){
  864. openPlaylist(json);
  865. redrawLib();
  866. });
  867. };
  868. mod.fnNewBlock = function() {
  869. var url = baseUrl+'Playlist/new';
  870. stopAudioPreview();
  871. $.post(url,
  872. {format: "json", type: 'block'},
  873. function(json){
  874. openPlaylist(json);
  875. redrawLib();
  876. });
  877. };
  878. mod.fnEdit = function(id, type, url) {
  879. if ($pl.is(":hidden")) {
  880. openPlaylistPanel();
  881. }
  882. stopAudioPreview();
  883. $.post(url,
  884. {format: "json", id: id, type: type},
  885. function(json){
  886. openPlaylist(json);
  887. });
  888. };
  889. mod.fnDelete = function(plid) {
  890. var url, id, lastMod;
  891. stopAudioPreview();
  892. id = (plid === undefined) ? getId() : plid;
  893. lastMod = getModified();
  894. type = $('#obj_type').val();
  895. url = baseUrl+'Playlist/delete';
  896. $.post(url,
  897. {format: "json", ids: id, modified: lastMod, type: type},
  898. function(json){
  899. openPlaylist(json);
  900. redrawLib();
  901. });
  902. };
  903. mod.fnWsDelete = function(wsid) {
  904. var url, id, lastMod;
  905. stopAudioPreview();
  906. id = (wsid === undefined) ? getId() : wsid;
  907. lastMod = getModified();
  908. type = $('#obj_type').val();
  909. url = baseUrl+'Webstream/delete';
  910. $.post(url,
  911. {format: "json", ids: id, modified: lastMod, type: type},
  912. function(json){
  913. openPlaylist(json);
  914. redrawLib();
  915. });
  916. };
  917. mod.disableUI = function() {
  918. $lib.block({
  919. message: "",
  920. theme: true,
  921. applyPlatformOpacityRules: false
  922. });
  923. $pl.block({
  924. message: "",
  925. theme: true,
  926. applyPlatformOpacityRules: false
  927. });
  928. };
  929. mod.fnOpenPlaylist = function(json) {
  930. openPlaylist(json);
  931. };
  932. mod.enableUI = function() {
  933. $lib.unblock();
  934. $pl.unblock();
  935. //Block UI changes the postion to relative to display the messages.
  936. $lib.css("position", "static");
  937. $pl.css("position", "static");
  938. setupUI();
  939. };
  940. function playlistResponse(json){
  941. if (json.error !== undefined) {
  942. playlistError(json);
  943. }
  944. else {
  945. setPlaylistContent(json);
  946. setFadeIcon();
  947. }
  948. mod.enableUI();
  949. }
  950. function playlistRequest(sUrl, oData) {
  951. var lastMod,
  952. obj_type = $('#obj_type').val();
  953. mod.disableUI();
  954. lastMod = getModified();
  955. oData["modified"] = lastMod;
  956. oData["obj_type"] = obj_type;
  957. oData["format"] = "json";
  958. $.post(
  959. sUrl,
  960. oData,
  961. playlistResponse
  962. );
  963. }
  964. mod.fnAddItems = function(aItems, iAfter, sAddType) {
  965. var sUrl = baseUrl+"playlist/add-items";
  966. oData = {"aItems": aItems, "afterItem": iAfter, "type": sAddType};
  967. playlistRequest(sUrl, oData);
  968. };
  969. mod.fnMoveItems = function(aIds, iAfter) {
  970. var sUrl = baseUrl+"playlist/move-items",
  971. oData = {"ids": aIds, "afterItem": iAfter};
  972. playlistRequest(sUrl, oData);
  973. };
  974. mod.fnDeleteItems = function(aItems) {
  975. var sUrl = baseUrl+"playlist/delete-items",
  976. oData = {"ids": aItems};
  977. playlistRequest(sUrl, oData);
  978. };
  979. mod.showFadesWaveform = function(e) {
  980. var $el = $(e.target),
  981. $parent = $el.parents("dl"),
  982. $li = $el.parents("li"),
  983. $fadeOut = $parent.find(".spl_fade_out"),
  984. $fadeIn = $parent.find(".spl_fade_in"),
  985. $html = $($("#tmpl-pl-fades").html()),
  986. tracks = [],
  987. dim = AIRTIME.utilities.findViewportDimensions(),
  988. playlistEditor,
  989. id1, id2,
  990. id = $li.attr("unqid");
  991. function removeDialog() {
  992. playlistEditor.stop();
  993. $html.dialog("destroy");
  994. $html.remove();
  995. }
  996. if ($fadeOut.length > 0) {
  997. tracks.push({
  998. src: $fadeOut.data("fadeout"),
  999. cuein: $fadeOut.data("cuein"),
  1000. cueout: $fadeOut.data("cueout"),
  1001. fades: [{
  1002. shape: $fadeOut.data("type"),
  1003. type: "FadeOut",
  1004. end: $fadeOut.data("cueout") - $fadeOut.data("cuein"),
  1005. start: $fadeOut.data("cueout") - $fadeOut.data("cuein") - $fadeOut.data("length")
  1006. }],
  1007. states: {
  1008. 'fadein': false,
  1009. 'shift': false
  1010. }
  1011. });
  1012. id1 = $fadeOut.data("item");
  1013. }
  1014. if ($fadeIn.length > 0) {
  1015. tracks.push({
  1016. src: $fadeIn.data("fadein"),
  1017. start: $fadeIn.data("offset"),
  1018. cuein: $fadeIn.data("cuein"),
  1019. cueout: $fadeIn.data("cueout"),
  1020. fades: [{
  1021. shape: $fadeIn.data("type"),
  1022. type: "FadeIn",
  1023. end: $fadeIn.data("length"),
  1024. start: 0
  1025. }],
  1026. states: {
  1027. 'fadeout': false,
  1028. 'shift': false
  1029. }
  1030. });
  1031. id2 = $fadeIn.data("item");
  1032. }
  1033. //set the first track to not be moveable (might only be one track depending on what follows)
  1034. //tracks[0].states["shift"] = false;
  1035. $html.dialog({
  1036. modal: true,
  1037. title: $.i18n._("Fade Editor"),
  1038. show: 'clip',
  1039. hide: 'clip',
  1040. width: dim.width - 100,
  1041. height: 350,
  1042. buttons: [
  1043. {text: $.i18n._("Cancel"), class: "btn btn-small", click: removeDialog},
  1044. {text: $.i18n._("Save"), class: "btn btn-small btn-inverse", click: function() {
  1045. var json = playlistEditor.getJson(),
  1046. offset,
  1047. fadeIn, fadeOut,
  1048. fade;
  1049. playlistEditor.stop();
  1050. if (json.length === 0)
  1051. {
  1052. id1 = undefined;
  1053. id2 = undefined;
  1054. }
  1055. else if (json.length === 1) {
  1056. fade = json[0]["fades"][0];
  1057. if (fade["type"] === "FadeOut") {
  1058. fadeOut = fade["end"] - fade["start"];
  1059. id2 = undefined; //incase of track decode error.
  1060. }
  1061. else {
  1062. fadeIn = fade["end"] - fade["start"];
  1063. id1 = undefined; //incase of track decode error.
  1064. }
  1065. }
  1066. else {
  1067. offset = json[0]["end"] - json[1]["start"];
  1068. fade = json[0]["fades"][0];
  1069. fadeOut = fade["end"] - fade["start"];
  1070. fade = json[1]["fades"][0];
  1071. fadeIn = fade["end"] - fade["start"];
  1072. }
  1073. fadeIn = (fadeIn === undefined) ? undefined : fadeIn.toFixed(1);
  1074. fadeOut = (fadeOut === undefined) ? undefined : fadeOut.toFixed(1);
  1075. changeCrossfade($html, id1, id2, fadeIn, fadeOut, offset, id);
  1076. }}
  1077. ],
  1078. open: function (event, ui) {
  1079. var config = new Config({
  1080. resolution: 15000,
  1081. state: "cursor",
  1082. mono: true,
  1083. timescale: true,
  1084. waveHeight: 80,
  1085. container: $html[0],
  1086. UITheme: "jQueryUI",
  1087. timeFormat: 'hh:mm:ss.u'
  1088. });
  1089. playlistEditor = new PlaylistEditor();
  1090. playlistEditor.setConfig(config);
  1091. playlistEditor.init(tracks);
  1092. },
  1093. close: removeDialog,
  1094. resizeStop: function(event, ui) {
  1095. playlistEditor.resize();
  1096. }
  1097. });
  1098. };
  1099. mod.showCuesWaveform = function(e) {
  1100. var $el = $(e.target),
  1101. $li = $el.parents("li"),
  1102. id = $li.attr("unqid"),
  1103. $parent = $el.parent(),
  1104. uri = $parent.data("uri"),
  1105. $html = $($("#tmpl-pl-cues").html()),
  1106. cueIn = $li.find('.spl_cue_in').data("cueIn"),
  1107. cueOut = $li.find('.spl_cue_out').data("cueOut"),
  1108. cueInSec = $li.find('.spl_cue_in').data("cueSec"),
  1109. cueOutSec = $li.find('.spl_cue_out').data("cueSec"),
  1110. tracks = [{
  1111. src: uri,
  1112. selected: {
  1113. start: cueInSec,
  1114. end: cueOutSec
  1115. }
  1116. }],
  1117. dim = AIRTIME.utilities.findViewportDimensions(),
  1118. playlistEditor;
  1119. function removeDialog() {
  1120. playlistEditor.stop();
  1121. $html.dialog("destroy");
  1122. $html.remove();
  1123. }
  1124. $html.find('.editor-cue-in').html(cueIn);
  1125. $html.find('.editor-cue-out').html(cueOut);
  1126. $html.on("click", ".set-cue-in", function(e) {
  1127. var cueIn = $html.find('.audio_start').val();
  1128. $html.find('.editor-cue-in').html(cueIn);
  1129. });
  1130. $html.on("click", ".set-cue-out", function(e) {
  1131. var cueOut = $html.find('.audio_end').val();
  1132. $html.find('.editor-cue-out').html(cueOut);
  1133. });
  1134. $html.dialog({
  1135. modal: true,
  1136. title: $.i18n._("Cue Editor"),
  1137. show: 'clip',
  1138. hide: 'clip',
  1139. width: dim.width - 100,
  1140. height: 325,
  1141. buttons: [
  1142. {text: $.i18n._("Cancel"), class: "btn btn-small", click: removeDialog},
  1143. {text: $.i18n._("Save"), class: "btn btn-small btn-inverse", click: function() {
  1144. var cueIn = $html.find('.editor-cue-in').html(),
  1145. cueOut = $html.find('.editor-cue-out').html();
  1146. playlistEditor.stop();
  1147. changeCues($html, id, cueIn, cueOut);
  1148. }}
  1149. ],
  1150. open: function (event, ui) {
  1151. var config = new Config({
  1152. resolution: 15000,
  1153. mono: true,
  1154. timescale: true,
  1155. waveHeight: 80,
  1156. container: $html[0],
  1157. UITheme: "jQueryUI",
  1158. timeFormat: 'hh:mm:ss.u'
  1159. });
  1160. playlistEditor = new PlaylistEditor();
  1161. playlistEditor.setConfig(config);
  1162. playlistEditor.init(tracks);
  1163. },
  1164. close: removeDialog,
  1165. resizeStop: function(event, ui) {
  1166. playlistEditor.resize();
  1167. }
  1168. });
  1169. };
  1170. mod.init = function() {
  1171. /*
  1172. $.contextMenu({
  1173. selector: '#spl_new, #ws_new',
  1174. trigger: "left",
  1175. ignoreRightClick: true,
  1176. items: {
  1177. "sp": {name: "New Playlist", callback: AIRTIME.playlist.fnNew},
  1178. "sb": {name: "New Smart Block", callback: AIRTIME.playlist.fnNewBlock},
  1179. "ws": {name: "New Webstream", callback: AIRTIME.playlist.fnWsNew}
  1180. }
  1181. });
  1182. */
  1183. $('#lib-new-pl').live('click', function(){AIRTIME.playlist.fnNew();});
  1184. $('#lib-new-bl').live('click', function(){AIRTIME.playlist.fnNewBlock();});
  1185. $('#lib-new-ws').live('click', function(){AIRTIME.playlist.fnWsNew();});
  1186. /*
  1187. $pl.delegate("#spl_new",
  1188. {"click": AIRTIME.playlist.fnNew});*/
  1189. $pl.delegate("#spl_delete", {"click": function(ev){
  1190. AIRTIME.playlist.fnDelete();
  1191. }});
  1192. $pl.delegate("#ws_delete", {"click": function(ev){
  1193. AIRTIME.playlist.fnWsDelete();
  1194. }});
  1195. $pl.delegate(".pl-waveform-cues-btn", {"click": function(ev){
  1196. AIRTIME.playlist.showCuesWaveform(ev);
  1197. }});
  1198. $pl.delegate(".pl-waveform-fades-btn", {"click": function(ev){
  1199. AIRTIME.playlist.showFadesWaveform(ev);
  1200. }});
  1201. setPlaylistEntryEvents();
  1202. setCueEvents();
  1203. setFadeEvents();
  1204. setFadeIcon();
  1205. initialEvents();
  1206. setUpPlaylist();
  1207. };
  1208. function setWidgetSize() {
  1209. viewport = AIRTIME.utilities.findViewportDimensions();
  1210. widgetHeight = viewport.height - 185;
  1211. width = Math.floor(viewport.width - 80);
  1212. var libTableHeight = widgetHeight - 175;
  1213. if (!$pl.is(':hidden')) {
  1214. $lib.height(widgetHeight)
  1215. .find(".dataTables_scrolling")
  1216. .css("max-height", libTableHeight)
  1217. .end()
  1218. .width(Math.floor(width * 0.55));
  1219. $pl.height(widgetHeight)
  1220. .width(Math.floor(width * 0.45));
  1221. } else {
  1222. $lib.height(widgetHeight)
  1223. .find(".dataTables_scrolling")
  1224. .css("max-height", libTableHeight)
  1225. .end()
  1226. .width(width + 40);
  1227. }
  1228. }
  1229. mod.onReady = function() {
  1230. $lib = $("#library_content");
  1231. $pl = $("#side_playlist");
  1232. setWidgetSize();
  1233. AIRTIME.library.libraryInit();
  1234. AIRTIME.playlist.init();
  1235. if ($pl.is(':hidden')) {
  1236. $lib.find("#library_display_length").append($togglePl.show());
  1237. }
  1238. $pl.find(".ui-icon-alert").qtip({
  1239. content: {
  1240. text: sprintf($.i18n._("%s is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't 'watched' anymore."), PRODUCT_NAME)
  1241. },
  1242. position:{
  1243. adjust: {
  1244. resize: true,
  1245. method: "flip flip"
  1246. },
  1247. at: "right center",
  1248. my: "left top",
  1249. viewport: $(window)
  1250. },
  1251. style: {
  1252. classes: "ui-tooltip-dark"
  1253. },
  1254. show: 'mouseover',
  1255. hide: 'mouseout'
  1256. });
  1257. };
  1258. mod.onResize = function() {
  1259. clearTimeout(resizeTimeout);
  1260. resizeTimeout = setTimeout(setWidgetSize, 100);
  1261. };
  1262. return AIRTIME;
  1263. }(AIRTIME || {}));
  1264. $(document).ready(AIRTIME.playlist.onReady);
  1265. $(window).resize(AIRTIME.playlist.onResize);