angularjs-foundation-rails 0.3.1.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }]);