editor.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. "use strict";
  2. $(document).ready(function() {
  3. var $editor = $('#editor');
  4. var $editorJs = $('#editor-javascript');
  5. var $editorHtml = $('#editor-html');
  6. var $editorCss = $('#editor-css');
  7. var $htmlContent = $('#html-content');
  8. var $selectorNav = $('#selector');
  9. var $fileSelect = $('#file-select');
  10. var $addExampleBtn = $('#add-example-btn');
  11. var $exampleForm = $('#add-example-form');
  12. var $exampleSave = $('#add-example-save');
  13. var $exampleCancel = $('#add-example-cancel');
  14. var $saveChanges = $('#save-changes');
  15. var $notification = $('#notification');
  16. var $revertEditor = $('#revert-editor');
  17. var $panelLeft = $('.panel-left');
  18. var $panelRight = $('.panel-right');
  19. var $panelWrap = $('.panel-container');
  20. var $window = $(window);
  21. var activeMode = 'html';
  22. var currentHash;
  23. var editor;
  24. var editorStorage = new LocalStorageDraft();
  25. var saveTimeout1;
  26. var saveTimeout2;
  27. var exampleList;
  28. /**
  29. * Make the left panel resizable
  30. */
  31. $panelLeft.resizable({
  32. handleSelector: ".splitter",
  33. resizeHeight: false,
  34. onDrag: function(e) {
  35. $editor.width($panelLeft.width());
  36. }
  37. });
  38. /**
  39. * Handle window resize
  40. */
  41. function onResize() {
  42. $editor.width($panelLeft.width());
  43. $panelWrap.height($window.height());
  44. }
  45. $window.resize(onResize);
  46. onResize();
  47. editor = ace.edit("editor");
  48. editor.setTheme("ace/theme/eclipse");
  49. editor.$blockScrolling = Infinity;
  50. editor.getSession().setUseWrapMode(true);
  51. /**
  52. * Set the current hash. If none given, take it from lococation.hash
  53. */
  54. function setCurrentHash(slug) {
  55. if(slug) {
  56. window.location.hash = currentHash = slug;
  57. }
  58. else {
  59. currentHash = window.location.hash ?
  60. window.location.hash.substr(1) : undefined;
  61. }
  62. }
  63. /**
  64. * Set editor mode (html, javascript, css)
  65. */
  66. function setEditorMode(mode) {
  67. editor.getSession().setMode("ace/mode/" + mode);
  68. }
  69. /**
  70. * Save a copy in localStorage
  71. */
  72. function saveToLocalStorage() {
  73. var editorContent = editor.getSession().getValue();
  74. editorStorage.saveSource(activeMode, editorContent);
  75. saveTimeout1 = undefined;
  76. }
  77. /**
  78. * React to changes in editor by saving a copy
  79. */
  80. function editorContentChanged() {
  81. // console.log('editorContent changed')
  82. if(saveTimeout1 || saveTimeout2) {
  83. clearTimeout(saveTimeout1);
  84. clearTimeout(saveTimeout2);
  85. }
  86. saveTimeout1 = setTimeout(saveToLocalStorage, 500);
  87. // saveTimeout2 = setTimeout(saveChanges, 1000);
  88. }
  89. editor.getSession().on('change', editorContentChanged);
  90. function setActiveTab(mode) {
  91. console.log('setting mode', mode);
  92. var elementId = 'show-' + mode;
  93. $('#show-' + activeMode).removeClass('active');
  94. activeMode = mode;
  95. $('#' + elementId).addClass('active');
  96. var ed = $('#editor-' + mode);
  97. setEditorMode(mode);
  98. editor.getSession().off('change');
  99. editor.getSession().setValue(ed[0].innerHTML);
  100. editor.getSession().on('change', editorContentChanged);
  101. }
  102. $('#tabs button').click(function() {
  103. saveToLocalStorage();
  104. var mode = $(this).prop('id').substr(5);
  105. setActiveTab(mode);
  106. })
  107. function loadAsync(url, dataType) {
  108. return new Promise(function(resolve, reject) {
  109. $.ajax({
  110. type: 'GET',
  111. url: url,
  112. success: function(data) {
  113. resolve(data);
  114. },
  115. error: function(jqXHR) {
  116. reject(new Error(jqXHR.responseText));
  117. }
  118. }, dataType);
  119. });
  120. }
  121. function loadExample(exampleSlug) {
  122. // console.log('loadExample', exampleSlug);
  123. var serverPath = 'exemples/' + exampleSlug + '/';
  124. loadAsync(serverPath + 'script.js', 'text')
  125. .then(javascript => $editorJs.html(javascript))
  126. .then(() => loadAsync(serverPath + 'contenu.html', 'text'))
  127. .then(() => loadAsync(serverPath + 'styles.css', 'text')
  128. .then(css => $editorCss.html(css))
  129. .catch(err => {
  130. return '';
  131. })
  132. )
  133. .then(html => {
  134. $editorHtml.html(html);
  135. $('iframe.panel-right')
  136. .prop('src', '/examples/' + exampleSlug)
  137. setActiveTab('html');
  138. setCurrentHash(exampleSlug);
  139. var sources = {
  140. html: $editorHtml.html(),
  141. javascript: $editorJs.html()
  142. };
  143. editorStorage.init(exampleSlug, sources);
  144. })
  145. .then(() => {
  146. var item = _.find(exampleList, { slug: exampleSlug });
  147. // console.log(item.test ? 'test' : 'no test');
  148. // loadJS('exemples/' + item.slug + '/test.js', function() {
  149. // $('#tests').show();
  150. // });
  151. });
  152. }
  153. function addFileSelectItem(item) {
  154. $fileSelect.append(
  155. '<option value="' + item.slug + '">' +
  156. item.title +
  157. '</option>'
  158. );
  159. }
  160. function loadExampleList() {
  161. $.get('exemples/liste.json', function(_exampleList) {
  162. exampleList = _exampleList;
  163. var restoredDraft;
  164. exampleList.forEach(addFileSelectItem);
  165. if(currentHash) {
  166. $fileSelect.val(currentHash);
  167. var item = _.find(exampleList, { slug: currentHash });
  168. if( ! item) {
  169. return;
  170. }
  171. restoredDraft = editorStorage.restore(item.slug);
  172. if(! restoredDraft) {
  173. loadExample(item.slug);
  174. }
  175. else {
  176. console.log('restore', item.slug, restoredDraft.sources);
  177. $editorHtml.html(restoredDraft.sources.html);
  178. $editorCss.html(restoredDraft.sources.css);
  179. $editorJs.html(restoredDraft.sources.javascript);
  180. $('iframe.panel-right')
  181. .prop('src', '/examples/' + item.slug)
  182. // loadJS('exemples/' + item.slug + '/script.js');
  183. // if(item.test) {
  184. // loadJS('exemples/' + item.slug + '/test.js', function() {
  185. // $('#tests').show();
  186. // });
  187. // }
  188. setActiveTab('html');
  189. }
  190. }
  191. }, 'json');
  192. }
  193. function notify(type, text) {
  194. $notification
  195. .addClass(type)
  196. .addClass('active');
  197. $notification.html(text);
  198. setTimeout(function() {
  199. $notification.removeClass('active');
  200. }, 2000);
  201. setTimeout(function() {
  202. $notification.removeClass(type);
  203. }, 3000);
  204. }
  205. function toggleEditor() {
  206. $addExampleBtn.toggle();
  207. $selectorNav.toggle();
  208. $exampleForm.toggle();
  209. }
  210. function saveExample(e) {
  211. e.preventDefault();
  212. var title = $(this).find('input[name="title"]').val();
  213. $.ajax({
  214. type: 'POST',
  215. url: '/examples',
  216. data: JSON.stringify({ title }),
  217. success: function(newExample) {
  218. clearAndCloseEditor();
  219. addFileSelectItem(newExample);
  220. $fileSelect.val(newExample.slug);
  221. // $fileSelect.trigger('change');
  222. notify('success', "Exemple créé !");
  223. },
  224. error: function(jqXHR, textStatus, errorThrown ) {
  225. notify('error', 'Erreur: ' + jqXHR.responseText);
  226. },
  227. contentType: 'application/json',
  228. dataType: 'json'
  229. });
  230. }
  231. function clearAndCloseEditor() {
  232. $exampleForm.find('input').val('');
  233. toggleEditor();
  234. }
  235. function revertEditor() {
  236. editorStorage.reset();
  237. location.reload();
  238. }
  239. function saveChanges() {
  240. var payload = editorStorage.getSources();
  241. $.ajax({
  242. type: 'PUT',
  243. url: '/examples/' + currentHash,
  244. data: JSON.stringify(payload),
  245. success: function(newExample) {
  246. notify('success', "Exemple sauvegardé !");
  247. loadExample(currentHash);
  248. },
  249. error: function(jqXHR, textStatus, errorThrown ) {
  250. notify('error', 'Erreur: ' + jqXHR.responseText);
  251. },
  252. contentType: 'application/json',
  253. dataType: 'json'
  254. });
  255. }
  256. setCurrentHash();
  257. $fileSelect.change(function() {
  258. loadExample($(this).val());
  259. });
  260. $addExampleBtn.click(toggleEditor);
  261. $exampleCancel.click(clearAndCloseEditor);
  262. $saveChanges.click(saveChanges);
  263. $exampleForm.submit(saveExample);
  264. $revertEditor.click(revertEditor);
  265. loadExampleList();
  266. });