angularjs-foundation-rails 0.3.1.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e82de542ed9a238a426dbc68a03ea1fabbbf72bc
4
- data.tar.gz: bf32f5a35a99e023acb30ce2ad6cffd76ce87124
3
+ metadata.gz: a1ee1624cc1249aedb3b659928ec9fc9c2b360cb
4
+ data.tar.gz: a82f8896ac489d36e2bb9270cf3e7db2e7f6abd9
5
5
  SHA512:
6
- metadata.gz: 44f9f9263b0c92e360e103e8c771800144b3dd948c582f63d02408b6f228e76214cd9900d37c3aeb4b6774fb2381ed46bb650326a69408c811ab9b007d2b2b5a
7
- data.tar.gz: b196302b21cb2fba1b73dee00c8760fa48a55c62cdb38569fb9abef498bf8d46677e968881a8209f10830bcf5c674e68967309f7d62f6a03c3c5ab42be118084
6
+ metadata.gz: c92ca7779c372cd81a377593560078cbe6a8fea43fb501943018ef9856fed9cb1e7208f5a1b06eeac4c6a3d04ffea212fd55568c07aa7efe01cd0921043f4b9e
7
+ data.tar.gz: 48e56152eb200b62b5a0e5101786dc664cf0bd647371596334d7e9f96a9e82aa8e8a8e4bc9ad064f05bfce504859108f0ec66da49de567725bd9b3588ee3cca8
@@ -1,7 +1,7 @@
1
1
  module Angularjs
2
2
  module Foundation
3
3
  module Rails
4
- VERSION = '0.3.1.2'
4
+ VERSION = '0.8.0'
5
5
  end
6
6
  end
7
7
  end
@@ -2,11 +2,11 @@
2
2
  * angular-mm-foundation
3
3
  * http://pineconellc.github.io/angular-foundation/
4
4
 
5
- * Version: 0.3.1 - 2014-08-19
5
+ * Version: 0.8.0 - 2015-10-13
6
6
  * License: MIT
7
7
  * (c) Pinecone, LLC
8
8
  */
9
- angular.module("mm.foundation", ["mm.foundation.tpls", "mm.foundation.accordion","mm.foundation.alert","mm.foundation.bindHtml","mm.foundation.buttons","mm.foundation.position","mm.foundation.dropdownToggle","mm.foundation.interchange","mm.foundation.transition","mm.foundation.modal","mm.foundation.offcanvas","mm.foundation.pagination","mm.foundation.tooltip","mm.foundation.popover","mm.foundation.progressbar","mm.foundation.rating","mm.foundation.tabs","mm.foundation.topbar","mm.foundation.tour","mm.foundation.typeahead"]);
9
+ angular.module("mm.foundation", ["mm.foundation.tpls", "mm.foundation.accordion","mm.foundation.alert","mm.foundation.bindHtml","mm.foundation.buttons","mm.foundation.position","mm.foundation.mediaQueries","mm.foundation.dropdownToggle","mm.foundation.interchange","mm.foundation.transition","mm.foundation.modal","mm.foundation.offcanvas","mm.foundation.pagination","mm.foundation.tooltip","mm.foundation.popover","mm.foundation.progressbar","mm.foundation.rating","mm.foundation.tabs","mm.foundation.topbar","mm.foundation.tour","mm.foundation.typeahead"]);
10
10
  angular.module("mm.foundation.tpls", ["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/topbar/has-dropdown.html","template/topbar/toggle-top-bar.html","template/topbar/top-bar-dropdown.html","template/topbar/top-bar-section.html","template/topbar/top-bar.html","template/tour/tour.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]);
11
11
  angular.module('mm.foundation.accordion', [])
12
12
 
@@ -30,7 +30,7 @@ angular.module('mm.foundation.accordion', [])
30
30
  });
31
31
  }
32
32
  };
33
-
33
+
34
34
  // This is called from the accordion-group directive to add itself to the accordion
35
35
  this.addGroup = function(groupScope) {
36
36
  var that = this;
@@ -45,7 +45,7 @@ angular.module('mm.foundation.accordion', [])
45
45
  this.removeGroup = function(group) {
46
46
  var index = this.groups.indexOf(group);
47
47
  if ( index !== -1 ) {
48
- this.groups.splice(this.groups.indexOf(group), 1);
48
+ this.groups.splice(index, 1);
49
49
  }
50
50
  };
51
51
 
@@ -83,7 +83,7 @@ angular.module('mm.foundation.accordion', [])
83
83
  accordionCtrl.addGroup(scope);
84
84
 
85
85
  scope.isOpen = false;
86
-
86
+
87
87
  if ( attrs.isOpen ) {
88
88
  getIsOpen = $parse(attrs.isOpen);
89
89
  setIsOpen = getIsOpen.assign;
@@ -150,7 +150,7 @@ angular.module('mm.foundation.accordion', [])
150
150
  angular.module("mm.foundation.alert", [])
151
151
 
152
152
  .controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
153
- $scope.closeable = 'close' in $attrs;
153
+ $scope.closeable = 'close' in $attrs && typeof $attrs.close !== "undefined";
154
154
  }])
155
155
 
156
156
  .directive('alert', function () {
@@ -229,7 +229,7 @@ angular.module('mm.foundation.buttons', [])
229
229
  function getFalseValue() {
230
230
  return getCheckboxValue(attrs.btnCheckboxFalse, false);
231
231
  }
232
-
232
+
233
233
  function getCheckboxValue(attributeValue, defaultValue) {
234
234
  var val = scope.$eval(attributeValue);
235
235
  return angular.isDefined(val) ? val : defaultValue;
@@ -332,6 +332,66 @@ angular.module('mm.foundation.position', [])
332
332
  };
333
333
  }]);
334
334
 
335
+ angular.module("mm.foundation.mediaQueries", [])
336
+ .factory('matchMedia', ['$document', '$window', function($document, $window) {
337
+ // MatchMedia for IE <= 9
338
+ return $window.matchMedia || (function matchMedia(doc, undefined){
339
+ var bool,
340
+ docElem = doc.documentElement,
341
+ refNode = docElem.firstElementChild || docElem.firstChild,
342
+ // fakeBody required for <FF4 when executed in <head>
343
+ fakeBody = doc.createElement("body"),
344
+ div = doc.createElement("div");
345
+
346
+ div.id = "mq-test-1";
347
+ div.style.cssText = "position:absolute;top:-100em";
348
+ fakeBody.style.background = "none";
349
+ fakeBody.appendChild(div);
350
+
351
+ return function (q) {
352
+ div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
353
+ docElem.insertBefore(fakeBody, refNode);
354
+ bool = div.offsetWidth === 42;
355
+ docElem.removeChild(fakeBody);
356
+ return {
357
+ matches: bool,
358
+ media: q
359
+ };
360
+ };
361
+
362
+ }($document[0]));
363
+ }])
364
+ .factory('mediaQueries', ['$document', 'matchMedia', function($document, matchMedia) {
365
+ var head = angular.element($document[0].querySelector('head'));
366
+ head.append('<meta class="foundation-mq-topbar" />');
367
+ head.append('<meta class="foundation-mq-small" />');
368
+ head.append('<meta class="foundation-mq-medium" />');
369
+ head.append('<meta class="foundation-mq-large" />');
370
+
371
+ var regex = /^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g;
372
+ var queries = {
373
+ topbar: getComputedStyle(head[0].querySelector('meta.foundation-mq-topbar')).fontFamily.replace(regex, ''),
374
+ small : getComputedStyle(head[0].querySelector('meta.foundation-mq-small')).fontFamily.replace(regex, ''),
375
+ medium : getComputedStyle(head[0].querySelector('meta.foundation-mq-medium')).fontFamily.replace(regex, ''),
376
+ large : getComputedStyle(head[0].querySelector('meta.foundation-mq-large')).fontFamily.replace(regex, '')
377
+ };
378
+
379
+ return {
380
+ topbarBreakpoint: function () {
381
+ return !matchMedia(queries.topbar).matches;
382
+ },
383
+ small: function () {
384
+ return matchMedia(queries.small).matches;
385
+ },
386
+ medium: function () {
387
+ return matchMedia(queries.medium).matches;
388
+ },
389
+ large: function () {
390
+ return matchMedia(queries.large).matches;
391
+ }
392
+ };
393
+ }]);
394
+
335
395
  /*
336
396
  * dropdownToggle - Provides dropdown menu functionality
337
397
  * @restrict class or attribute
@@ -344,22 +404,30 @@ angular.module('mm.foundation.position', [])
344
404
  </li>
345
405
  </ul>
346
406
  */
