edlp_studio.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. (function ($, Drupal, drupalSettings) {
  2. var _settings = drupalSettings.edlp_studio;
  3. var $composer;
  4. // audio play is handled by edlp_theme
  5. function init(){
  6. // console.log('Studio Init');
  7. initEvents();
  8. initStudio();
  9. };
  10. function initEvents(){
  11. $('body')
  12. .on('new-audio-cartel-loaded', initAjaxChutierLinks)
  13. .on('new-content-ajax-loaded', initStudio)
  14. .on('all-modal-closed', initStudio);
  15. };
  16. function initStudio(){
  17. if($('#studio-ui').length){
  18. $composer = $('.composition_ui .composer', '#studio-ui');
  19. initAjaxChutierLinks();
  20. initAjaxCompoLinks();
  21. initDragAndDropUI();
  22. $('body').trigger({'type':'studio-initialized'});
  23. }else{
  24. $('body').trigger({'type':'studio-not-active'});
  25. }
  26. }
  27. // ___ _ _ _ _ _ _ _ _ _
  28. // / __| |_ _ _| |_(_)___ _ _ | \| |___ __| |___ | | (_)_ _ | |__ ___
  29. // | (__| ' \ || | _| / -_) '_| | .` / _ \/ _` / -_) | |__| | ' \| / /(_-<
  30. // \___|_||_\_,_|\__|_\___|_| |_|\_\___/\__,_\___| |____|_|_||_|_\_\/__/
  31. function initAjaxChutierLinks(){
  32. //console.log('studio initAjaxChutierLinks');
  33. $('.chutier-ajax-link:not(.ajax-enabled)')
  34. .addClass('ajax-enabled')
  35. .on('click', onClickChutierAjaxLink);
  36. };
  37. function onClickChutierAjaxLink(e){
  38. //console.log('studio onClickAjaxLink chutier');
  39. e.preventDefault();
  40. addRemoveToChutier($(this));
  41. return false;
  42. };
  43. function addRemoveToChutier($link){
  44. // var ajax_path = 'edlp_studio/ajax/chutier/add/'+id; // + '/' +cid;
  45. var ajax_path = $link.attr('data-drupal-link-system-path');
  46. var path = window.location.origin + drupalSettings.path.baseUrl + ajax_path;
  47. $link.addClass('ajax-loading');
  48. $.getJSON(path, {})
  49. .done(function(data){
  50. onActionToChutierDone($link, data);
  51. })
  52. .fail(function(jqxhr, textStatus, error){
  53. onErrorActionToChutier(jqxhr, textStatus, error, $link);
  54. });
  55. };
  56. function onActionToChutierDone($link, data){
  57. //console.log('onActionToChutierDone',data);
  58. $('body').trigger({
  59. 'type':'chutier-action-done',
  60. 'action_done':data.action_done,
  61. 'new_action':data.action_done == 'add' ? 'remove' : 'add',
  62. 'target_id':$link.attr('target_id'),
  63. });
  64. $link.replaceWith(data.new_link);
  65. initAjaxChutierLinks();
  66. // reload Studio chutier_ui's documents list
  67. updateStudioChutier();
  68. };
  69. function onErrorActionToChutier(jqxhr, textStatus, error, $link){
  70. console.warn('action to chuttier load failed : '+error, jqxhr.responseText);
  71. };
  72. // ___ _ _ _
  73. // / __|___ _ __ _ __ ___ __(_) |_(_)___ _ _ ___
  74. // | (__/ _ \ ' \| '_ \/ _ (_-< | _| / _ \ ' \(_-<
  75. // \___\___/_|_|_| .__/\___/__/_|\__|_\___/_||_/__/
  76. // |_|
  77. function initAjaxCompoLinks(){
  78. //console.log('studio initAjaxCompoLinks');
  79. $('.new-composition-link:not(.ajax-enabled)')
  80. .on('click', onClickNewCompoLink)
  81. .addClass('ajax-enabled');
  82. $('.composition-link:not(.ajax-enabled)')
  83. .on('click', onClickCompoLink)
  84. .addClass('ajax-enabled');
  85. $('.delete-composition-link:not(.ajax-enabled)')
  86. .on('click', onClickDeleteCompoLink)
  87. .addClass('ajax-enabled');
  88. };
  89. // ___ ___
  90. // / _ \ _ __ ___ _ _ / __|___ _ __ _ __ ___
  91. // | (_) | '_ \/ -_) ' \ | (__/ _ \ ' \| '_ \/ _ \
  92. // \___/| .__/\___|_||_| \___\___/_|_|_| .__/\___/
  93. // |_| |_|
  94. function onClickCompoLink(e){
  95. e.preventDefault();
  96. //console.log('onClickCompoLink');
  97. openCompo($(this));
  98. return false;
  99. };
  100. function openCompo($link){
  101. var cid = $link.attr('cid');
  102. var ajax_path = _settings.open_compo_ajax_url+'/'+cid;
  103. var path = window.location.origin + Drupal.url(ajax_path);
  104. $link.addClass('ajax-loading');
  105. $composer.addClass('ajax-loading');
  106. $.getJSON(path, {})
  107. .done(function(data){
  108. onOpenCompoDone(data, $link);
  109. })
  110. .fail(function(jqxhr, textStatus, error){
  111. onErrorOpenCompo(jqxhr, textStatus, error, $link);
  112. });
  113. };
  114. function onOpenCompoDone(data, $link){
  115. //console.log('onActionToCompoDone',data);
  116. $('.composition-link').removeClass('is-active');
  117. $link.removeClass('ajax-loading').addClass('is-active');
  118. if($('.composition', $composer).length){
  119. $('.composition', $composer).replaceWith(data.compo);
  120. }else{
  121. $('header', $composer).after(data.compo);
  122. }
  123. $composer.removeClass('ajax-loading');
  124. initDragAndDropUI();
  125. $('body').trigger({
  126. 'type':'on-studio-compo-opened'
  127. });
  128. };
  129. function onErrorOpenCompo(jqxhr, textStatus, error, $link){
  130. $link.removeClass('ajax-loading');
  131. console.warn('open compo load failed : '+error, jqxhr.responseText);
  132. };
  133. // _ _ _____ __ __ __ ___ _ __ _ __ ___
  134. // | ' \/ -_) V V / / _/ _ \ ' \| '_ \/ _ \
  135. // |_||_\___|\_/\_/ \__\___/_|_|_| .__/\___/
  136. // |_|
  137. function onClickNewCompoLink(e){
  138. e.preventDefault();
  139. setInputForNewCompoName($(this));
  140. return false;
  141. };
  142. function setInputForNewCompoName($link){
  143. var $form = $('<form>').addClass('new-compo-form')
  144. .append($('<input>').attr('type', 'text').attr('placeholder', 'new name'))
  145. .append($('<button>').attr('type', 'submit').html('+'))
  146. .submit(function(e){
  147. onNewCompoFormSubmit(e, $link, $(this));
  148. });
  149. $link
  150. .after($form)
  151. .addClass('folded');
  152. $form.children('input[type="text"]').focus();
  153. };
  154. function onNewCompoFormSubmit(e, $link, $form){
  155. var name = $('input[type="text"]',$form).val();
  156. //console.log('onNewCompoFormSubmit', name);
  157. if(name != ''){
  158. $form.addClass('ajax-loading').children('*').attr('disabled', 'disabled');
  159. createNewCompo(name, $link, $form);
  160. }
  161. e.preventDefault();
  162. };
  163. function createNewCompo(name,$link, $form){
  164. var ajax_path = $link.attr('data-drupal-link-system-path');
  165. var path = window.location.origin + drupalSettings.path.baseUrl + ajax_path;
  166. // $link.addClass('ajax-loading');
  167. $.getJSON(path, {
  168. 'new_name':name
  169. })
  170. .done(function(data){
  171. onCreateCompoDone(data, $link, $form);
  172. })
  173. .fail(function(jqxhr, textStatus, error){
  174. onErrorCreateCompo(jqxhr, textStatus, error, $link);
  175. });
  176. };
  177. function onCreateCompoDone(data, $link, $form){
  178. //console.log('onActionToCompoDone',data);
  179. var $new_link = $(data.new_link);
  180. var $delete_link = $(data.delete_link);
  181. $link
  182. .removeClass('folded')
  183. .parents('li')
  184. .before($('<li>').append($new_link).append($delete_link));
  185. $form.remove();
  186. // open new composition to composer
  187. initAjaxCompoLinks();
  188. openCompo($new_link);
  189. };
  190. function onErrorCreateCompo(jqxhr, textStatus, error, $link){
  191. console.warn('action to compo load failed : '+error, jqxhr.responseText);
  192. };
  193. // ___ _ _
  194. // | \ ___| |___| |_ ___ __ ___ _ __ _ __ ___
  195. // | |) / -_) / -_) _/ -_) / _/ _ \ ' \| '_ \/ _ \
  196. // |___/\___|_\___|\__\___| \__\___/_|_|_| .__/\___/
  197. // |_|
  198. function onClickDeleteCompoLink(e){
  199. e.preventDefault();
  200. // TODO: confirm compo deletion
  201. deleteCompo($(this));
  202. return false;
  203. };
  204. function deleteCompo($link){
  205. var ajax_path = $link.attr('data-drupal-link-system-path');
  206. var path = window.location.origin + Drupal.url(ajax_path);
  207. $link.parents('li').addClass('ajax-loading');
  208. $.getJSON(path, {})
  209. .done(function(data){
  210. onDeleteCompoDone(data, $link);
  211. })
  212. .fail(function(jqxhr, textStatus, error){
  213. onErrorDeleteCompo(jqxhr, textStatus, error, $link);
  214. });
  215. };
  216. function onDeleteCompoDone(data, $link, $form){
  217. //console.log('onDeleteCompoDone',data);
  218. if(data.status == "ok"){
  219. $link.parents('li').remove();
  220. //console.log("$('.composition-link').length", $('.composition-link').length);
  221. if($('.composition-link').length){
  222. openCompo($('.composition-link').eq(0));
  223. }else{
  224. $('.composition', $composer).html();
  225. }
  226. }else{
  227. console.warn(data.message);
  228. }
  229. };
  230. function onErrorDeleteCompo(jqxhr, textStatus, error, $link){
  231. $link.parents('li').removeClass('ajax-loading');
  232. console.warn('delete compo load failed : '+error, jqxhr.responseText);
  233. };
  234. // ___ _ _ _ _
  235. // / __| |_ _ _ __| (_)___ ___ _ _(_)
  236. // \__ \ _| || / _` | / _ \___| || | |
  237. // |___/\__|\_,_\__,_|_\___/ \_,_|_|
  238. // this seems dirty
  239. function updateStudioChutier(){
  240. $studioChutier = $('#studio-ui .chutier_ui');
  241. if($studioChutier.length){
  242. var ajax_path = _settings.chutier_ui_ajax;
  243. var path = window.location.origin + drupalSettings.path.baseUrl + ajax_path;
  244. $studioChutier.addClass('loading');
  245. $.getJSON(path, {})
  246. .done(function(data){
  247. onLoadedChutier($studioChutier, data);
  248. })
  249. .fail(function(jqxhr, textStatus, error){
  250. onLoadChutierError(jqxhr, textStatus, error, $studioChutier);
  251. });
  252. }
  253. };
  254. function onLoadedChutier($studioChutier, data){
  255. $studioChutier.replaceWith(data.rendered);
  256. initAjaxChutierLinks();
  257. // set chutier element draggable again
  258. setChutierDraggable();
  259. $('body').trigger({
  260. 'type':'on-studio-chutier-updated'
  261. });
  262. }
  263. function onLoadChutierError(jqxhr, textStatus, error, $studioChutier){
  264. console.warn('Chutier load failed', jqxhr.responseText);
  265. $studioChutier.removeClass('loading');
  266. }
  267. // ___ __ ___ _ _ ___
  268. // | \ _ _ __ _ __ _ / _|___ | \ _ _ ___ _ __ | | | |_ _|
  269. // | |) | '_/ _` / _` | > _|_ _| | |) | '_/ _ \ '_ \ | |_| || |
  270. // |___/|_| \__,_\__, | \_____| |___/|_| \___/ .__/ \___/|___|
  271. // |___/ |_|
  272. function initDragAndDropUI(){
  273. // check if field--name-documents exists
  274. if (!$('.composition_ui .composer .composition .field--name-documents').length) {
  275. // if not create it
  276. $field_documents = $('<div>')
  277. .addClass('field').addClass('field--name-documents')
  278. .appendTo('.composition_ui .composer .composition');
  279. }else{
  280. // add real dom square element to handle sorting
  281. $field_documents = $('.composition_ui .composer .composition .field--name-documents'); $('.field__item', $field_documents).each(function(i){
  282. $(this).prepend($('<span>').addClass('handler'));
  283. });
  284. }
  285. // create remove dropzone
  286. var $remove_zone = $('<div>').addClass('remove-drop-zone')
  287. .appendTo('.composition_ui .composer .composition')
  288. .droppable({
  289. tolerance:'pointer',
  290. // scope:'composition_ui',
  291. over:function(e,ui){
  292. // console.log('on over remove : ui', ui);
  293. ui.draggable.addClass('ready-to-remove');
  294. },
  295. out:function(e,ui){
  296. // console.log('on over remove : ui', ui);
  297. ui.draggable.removeClass('ready-to-remove');
  298. },
  299. drop:function(e,ui){
  300. // console.log('on drop remove : ui', ui);
  301. ui.draggable.remove();
  302. // onOrderChanged(ui);
  303. }
  304. });
  305. // create sortable
  306. $field_documents.sortable({
  307. revert:false,
  308. handle: ".handler",
  309. receive:function(e, ui){
  310. $('.field__item', this).attr('style', '');
  311. // TODO: trigger event to enable new audiolink player
  312. },
  313. update:function(e, ui){
  314. onOrderChanged(e, ui);
  315. },
  316. connectWith : $remove_zone,
  317. });
  318. // set chutier element draggable
  319. setChutierDraggable();
  320. };
  321. function setChutierDraggable(){
  322. $('.chutier_ui .item-list li>div').draggable({
  323. containment:$('#studio-ui'),
  324. scroll:false,
  325. helper:function(e){
  326. // we reproduce here the irem structure of destination sortable elements
  327. // var $audio_link = $('.audio-link',this);
  328. return $('<div>').addClass('field__item')
  329. .append(
  330. $('<article>').addClass('node').append(
  331. $('<h2>').addClass('node-title').append(
  332. // $('<a>')
  333. // .attr('nid', $audio_link.attr('nid'))
  334. // .html($audio_link.html())
  335. $('.audio-link',this).clone().removeClass('ajax-enable')
  336. )
  337. )
  338. )
  339. .prepend($('<span>').addClass('handler'));
  340. },
  341. // cursor:'grab',
  342. cursorAt:{bottom:10,left:10},
  343. zIndex:999,
  344. revert:true,
  345. revertDuration:0,
  346. connectToSortable:$('.composition_ui .composer .composition .field--name-documents'),
  347. });
  348. }
  349. function onOrderChanged(e, ui){
  350. //console.log('onOrderChanged : e', e);
  351. var cid = $(e.target).parents('.composition').attr('cid');
  352. var documents = {};
  353. $('a', e.target).each(function(i) {
  354. // console.log(this);
  355. documents[i] = $(this).attr('nid');
  356. });
  357. // console.log(documents);
  358. recordCompoList(cid, documents);
  359. };
  360. function recordCompoList(cid, docs){
  361. //console.log('recordCompoList '+cid, docs);
  362. var ajax_path = _settings.save_compo_ajax_url+'/'+cid;
  363. var path = window.location.origin + Drupal.url(ajax_path);
  364. //console.log('path', path);
  365. $.getJSON(path, {
  366. documents:docs
  367. })
  368. .done(function(data){
  369. onRecordCompoDone(data);
  370. })
  371. .fail(function(jqxhr, textStatus, error){
  372. onErrorRecordCompo(jqxhr, textStatus, error);
  373. });
  374. $('body').trigger({
  375. 'type':'on-studio-compo-updated'
  376. });
  377. }
  378. function onRecordCompoDone(data){
  379. //console.log('onDeleteCompoDone',data);
  380. if(data.status == "ok"){
  381. }else{
  382. console.warn(data.message);
  383. }
  384. };
  385. function onErrorRecordCompo(jqxhr, textStatus, error){
  386. console.warn('record compo failed : '+error, jqxhr.responseText);
  387. };
  388. init();
  389. })(jQuery, Drupal, drupalSettings);