fl-builder-ui-main-menu.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. (function($, FLBuilder) {
  2. /**
  3. * Base prototype for views in the menu
  4. */
  5. var PanelView = FLExtendableObject.create({
  6. templateName: "fl-main-menu-panel-view",
  7. name: "Untitled View",
  8. isShowing: false,
  9. isRootView: false,
  10. items: {},
  11. /**
  12. * Initialize the view
  13. *
  14. * @return void
  15. */
  16. init: function() {
  17. this.template = wp.template(this.templateName);
  18. },
  19. /**
  20. * Render the view
  21. *
  22. * @return String
  23. */
  24. render: function() {
  25. return this.template(this);
  26. },
  27. /**
  28. * Setup Events
  29. *
  30. * @return void
  31. */
  32. bindEvents: function() {
  33. this.$items = this.$el.find('.fl-builder--menu-item');
  34. },
  35. /**
  36. * Make this the current view
  37. *
  38. * @return void
  39. */
  40. show: function() {
  41. this.$el.addClass('is-showing');
  42. this.isShowing = true;
  43. },
  44. /**
  45. * Resign the active view
  46. *
  47. * @return void
  48. */
  49. hide: function() {
  50. this.$el.removeClass('is-showing');
  51. this.isShowing = false;
  52. },
  53. /**
  54. * Handle transitioning the view in
  55. *
  56. * @return void
  57. */
  58. transitionIn: function(reverse) {
  59. requestAnimationFrame( this.show.bind(this) );
  60. },
  61. /**
  62. * Handle transition away from the view
  63. *
  64. * @return void
  65. */
  66. transitionOut: function(reverse) {
  67. this.hide();
  68. },
  69. });
  70. /**
  71. * Menu Panel
  72. */
  73. var MainMenuPanel = FLExtendableObject.create({
  74. templateName: 'fl-main-menu-panel',
  75. template: null,
  76. menu: null,
  77. views: {},
  78. viewNavigationStack: [],
  79. isShowing: false,
  80. shouldShowTabs: false,
  81. /**
  82. * Setup and render the menu
  83. *
  84. * @return void
  85. */
  86. init: function() {
  87. // Render Panel
  88. this.template = wp.template(this.templateName);
  89. $( 'body', window.parent.document ).prepend( this.template(this) );
  90. this.$el = $('.fl-builder--main-menu-panel', window.parent.document);
  91. this.$el.find('.fl-builder--main-menu-panel-views').html('');
  92. // Render Views
  93. for (var key in FLBuilderConfig.mainMenu) {
  94. this.renderPanel( key );
  95. }
  96. // Event Listeners
  97. $('body', window.parent.document).on('click', '.fl-builder--main-menu-panel .pop-view', this.goToPreviousView.bind(this));
  98. this.$tabs = this.$el.find('.fl-builder--tabs > span'); /* on purpose */
  99. this.$tabs.on('click', this.onItemClick.bind(this));
  100. this.$barTitle = $('.fl-builder-bar-title', window.parent.document); /* on purpose */
  101. $('body', window.parent.document).on('click', '.fl-builder-bar-title', this.toggle.bind(this));
  102. var hide = this.hide.bind(this);
  103. FLBuilder.addHook('didShowPublishActions', hide);
  104. FLBuilder.addHook('didBeginSearch', hide);
  105. FLBuilder.addHook('didBeginPreview', hide);
  106. FLBuilder.addHook('didShowContentPanel', hide);
  107. FLBuilder.addHook('endEditingSession', hide);
  108. FLBuilder.addHook('didFocusSearchBox', hide);
  109. FLBuilder.addHook('didEnterRevisionPreview', hide);
  110. FLBuilder.addHook('didFailSettingsSave', hide);
  111. FLBuilder.addHook('showKeyboardShortcuts', hide);
  112. this.$mask = $('.fl-builder--main-menu-panel-mask', window.parent.document);
  113. this.$mask.on('click', hide);
  114. Tools.init();
  115. Help.init();
  116. },
  117. /**
  118. * Render the panel
  119. *
  120. * @param String key
  121. * @return void
  122. */
  123. renderPanel: function( key ) {
  124. var data, view, $html;
  125. var current = this.views[ key ];
  126. data = FLBuilderConfig.mainMenu[ key ];
  127. data.handle = key;
  128. view = PanelView.create( data );
  129. view.init();
  130. $html = $( view.render() );
  131. view.$el = $html;
  132. $( '.fl-builder--main-menu-panel-views', window.parent.document ).append( $html );
  133. view.bindEvents();
  134. view.$el.find( '.fl-builder--menu-item' ).on( 'click', this.onItemClick.bind( this ) );
  135. if ( 'undefined' !== typeof current ) {
  136. current.$el.remove();
  137. if ( current.isShowing ) {
  138. this.currentView = view
  139. view.show();
  140. }
  141. }
  142. if ( view.isRootView ) {
  143. this.rootView = view;
  144. this.currentView = view;
  145. }
  146. this.views[ key ] = view;
  147. },
  148. /**
  149. * Show the menu
  150. *
  151. * @return void
  152. */
  153. show: function() {
  154. if (this.isShowing) return;
  155. this.$el.addClass('is-showing');
  156. this.$barTitle.addClass('is-showing-menu');
  157. this.currentView.transitionIn();
  158. this.isShowing = true;
  159. this.$mask.show();
  160. FLBuilder.triggerHook('didOpenMainMenu');
  161. },
  162. /**
  163. * Hide the menu
  164. *
  165. * @return void
  166. */
  167. hide: function() {
  168. if (!this.isShowing) return;
  169. this.$el.removeClass('is-showing');
  170. this.$barTitle.removeClass('is-showing-menu');
  171. this.isShowing = false;
  172. this.resetViews();
  173. this.$mask.hide();
  174. },
  175. /**
  176. * Toggle show/hide the menu
  177. *
  178. * @return void
  179. */
  180. toggle: function() {
  181. if (this.isShowing) {
  182. this.hide();
  183. } else {
  184. this.show();
  185. }
  186. },
  187. /**
  188. * Handle item click
  189. *
  190. * @param {Event} e
  191. * @return void
  192. */
  193. onItemClick: function(e) {
  194. var $item = $(e.currentTarget, window.parent.document),
  195. type = $item.data('type');
  196. switch (type) {
  197. case "view":
  198. var name = $item.data('view');
  199. this.goToView(name);
  200. break;
  201. case "event":
  202. var hook = $item.data('event');
  203. FLBuilder.triggerHook(hook, $item);
  204. break;
  205. case "link":
  206. // follow link
  207. break;
  208. }
  209. },
  210. /**
  211. * Display a specific view
  212. *
  213. * @param String name
  214. * @return void
  215. */
  216. goToView: function(name) {
  217. var currentView = this.currentView;
  218. var newView = this.views[name];
  219. currentView.transitionOut();
  220. newView.transitionIn();
  221. this.currentView = newView;
  222. this.viewNavigationStack.push(currentView);
  223. },
  224. /**
  225. * Pop a view off the stack
  226. *
  227. * @return void
  228. */
  229. goToPreviousView: function() {
  230. var currentView = this.currentView;
  231. var newView = this.viewNavigationStack.pop();
  232. currentView.transitionOut(true);
  233. newView.transitionIn(true);
  234. this.currentView = newView;
  235. $('.fl-builder-bar-title-caret', window.parent.document).focus();
  236. },
  237. /**
  238. * Reset to root view
  239. *
  240. * @return void
  241. */
  242. resetViews: function() {
  243. if (this.currentView != this.rootView ) {
  244. this.currentView.hide();
  245. this.rootView.show();
  246. this.currentView = this.rootView;
  247. this.viewNavigationStack = [];
  248. }
  249. },
  250. });
  251. FLBuilder.MainMenu = MainMenuPanel;
  252. /**
  253. * Handle tools menu actions
  254. */
  255. var Tools = {
  256. /**
  257. * Setup listeners for tools actions
  258. * @return void
  259. */
  260. init: function() {
  261. FLBuilder.addHook('saveTemplate', this.saveTemplate.bind(this));
  262. FLBuilder.addHook('saveCoreTemplate', this.saveCoreTemplate.bind(this));
  263. FLBuilder.addHook('duplicateLayout', this.duplicateLayout.bind(this));
  264. FLBuilder.addHook('showLayoutSettings', this.showLayoutSettings.bind(this));
  265. FLBuilder.addHook('showGlobalSettings', this.showGlobalSettings.bind(this));
  266. FLBuilder.addHook('showGlobalStyles', this.showGlobalStyles.bind(this));
  267. FLBuilder.addHook('toggleUISkin', this.toggleUISkin.bind(this));
  268. FLBuilder.addHook('clearLayoutCache', this.clearLayoutCache.bind(this));
  269. FLBuilder.addHook('launchThemerLayouts', this.launchThemerLayouts.bind(this));
  270. FLBuilder.addHook('toggleOutlinePanel', this.toggleOutlinePanel.bind(this));
  271. FLBuilder.addHook('toggleMediaLibrary', this.toggleMediaLibrary.bind(this));
  272. // Show Keyboard Shortcuts
  273. if ( 'FL' in window && 'Builder' in FL ) {
  274. var actions = FL.Builder.data.getSystemActions();
  275. FLBuilder.addHook( 'showKeyboardShortcuts', function() {
  276. actions.setShouldShowShortcuts( true );
  277. });
  278. }
  279. },
  280. /**
  281. * Show the save template lightbox
  282. * @return void
  283. */
  284. saveTemplate: function() {
  285. FLBuilder._saveUserTemplateClicked();
  286. MainMenuPanel.hide();
  287. },
  288. /**
  289. * Show save core template lightbox
  290. * @return void
  291. */
  292. saveCoreTemplate: function() {
  293. FLBuilderCoreTemplatesAdmin._saveClicked();
  294. MainMenuPanel.hide();
  295. },
  296. /**
  297. * Trigger duplicate layout
  298. * @return void
  299. */
  300. duplicateLayout: function() {
  301. FLBuilder._duplicateLayoutClicked();
  302. MainMenuPanel.hide();
  303. },
  304. /**
  305. * Show the global settings lightbox
  306. * @return void
  307. */
  308. showGlobalSettings: function() {
  309. FLBuilder._globalSettingsClicked();
  310. MainMenuPanel.hide();
  311. },
  312. /**
  313. * Show the global style settings lightbox
  314. * @return void
  315. */
  316. showGlobalStyles: function() {
  317. FLBuilder._globalStylesClicked();
  318. MainMenuPanel.hide();
  319. },
  320. /**
  321. * Show the layout js/css lightbox
  322. * @return void
  323. */
  324. showLayoutSettings: function() {
  325. FLBuilder._layoutSettingsClicked();
  326. MainMenuPanel.hide();
  327. },
  328. /**
  329. * Clear cache for this layout
  330. * @return void
  331. */
  332. clearLayoutCache: function() {
  333. FLBuilder.ajax({
  334. action: 'clear_cache'
  335. }, function() {
  336. location.href = FLBuilderConfig.editUrl;
  337. });
  338. FLBuilder.showAjaxLoader();
  339. MainMenuPanel.hide();
  340. },
  341. /**
  342. * Toggle between the UI Skins
  343. * @var Event
  344. * @return void
  345. */
  346. toggleUISkin: function(e) {
  347. const colorScheme = FL.Builder.data.getSystemState().colorScheme;
  348. let newColorScheme = ''
  349. // cycle modes...
  350. if ( 'light' === colorScheme ) {
  351. newColorScheme = 'dark';
  352. } else if ( 'dark' === colorScheme ) {
  353. newColorScheme = 'auto';
  354. } else {
  355. newColorScheme = 'light';
  356. }
  357. FL.Builder.data.getSystemActions().setColorScheme( newColorScheme );
  358. $('.current-mode').html( '(' + newColorScheme + ')' );
  359. },
  360. /**
  361. * @return void
  362. */
  363. launchThemerLayouts: function() {
  364. if ( FLBuilderConfig.lite ) {
  365. FLBuilder._showProMessage( 'Themer Layouts' );
  366. } else {
  367. window.open( FLBuilderConfig.themerLayoutsUrl );
  368. }
  369. MainMenuPanel.hide();
  370. },
  371. /**
  372. * @return void
  373. */
  374. toggleOutlinePanel: function() {
  375. FL.Builder.togglePanel('outline');
  376. },
  377. /**
  378. * @return void
  379. */
  380. toggleMediaLibrary: function() {
  381. var mediaLibrary = wp.media( {
  382. multiple: false
  383. });
  384. mediaLibrary.fl_changed = false;
  385. mediaLibrary.on( 'open', function() {
  386. $(mediaLibrary.el).find('.media-toolbar').hide();
  387. });
  388. mediaLibrary.on( 'selection:toggle', function() {
  389. $(mediaLibrary.el).find('button.delete-attachment, a.edit-attachment').on('click', function() {
  390. mediaLibrary.fl_changed = true;
  391. });
  392. $(mediaLibrary.el).find('textarea, input').on('change', function() {
  393. mediaLibrary.fl_changed = true;
  394. });
  395. });
  396. mediaLibrary.on( 'library:selection:add', function() {
  397. mediaLibrary.fl_changed = true;
  398. });
  399. mediaLibrary.on( 'closed, close, escape', function() {
  400. if ( mediaLibrary.fl_changed ) {
  401. window.parent.location.reload();
  402. }
  403. })
  404. MainMenuPanel.hide();
  405. mediaLibrary.open();
  406. },
  407. }
  408. var Help = {
  409. /**
  410. * Init the help controller
  411. * @return void
  412. */
  413. init: function() {
  414. FLBuilder.addHook('beginTour', this.onStartTourClicked.bind(this));
  415. },
  416. /**
  417. * Handle tour item click
  418. *
  419. * @return void
  420. */
  421. onStartTourClicked: function() {
  422. FLBuilderTour.start();
  423. MainMenuPanel.hide();
  424. },
  425. }
  426. })(jQuery, FLBuilder);