diff options
Diffstat (limited to 'afm-client/bower_components/foundation-apps/js/angular/components')
26 files changed, 2306 insertions, 0 deletions
diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html new file mode 100644 index 0000000..2bc4892 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion-item.html @@ -0,0 +1,4 @@ +<div class="accordion-item" ng-class="{'is-active': active}"> + <div class="accordion-title" ng-click="activate()">{{ title }}</div> + <div class="accordion-content" ng-transclude></div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html new file mode 100644 index 0000000..344586e --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.html @@ -0,0 +1,2 @@ +<div class="accordion" ng-transclude> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js new file mode 100644 index 0000000..2b2dac7 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/accordion/accordion.js @@ -0,0 +1,107 @@ +(function() { + 'use strict'; + + angular.module('foundation.accordion', []) + .controller('ZfAccordionController', zfAccordionController) + .directive('zfAccordion', zfAccordion) + .directive('zfAccordionItem', zfAccordionItem) + ; + + zfAccordionController.$inject = ['$scope']; + + function zfAccordionController($scope) { + var controller = this; + var sections = controller.sections = $scope.sections = []; + var multiOpen = controller.multiOpen = $scope.multiOpen = $scope.multiOpen || false; + var collapsible = controller.collapsible = $scope.collapsible = $scope.multiOpen || $scope.collapsible || true; //multi open infers a collapsible true + var autoOpen = controller.autoOpen = $scope.autoOpen = $scope.autoOpen || true; //auto open opens first tab on render + + controller.select = function(selectSection) { + sections.forEach(function(section) { + //if multi open is allowed, toggle a tab + if(controller.multiOpen) { + if(section.scope === selectSection) { + section.scope.active = !section.scope.active; + } + } else { + //non multi open will close all tabs and open one + if(section.scope === selectSection) { + //if collapsible is allowed, a tab will toggle + section.scope.active = collapsible ? !section.scope.active : true; + } else { + section.scope.active = false; + } + } + + }); + }; + + controller.addSection = function addsection(sectionScope) { + sections.push({ scope: sectionScope }); + + if(sections.length === 1 && autoOpen === true) { + sections[0].active = true; + sections[0].scope.active = true; + } + }; + + controller.closeAll = function() { + sections.forEach(function(section) { + section.scope.active = false; + }); + }; + } + + function zfAccordion() { + var directive = { + restrict: 'EA', + transclude: 'true', + replace: true, + templateUrl: 'components/accordion/accordion.html', + controller: 'ZfAccordionController', + scope: { + multiOpen: '@?', + collapsible: '@?', + autoOpen: '@?' + }, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller) { + scope.multiOpen = controller.multiOpen = scope.multiOpen === "true" ? true : false; + scope.collapsible = controller.collapsible = scope.collapsible === "true" ? true : false; + scope.autoOpen = controller.autoOpen = scope.autoOpen === "true" ? true : false; + } + } + + //accordion item + function zfAccordionItem() { + var directive = { + restrict: 'EA', + templateUrl: 'components/accordion/accordion-item.html', + transclude: true, + scope: { + title: '@' + }, + require: '^zfAccordion', + replace: true, + controller: function() {}, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller, transclude) { + scope.active = false; + controller.addSection(scope); + + scope.activate = function() { + controller.select(scope); + }; + + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html new file mode 100644 index 0000000..6df405c --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-button.html @@ -0,0 +1,6 @@ +<div> + <a href="#" + class="button" + ng-if="title.length > 0">{{ title }}</a> + <div ng-transclude></div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html new file mode 100644 index 0000000..cafb733 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet-content.html @@ -0,0 +1,8 @@ +<div + class="action-sheet {{ position }}" + ng-class="{'is-active': active}" + > + <div + ng-transclude> + </div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html new file mode 100644 index 0000000..0b1006c --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.html @@ -0,0 +1,3 @@ +<div class="action-sheet-container" + ng-transclude> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js new file mode 100644 index 0000000..e38b67a --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/actionsheet/actionsheet.js @@ -0,0 +1,226 @@ +(function() { + 'use strict'; + + angular.module('foundation.actionsheet', ['foundation.core']) + .controller('ZfActionSheetController', zfActionSheetController) + .directive('zfActionSheet', zfActionSheet) + .directive('zfAsContent', zfAsContent) + .directive('zfAsButton', zfAsButton) + .service('FoundationActionSheet', FoundationActionSheet) + ; + + FoundationActionSheet.$inject = ['FoundationApi']; + + function FoundationActionSheet(foundationApi) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + } + + zfActionSheetController.$inject = ['$scope', 'FoundationApi']; + + function zfActionSheetController($scope, foundationApi) { + var controller = this; + var content = controller.content = $scope.content; + var container = controller.container = $scope.container; + var body = angular.element(document.body); + + controller.registerContent = function(scope) { + content = scope; + content.active = false; + }; + + controller.registerContainer = function(scope) { + container = scope; + container.active = false; + }; + + controller.toggle = toggle; + controller.hide = hide; + + controller.registerListener = function() { + document.body.addEventListener('click', listenerLogic); + }; + + controller.deregisterListener = function() { + document.body.removeEventListener('click', listenerLogic); + } + + function listenerLogic(e) { + var el = e.target; + var insideActionSheet = false; + + do { + if(el.classList && el.classList.contains('action-sheet-container')) { + insideActionSheet = true; + break; + } + + } while ((el = el.parentNode)); + + if(!insideActionSheet) { + // if the element has a toggle attribute, do nothing + if (e.target.attributes['zf-toggle'] || e.target.attributes['zf-hard-toggle']) { + return; + }; + // if the element is outside the action sheet and is NOT a toggle element, hide + hide(); + } + } + + function hide() { + content.hide(); + container.hide(); + + content.$apply(); + container.$apply(); + } + + function toggle() { + content.toggle(); + container.toggle(); + + content.$apply(); + container.$apply(); + } + } + + zfActionSheet.$inject = ['FoundationApi']; + + function zfActionSheet(foundationApi) { + var directive = { + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'components/actionsheet/actionsheet.html', + controller: 'ZfActionSheetController', + compile: compile + }; + + return directive; + + function compile() { + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs) { + iAttrs.$set('zf-closable', 'actionsheet'); + } + + function postLink(scope, element, attrs, controller) { + var id = attrs.id || foundationApi.generateUuid(); + attrs.$set('id', id); + + scope.active = false; + + foundationApi.subscribe(id, function(msg) { + if (msg === 'toggle') { + controller.toggle(); + } + + if (msg === 'hide' || msg === 'close') { + controller.hide(); + } + + }); + + controller.registerContainer(scope); + + scope.toggle = function() { + scope.active = !scope.active; + return; + }; + + scope.hide = function() { + scope.active = false; + return; + }; + } + } + } + + zfAsContent.$inject = ['FoundationApi']; + + function zfAsContent(foundationApi) { + var directive = { + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'components/actionsheet/actionsheet-content.html', + require: '^zfActionSheet', + scope: { + position: '@?' + }, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller) { + scope.active = false; + scope.position = scope.position || 'bottom'; + controller.registerContent(scope); + + scope.toggle = function() { + scope.active = !scope.active; + if(scope.active) { + controller.registerListener(); + } else { + controller.deregisterListener(); + } + + return; + }; + + scope.hide = function() { + scope.active = false; + controller.deregisterListener(); + return; + }; + } + } + + zfAsButton.$inject = ['FoundationApi']; + + function zfAsButton(foundationApi) { + var directive = { + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'components/actionsheet/actionsheet-button.html', + require: '^zfActionSheet', + scope: { + title: '@?' + }, + link: link + } + + return directive; + + function link(scope, element, attrs, controller) { + + element.on('click', function(e) { + controller.toggle(); + e.preventDefault(); + }); + + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/common/common.js b/afm-client/bower_components/foundation-apps/js/angular/components/common/common.js new file mode 100644 index 0000000..a818a6d --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/common/common.js @@ -0,0 +1,171 @@ +(function() { + 'use strict'; + + angular.module('foundation.common', ['foundation.core']) + .directive('zfClose', zfClose) + .directive('zfOpen', zfOpen) + .directive('zfToggle', zfToggle) + .directive('zfEscClose', zfEscClose) + .directive('zfSwipeClose', zfSwipeClose) + .directive('zfHardToggle', zfHardToggle) + ; + + zfClose.$inject = ['FoundationApi']; + + function zfClose(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + function link(scope, element, attrs) { + var targetId = ''; + if (attrs.zfClose) { + targetId = attrs.zfClose; + } else { + var parentElement= false; + var tempElement = element.parent(); + //find parent modal + while(parentElement === false) { + if(tempElement[0].nodeName == 'BODY') { + parentElement = ''; + } + + if(typeof tempElement.attr('zf-closable') !== 'undefined' && tempElement.attr('zf-closable') !== false) { + parentElement = tempElement; + } + + tempElement = tempElement.parent(); + } + targetId = parentElement.attr('id'); + } + + element.on('click', function(e) { + foundationApi.publish(targetId, 'close'); + e.preventDefault(); + }); + } + } + + zfOpen.$inject = ['FoundationApi']; + + function zfOpen(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + function link(scope, element, attrs) { + element.on('click', function(e) { + foundationApi.publish(attrs.zfOpen, 'open'); + e.preventDefault(); + }); + } + } + + zfToggle.$inject = ['FoundationApi']; + + function zfToggle(foundationApi) { + var directive = { + restrict: 'A', + link: link + } + + return directive; + + function link(scope, element, attrs) { + element.on('click', function(e) { + foundationApi.publish(attrs.zfToggle, 'toggle'); + e.preventDefault(); + }); + } + } + + zfEscClose.$inject = ['FoundationApi']; + + function zfEscClose(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + function link(scope, element, attrs) { + element.on('keyup', function(e) { + if (e.keyCode === 27) { + foundationApi.closeActiveElements(); + } + e.preventDefault(); + }); + } + } + + zfSwipeClose.$inject = ['FoundationApi']; + + function zfSwipeClose(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + return directive; + + function link($scope, element, attrs) { + var swipeDirection; + var hammerElem; + if (Hammer) { + hammerElem = new Hammer(element[0]); + // set the options for swipe (to make them a bit more forgiving in detection) + hammerElem.get('swipe').set({ + direction: Hammer.DIRECTION_ALL, + threshold: 5, // this is how far the swipe has to travel + velocity: 0.5 // and this is how fast the swipe must travel + }); + } + // detect what direction the directive is pointing + switch (attrs.zfSwipeClose) { + case 'right': + swipeDirection = 'swiperight'; + break; + case 'left': + swipeDirection = 'swipeleft'; + break; + case 'up': + swipeDirection = 'swipeup'; + break; + case 'down': + swipeDirection = 'swipedown'; + break; + default: + swipeDirection = 'swipe'; + } + hammerElem.on(swipeDirection, function() { + foundationApi.publish(attrs.id, 'close'); + }); + } + } + + zfHardToggle.$inject = ['FoundationApi']; + + function zfHardToggle(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + function link(scope, element, attrs) { + element.on('click', function(e) { + foundationApi.closeActiveElements({exclude: attrs.zfHardToggle}); + foundationApi.publish(attrs.zfHardToggle, 'toggle'); + e.preventDefault(); + }); + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js b/afm-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js new file mode 100644 index 0000000..19cf192 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/iconic/iconic.js @@ -0,0 +1,186 @@ +(function () { + 'use strict'; + + angular.module('foundation.iconic', []) + .provider('Iconic', Iconic) + .directive('zfIconic', zfIconic) + ; + + // iconic wrapper + function Iconic() { + // default path + var assetPath = 'assets/img/iconic/'; + + /** + * Sets the path used to locate the iconic SVG files + * @param {string} path - the base path used to locate the iconic SVG files + */ + this.setAssetPath = function (path) { + assetPath = angular.isString(path) ? path : assetPath; + }; + + /** + * Service implementation + * @returns {{}} + */ + this.$get = function () { + var iconicObject = new IconicJS(); + + var service = { + getAccess: getAccess, + getAssetPath: getAssetPath + }; + + return service; + + /** + * + * @returns {Window.IconicJS} + */ + function getAccess() { + return iconicObject; + } + + /** + * + * @returns {string} + */ + function getAssetPath() { + return assetPath; + } + }; + } + + zfIconic.$inject = ['Iconic', 'FoundationApi', '$compile']; + + function zfIconic(iconic, foundationApi, $compile) { + var directive = { + restrict: 'A', + template: '<img ng-transclude>', + transclude: true, + replace: true, + scope: { + dynSrc: '=?', + dynIcon: '=?', + size: '@?', + icon: '@', + iconDir: '@?' + }, + compile: compile + }; + + return directive; + + function compile() { + var contents, assetPath; + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, element, attrs) { + + if (scope.iconDir) { + // path set via attribute + assetPath = scope.iconDir; + } else { + // default path + assetPath = iconic.getAssetPath(); + } + // make sure ends with / + if (assetPath.charAt(assetPath.length - 1) !== '/') { + assetPath += '/'; + } + + if (scope.dynSrc) { + attrs.$set('data-src', scope.dynSrc); + } else if (scope.dynIcon) { + attrs.$set('data-src', assetPath + scope.dynIcon + '.svg'); + } else { + if (scope.icon) { + attrs.$set('data-src', assetPath + scope.icon + '.svg'); + } else { + // To support expressions on data-src + attrs.$set('data-src', attrs.src); + } + } + + // check if size already added as class + if (!element.hasClass('iconic-sm') && !element.hasClass('iconic-md') && !element.hasClass('iconic-lg')) { + var iconicClass; + switch (scope.size) { + case 'small': + iconicClass = 'iconic-sm'; + break; + case 'medium': + iconicClass = 'iconic-md'; + break; + case 'large': + iconicClass = 'iconic-lg'; + break; + default: + iconicClass = 'iconic-fluid'; + } + element.addClass(iconicClass); + } + + // save contents of un-inject html, to use for dynamic re-injection + contents = element[0].outerHTML; + } + + function postLink(scope, element, attrs) { + var svgElement, ico = iconic.getAccess(); + + injectSvg(element[0]); + + foundationApi.subscribe('resize', function () { + // only run update on current element + ico.update(element[0]); + }); + + // handle dynamic updating of src + if (scope.dynSrc) { + scope.$watch('dynSrc', function (newVal, oldVal) { + if (newVal && newVal !== oldVal) { + reinjectSvg(scope.dynSrc); + } + }); + } + // handle dynamic updating of icon + if (scope.dynIcon) { + scope.$watch('dynIcon', function (newVal, oldVal) { + if (newVal && newVal !== oldVal) { + reinjectSvg(assetPath + scope.dynIcon + '.svg'); + } + }); + } + + function reinjectSvg(newSrc) { + if (svgElement) { + // set html + svgElement.empty(); + svgElement.append(angular.element(contents)); + + // set new source + svgElement.attr('data-src', newSrc); + + // reinject + injectSvg(svgElement[0]); + } + } + + function injectSvg(element) { + ico.inject(element, { + each: function (injectedElem) { + // compile injected svg + var angElem = angular.element(injectedElem); + svgElement = $compile(angElem)(angElem.scope()); + } + }); + } + } + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js b/afm-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js new file mode 100644 index 0000000..74ea897 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/interchange/interchange.js @@ -0,0 +1,94 @@ +(function() { + 'use strict'; + + angular.module('foundation.interchange', ['foundation.core', 'foundation.mediaquery']) + .directive('zfInterchange', zfInterchange) + ; + + zfInterchange.$inject = [ '$compile', '$http', '$templateCache', 'FoundationApi', 'FoundationMQ']; + + function zfInterchange($compile, $http, $templateCache, foundationApi, foundationMQ) { + + var directive = { + restrict: 'EA', + transclude: 'element', + scope: { + position: '@' + }, + replace: true, + template: '<div></div>', + link: link + }; + + return directive; + + function link(scope, element, attrs, ctrl, transclude) { + var childScope, current, scenarios, innerTemplates; + + var globalQueries = foundationMQ.getMediaQueries(); + + //setup + foundationApi.subscribe('resize', function(msg) { + transclude(function(clone, newScope) { + if(!scenarios || !innerTemplates) { + collectInformation(clone); + } + + var ruleMatches = foundationMQ.match(scenarios); + var scenario = ruleMatches.length === 0 ? null : scenarios[ruleMatches[0].ind]; + + //this could use some love + if(scenario && checkScenario(scenario)) { + var compiled; + + if(childScope) { + childScope.$destroy(); + childScope = null; + } + + if(typeof scenario.templ !== 'undefined') { + childScope = newScope; + + //temp container + var tmp = document.createElement('div'); + tmp.appendChild(innerTemplates[scenario.templ][0]); + + element.html(tmp.innerHTML); + $compile(element.contents())(childScope); + current = scenario; + } else { + var loader = templateLoader(scenario.src); + loader.success(function(html) { + childScope = newScope; + element.html(html); + }).then(function(){ + $compile(element.contents())(childScope); + current = scenario; + }); + } + } + }); + + }); + + //init + foundationApi.publish('resize', 'initial resize'); + + function templateLoader(templateUrl) { + return $http.get(templateUrl, {cache: $templateCache}); + } + + function collectInformation(el) { + var data = foundationMQ.collectScenariosFromElement(el); + + scenarios = data.scenarios; + innerTemplates = data.templates; + } + + function checkScenario(scenario) { + return !current || current !== scenario; + } + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.html b/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.html new file mode 100644 index 0000000..83618db --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.html @@ -0,0 +1,9 @@ +<div + class="modal-overlay" + ng-click="hideOverlay()"> + <aside + class="modal" + ng-click="$event.stopPropagation();" + ng-transclude> + </aside> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.js b/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.js new file mode 100644 index 0000000..415f21b --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/modal/modal.js @@ -0,0 +1,291 @@ +(function() { + 'use strict'; + + angular.module('foundation.modal', ['foundation.core']) + .directive('zfModal', modalDirective) + .factory('ModalFactory', ModalFactory) + ; + + FoundationModal.$inject = ['FoundationApi', 'ModalFactory']; + + function FoundationModal(foundationApi, ModalFactory) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + service.newModal = newModal; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + + //new modal has to be controlled via the new instance + function newModal(config) { + return new ModalFactory(config); + } + } + + modalDirective.$inject = ['FoundationApi']; + + function modalDirective(foundationApi) { + + var directive = { + restrict: 'EA', + templateUrl: 'components/modal/modal.html', + transclude: true, + scope: true, + replace: true, + compile: compile + }; + + return directive; + + function compile(tElement, tAttrs, transclude) { + var type = 'modal'; + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs, controller) { + iAttrs.$set('zf-closable', type); + } + + function postLink(scope, element, attrs) { + var dialog = angular.element(element.children()[0]); + + scope.active = scope.active || false; + scope.overlay = attrs.overlay === 'false' ? false : true; + scope.overlayClose = attrs.overlayClose === 'false' ? false : true; + + var animationIn = attrs.animationIn || 'fadeIn'; + var animationOut = attrs.animationOut || 'fadeOut'; + + var overlayIn = 'fadeIn'; + var overlayOut = 'fadeOut'; + + scope.hideOverlay = function() { + if(scope.overlayClose) { + scope.hide(); + } + }; + + scope.hide = function() { + scope.active = false; + animate(); + return; + }; + + scope.show = function() { + scope.active = true; + animate(); + dialog.tabIndex = -1; + dialog[0].focus(); + return; + }; + + scope.toggle = function() { + scope.active = !scope.active; + animate(); + return; + }; + + init(); + + //setup + foundationApi.subscribe(attrs.id, function(msg) { + if(msg === 'show' || msg === 'open') { + scope.show(); + } else if (msg === 'close' || msg === 'hide') { + scope.hide(); + } else if (msg === 'toggle') { + scope.toggle(); + } + + if (scope.$root && !scope.$root.$$phase) { + scope.$apply(); + } + + return; + }); + + function animate() { + //animate both overlay and dialog + if(!scope.overlay) { + element.css('background', 'transparent'); + } + + foundationApi.animate(element, scope.active, overlayIn, overlayOut); + foundationApi.animate(dialog, scope.active, animationIn, animationOut); + } + + function init() { + if(scope.active) { + scope.show(); + } + } + } + } + } + + ModalFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', '$q', 'FoundationApi']; + + function ModalFactory($http, $templateCache, $rootScope, $compile, $timeout, $q, foundationApi) { + return modalFactory; + + function modalFactory(config) { + var self = this, //for prototype functions + container = angular.element(config.container || document.body), + id = config.id || foundationApi.generateUuid(), + attached = false, + destroyed = false, + html, + element, + fetched, + scope, + contentScope + ; + + var props = [ + 'animationIn', + 'animationOut', + 'overlay', + 'overlayClose' + ]; + + if(config.templateUrl) { + //get template + fetched = $http.get(config.templateUrl, { + cache: $templateCache + }).then(function (response) { + html = response.data; + assembleDirective(); + }); + + } else if(config.template) { + //use provided template + fetched = true; + html = config.template; + assembleDirective(); + } + + self.activate = activate; + self.deactivate = deactivate; + self.toggle = toggle; + self.destroy = destroy; + + + return { + activate: activate, + deactivate: deactivate, + toggle: toggle, + destroy: destroy + }; + + function checkStatus() { + if(destroyed) { + throw "Error: Modal was destroyed. Delete the object and create a new ModalFactory instance." + } + } + + function activate() { + checkStatus(); + $timeout(function() { + init(true); + foundationApi.publish(id, 'show'); + }, 0, false); + } + + function deactivate() { + checkStatus(); + $timeout(function() { + init(false); + foundationApi.publish(id, 'hide'); + }, 0, false); + } + + function toggle() { + checkStatus(); + $timeout(function() { + init(true); + foundationApi.publish(id, 'toggle'); + }, 0, false); + } + + function init(state) { + $q.when(fetched).then(function() { + if(!attached && html.length > 0) { + var modalEl = container.append(element); + + scope.active = state; + $compile(element)(scope); + + attached = true; + } + }); + } + + function assembleDirective() { + // check for duplicate elements to prevent factory from cloning modals + if (document.getElementById(id)) { + return; + } + + html = '<zf-modal id="' + id + '">' + html + '</zf-modal>'; + + element = angular.element(html); + + scope = $rootScope.$new(); + + // account for directive attributes + for(var i = 0; i < props.length; i++) { + var prop = props[i]; + + if(config[prop]) { + switch (prop) { + case 'animationIn': + element.attr('animation-in', config[prop]); + break; + case 'animationOut': + element.attr('animation-out', config[prop]); + break; + default: + element.attr(prop, config[prop]); + } + } + } + // access view scope variables + if (config.contentScope) { + contentScope = config.contentScope; + for (var prop in config.contentScope) { + if (config.contentScope.hasOwnProperty(prop)) { + scope[prop] = config.contentScope[prop]; + } + } + } + } + + function destroy() { + self.deactivate(); + setTimeout(function() { + scope.$destroy(); + element.remove(); + destroyed = true; + }, 3000); + foundationApi.unsubscribe(id); + } + + } + + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html new file mode 100644 index 0000000..9193026 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-set.html @@ -0,0 +1,9 @@ +<div class="notification-container {{position}}"> + <zf-notification ng-repeat="notification in notifications" + title="notification.title" + image="notification.image" + notif-id = "notification.id" + color="notification.color" + autoclose="notification.autoclose" + >{{ notification.content }}</zf-notification> +</div>
\ No newline at end of file diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html new file mode 100644 index 0000000..f524eed --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification-static.html @@ -0,0 +1,12 @@ +<div zf-swipe-close="swipe" class="static-notification {{ color }} {{ position }}"> + <a href="#" + class="close-button" + ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">×</a> + <div class="notification-icon" ng-if="image"> + <img ng-src="{{ image }}"/> + </div> + <div class="notification-content"> + <h1>{{ title }}</h1> + <p ng-transclude></p> + </div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.html b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.html new file mode 100644 index 0000000..a311f01 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.html @@ -0,0 +1,12 @@ +<div zf-swipe-close="swipe" class="notification {{ color }}"> + <a href="#" + class="close-button" + ng-click="hide(); $event.preventDefault(); $event.stopPropagation()">×</a> + <div class="notification-icon" ng-if="image"> + <img ng-src="{{ image }}"/> + </div> + <div class="notification-content"> + <h1>{{ title }}</h1> + <p ng-transclude></p> + </div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.js b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.js new file mode 100644 index 0000000..2c0e3bc --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/notification/notification.js @@ -0,0 +1,417 @@ +(function() { + 'use strict'; + + angular.module('foundation.notification', ['foundation.core']) + .controller('ZfNotificationController', ZfNotificationController) + .directive('zfNotificationSet', zfNotificationSet) + .directive('zfNotification', zfNotification) + .directive('zfNotificationStatic', zfNotificationStatic) + .directive('zfNotify', zfNotify) + .factory('NotificationFactory', NotificationFactory) + .service('FoundationNotification', FoundationNotification) + ; + + FoundationNotification.$inject = ['FoundationApi', 'NotificationFactory']; + + function FoundationNotification(foundationApi, NotificationFactory) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + + function toggle(target) { + foundationApi.publish(target, 'toggle'); + } + + function createNotificationSet(config) { + return new NotificationFactory(config); + } + } + + + ZfNotificationController.$inject = ['$scope', 'FoundationApi']; + + function ZfNotificationController($scope, foundationApi) { + var controller = this; + controller.notifications = $scope.notifications = $scope.notifications || []; + + controller.addNotification = function(info) { + var id = foundationApi.generateUuid(); + info.id = id; + $scope.notifications.push(info); + }; + + controller.removeNotification = function(id) { + $scope.notifications.forEach(function(notification) { + if(notification.id === id) { + var ind = $scope.notifications.indexOf(notification); + $scope.notifications.splice(ind, 1); + } + }); + }; + + controller.clearAll = function() { + while($scope.notifications.length > 0) { + $scope.notifications.pop(); + } + }; + } + + zfNotificationSet.$inject = ['FoundationApi']; + + function zfNotificationSet(foundationApi) { + var directive = { + restrict: 'EA', + templateUrl: 'components/notification/notification-set.html', + controller: 'ZfNotificationController', + replace: true, + scope: { + position: '@' + }, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller) { + scope.position = scope.position ? scope.position.split(' ').join('-') : 'top-right'; + + foundationApi.subscribe(attrs.id, function(msg) { + if(msg === 'clearall') { + controller.clearAll(); + } + else { + controller.addNotification(msg); + if (!scope.$root.$$phase) { + scope.$apply(); + } + } + }); + } + } + + zfNotification.$inject = ['FoundationApi']; + + function zfNotification(foundationApi) { + var directive = { + restrict: 'EA', + templateUrl: 'components/notification/notification.html', + replace: true, + transclude: true, + require: '^zfNotificationSet', + controller: function() { }, + scope: { + title: '=?', + content: '=?', + image: '=?', + notifId: '=', + color: '=?', + autoclose: '=?' + }, + compile: compile + }; + + return directive; + + function compile() { + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs) { + iAttrs.$set('zf-closable', 'notification'); + } + + function postLink(scope, element, attrs, controller) { + scope.active = false; + var animationIn = attrs.animationIn || 'fadeIn'; + var animationOut = attrs.animationOut || 'fadeOut'; + var hammerElem; + + //due to dynamic insertion of DOM, we need to wait for it to show up and get working! + setTimeout(function() { + scope.active = true; + foundationApi.animate(element, scope.active, animationIn, animationOut); + }, 50); + + scope.hide = function() { + scope.active = false; + foundationApi.animate(element, scope.active, animationIn, animationOut); + setTimeout(function() { + controller.removeNotification(scope.notifId); + }, 50); + }; + + // close if autoclose + if (scope.autoclose) { + setTimeout(function() { + if (scope.active) { + scope.hide(); + } + }, parseInt(scope.autoclose)); + }; + + // close on swipe + if (Hammer) { + hammerElem = new Hammer(element[0]); + // set the options for swipe (to make them a bit more forgiving in detection) + hammerElem.get('swipe').set({ + direction: Hammer.DIRECTION_ALL, + threshold: 5, // this is how far the swipe has to travel + velocity: 0.5 // and this is how fast the swipe must travel + }); + } + + hammerElem.on('swipe', function() { + if (scope.active) { + scope.hide(); + } + }); + } + } + } + + zfNotificationStatic.$inject = ['FoundationApi']; + + function zfNotificationStatic(foundationApi) { + var directive = { + restrict: 'EA', + templateUrl: 'components/notification/notification-static.html', + replace: true, + transclude: true, + scope: { + title: '@?', + content: '@?', + image: '@?', + color: '@?', + autoclose: '@?' + }, + compile: compile + }; + + return directive; + + function compile() { + var type = 'notification'; + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs, controller) { + iAttrs.$set('zf-closable', type); + } + + function postLink(scope, element, attrs, controller) { + scope.position = attrs.position ? attrs.position.split(' ').join('-') : 'top-right'; + + var animationIn = attrs.animationIn || 'fadeIn'; + var animationOut = attrs.animationOut || 'fadeOut'; + + //setup + foundationApi.subscribe(attrs.id, function(msg) { + if(msg == 'show' || msg == 'open') { + scope.show(); + // close if autoclose + if (scope.autoclose) { + setTimeout(function() { + if (scope.active) { + scope.hide(); + } + }, parseInt(scope.autoclose)); + }; + } else if (msg == 'close' || msg == 'hide') { + scope.hide(); + } else if (msg == 'toggle') { + scope.toggle(); + // close if autoclose + if (scope.autoclose) { + setTimeout(function() { + if (scope.active) { + scope.toggle(); + } + }, parseInt(scope.autoclose)); + }; + } + + foundationApi.animate(element, scope.active, animationIn, animationOut); + scope.$apply(); + + return; + }); + + scope.hide = function() { + scope.active = false; + foundationApi.animate(element, scope.active, animationIn, animationOut); + return; + }; + + scope.show = function() { + scope.active = true; + foundationApi.animate(element, scope.active, animationIn, animationOut); + return; + }; + + scope.toggle = function() { + scope.active = !scope.active; + foundationApi.animate(element, scope.active, animationIn, animationOut); + return; + }; + + } + } + } + + zfNotify.$inject = ['FoundationApi']; + + function zfNotify(foundationApi) { + var directive = { + restrict: 'A', + scope: { + title: '@?', + content: '@?', + color: '@?', + image: '@?', + autoclose: '@?' + }, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller) { + element.on('click', function(e) { + foundationApi.publish(attrs.zfNotify, { + title: scope.title, + content: scope.content, + color: scope.color, + image: scope.image, + autoclose: scope.autoclose + }); + e.preventDefault(); + }); + } + } + + NotificationFactory.$inject = ['$http', '$templateCache', '$rootScope', '$compile', '$timeout', 'FoundationApi']; + + function NotificationFactory($http, $templateCache, $rootScope, $compile, $timeout, foundationApi) { + return notificationFactory; + + function notificationFactory(config) { + var self = this, //for prototype functions + container = angular.element(config.container || document.body), + id = config.id || foundationApi.generateUuid(), + attached = false, + destroyed = false, + html, + element, + scope, + contentScope + ; + + var props = [ + 'position' + ]; + + assembleDirective(); + + self.addNotification = addNotification; + self.clearAll = clearAll; + self.destroy = destroy; + + return { + addNotification: addNotification, + clearAll: clearAll, + destroy: destroy + }; + + function checkStatus() { + if(destroyed) { + throw "Error: Notification Set was destroyed. Delete the object and create a new NotificationFactory instance." + } + } + + function addNotification(notification) { + checkStatus(); + $timeout(function() { + foundationApi.publish(id, notification); + }, 0, false); + } + + function clearAll() { + checkStatus(); + $timeout(function() { + foundationApi.publish(id, 'clearall'); + }, 0, false); + } + + function init(state) { + if(!attached && html.length > 0) { + var modalEl = container.append(element); + + scope.active = state; + $compile(element)(scope); + + attached = true; + } + } + + function assembleDirective() { + // check for duplicate element to prevent factory from cloning notification sets + if (document.getElementById(id)) { + return; + } + html = '<zf-notification-set id="' + id + '"></zf-notification-set>'; + + element = angular.element(html); + + scope = $rootScope.$new(); + + for(var i = 0; i < props.length; i++) { + if(config[props[i]]) { + element.attr(props[i], config[props[i]]); + } + } + + // access view scope variables + if (config.contentScope) { + contentScope = config.contentScope; + for (var prop in contentScope) { + if (contentScope.hasOwnProperty(prop)) { + scope[prop] = contentScope[prop]; + } + } + } + init(true); + } + + function destroy() { + self.clearAll(); + setTimeout(function() { + scope.$destroy(); + element.remove(); + destroyed = true; + }, 3000); + foundationApi.unsubscribe(id); + } + + } + + } +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html b/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html new file mode 100644 index 0000000..233cb02 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.html @@ -0,0 +1,5 @@ +<div + class="off-canvas {{ position }}" + ng-class="{'is-active': active}" + ng-transclude> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js b/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js new file mode 100644 index 0000000..b1d6cff --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/offcanvas/offcanvas.js @@ -0,0 +1,102 @@ +(function() { + 'use strict'; + + angular.module('foundation.offcanvas', ['foundation.core']) + .directive('zfOffcanvas', zfOffcanvas) + .service('FoundationOffcanvas', FoundationOffcanvas) + ; + + FoundationOffcanvas.$inject = ['FoundationApi']; + + function FoundationOffcanvas(foundationApi) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + + function toggle(target) { + foundationApi.publish(target, 'toggle'); + } + } + + zfOffcanvas.$inject = ['FoundationApi']; + + function zfOffcanvas(foundationApi) { + var directive = { + restrict: 'EA', + templateUrl: 'components/offcanvas/offcanvas.html', + transclude: true, + scope: { + position: '@' + }, + replace: true, + compile: compile + }; + + return directive; + + function compile(tElement, tAttrs, transclude) { + var type = 'offcanvas'; + + return { + pre: preLink, + post: postLink + } + + function preLink(scope, iElement, iAttrs, controller) { + iAttrs.$set('zf-closable', type); + document.body.classList.add('has-off-canvas'); + } + + function postLink(scope, element, attrs) { + scope.position = scope.position || 'left'; + + scope.active = false; + //setup + foundationApi.subscribe(attrs.id, function(msg) { + if(msg === 'show' || msg === 'open') { + scope.show(); + } else if (msg === 'close' || msg === 'hide') { + scope.hide(); + } else if (msg === 'toggle') { + scope.toggle(); + } + + if (!scope.$root.$$phase) { + scope.$apply(); + } + + return; + }); + + scope.hide = function() { + scope.active = false; + return; + }; + + scope.show = function() { + scope.active = true; + return; + }; + + scope.toggle = function() { + scope.active = !scope.active; + return; + }; + } + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.html b/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.html new file mode 100644 index 0000000..75a5b48 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.html @@ -0,0 +1,6 @@ +<div + class="panel" + ng-class="positionClass" + ng-transclude + > +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.js b/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.js new file mode 100644 index 0000000..396ca28 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/panel/panel.js @@ -0,0 +1,144 @@ +(function() { + 'use strict'; + + angular.module('foundation.panel', ['foundation.core']) + .directive('zfPanel', zfPanel) + .service('FoundationPanel', FoundationPanel) + ; + + FoundationPanel.$inject = ['FoundationApi']; + + function FoundationPanel(foundationApi) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + } + + zfPanel.$inject = ['FoundationApi', '$window']; + + function zfPanel(foundationApi, $window) { + var directive = { + restrict: 'EA', + templateUrl: 'components/panel/panel.html', + transclude: true, + scope: { + position: '@?' + }, + replace: true, + compile: compile + }; + + return directive; + + function compile(tElement, tAttrs, transclude) { + var type = 'panel'; + + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs, controller) { + iAttrs.$set('zf-closable', type); + scope.position = scope.position || 'left'; + scope.positionClass = 'panel-' + scope.position; + } + + function postLink(scope, element, attrs) { + scope.active = false; + var animationIn, animationOut; + var globalQueries = foundationApi.getSettings().mediaQueries; + + //urgh, there must be a better way + if(scope.position === 'left') { + animationIn = attrs.animationIn || 'slideInRight'; + animationOut = attrs.animationOut || 'slideOutLeft'; + } else if (scope.position === 'right') { + animationIn = attrs.animationIn || 'slideInLeft'; + animationOut = attrs.animationOut || 'slideOutRight'; + } else if (scope.position === 'top') { + animationIn = attrs.animationIn || 'slideInDown'; + animationOut = attrs.animationOut || 'slideOutUp'; + } else if (scope.position === 'bottom') { + animationIn = attrs.animationIn || 'slideInUp'; + animationOut = attrs.animationOut || 'slideOutBottom'; + } + + + //setup + foundationApi.subscribe(attrs.id, function(msg) { + var panelPosition = $window.getComputedStyle(element[0]).getPropertyValue("position"); + + // patch to prevent panel animation on larger screen devices + if (panelPosition !== 'absolute') { + return; + } + + if(msg == 'show' || msg == 'open') { + scope.show(); + } else if (msg == 'close' || msg == 'hide') { + scope.hide(); + } else if (msg == 'toggle') { + scope.toggle(); + } + + if (!scope.$root.$$phase) { + scope.$apply(); + } + + return; + }); + + scope.hide = function() { + if(scope.active){ + scope.active = false; + foundationApi.animate(element, scope.active, animationIn, animationOut); + } + + return; + }; + + scope.show = function() { + if(!scope.active){ + scope.active = true; + foundationApi.animate(element, scope.active, animationIn, animationOut); + } + + return; + }; + + scope.toggle = function() { + scope.active = !scope.active; + foundationApi.animate(element, scope.active, animationIn, animationOut); + + return; + }; + + element.on('click', function(e) { + //check sizing + var srcEl = e.srcElement; + + if(!matchMedia(globalQueries.medium).matches && srcEl.href && srcEl.href.length > 0) { + //hide element if it can't match at least medium + scope.hide(); + foundationApi.animate(element, scope.active, animationIn, animationOut); + } + }); + } + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.html b/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.html new file mode 100644 index 0000000..50abed7 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.html @@ -0,0 +1,2 @@ +<div class="popup" ng-class="{'is-active': active }" ng-transclude> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.js b/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.js new file mode 100644 index 0000000..f51b1c6 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/popup/popup.js @@ -0,0 +1,160 @@ +(function() { + 'use strict'; + + angular.module('foundation.popup', ['foundation.core']) + .directive('zfPopup', zfPopup) + .directive('zfPopupToggle', zfPopupToggle) + .service('FoundationPopup', FoundationPopup) + ; + + FoundationPopup.$inject = ['FoundationApi']; + + function FoundationPopup(foundationApi) { + var service = {}; + + service.activate = activate; + service.deactivate = deactivate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + //target should be element ID + function deactivate(target) { + foundationApi.publish(target, 'hide'); + } + + function toggle(target, popupTarget) { + foundationApi.publish(target, ['toggle', popupTarget]); + } + } + + zfPopup.$inject = ['FoundationApi']; + + function zfPopup(foundationApi) { + var directive = { + restrict: 'EA', + transclude: true, + replace: true, + templateUrl: 'components/popup/popup.html', + scope: { + pinTo: '@?', + pinAt: '@?', + target: '@?' + }, + compile: compile + }; + + return directive; + + function compile() { + return { + pre: preLink, + post: postLink + }; + + function preLink(scope, iElement, iAttrs) { + iAttrs.$set('zf-closable', 'popup'); + } + + function postLink(scope, element, attrs) { + scope.active = false; + scope.target = scope.target || false; + + var attachment = scope.pinTo || 'top center'; + var targetAttachment = scope.pinAt || 'bottom center'; + var tetherInit = false; + var tether = {}; + + //setup + foundationApi.subscribe(attrs.id, function(msg) { + if(msg[0] === 'show' || msg[0] === 'open') { + scope.show(msg[1]); + } else if (msg[0] === 'close' || msg[0] === 'hide') { + scope.hide(); + } else if (msg[0] === 'toggle') { + scope.toggle(msg[1]); + } + + scope.$apply(); + + return; + }); + + + scope.hide = function() { + scope.active = false; + tetherElement(); + tether.disable(); + return; + }; + + scope.show = function(newTarget) { + scope.active = true; + tetherElement(newTarget); + tether.enable(); + + return; + }; + + scope.toggle = function(newTarget) { + scope.active = !scope.active; + tetherElement(newTarget); + + if(scope.active) { + tether.enable(); + } else { + tether.disable(); + } + + return; + }; + + function tetherElement(target) { + if(tetherInit) { + return; + } + + scope.target = scope.target ? document.getElementById(scope.target) : document.getElementById(target); + + tether = new Tether({ + element: element[0], + target: scope.target, + attachment: attachment, + targetAttachment: targetAttachment, + enable: false + }); + + tetherInit = true; + } + + } + } + } + + zfPopupToggle.$inject = ['FoundationApi']; + + function zfPopupToggle(foundationApi) { + var directive = { + restrict: 'A', + link: link + }; + + return directive; + + function link(scope, element, attrs) { + var target = attrs.zfPopupToggle; + var id = attrs.id || foundationApi.generateUuid(); + attrs.$set('id', id); + + element.on('click', function(e) { + foundationApi.publish(target, ['toggle', id]); + e.preventDefault(); + }); + } + } + +})(); diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html new file mode 100644 index 0000000..6ae46e7 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab-content.html @@ -0,0 +1,8 @@ +<div class="tab-contents"> + <div zf-tab-individual + class="tab-content" + ng-class="{'is-active': tab.active}" + ng-repeat="tab in tabs" + tab="tab"> + </div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html new file mode 100644 index 0000000..082bf86 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tab.html @@ -0,0 +1,3 @@ +<div class="tab-item" + ng-class="{'is-active': active}" + ng-click="makeActive()">{{ title }}</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html new file mode 100644 index 0000000..b8a66f5 --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.html @@ -0,0 +1,8 @@ +<div> + <div class="tabs" ng-transclude> + </div> + <div zf-tab-content + target="{{ id }}" + ng-if="showTabContent"> + </div> +</div> diff --git a/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js new file mode 100644 index 0000000..3818a2a --- /dev/null +++ b/afm-client/bower_components/foundation-apps/js/angular/components/tabs/tabs.js @@ -0,0 +1,311 @@ +(function() { + 'use strict'; + + angular.module('foundation.tabs', ['foundation.core']) + .controller('ZfTabsController', ZfTabsController) + .directive('zfTabs', zfTabs) + .directive('zfTabContent', zfTabContent) + .directive('zfTab', zfTab) + .directive('zfTabIndividual', zfTabIndividual) + .directive('zfTabHref', zfTabHref) + .directive('zfTabCustom', zfTabCustom) + .directive('zfTabContentCustom', zfTabContentCustom) + .service('FoundationTabs', FoundationTabs) + ; + + FoundationTabs.$inject = ['FoundationApi']; + + function FoundationTabs(foundationApi) { + var service = {}; + + service.activate = activate; + + return service; + + //target should be element ID + function activate(target) { + foundationApi.publish(target, 'show'); + } + + } + + ZfTabsController.$inject = ['$scope', 'FoundationApi']; + + function ZfTabsController($scope, foundationApi) { + var controller = this; + var tabs = controller.tabs = $scope.tabs = []; + var id = ''; + + controller.select = function(selectTab) { + tabs.forEach(function(tab) { + tab.active = false; + tab.scope.active = false; + + if(tab.scope === selectTab) { + foundationApi.publish(id, ['activate', tab]); + + tab.active = true; + tab.scope.active = true; + } + }); + + }; + + controller.addTab = function addTab(tabScope) { + tabs.push({ scope: tabScope, active: false, parentContent: controller.id }); + + if(tabs.length === 1) { + tabs[0].active = true; + tabScope.active = true; + } + }; + + controller.getId = function() { + return id; + }; + + controller.setId = function(newId) { + id = newId; + }; + } + + zfTabs.$inject = ['FoundationApi']; + + function zfTabs(foundationApi) { + var directive = { + restrict: 'EA', + transclude: 'true', + replace: true, + templateUrl: 'components/tabs/tabs.html', + controller: 'ZfTabsController', + scope: { + displaced: '@?' + }, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller) { + scope.id = attrs.id || foundationApi.generateUuid(); + scope.showTabContent = scope.displaced !== 'true'; + attrs.$set('id', scope.id); + controller.setId(scope.id); + + //update tabs in case tab-content doesn't have them + var updateTabs = function() { + foundationApi.publish(scope.id + '-tabs', scope.tabs); + }; + + foundationApi.subscribe(scope.id + '-get-tabs', function() { + updateTabs(); + }); + } + } + + zfTabContent.$inject = ['FoundationApi']; + + function zfTabContent(foundationApi) { + var directive = { + restrict: 'A', + transclude: 'true', + replace: true, + scope: { + tabs: '=?', + target: '@' + }, + templateUrl: 'components/tabs/tab-content.html', + link: link + }; + + return directive; + + function link(scope, element, attrs, ctrl) { + scope.tabs = scope.tabs || []; + var id = scope.target; + + foundationApi.subscribe(id, function(msg) { + if(msg[0] === 'activate') { + var tabId = msg[1]; + scope.tabs.forEach(function (tab) { + tab.scope.active = false; + tab.active = false; + + if(tab.scope.id === id) { + tab.scope.active = true; + tab.active = true; + } + }); + } + }); + + //if tabs empty, request tabs + if(scope.tabs.length === 0) { + foundationApi.subscribe(id + '-tabs', function(tabs) { + scope.tabs = tabs; + }); + + foundationApi.publish(id + '-get-tabs', ''); + } + } + } + + zfTab.$inject = ['FoundationApi']; + + function zfTab(foundationApi) { + var directive = { + restrict: 'EA', + templateUrl: 'components/tabs/tab.html', + transclude: true, + scope: { + title: '@' + }, + require: '^zfTabs', + replace: true, + link: link + }; + + return directive; + + function link(scope, element, attrs, controller, transclude) { + scope.id = attrs.id || foundationApi.generateUuid(); + scope.active = false; + scope.transcludeFn = transclude; + controller.addTab(scope); + + foundationApi.subscribe(scope.id, function(msg) { + if(msg === 'show' || msg === 'open' || msg === 'activate') { + scope.makeActive(); + } + }); + + scope.makeActive = function() { + controller.select(scope); + }; + } + } + + zfTabIndividual.$inject = ['FoundationApi']; + + function zfTabIndividual(foundationApi) { + var directive = { + restrict: 'EA', + transclude: 'true', + link: link + }; + + return directive; + + function link(scope, element, attrs, ctrl, transclude) { + var tab = scope.$eval(attrs.tab); + var id = tab.scope.id; + + tab.scope.transcludeFn(tab.scope, function(tabContent) { + element.append(tabContent); + }); + + foundationApi.subscribe(tab.scope.id, function(msg) { + foundationApi.publish(tab.parentContent, ['activate', tab.scope.id]); + scope.$apply(); + }); + + } + } + + //custom tabs + + zfTabHref.$inject = ['FoundationApi']; + + function zfTabHref(foundationApi) { + var directive = { + restrict: 'A', + replace: false, + link: link + } + + return directive; + + function link(scope, element, attrs, ctrl) { + var target = attrs.zfTabHref; + + foundationApi.subscribe(target, function(msg) { + if(msg === 'activate' || msg === 'show' || msg === 'open') { + makeActive(); + } + }); + + + element.on('click', function(e) { + foundationApi.publish(target, 'activate'); + makeActive(); + e.preventDefault(); + }); + + function makeActive() { + element.parent().children().removeClass('is-active'); + element.addClass('is-active'); + } + } + } + + zfTabCustom.$inject = ['FoundationApi']; + + function zfTabCustom(foundationApi) { + var directive = { + restrict: 'A', + replace: false, + link: link + }; + + return directive; + + function link(scope, element, attrs, ctrl, transclude) { + var children = element.children(); + angular.element(children[0]).addClass('is-active'); + } + } + + zfTabContentCustom.$inject = ['FoundationApi']; + + function zfTabContentCustom(foundationApi) { + return { + restrict: 'A', + link: link + }; + + function link(scope, element, attrs) { + var tabs = []; + var children = element.children(); + + angular.forEach(children, function(node) { + if(node.id) { + var tabId = node.id; + tabs.push(tabId); + foundationApi.subscribe(tabId, function(msg) { + if(msg === 'activate' || msg === 'show' || msg === 'open') { + activateTabs(tabId); + } + }); + + if(tabs.length === 1) { + var el = angular.element(node); + el.addClass('is-active'); + } + } + }); + + function activateTabs(tabId) { + var tabNodes = element.children(); + angular.forEach(tabNodes, function(node) { + var el = angular.element(node); + el.removeClass('is-active'); + if(el.attr('id') === tabId) { + el.addClass('is-active'); + } + + }); + } + } + } + +})(); |