347
- angular.module('mm.foundation.dropdownToggle', [ 'mm.foundation.position' ])
407
+ angular.module('mm.foundation.dropdownToggle', [ 'mm.foundation.position', 'mm.foundation.mediaQueries' ])
408
+
409
+ .controller('DropdownToggleController', ['$scope', '$attrs', 'mediaQueries', function($scope, $attrs, mediaQueries) {
410
+ this.small = function() {
411
+ return mediaQueries.small() && !mediaQueries.medium();
412
+ };
413
+ }])
348
414
 
349
- .directive('dropdownToggle', ['$document', '$location', '$position', function ($document, $location, $position) {
415
+ .directive('dropdownToggle', ['$document', '$window', '$location', '$position', function ($document, $window, $location, $position) {
350
416
  var openElement = null,
351
417
  closeMenu = angular.noop;
352
418
  return {
353
419
  restrict: 'CA',
354
- scope: {
355
- dropdownToggle: '@'
356
- },
357
- link: function(scope, element, attrs) {
358
- var dropdown = angular.element($document[0].querySelector(scope.dropdownToggle));
420
+ controller: 'DropdownToggleController',
421
+ link: function(scope, element, attrs, controller) {
422
+ var parent = element.parent(),
423
+ dropdown = angular.element($document[0].querySelector(attrs.dropdownToggle));
359
424
 
360
- scope.$watch('$location.path', function() { closeMenu(); });
361
- element.bind('click', function (event) {
362
- dropdown = angular.element($document[0].querySelector(scope.dropdownToggle));
425
+ var parentHasDropdown = function() {
426
+ return parent.hasClass('has-dropdown');
427
+ };
428
+
429
+ var onClick = function (event) {
430
+ dropdown = angular.element($document[0].querySelector(attrs.dropdownToggle));
363
431
  var elementWasOpen = (element === openElement);
364
432
 
365
433
  event.preventDefault();
@@ -370,30 +438,68 @@ angular.module('mm.foundation.dropdownToggle', [ 'mm.foundation.position' ])
370
438
  }
371
439
 
372
440
  if (!elementWasOpen && !element.hasClass('disabled') && !element.prop('disabled')) {
373
- dropdown.css('display', 'block');
441
+ dropdown.css('display', 'block'); // We display the element so that offsetParent is populated
442
+ dropdown.addClass('f-open-dropdown');
374
443
 
375
444
  var offset = $position.offset(element);
376
445
  var parentOffset = $position.offset(angular.element(dropdown[0].offsetParent));
377
-
378
- dropdown.css({
379
- left: offset.left - parentOffset.left + 'px',
446
+ var dropdownWidth = dropdown.prop('offsetWidth');
447
+ var css = {
380
448
  top: offset.top - parentOffset.top + offset.height + 'px'
381
- });
449
+ };
450
+
451
+ if (controller.small()) {
452
+ css.left = Math.max((parentOffset.width - dropdownWidth) / 2, 8) + 'px';
453
+ css.position = 'absolute';
454
+ css.width = '95%';
455
+ css['max-width'] = 'none';
456
+ }
457
+ else {
458
+ var left = Math.round(offset.left - parentOffset.left);
459
+ var rightThreshold = $window.innerWidth - dropdownWidth - 8;
460
+ if (left > rightThreshold) {
461
+ left = rightThreshold;
462
+ dropdown.removeClass('left').addClass('right');
463
+ }
464
+ css.left = left + 'px';
465
+ css.position = null;
466
+ css['max-width'] = null;
467
+ }
468
+
469
+ dropdown.css(css);
470
+ element.addClass('expanded');
471
+
472
+ if (parentHasDropdown()) {
473
+ parent.addClass('hover');
474
+ }
382
475
 
383
476
  openElement = element;
477
+
384
478
  closeMenu = function (event) {
385
- $document.unbind('click', closeMenu);
479
+ $document.off('click', closeMenu);
386
480
  dropdown.css('display', 'none');
481
+ dropdown.removeClass('f-open-dropdown');
482
+ element.removeClass('expanded');
387
483
  closeMenu = angular.noop;
388
484
  openElement = null;
485
+ if (parent.hasClass('hover')) {
486
+ parent.removeClass('hover');
487
+ }
389
488
  };
390
- $document.bind('click', closeMenu);
489
+ $document.on('click', closeMenu);
391
490
  }
392
- });
491
+ };
393
492
 
394
493
  if (dropdown) {
395
494
  dropdown.css('display', 'none');
396
495
  }
496
+
497
+ scope.$watch('$location.path', function() { closeMenu(); });
498
+
499
+ element.on('click', onClick);
500
+ element.on('$destroy', function() {
501
+ element.off('click', onClick);
502
+ });
397
503
  }
398
504
  };
399
505
  }]);
@@ -406,7 +512,7 @@ angular.module('mm.foundation.dropdownToggle', [ 'mm.foundation.position' ])
406
512
  * Package containing all services and directives
407
513
  * about the `interchange` module
408
514
  */
409
- angular.module('mm.foundation.interchange', [])
515
+ angular.module('mm.foundation.interchange', ['mm.foundation.mediaQueries'])
410
516
 
411
517
  /**
412
518
  * @ngdoc function
@@ -492,7 +598,7 @@ angular.module('mm.foundation.interchange', [])
492
598
  *
493
599
  * Tools to help with the `interchange` module.
494
600
  */
495
- .factory('interchangeTools', ['$window', 'interchangeQueries', function ($window, namedQueries) {
601
+ .factory('interchangeTools', ['$window', 'matchMedia', 'interchangeQueries', function ($window, matchMedia, namedQueries) {
496
602
 
497
603
  /**
498
604
  * @ngdoc method
@@ -556,7 +662,7 @@ angular.module('mm.foundation.interchange', [])
556
662
  var file, media, match;
557
663
  for (file in files) {
558
664
  media = namedQueries[file] || file;
559
- match = $window.matchMedia(media);
665
+ match = matchMedia(media);
560
666
  if (match.matches) {
561
667
  return files[file];
562
668
  }
@@ -877,12 +983,12 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
877
983
  };
878
984
  }])
879
985
 
880
- .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
881
- function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
986
+ .factory('$modalStack', ['$window', '$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
987
+ function ($window, $transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {
882
988
 
883
989
  var OPENED_MODAL_CLASS = 'modal-open';
884
990
 
885
- var backdropDomEl, backdropScope;
991
+ var backdropDomEl, backdropScope, cssTop;
886
992
  var openedWindows = $$stackedMap.createNew();
887
993
  var $modalStack = {};
888
994
 
@@ -904,16 +1010,18 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
904
1010
  });
905
1011
 
906
1012
  function removeModalWindow(modalInstance) {
907
-
908
- var body = $document.find('body').eq(0);
1013
+ var parent = $document.find(modalInstance.options.parent).eq(0);
909
1014
  var modalWindow = openedWindows.get(modalInstance).value;
910
1015
 
911
1016
  //clean up the stack
912
1017
  openedWindows.remove(modalInstance);
913
1018
 
914
1019
  //remove window DOM element
915
- removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, checkRemoveBackdrop);
916
- body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1020
+ removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {
1021
+ modalWindow.modalScope.$destroy();
1022
+ parent.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
1023
+ checkRemoveBackdrop();
1024
+ });
917
1025
  }
918
1026
 
919
1027
  function checkRemoveBackdrop() {
@@ -961,6 +1069,14 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
961
1069
  }
962
1070
  }
963
1071
 
1072
+ function calculateModalTop(modalElement, offset) {
1073
+ if (angular.isUndefined(offset)) {
1074
+ offset = 0;
1075
+ }
1076
+ var scrollY = $window.pageYOffset || 0;
1077
+ return offset + scrollY;
1078
+ }
1079
+
964
1080
  $document.bind('keydown', function (evt) {
965
1081
  var modal;
966
1082
 
@@ -975,48 +1091,68 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
975
1091
  });
976
1092
 
977
1093
  $modalStack.open = function (modalInstance, modal) {
978
-
979
- openedWindows.add(modalInstance, {
1094
+ modalInstance.options = {
980
1095
  deferred: modal.deferred,
981
1096
  modalScope: modal.scope,
982
1097
  backdrop: modal.backdrop,
983
- keyboard: modal.keyboard
984
- });
1098
+ keyboard: modal.keyboard,
1099
+ parent: modal.parent
1100
+ };
1101
+ openedWindows.add(modalInstance, modalInstance.options);
985
1102
 
986
- var body = $document.find('body').eq(0),
1103
+ var parent = $document.find(modal.parent).eq(0),
987
1104
  currBackdropIndex = backdropIndex();
988
1105
 
989
1106
  if (currBackdropIndex >= 0 && !backdropDomEl) {
990
1107
  backdropScope = $rootScope.$new(true);
991
1108
  backdropScope.index = currBackdropIndex;
992
1109
  backdropDomEl = $compile('<div modal-backdrop></div>')(backdropScope);
993
- body.append(backdropDomEl);
1110
+ parent.append(backdropDomEl);
994
1111
  }
995
-
996
- var angularDomEl = angular.element('<div modal-window></div>');
997
- angularDomEl.attr('window-class', modal.windowClass);
998
- angularDomEl.attr('index', openedWindows.length() - 1);
999
- angularDomEl.attr('animate', 'animate');
1112
+
1113
+ // Create a faux modal div just to measure its
1114
+ // distance to top
1115
+ var faux = angular.element('<div class="reveal-modal" style="z-index:-1""></div>');
1116
+ parent.append(faux[0]);
1117
+ cssTop = parseInt($window.getComputedStyle(faux[0]).top) || 0;
1118
+ var openAt = calculateModalTop(faux, cssTop);
1119
+ faux.remove();
1120
+
1121
+ var angularDomEl = angular.element('<div modal-window style="visibility: visible; top:' + openAt +'px;"></div>')
1122
+ .attr({
1123
+ 'window-class': modal.windowClass,
1124
+ 'index': openedWindows.length() - 1,
1125
+ 'animate': 'animate'
1126
+ });
1000
1127
  angularDomEl.html(modal.content);
1001
1128
 
1002
1129
  var modalDomEl = $compile(angularDomEl)(modal.scope);
1003
1130
  openedWindows.top().value.modalDomEl = modalDomEl;
1004
- body.append(modalDomEl);
1005
- body.addClass(OPENED_MODAL_CLASS);
1131
+ parent.append(modalDomEl);
1132
+ parent.addClass(OPENED_MODAL_CLASS);
1006
1133
  };
1007
1134
 
1008
- $modalStack.close = function (modalInstance, result) {
1135
+ $modalStack.reposition = function (modalInstance) {
1009
1136
  var modalWindow = openedWindows.get(modalInstance).value;
1010
1137
  if (modalWindow) {
1011
- modalWindow.deferred.resolve(result);
1138
+ var modalDomEl = modalWindow.modalDomEl;
1139
+ var top = calculateModalTop(modalDomEl, cssTop);
1140
+ modalDomEl.css('top', top + "px");
1141
+ }
1142
+ };
1143
+
1144
+ $modalStack.close = function (modalInstance, result) {
1145
+ var modalWindow = openedWindows.get(modalInstance);
1146
+ if (modalWindow) {
1147
+ modalWindow.value.deferred.resolve(result);
1012
1148
  removeModalWindow(modalInstance);
1013
1149
  }
1014
1150
  };
1015
1151
 
1016
1152
  $modalStack.dismiss = function (modalInstance, reason) {
1017
- var modalWindow = openedWindows.get(modalInstance).value;
1153
+ var modalWindow = openedWindows.get(modalInstance);
1018
1154
  if (modalWindow) {
1019
- modalWindow.deferred.reject(reason);
1155
+ modalWindow.value.deferred.reject(reason);
1020
1156
  removeModalWindow(modalInstance);
1021
1157
  }
1022
1158
  };
@@ -1079,6 +1215,9 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
1079
1215
  },
1080
1216
  dismiss: function (reason) {
1081
1217
  $modalStack.dismiss(modalInstance, reason);
1218
+ },
1219
+ reposition: function () {
1220
+ $modalStack.reposition(modalInstance);
1082
1221
  }
1083
1222
  };
1084
1223
 
@@ -1113,6 +1252,9 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
1113
1252
  });
1114
1253
 
1115
1254
  ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
1255
+ if (modalOptions.controllerAs) {
1256
+ modalScope[modalOptions.controllerAs] = ctrlInstance;
1257
+ }
1116
1258
  }
1117
1259
 
1118
1260
  $modalStack.open(modalInstance, {
@@ -1121,7 +1263,8 @@ angular.module('mm.foundation.modal', ['mm.foundation.transition'])
1121
1263
  content: tplAndVars[0],
1122
1264
  backdrop: modalOptions.backdrop,
1123
1265
  keyboard: modalOptions.keyboard,
1124
- windowClass: modalOptions.windowClass
1266
+ windowClass: modalOptions.windowClass,
1267
+ parent: modalOptions.parent || 'body'
1125
1268
  });
1126
1269
 
1127
1270
  }, function resolveError(reason) {
@@ -1496,7 +1639,7 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1496
1639
 
1497
1640
  // The options specified to the provider globally.
1498
1641
  var globalOptions = {};
1499
-
1642
+
1500
1643
  /**
1501
1644
  * `options({})` allows global configuration of all tooltips in the
1502
1645
  * application.
@@ -1506,9 +1649,9 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1506
1649
  * $tooltipProvider.options( { placement: 'left' } );
1507
1650
  * });
1508
1651
  */
1509
- this.options = function( value ) {
1510
- angular.extend( globalOptions, value );
1511
- };
1652
+ this.options = function( value ) {
1653
+ angular.extend( globalOptions, value );
1654
+ };
1512
1655
 
1513
1656
  /**
1514
1657
  * This allows you to extend the set of trigger mappings available. E.g.:
@@ -1565,7 +1708,7 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1565
1708
 
1566
1709
  var startSym = $interpolate.startSymbol();
1567
1710
  var endSym = $interpolate.endSymbol();
1568
- var template =
1711
+ var template =
1569
1712
  '<div '+ directiveName +'-popup '+
1570
1713
  'title="'+startSym+'tt_title'+endSym+'" '+
1571
1714
  'content="'+startSym+'tt_content'+endSym+'" '+
@@ -1690,7 +1833,7 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1690
1833
  // Set the initial positioning.
1691
1834
  tooltip.css({ top: 0, left: 0, display: 'block' });
1692
1835
 
1693
- // Now we add it to the DOM because need some info about it. But it's not
1836
+ // Now we add it to the DOM because need some info about it. But it's not
1694
1837
  // visible yet anyway.
1695
1838
  if ( appendToBody ) {
1696
1839
  $document.find( 'body' ).append( tooltip );
@@ -1717,7 +1860,7 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1717
1860
  //if tooltip is going to be shown after delay, we must cancel this
1718
1861
  $timeout.cancel( popupTimeout );
1719
1862
 
1720
- // And now we remove it from the DOM. However, if we have animation, we
1863
+ // And now we remove it from the DOM. However, if we have animation, we
1721
1864
  // need to wait for it to expire beforehand.
1722
1865
  // FIXME: this is a placeholder for a port of the transitions library.
1723
1866
  if ( scope.tt_animation ) {
@@ -1760,24 +1903,34 @@ angular.module( 'mm.foundation.tooltip', [ 'mm.foundation.position', 'mm.foundat
1760
1903
  scope.tt_title = val;
1761
1904
  });
1762
1905
 
1906
+ attrs[prefix+'Placement'] = attrs[prefix+'Placement'] || null;
1907
+
1763
1908
  attrs.$observe( prefix+'Placement', function ( val ) {
1764
- scope.tt_placement = angular.isDefined( val ) ? val : options.placement;
1909
+ scope.tt_placement = angular.isDefined( val ) && val ? val : options.placement;
1765
1910
  });
1766
1911
 
1912
+ attrs[prefix+'PopupDelay'] = attrs[prefix+'PopupDelay'] || null;
1913
+
1767
1914
  attrs.$observe( prefix+'PopupDelay', function ( val ) {
1768
1915
  var delay = parseInt( val, 10 );
1769
1916
  scope.tt_popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
1770
1917
  });
1771
1918
 
1772
1919
  var unregisterTriggers = function() {
1773
- if (hasRegisteredTriggers) {
1774
- element.unbind( triggers.show, showTooltipBind );
1775
- element.unbind( triggers.hide, hideTooltipBind );
1920
+ if ( hasRegisteredTriggers ) {
1921
+ if ( angular.isFunction( triggers.show ) ) {
1922
+ unregisterTriggerFunction();
1923
+ } else {
1924
+ element.unbind( triggers.show, showTooltipBind );
1925
+ element.unbind( triggers.hide, hideTooltipBind );
1926
+ }
1776
1927
  }
1777
1928
  };
1778
1929
 
1779
1930
  var unregisterTriggerFunction = function () {};
1780
1931
 
1932
+ attrs[prefix+'Trigger'] = attrs[prefix+'Trigger'] || null;
1933
+
1781
1934
  attrs.$observe( prefix+'Trigger', function ( val ) {
1782
1935
  unregisterTriggers();
1783
1936
  unregisterTriggerFunction();
@@ -2070,6 +2223,8 @@ angular.module('mm.foundation.tabs', [])
2070
2223
  var ctrl = this,
2071
2224
  tabs = ctrl.tabs = $scope.tabs = [];
2072
2225
 
2226
+ if (angular.isUndefined($scope.openOnLoad)) { $scope.openOnLoad = true; }
2227
+
2073
2228
  ctrl.select = function(tab) {
2074
2229
  angular.forEach(tabs, function(tab) {
2075
2230
  tab.active = false;
@@ -2079,7 +2234,7 @@ angular.module('mm.foundation.tabs', [])
2079
2234
 
2080
2235
  ctrl.addTab = function addTab(tab) {
2081
2236
  tabs.push(tab);
2082
- if (tabs.length === 1 || tab.active) {
2237
+ if ($scope.openOnLoad && (tabs.length === 1 || tab.active)) {
2083
2238
  ctrl.select(tab);
2084
2239
  }
2085
2240
  };
@@ -2131,7 +2286,9 @@ angular.module('mm.foundation.tabs', [])
2131
2286
  restrict: 'EA',
2132
2287
  transclude: true,
2133
2288
  replace: true,
2134
- scope: {},
2289
+ scope: {
2290
+ openOnLoad: '=?'
2291
+ },
2135
2292
  controller: 'TabsetController',
2136
2293
  templateUrl: 'template/tabs/tabset.html',
2137
2294
  link: function(scope, element, attrs) {
@@ -2258,6 +2415,9 @@ angular.module('mm.foundation.tabs', [])
2258
2415
  }
2259
2416
 
2260
2417
  scope.$watch('active', function(active) {
2418
+ if( !angular.isFunction(setActive) ){
2419
+ return;
2420
+ }
2261
2421
  // Note this watcher also initializes and assigns scope.active to the
2262
2422
  // attrs.active expression.
2263
2423
  setActive(scope.$parent, active);
@@ -2344,508 +2504,462 @@ angular.module('mm.foundation.tabs', [])
2344
2504
 
2345
2505
  ;
2346
2506
 
2507
+ angular.module("mm.foundation.topbar", ['mm.foundation.mediaQueries'])
2508
+ .factory('closest', [function() {
2509
+ return function(el, selector) {
2510
+ var matchesSelector = function (node, selector) {
2511
+ var nodes = (node.parentNode || node.document).querySelectorAll(selector);
2512
+ var i = -1;
2513
+ while (nodes[++i] && nodes[i] != node){}
2514
+ return !!nodes[i];
2515
+ };
2347
2516
 
2348
- angular.module("mm.foundation.topbar", [])
2349
- .factory('mediaQueries', ['$document', '$window', function($document, $window){
2350
- var head = angular.element($document[0].querySelector('head'));
2351
- head.append('<meta class="foundation-mq-topbar" />');
2352
- head.append('<meta class="foundation-mq-small" />');
2353
- head.append('<meta class="foundation-mq-medium" />');
2354
- head.append('<meta class="foundation-mq-large" />');
2517
+ var element = el[0];
2518
+ while (element) {
2519
+ if (matchesSelector(element, selector)) {
2520
+ return angular.element(element);
2521
+ } else {
2522
+ element = element.parentElement;
2523
+ }
2524
+ }
2525
+ return false;
2526
+ };
2527
+ }])
2528
+ .directive('topBar', ['$timeout','$compile', '$window', '$document', 'mediaQueries',
2529
+ function($timeout, $compile, $window, $document, mediaQueries) {
2530
+ return {
2531
+ scope: {
2532
+ stickyClass : '@',
2533
+ backText: '@',
2534
+ stickyOn : '=',
2535
+ customBackText: '=',
2536
+ isHover: '=',
2537
+ mobileShowParentLink: '=',
2538
+ scrolltop : '=',
2539
+ },
2540
+ restrict: 'EA',
2541
+ replace: true,
2542
+ templateUrl: 'template/topbar/top-bar.html',
2543
+ transclude: true,
2544
+ controller: ['$window', '$scope', 'closest', function($window, $scope, closest) {
2545
+ $scope.settings = {};
2546
+ $scope.settings.stickyClass = $scope.stickyClass || 'sticky';
2547
+ $scope.settings.backText = $scope.backText || 'Back';
2548
+ $scope.settings.stickyOn = $scope.stickyOn || 'all';
2355
2549
 
2356
- // MatchMedia for IE <= 9
2357
- var matchMedia = $window.matchMedia || (function(doc, undefined){
2358
- var bool,
2359
- docElem = doc.documentElement,
2360
- refNode = docElem.firstElementChild || docElem.firstChild,
2361
- // fakeBody required for <FF4 when executed in <head>
2362
- fakeBody = doc.createElement("body"),
2363
- div = doc.createElement("div");
2550
+ $scope.settings.customBackText = $scope.customBackText === undefined ? true : $scope.customBackText;
2551
+ $scope.settings.isHover = $scope.isHover === undefined ? true : $scope.isHover;
2552
+ $scope.settings.mobileShowParentLink = $scope.mobileShowParentLink === undefined ? true : $scope.mobileShowParentLink;
2553
+ $scope.settings.scrolltop = $scope.scrolltop === undefined ? true : $scope.scrolltop; // jump to top when sticky nav menu toggle is clicked
2364
2554
 
2365
- div.id = "mq-test-1";
2366
- div.style.cssText = "position:absolute;top:-100em";
2367
- fakeBody.style.background = "none";
2368
- fakeBody.appendChild(div);
2555
+ this.settings = $scope.settings;
2369
2556
 
2370
- return function (q) {
2371
- div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
2372
- docElem.insertBefore(fakeBody, refNode);
2373
- bool = div.offsetWidth === 42;
2374
- docElem.removeChild(fakeBody);
2375
- return {
2376
- matches: bool,
2377
- media: q
2378
- };
2379
- };
2557
+ $scope.index = 0;
2380
2558
 
2381
- }($document[0]));
2559
+ var outerHeight = function(el) {
2560
+ var height = el.offsetHeight;
2561
+ var style = el.currentStyle || getComputedStyle(el);
2382
2562
 
2383
- var regex = /^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g;
2384
- var queries = {
2385
- topbar: getComputedStyle(head[0].querySelector('meta.foundation-mq-topbar')).fontFamily.replace(regex, ''),
2386
- small : getComputedStyle(head[0].querySelector('meta.foundation-mq-small')).fontFamily.replace(regex, ''),
2387
- medium : getComputedStyle(head[0].querySelector('meta.foundation-mq-medium')).fontFamily.replace(regex, ''),
2388
- large : getComputedStyle(head[0].querySelector('meta.foundation-mq-large')).fontFamily.replace(regex, '')
2563
+ height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
2564
+ return height;
2389
2565
  };
2390
2566
 
2391
- return {
2392
- topbarBreakpoint: function () {
2393
- return !matchMedia(queries.topbar).matches;
2394
- },
2395
- small: function () {
2396
- return matchMedia(queries.small).matches;
2397
- },
2398
- medium: function () {
2399
- return matchMedia(queries.medium).matches;
2400
- },
2401
- large: function () {
2402
- return matchMedia(queries.large).matches;
2403
- }
2404
- };
2405
2567
 
2406
- }])
2407
- .factory('closest', [function(){
2408
- return function(el, selector) {
2409
- var matchesSelector = function (node, selector) {
2410
- var nodes = (node.parentNode || node.document).querySelectorAll(selector);
2411
- var i = -1;
2412
- while (nodes[++i] && nodes[i] != node){}
2413
- return !!nodes[i];
2414
- };
2568
+ var sections = [];
2415
2569
 
2416
- var element = el[0];
2417
- while (element) {
2418
- if (matchesSelector(element, selector)) {
2419
- return angular.element(element);
2420
- } else {
2421
- element = element.parentElement;
2422
- }
2423
- }
2424
- return false;
2570
+ this.addSection = function(section) {
2571
+ sections.push(section);
2425
2572
  };
2426
- }])
2427
- .directive('topBar', ['$timeout','$compile', '$window', '$document', 'mediaQueries',
2428
- function ($timeout, $compile, $window, $document, mediaQueries) {
2429
- return {
2430
- scope: {
2431
- stickyClass : '@',
2432
- backText: '@',
2433
- stickyOn : '=',
2434
- customBackText: '=',
2435
- isHover: '=',
2436
- mobileShowParentLink: '=',
2437
- scrolltop : '=',
2438
- },
2439
- restrict: 'EA',
2440
- replace: true,
2441
- templateUrl: 'template/topbar/top-bar.html',
2442
- transclude: true,
2443
- link: function ($scope, element, attrs) {
2444
- var topbar = $scope.topbar = element;
2445
- var topbarContainer = topbar.parent();
2446
- var body = angular.element($document[0].querySelector('body'));
2447
-
2448
- var isSticky = $scope.isSticky = function () {
2449
- var sticky = topbarContainer.hasClass($scope.settings.stickyClass);
2450
- if (sticky && $scope.settings.stickyOn === 'all') {
2451
- return true;
2452
- } else if (sticky && mediaQueries.small() && $scope.settings.stickyOn === 'small') {
2453
- return true;
2454
- } else if (sticky && mediaQueries.medium() && $scope.settings.stickyOn === 'medium') {
2455
- return true;
2456
- } else if (sticky && mediaQueries.large() && $scope.settings.stickyOn === 'large') {
2457
- return true;
2458
- }
2459
- return false;
2460
- };
2461
2573
 
2462
- var updateStickyPositioning = function(){
2463
- if (!$scope.stickyTopbar || !$scope.isSticky()) {
2464
- return;
2465
- }
2466
-
2467
- var $class = angular.element($document[0].querySelector('.' + $scope.settings.stickyClass));
2468
- var distance = stickyoffset;
2469
-
2470
- if ($window.scrollY > distance && !$class.hasClass('fixed')) {
2471
- $class.addClass('fixed');
2472
- body.css('padding-top', $scope.originalHeight + 'px');
2473
- } else if ($window.scrollY <= distance && $class.hasClass('fixed')) {
2474
- $class.removeClass('fixed');
2475
- body.css('padding-top', '');
2476
- }
2477
- };
2574
+ this.removeSection = function(section) {
2575
+ var index = sections.indexOf(section);
2576
+ if (index > -1) {
2577
+ sections.splice(index, 1);
2578
+ }
2579
+ };
2478
2580
 
2479
- $scope.toggle = function(on) {
2480
- if(!mediaQueries.topbarBreakpoint()){
2481
- return false;
2482
- }
2483
-
2484
- var expand = (on === undefined) ? !topbar.hasClass('expanded') : on;
2485
-
2486
- if (expand){
2487
- topbar.addClass('expanded');
2488
- }
2489
- else {
2490
- topbar.removeClass('expanded');
2491
- }
2492
-
2493
- if ($scope.settings.scrolltop) {
2494
- if (!expand && topbar.hasClass('fixed')) {
2495
- topbar.parent().addClass('fixed');
2496
- topbar.removeClass('fixed');
2497
- body.css('padding-top', $scope.originalHeight + 'px');
2498
- } else if (expand && topbar.parent().hasClass('fixed')) {
2499
- topbar.parent().removeClass('fixed');
2500
- topbar.addClass('fixed');
2501
- body.css('padding-top', '');
2502
- $window.scrollTo(0,0);
2503
- }
2504
- } else {
2505
- if(isSticky()) {
2506
- topbar.parent().addClass('fixed');
2507
- }
2508
-
2509
- if(topbar.parent().hasClass('fixed')) {
2510
- if (!expand) {
2511
- topbar.removeClass('fixed');
2512
- topbar.parent().removeClass('expanded');
2513
- updateStickyPositioning();
2514
- } else {
2515
- topbar.addClass('fixed');
2516
- topbar.parent().addClass('expanded');
2517
- body.css('padding-top', $scope.originalHeight + 'px');
2518
- }
2519
- }
2520
- }
2521
- };
2581
+ var dir = /rtl/i.test($document.find('html').attr('dir')) ? 'right' : 'left';
2522
2582
 
2523
- if(topbarContainer.hasClass('fixed') || isSticky() ) {
2524
- $scope.stickyTopbar = true;
2525
- $scope.height = topbarContainer[0].offsetHeight;
2526
- var stickyoffset = topbarContainer[0].getBoundingClientRect().top;
2527
- } else {
2528
- $scope.height = topbar[0].offsetHeight;
2529
- }
2583
+ $scope.$watch('index', function(index) {
2584
+ for(var i = 0; i < sections.length; i++){
2585
+ sections[i].move(dir, index);
2586
+ }
2587
+ });
2530
2588
 
2531
- $scope.originalHeight = $scope.height;
2589
+ this.toggle = function(on) {
2590
+ $scope.toggle(on);
2591
+ for(var i = 0; i < sections.length; i++){
2592
+ sections[i].reset();
2593
+ }
2594
+ $scope.index = 0;
2595
+ $scope.height = '';
2596
+ $scope.$apply();
2597
+ };
2532
2598
 
2533
- $scope.$watch('height', function(h){
2534
- if(h){
2535
- topbar.css('height', h + 'px');
2536
- } else {
2537
- topbar.css('height', '');
2538
- }
2539
- });
2599
+ this.back = function(event) {
2600
+ if($scope.index < 1 || !mediaQueries.topbarBreakpoint()){
2601
+ return;
2602
+ }
2540
2603
 
2541
- var lastBreakpoint = mediaQueries.topbarBreakpoint();
2604
+ var $link = angular.element(event.currentTarget);
2605
+ var $movedLi = closest($link, 'li.moved');
2606
+ var $previousLevelUl = $movedLi.parent();
2607
+ $scope.index = $scope.index -1;
2542
2608
 
2543
- angular.element($window).bind('resize', function(){
2544
- var currentBreakpoint = mediaQueries.topbarBreakpoint();
2545
- if(lastBreakpoint === currentBreakpoint){
2546
- return;
2547
- }
2548
- lastBreakpoint = mediaQueries.topbarBreakpoint();
2609
+ if($scope.index === 0){
2610
+ $scope.height = '';
2611
+ } else {
2612
+ $scope.height = $scope.originalHeight + outerHeight($previousLevelUl[0]);
2613
+ }
2549
2614
 
2550
- topbar.removeClass('expanded');
2551
- topbar.parent().removeClass('expanded');
2552
- $scope.height = '';
2615
+ $timeout(function() {
2616
+ $movedLi.removeClass('moved');
2617
+ }, 300);
2618
+ };
2553
2619
 
2554
- var sections = angular.element(topbar[0].querySelectorAll('section'));
2555
- angular.forEach(sections, function(section){
2556
- angular.element(section.querySelectorAll('li.moved')).removeClass('moved');
2557
- });
2620
+ this.forward = function(event) {
2621
+ if(!mediaQueries.topbarBreakpoint()){
2622
+ return false;
2623
+ }
2558
2624
 
2559
- $scope.$apply();
2560
- });
2625
+ var $link = angular.element(event.currentTarget);
2626
+ var $selectedLi = closest($link, 'li');
2627
+ $selectedLi.addClass('moved');
2628
+ $scope.height = $scope.originalHeight + outerHeight($link.parent()[0].querySelector('ul'));
2629
+ $scope.index = $scope.index + 1;
2630
+ $scope.$apply();
2631
+ };
2561
2632
 
2562
- // update sticky positioning
2563
- angular.element($window).bind("scroll", function() {
2564
- updateStickyPositioning();
2565
- $scope.$apply();
2566
- });
2633
+ }],
2634
+ link: function(scope, element, attrs) {
2635
+ var topbar = scope.topbar = element;
2636
+ var topbarContainer = topbar.parent();
2637
+ var body = angular.element($document[0].querySelector('body'));
2638
+ var lastBreakpoint = mediaQueries.topbarBreakpoint();
2639
+
2640
+ var isSticky = scope.isSticky = function() {
2641
+ var sticky = topbarContainer.hasClass(scope.settings.stickyClass);
2642
+ if (sticky && scope.settings.stickyOn === 'all') {
2643
+ return true;
2644
+ } else if (sticky && mediaQueries.small() && scope.settings.stickyOn === 'small') {
2645
+ return true;
2646
+ } else if (sticky && mediaQueries.medium() && scope.settings.stickyOn === 'medium') {
2647
+ return true;
2648
+ } else if (sticky && mediaQueries.large() && scope.settings.stickyOn === 'large') {
2649
+ return true;
2650
+ }
2651
+ return false;
2652
+ };
2567
2653
 
2568
- $scope.$on('$destroy', function(){
2569
- angular.element($window).unbind("scroll");
2570
- angular.element($window).unbind("resize");
2571
- });
2654
+ var updateStickyPositioning = function() {
2655
+ if (!scope.stickyTopbar || !scope.isSticky()) {
2656
+ return;
2657
+ }
2572
2658
 
2573
- if (topbarContainer.hasClass('fixed')) {
2574
- body.css('padding-top', $scope.originalHeight + 'px');
2575
- }
2659
+ var distance = stickyoffset;
2576
2660
 
2577
- },
2578
- controller: ['$window', '$scope', 'closest', function($window, $scope, closest) {
2579
- $scope.settings = {};
2580
- $scope.settings.stickyClass = $scope.stickyClass || 'sticky';
2581
- $scope.settings.backText = $scope.backText || 'Back';
2582
- $scope.settings.stickyOn = $scope.stickyOn || 'all';
2661
+ if ($window.pageYOffset > distance && !topbarContainer.hasClass('fixed')) {
2662
+ topbarContainer.addClass('fixed');
2663
+ body.css('padding-top', scope.originalHeight + 'px');
2664
+ } else if ($window.pageYOffset <= distance && topbarContainer.hasClass('fixed')) {
2665
+ topbarContainer.removeClass('fixed');
2666
+ body.css('padding-top', '');
2667
+ }
2668
+ };
2583
2669
 
2584
- $scope.settings.customBackText = $scope.customBackText === undefined ? true : $scope.customBackText;
2585
- $scope.settings.isHover = $scope.isHover === undefined ? true : $scope.isHover;
2586
- $scope.settings.mobileShowParentLink = $scope.mobileShowParentLink === undefined ? true : $scope.mobileShowParentLink;
2587
- $scope.settings.scrolltop = $scope.scrolltop === undefined ? true : $scope.scrolltop; // jump to top when sticky nav menu toggle is clicked
2670
+ var onResize = function() {
2671
+ var currentBreakpoint = mediaQueries.topbarBreakpoint();
2672
+ if(lastBreakpoint === currentBreakpoint){
2673
+ return;
2674
+ }
2675
+ lastBreakpoint = mediaQueries.topbarBreakpoint();
2588
2676
 
2589
- this.settings = $scope.settings;
2677
+ topbar.removeClass('expanded');
2678
+ topbar.parent().removeClass('expanded');
2679
+ scope.height = '';
2590
2680
 
2591
- $scope.index = 0;
2681
+ var sections = angular.element(topbar[0].querySelectorAll('section'));
2682
+ angular.forEach(sections, function(section) {
2683
+ angular.element(section.querySelectorAll('li.moved')).removeClass('moved');
2684
+ });
2592
2685
 
2593
- var outerHeight = function(el){
2594
- var height = el.offsetHeight;
2595
- var style = el.currentStyle || getComputedStyle(el);
2686
+ scope.$apply();
2687
+ };
2596
2688
 
2597
- height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10);
2598
- return height;
2599
- };
2689
+ var onScroll = function() {
2690
+ updateStickyPositioning();
2691
+ scope.$apply();
2692
+ };
2600
2693
 
2694
+ scope.toggle = function(on) {
2695
+ if(!mediaQueries.topbarBreakpoint()){
2696
+ return false;
2697
+ }
2601
2698
 
2602
- var sections = [];
2699
+ var expand = (on === undefined) ? !topbar.hasClass('expanded') : on;
2603
2700
 
2604
- this.addSection = function(section){
2605
- sections.push(section);
2606
- };
2701
+ if (expand) {
2702
+ topbar.addClass('expanded');
2703
+ }
2704
+ else {
2705
+ topbar.removeClass('expanded');
2706
+ }
2607
2707
 
2608
- this.removeSection = function(section){
2609
- var index = sections.indexOf(section);
2610
- if (index > -1) {
2611
- sections.splice(index, 1);
2612
- }
2613
- };
2708
+ if (scope.settings.scrolltop) {
2709
+ if (!expand && topbar.hasClass('fixed')) {
2710
+ topbar.parent().addClass('fixed');
2711
+ topbar.removeClass('fixed');
2712
+ body.css('padding-top', scope.originalHeight + 'px');
2713
+ } else if (expand && topbar.parent().hasClass('fixed')) {
2714
+ topbar.parent().removeClass('fixed');
2715
+ topbar.addClass('fixed');
2716
+ body.css('padding-top', '');
2717
+ $window.scrollTo(0,0);
2718
+ }
2719
+ } else {
2720
+ if(isSticky()) {
2721
+ topbar.parent().addClass('fixed');
2722
+ }
2614
2723
 
2615
- var dir = /rtl/i.test($document.find('html').attr('dir')) ? 'right' : 'left';
2724
+ if(topbar.parent().hasClass('fixed')) {
2725
+ if (!expand) {
2726
+ topbar.removeClass('fixed');
2727
+ topbar.parent().removeClass('expanded');
2728
+ updateStickyPositioning();
2729
+ } else {
2730
+ topbar.addClass('fixed');
2731
+ topbar.parent().addClass('expanded');
2732
+ body.css('padding-top', scope.originalHeight + 'px');
2733
+ }
2734
+ }
2735
+ }
2736
+ };
2616
2737
 
2617
- $scope.$watch('index', function(index){
2618
- for(var i = 0; i < sections.length; i++){
2619
- sections[i].move(dir, index);
2620
- }
2621
- });
2738
+ if(topbarContainer.hasClass('fixed') || isSticky() ) {
2739
+ scope.stickyTopbar = true;
2740
+ scope.height = topbarContainer[0].offsetHeight;
2741
+ var stickyoffset = topbarContainer[0].getBoundingClientRect().top + $window.pageYOffset;
2742
+ } else {
2743
+ scope.height = topbar[0].offsetHeight;
2744
+ }
2622
2745
 
2623
- this.toggle = function(on){
2624
- $scope.toggle(on);
2625
- for(var i = 0; i < sections.length; i++){
2626
- sections[i].reset();
2627
- }
2628
- $scope.index = 0;
2629
- $scope.height = '';
2630
- $scope.$apply();
2631
- };
2746
+ scope.originalHeight = scope.height;
2632
2747
 
2633
- this.back = function(event) {
2634
- if($scope.index < 1 || !mediaQueries.topbarBreakpoint()){
2635
- return;
2636
- }
2637
-
2638
- var $link = angular.element(event.currentTarget);
2639
- var $movedLi = closest($link, 'li.moved');
2640
- var $previousLevelUl = $movedLi.parent();
2641
- $scope.index = $scope.index -1;
2642
-
2643
- if($scope.index === 0){
2644
- $scope.height = '';
2645
- } else {
2646
- $scope.height = $scope.originalHeight + outerHeight($previousLevelUl[0]);
2647
- }
2648
-
2649
- $timeout(function () {
2650
- $movedLi.removeClass('moved');
2651
- }, 300);
2652
- };
2748
+ scope.$watch('height', function(h) {
2749
+ if(h){
2750
+ topbar.css('height', h + 'px');
2751
+ } else {
2752
+ topbar.css('height', '');
2753
+ }
2754
+ });
2653
2755
 
2654
- this.forward = function(event) {
2655
- if(!mediaQueries.topbarBreakpoint()){
2656
- return false;
2657
- }
2658
-
2659
- var $link = angular.element(event.currentTarget);
2660
- var $selectedLi = closest($link, 'li');
2661
- $selectedLi.addClass('moved');
2662
- $scope.height = $scope.originalHeight + outerHeight($link.parent()[0].querySelector('ul'));
2663
- $scope.index = $scope.index + 1;
2664
- $scope.$apply();
2665
- };
2756
+ angular.element($window).bind('resize', onResize);
2757
+ angular.element($window).bind('scroll', onScroll);
2666
2758
 
2667
- }]
2668
- };
2669
- }])
2670
- .directive('toggleTopBar', ['closest', function (closest) {
2671
- return {
2672
- scope: {},
2673
- require: '^topBar',
2674
- restrict: 'A',
2675
- replace: true,
2676
- templateUrl: 'template/topbar/toggle-top-bar.html',
2677
- transclude: true,
2678
- link: function ($scope, element, attrs, topBar) {
2679
- element.bind('click', function(event) {
2680
- var li = closest(angular.element(event.currentTarget), 'li');
2681
- if(!li.hasClass('back') && !li.hasClass('has-dropdown')) {
2682
- topBar.toggle();
2683
- }
2684
- });
2759
+ scope.$on('$destroy', function() {
2760
+ angular.element($window).unbind('scroll', onResize);
2761
+ angular.element($window).unbind('resize', onScroll);
2762
+ });
2685
2763
 
2686
- $scope.$on('$destroy', function(){
2687
- element.unbind('click');
2688
- });
2689
- }
2690
- };
2691
- }])
2692
- .directive('topBarSection', ['$compile', 'closest', function ($compile, closest) {
2693
- return {
2694
- scope: {},
2695
- require: '^topBar',
2696
- restrict: 'EA',
2697
- replace: true,
2698
- templateUrl: 'template/topbar/top-bar-section.html',
2699
- transclude: true,
2700
- link: function ($scope, element, attrs, topBar) {
2701
- var section = element;
2702
-
2703
- $scope.reset = function(){
2704
- angular.element(section[0].querySelectorAll('li.moved')).removeClass('moved');
2705
- };
2764
+ if (topbarContainer.hasClass('fixed')) {
2765
+ body.css('padding-top', scope.originalHeight + 'px');
2766
+ }
2767
+ }
2768
+ };
2769
+ }]
2770
+ )
2771
+ .directive('toggleTopBar', ['closest', function (closest) {
2772
+ return {
2773
+ scope: {},
2774
+ require: '^topBar',
2775
+ restrict: 'A',
2776
+ replace: true,
2777
+ templateUrl: 'template/topbar/toggle-top-bar.html',
2778
+ transclude: true,
2779
+ link: function(scope, element, attrs, topBar) {
2780
+ element.bind('click', function(event) {
2781
+ var li = closest(angular.element(event.currentTarget), 'li');
2782
+ if(!li.hasClass('back') && !li.hasClass('has-dropdown')) {
2783
+ topBar.toggle();
2784
+ }
2785
+ });
2706
2786
 
2707
- $scope.move = function(dir, index){
2708
- if(dir === 'left'){
2709
- section.css({"left": index * -100 + '%'});
2710
- }
2711
- else {
2712
- section.css({"right": index * -100 + '%'});
2713
- }
2714
- };
2787
+ scope.$on('$destroy', function() {
2788
+ element.unbind('click');
2789
+ });
2790
+ }
2791
+ };
2792
+ }])
2793
+ .directive('topBarSection', ['$compile', 'closest', function($compile, closest) {
2794
+ return {
2795
+ scope: {},
2796
+ require: '^topBar',
2797
+ restrict: 'EA',
2798
+ replace: true,
2799
+ templateUrl: 'template/topbar/top-bar-section.html',
2800
+ transclude: true,
2801
+ link: function(scope, element, attrs, topBar) {
2802
+ var section = element;
2715
2803
 
2716
- topBar.addSection($scope);
2804
+ scope.reset = function() {
2805
+ angular.element(section[0].querySelectorAll('li.moved')).removeClass('moved');
2806
+ };
2717
2807
 
2718
- $scope.$on("$destroy", function(){
2719
- topBar.removeSection($scope);
2720
- });
2808
+ scope.move = function(dir, index) {
2809
+ if(dir === 'left'){
2810
+ section.css({"left": index * -100 + '%'});
2811
+ }
2812
+ else {
2813
+ section.css({"right": index * -100 + '%'});
2814
+ }
2815
+ };
2721
2816
 
2722
- // Top level links close menu on click
2723
- var links = section[0].querySelectorAll('li>a');
2724
- angular.forEach(links, function(link){
2725
- var $link = angular.element(link);
2726
- var li = closest($link, 'li');
2727
- if(li.hasClass('has-dropdown') || li.hasClass('back') || li.hasClass('title')){
2728
- return;
2729
- }
2730
-
2731
- $link.bind('click', function(){
2732
- topBar.toggle(false);
2733
- });
2734
-
2735
- $scope.$on('$destroy', function(){
2736
- $link.bind('click');
2737
- });
2738
- });
2817
+ topBar.addSection(scope);
2739
2818
 
2740
- }
2741
- };
2742
- }])
2743
- .directive('hasDropdown', ['mediaQueries', function (mediaQueries) {
2744
- return {
2745
- scope: {},
2746
- require: '^topBar',
2747
- restrict: 'A',
2748
- templateUrl: 'template/topbar/has-dropdown.html',
2749
- replace: true,
2750
- transclude: true,
2751
- link: function ($scope, element, attrs, topBar) {
2752
- $scope.triggerLink = element.children('a')[0];
2753
-
2754
- var $link = angular.element($scope.triggerLink);
2755
-
2756
- $link.bind('click', function(event){
2757
- topBar.forward(event);
2758
- });
2759
- $scope.$on('$destroy', function(){
2760
- $link.unbind('click');
2761
- });
2819
+ scope.$on("$destroy", function() {
2820
+ topBar.removeSection(scope);
2821
+ });
2762
2822
 
2763
- element.bind('mouseenter', function() {
2764
- if(topBar.settings.isHover && !mediaQueries.topbarBreakpoint()){
2765
- element.addClass('not-click');
2766
- }
2767
- });
2768
- element.bind('click', function(event) {
2769
- if(!topBar.settings.isHover && !mediaQueries.topbarBreakpoint()){
2770
- element.toggleClass('not-click');
2771
- }
2772
- });
2823
+ // Top level links close menu on click
2824
+ var links = section[0].querySelectorAll('li>a');
2825
+ angular.forEach(links, function(link) {
2826
+ var $link = angular.element(link);
2827
+ var li = closest($link, 'li');
2828
+ if (li.hasClass('has-dropdown') || li.hasClass('back') || li.hasClass('title')) {
2829
+ return;
2830
+ }
2773
2831
 
2774
- element.bind('mouseleave', function() {
2775
- element.removeClass('not-click');
2776
- });
2832
+ $link.bind('click', function() {
2833
+ topBar.toggle(false);
2834
+ });
2777
2835
 
2778
- $scope.$on('$destroy', function(){
2779
- element.unbind('click');
2780
- element.unbind('mouseenter');
2781
- element.unbind('mouseleave');
2782
- });
2783
- },
2784
- controller: ['$window', '$scope', function($window, $scope) {
2785
- this.triggerLink = $scope.triggerLink;
2786
- }]
2787
- };
2788
- }])
2789
- .directive('topBarDropdown', ['$compile', function ($compile) {
2790
- return {
2791
- scope: {},
2792
- require: ['^topBar', '^hasDropdown'],
2793
- restrict: 'A',
2794
- replace: true,
2795
- templateUrl: 'template/topbar/top-bar-dropdown.html',
2796
- transclude: true,
2797
- link: function ($scope, element, attrs, ctrls) {
2836
+ scope.$on('$destroy', function() {
2837
+ $link.bind('click');
2838
+ });
2839
+ });
2840
+ }
2841
+ };
2842
+ }])
2843
+ .directive('hasDropdown', ['mediaQueries', function (mediaQueries) {
2844
+ return {
2845
+ scope: {},
2846
+ require: '^topBar',
2847
+ restrict: 'A',
2848
+ templateUrl: 'template/topbar/has-dropdown.html',
2849
+ replace: true,
2850
+ transclude: true,
2851
+ link: function(scope, element, attrs, topBar) {
2852
+ scope.triggerLink = element.children('a')[0];
2798
2853
 
2799
- var topBar = ctrls[0];
2800
- var hasDropdown = ctrls[1];
2854
+ var $link = angular.element(scope.triggerLink);
2801
2855
 
2802
- var $link = angular.element(hasDropdown.triggerLink);
2803
- var url = $link.attr('href');
2856
+ $link.bind('click', function(event) {
2857
+ topBar.forward(event);
2858
+ });
2859
+ scope.$on('$destroy', function() {
2860
+ $link.unbind('click');
2861
+ });
2804
2862
 
2805
- $scope.linkText = $link.text();
2863
+ element.bind('mouseenter', function() {
2864
+ if(topBar.settings.isHover && !mediaQueries.topbarBreakpoint()){
2865
+ element.addClass('not-click');
2866
+ }
2867
+ });
2868
+ element.bind('click', function(event) {
2869
+ if(!topBar.settings.isHover && !mediaQueries.topbarBreakpoint()){
2870
+ element.toggleClass('not-click');
2871
+ }
2872
+ });
2806
2873
 
2807
- $scope.back = function(event){
2808
- topBar.back(event);
2809
- };
2874
+ element.bind('mouseleave', function() {
2875
+ element.removeClass('not-click');
2876
+ });
2810
2877
 
2811
- // Add back link
2812
- if (topBar.settings.customBackText) {
2813
- $scope.backText = topBar.settings.backText;
2814
- } else {
2815
- $scope.backText = '&laquo; ' + $link.html();
2816
- }
2878
+ scope.$on('$destroy', function() {
2879
+ element.unbind('click');
2880
+ element.unbind('mouseenter');
2881
+ element.unbind('mouseleave');
2882
+ });
2883
+ },
2884
+ controller: ['$window', '$scope', function($window, $scope) {
2885
+ this.triggerLink = $scope.triggerLink;
2886
+ }]
2887
+ };
2888
+ }])
2889
+ .directive('topBarDropdown', ['$compile', function($compile) {
2890
+ return {
2891
+ scope: {},
2892
+ require: ['^topBar', '^hasDropdown'],
2893
+ restrict: 'A',
2894
+ replace: true,
2895
+ templateUrl: 'template/topbar/top-bar-dropdown.html',
2896
+ transclude: true,
2897
+ link: function(scope, element, attrs, ctrls) {
2898
+ var topBar = ctrls[0];
2899
+ var hasDropdown = ctrls[1];
2900
+ var $link = angular.element(hasDropdown.triggerLink);
2901
+ var url = $link.attr('href');
2902
+ var $titleLi;
2817
2903
 
2818
- var $titleLi;
2819
- if (topBar.settings.mobileShowParentLink && url && url.length > 1) {
2820
- $titleLi = angular.element('<li class="title back js-generated">' +
2821
- '<h5><a href="#" ng-click="back($event);">{{backText}}</a></h5></li>' +
2822
- '<li><a class="parent-link js-generated" href="' +
2823
- url + '">{{linkText}}</a></li>');
2824
- } else {
2825
- $titleLi = angular.element('<li class="title back js-generated">' +
2826
- '<h5><a href="" ng-click="back($event);">{{backText}}</a></h5></li>');
2827
- }
2904
+ scope.linkText = $link.text();
2828
2905
 
2829
- $compile($titleLi)($scope);
2830
- element.prepend($titleLi);
2831
- }
2832
- };
2833
- }]);
2906
+ scope.back = function(event) {
2907
+ topBar.back(event);
2908
+ };
2909
+
2910
+ // Add back link
2911
+ if (topBar.settings.customBackText) {
2912
+ scope.backText = topBar.settings.backText;
2913
+ } else {
2914
+ scope.backText = '&laquo; ' + $link.html();
2915
+ }
2916
+
2917
+ if (topBar.settings.mobileShowParentLink && url && url.length > 1) {
2918
+ $titleLi = angular.element('<li class="title back js-generated">' +
2919
+ '<h5><a href="#" ng-click="back($event);">{{backText}}</a></h5></li>' +
2920
+ '<li><a class="parent-link js-generated" href="' +
2921
+ url + '">{{linkText}}</a></li>');
2922
+ } else {
2923
+ $titleLi = angular.element('<li class="title back js-generated">' +
2924
+ '<h5><a href="" ng-click="back($event);">{{backText}}</a></h5></li>');
2925
+ }
2926
+
2927
+ $compile($titleLi)(scope);
2928
+ element.prepend($titleLi);
2929
+ }
2930
+ };
2931
+ }]);
2834
2932
 
2835
2933
  angular.module( 'mm.foundation.tour', [ 'mm.foundation.position', 'mm.foundation.tooltip' ] )
2836
2934
 
2837
2935
  .service( '$tour', [ '$window', function ( $window ) {
2838
- var currentIndex = getCurrentStep();
2936
+ var currentIndex = getStoredCurrentStep();
2839
2937
  var ended = false;
2840
2938
  var steps = {};
2841
2939
 
2842
- function getCurrentStep() {
2843
- return parseInt( $window.localStorage.getItem( 'mm.tour.step' ), 10 );
2940
+ function getStoredCurrentStep() {
2941
+ try {
2942
+ return parseInt( $window.localStorage.getItem( 'mm.tour.step' ), 10 );
2943
+ } catch(e) {
2944
+ if (e.name !== "SecurityError") {
2945
+ throw e;
2946
+ }
2947
+ }
2948
+ }
2949
+
2950
+ function storeCurrentStep() {
2951
+ try {
2952
+ $window.localStorage.setItem( 'mm.tour.step', currentIndex );
2953
+ } catch(e) {
2954
+ if (e.name !== "SecurityError") {
2955
+ throw e;
2956
+ }
2957
+ }
2844
2958
  }
2845
2959
 
2846
2960
  function setCurrentStep(step) {
2847
2961
  currentIndex = step;
2848
- $window.localStorage.setItem( 'mm.tour.step', step );
2962
+ storeCurrentStep();
2849
2963
  }
2850
2964
 
2851
2965
  this.add = function ( index, attrs ) {
@@ -2901,6 +3015,8 @@ angular.module( 'mm.foundation.tour', [ 'mm.foundation.position', 'mm.foundation
2901
3015
  element.remove();
2902
3016
  $tour.next();
2903
3017
  };
3018
+
3019
+ scope.$on('$locationChangeSuccess', scope.endTour);
2904
3020
  }
2905
3021
  };
2906
3022
  }])
@@ -2932,7 +3048,7 @@ angular.module( 'mm.foundation.tour', [ 'mm.foundation.position', 'mm.foundation
2932
3048
  return true;
2933
3049
  }
2934
3050
  }
2935
-
3051
+
2936
3052
  return false;
2937
3053
  }
2938
3054
 
@@ -3069,10 +3185,10 @@ angular.module('mm.foundation.typeahead', ['mm.foundation.position', 'mm.foundat
3069
3185
  } else {
3070
3186
  resetMatches();
3071
3187
  }
3072
- isLoadingSetter(originalScope, false);
3073
3188
  }
3074
3189
  }, function(){
3075
3190
  resetMatches();
3191
+ }).finally(function() {
3076
3192
  isLoadingSetter(originalScope, false);
3077
3193
  });
3078
3194
  };
@@ -3294,8 +3410,8 @@ angular.module('mm.foundation.typeahead', ['mm.foundation.position', 'mm.foundat
3294
3410
  angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
3295
3411
  $templateCache.put("template/accordion/accordion-group.html",
3296
3412
  "<dd>\n" +
3297
- " <a ng-click=\"isOpen = !isOpen\" accordion-transclude=\"heading\">{{heading}}</a>\n" +
3298
- " <div class=\"content\" ng-style=\"isOpen ? {display: 'block'} : {}\" ng-transclude></div>\n" +
3413
+ " <a ng-click=\"isOpen = !isOpen\" ng-class=\"{ active: isOpen }\" accordion-transclude=\"heading\">{{heading}}</a>\n" +
3414
+ " <div class=\"content\" ng-class=\"{ active: isOpen }\" ng-transclude></div>\n" +
3299
3415
  "</dd>\n" +
3300
3416
  "");
3301
3417
  }]);
@@ -3324,8 +3440,7 @@ angular.module("template/modal/backdrop.html", []).run(["$templateCache", functi
3324
3440
  angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
3325
3441
  $templateCache.put("template/modal/window.html",
3326
3442
  "<div tabindex=\"-1\" class=\"reveal-modal fade {{ windowClass }}\"\n" +
3327
- " ng-class=\"{in: animate}\" ng-click=\"close($event)\"\n" +
3328
- " style=\"display: block; position: fixed; visibility: visible\">\n" +
3443
+ " ng-class=\"{in: animate}\" style=\"display: block; visibility: visible\">\n" +
3329
3444
  " <div ng-transclude></div>\n" +
3330
3445
  "</div>\n" +
3331
3446
  "");
@@ -3496,4 +3611,4 @@ angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCac
3496
3611
  " </li>\n" +
3497
3612
  "</ul>\n" +
3498
3613
  "");
3499
- }]);
3614
+ }]);