PageRenderTime 1130ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/app/core/directives/ms-shortcuts/ms-shortcuts.directive.js

https://gitlab.com/edied/TelevidaWeb
JavaScript | 487 lines | 290 code | 70 blank | 127 comment | 27 complexity | d26be609c2c390f411a315334fe3c419 MD5 | raw file
  1. (function ()
  2. {
  3. 'use strict';
  4. angular
  5. .module('app.core')
  6. .controller('MsShortcutsController', MsShortcutsController)
  7. .directive('msShortcuts', msShortcutsDirective);
  8. /** @ngInject */
  9. function MsShortcutsController($scope, $cookies, $document, $timeout, $q, msNavigationService)
  10. {
  11. var vm = this;
  12. // Data
  13. vm.query = '';
  14. vm.queryOptions = {
  15. debounce: 300
  16. };
  17. vm.resultsLoading = false;
  18. vm.selectedResultIndex = 0;
  19. vm.ignoreMouseEvents = false;
  20. vm.mobileBarActive = false;
  21. vm.results = null;
  22. vm.shortcuts = [];
  23. vm.sortableOptions = {
  24. ghostClass : 'ghost',
  25. forceFallback: true,
  26. fallbackClass: 'dragging',
  27. onSort : function ()
  28. {
  29. vm.saveShortcuts();
  30. }
  31. };
  32. // Methods
  33. vm.populateResults = populateResults;
  34. vm.loadShortcuts = loadShortcuts;
  35. vm.saveShortcuts = saveShortcuts;
  36. vm.addShortcut = addShortcut;
  37. vm.removeShortcut = removeShortcut;
  38. vm.handleResultClick = handleResultClick;
  39. vm.absorbEvent = absorbEvent;
  40. vm.handleKeydown = handleKeydown;
  41. vm.handleMouseenter = handleMouseenter;
  42. vm.temporarilyIgnoreMouseEvents = temporarilyIgnoreMouseEvents;
  43. vm.ensureSelectedResultIsVisible = ensureSelectedResultIsVisible;
  44. vm.toggleMobileBar = toggleMobileBar;
  45. //////////
  46. init();
  47. function init()
  48. {
  49. // Load the shortcuts
  50. vm.loadShortcuts().then(
  51. // Success
  52. function (response)
  53. {
  54. vm.shortcuts = response;
  55. // Add shortcuts as results by default
  56. if ( vm.shortcuts.length > 0 )
  57. {
  58. vm.results = response;
  59. }
  60. }
  61. );
  62. // Watch the model changes to trigger the search
  63. $scope.$watch('MsShortcuts.query', function (current, old)
  64. {
  65. if ( angular.isUndefined(current) )
  66. {
  67. return;
  68. }
  69. if ( angular.equals(current, old) )
  70. {
  71. return;
  72. }
  73. // Show the loader
  74. vm.resultsLoading = true;
  75. // Populate the results
  76. vm.populateResults().then(
  77. // Success
  78. function (response)
  79. {
  80. vm.results = response;
  81. },
  82. // Error
  83. function ()
  84. {
  85. vm.results = [];
  86. }
  87. ).finally(
  88. function ()
  89. {
  90. // Hide the loader
  91. vm.resultsLoading = false;
  92. }
  93. );
  94. });
  95. }
  96. /**
  97. * Populate the results
  98. */
  99. function populateResults()
  100. {
  101. var results = [],
  102. flatNavigation = msNavigationService.getFlatNavigation(),
  103. deferred = $q.defer();
  104. // Iterate through the navigation array and
  105. // make sure it doesn't have any groups or
  106. // none ui-sref items
  107. for ( var x = 0; x < flatNavigation.length; x++ )
  108. {
  109. if ( flatNavigation[x].uisref )
  110. {
  111. results.push(flatNavigation[x]);
  112. }
  113. }
  114. // If there is a query, filter the results
  115. if ( vm.query )
  116. {
  117. results = results.filter(function (item)
  118. {
  119. if ( angular.lowercase(item.title).search(angular.lowercase(vm.query)) > -1 )
  120. {
  121. return true;
  122. }
  123. });
  124. // Iterate through one last time and
  125. // add required properties to items
  126. for ( var i = 0; i < results.length; i++ )
  127. {
  128. // Add false to hasShortcut by default
  129. results[i].hasShortcut = false;
  130. // Test if the item is in the shortcuts list
  131. for ( var y = 0; y < vm.shortcuts.length; y++ )
  132. {
  133. if ( vm.shortcuts[y]._id === results[i]._id )
  134. {
  135. results[i].hasShortcut = true;
  136. break;
  137. }
  138. }
  139. }
  140. }
  141. else
  142. {
  143. // If the query is empty, that means
  144. // there is nothing to search for so
  145. // we will populate the results with
  146. // current shortcuts if there is any
  147. if ( vm.shortcuts.length > 0 )
  148. {
  149. results = vm.shortcuts;
  150. }
  151. }
  152. // Reset the selected result
  153. vm.selectedResultIndex = 0;
  154. // Fake the service delay
  155. $timeout(function ()
  156. {
  157. // Resolve the promise
  158. deferred.resolve(results);
  159. }, 250);
  160. // Return a promise
  161. return deferred.promise;
  162. }
  163. /**
  164. * Load shortcuts
  165. */
  166. function loadShortcuts()
  167. {
  168. var deferred = $q.defer();
  169. // For the demo purposes, we will
  170. // load the shortcuts from the cookies.
  171. // But here you can make an API call
  172. // to load them from the DB.
  173. var shortcuts = angular.fromJson($cookies.get('FUSE.shortcuts'));
  174. // No cookie available. Generate one
  175. // for the demo purposes...
  176. if ( angular.isUndefined(shortcuts) )
  177. {
  178. shortcuts = [];
  179. $cookies.put('FUSE.shortcuts', angular.toJson(shortcuts));
  180. }
  181. // Resolve the promise
  182. deferred.resolve(shortcuts);
  183. return deferred.promise;
  184. }
  185. /**
  186. * Save the shortcuts
  187. */
  188. function saveShortcuts()
  189. {
  190. var deferred = $q.defer();
  191. // For the demo purposes, we will
  192. // keep the shortcuts in the cookies.
  193. // But here you can make an API call
  194. // to save them to the DB.
  195. $cookies.put('FUSE.shortcuts', angular.toJson(vm.shortcuts));
  196. // Fake the service delay
  197. $timeout(function ()
  198. {
  199. deferred.resolve({'success': true});
  200. }, 250);
  201. return deferred.promise;
  202. }
  203. /**
  204. * Add item as shortcut
  205. *
  206. * @param item
  207. */
  208. function addShortcut(item)
  209. {
  210. // Update the hasShortcut status
  211. item.hasShortcut = true;
  212. // Add as a shortcut
  213. vm.shortcuts.push(item);
  214. // Save the shortcuts
  215. vm.saveShortcuts();
  216. }
  217. /**
  218. * Remove item from shortcuts
  219. *
  220. * @param item
  221. */
  222. function removeShortcut(item)
  223. {
  224. // Update the hasShortcut status
  225. item.hasShortcut = false;
  226. // Remove the shortcut
  227. for ( var x = 0; x < vm.shortcuts.length; x++ )
  228. {
  229. if ( vm.shortcuts[x]._id === item._id )
  230. {
  231. // Remove the x-th item from the array
  232. vm.shortcuts.splice(x, 1);
  233. // If we aren't searching for anything...
  234. if ( !vm.query )
  235. {
  236. // If all the shortcuts have been removed,
  237. // null-ify the results
  238. if ( vm.shortcuts.length === 0 )
  239. {
  240. vm.results = null;
  241. }
  242. // Otherwise update the selected index
  243. else
  244. {
  245. if ( x >= vm.shortcuts.length )
  246. {
  247. vm.selectedResultIndex = vm.shortcuts.length - 1;
  248. }
  249. }
  250. }
  251. }
  252. }
  253. // Save the shortcuts
  254. vm.saveShortcuts();
  255. }
  256. /**
  257. * Handle the result click
  258. *
  259. * @param item
  260. */
  261. function handleResultClick(item)
  262. {
  263. // Add or remove the shortcut
  264. if ( item.hasShortcut )
  265. {
  266. vm.removeShortcut(item);
  267. }
  268. else
  269. {
  270. vm.addShortcut(item);
  271. }
  272. }
  273. /**
  274. * Absorb the given event
  275. *
  276. * @param event
  277. */
  278. function absorbEvent(event)
  279. {
  280. event.preventDefault();
  281. }
  282. /**
  283. * Handle keydown
  284. *
  285. * @param event
  286. */
  287. function handleKeydown(event)
  288. {
  289. var keyCode = event.keyCode,
  290. keys = [38, 40];
  291. // Prevent the default action if
  292. // one of the keys are pressed that
  293. // we are listening
  294. if ( keys.indexOf(keyCode) > -1 )
  295. {
  296. event.preventDefault();
  297. }
  298. switch ( keyCode )
  299. {
  300. // Enter
  301. case 13:
  302. // Trigger result click
  303. vm.handleResultClick(vm.results[vm.selectedResultIndex]);
  304. break;
  305. // Up Arrow
  306. case 38:
  307. // Decrease the selected result index
  308. if ( vm.selectedResultIndex - 1 >= 0 )
  309. {
  310. // Decrease the selected index
  311. vm.selectedResultIndex--;
  312. // Make sure the selected result is in the view
  313. vm.ensureSelectedResultIsVisible();
  314. }
  315. break;
  316. // Down Arrow
  317. case 40:
  318. // Increase the selected result index
  319. if ( vm.selectedResultIndex + 1 < vm.results.length )
  320. {
  321. // Increase the selected index
  322. vm.selectedResultIndex++;
  323. // Make sure the selected result is in the view
  324. vm.ensureSelectedResultIsVisible();
  325. }
  326. break;
  327. default:
  328. break;
  329. }
  330. }
  331. /**
  332. * Handle mouseenter
  333. *
  334. * @param index
  335. */
  336. function handleMouseenter(index)
  337. {
  338. if ( vm.ignoreMouseEvents )
  339. {
  340. return;
  341. }
  342. // Update the selected result index
  343. // with the given index
  344. vm.selectedResultIndex = index;
  345. }
  346. /**
  347. * Set a variable for a limited time
  348. * to make other functions to ignore
  349. * the mouse events
  350. */
  351. function temporarilyIgnoreMouseEvents()
  352. {
  353. // Set the variable
  354. vm.ignoreMouseEvents = true;
  355. // Cancel the previous timeout
  356. $timeout.cancel(vm.mouseEventIgnoreTimeout);
  357. // Set the timeout
  358. vm.mouseEventIgnoreTimeout = $timeout(function ()
  359. {
  360. vm.ignoreMouseEvents = false;
  361. }, 250);
  362. }
  363. /**
  364. * Ensure the selected result will
  365. * always be visible on the results
  366. * area
  367. */
  368. function ensureSelectedResultIsVisible()
  369. {
  370. var resultsEl = $document.find('#ms-shortcut-add-menu').find('.results'),
  371. selectedItemEl = angular.element(resultsEl.find('.result')[vm.selectedResultIndex]);
  372. if ( resultsEl && selectedItemEl )
  373. {
  374. var top = selectedItemEl.position().top - 8,
  375. bottom = selectedItemEl.position().top + selectedItemEl.outerHeight() + 8;
  376. // Start ignoring mouse events
  377. vm.temporarilyIgnoreMouseEvents();
  378. if ( resultsEl.scrollTop() > top )
  379. {
  380. resultsEl.scrollTop(top);
  381. }
  382. if ( bottom > (resultsEl.height() + resultsEl.scrollTop()) )
  383. {
  384. resultsEl.scrollTop(bottom - resultsEl.height());
  385. }
  386. }
  387. }
  388. /**
  389. * Toggle mobile bar
  390. */
  391. function toggleMobileBar()
  392. {
  393. vm.mobileBarActive = !vm.mobileBarActive;
  394. }
  395. }
  396. /** @ngInject */
  397. function msShortcutsDirective()
  398. {
  399. return {
  400. restrict : 'E',
  401. scope : {},
  402. require : 'msShortcuts',
  403. controller : 'MsShortcutsController as MsShortcuts',
  404. bindToController: {},
  405. templateUrl : 'app/core/directives/ms-shortcuts/ms-shortcuts.html',
  406. compile : function (tElement)
  407. {
  408. // Add class
  409. tElement.addClass('ms-shortcuts');
  410. return function postLink(scope, iElement)
  411. {
  412. // Data
  413. };
  414. }
  415. };
  416. }
  417. })();