foundation-apps
Version:
A responsive, Angular-powered framework for web apps from ZURB.
1,385 lines (1,114 loc) • 111 kB
JavaScript
/*!
* iconic.js v0.4.0 - The Iconic JavaScript library
* Copyright (c) 2014 Waybury - http://useiconic.com
*/
!function(a){"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):"undefined"!=typeof window?window.IconicJS=a():"undefined"!=typeof global?global.IconicJS=a():"undefined"!=typeof self&&(self.IconicJS=a())}(function(){var a;return function b(a,c,d){function e(g,h){if(!c[g]){if(!a[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};a[g][0].call(j.exports,function(b){var c=a[g][1][b];return e(c?c:b)},j,j.exports,b,a,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){var c=(a("./modules/polyfills"),a("./modules/svg-injector")),d=a("./modules/extend"),e=a("./modules/responsive"),f=a("./modules/position"),g=a("./modules/container"),h=a("./modules/log"),i={},j=window.iconicSmartIconApis={},k=("file:"===window.location.protocol,0),l=function(a,b,e){b=d({},i,b||{});var f={evalScripts:b.evalScripts,pngFallback:b.pngFallback};f.each=function(a){if(a)if("string"==typeof a)h.debug(a);else if(a instanceof SVGSVGElement){var c=a.getAttribute("data-icon");if(c&&j[c]){var d=j[c](a);for(var e in d)a[e]=d[e]}/iconic-bg-/.test(a.getAttribute("class"))&&g.addBackground(a),m(a),k++,b&&b.each&&"function"==typeof b.each&&b.each(a)}},"string"==typeof a&&(a=document.querySelectorAll(a)),c(a,f,e)},m=function(a){var b=[];a?"string"==typeof a?b=document.querySelectorAll(a):void 0!==a.length?b=a:"object"==typeof a&&b.push(a):b=document.querySelectorAll("svg.iconic"),Array.prototype.forEach.call(b,function(a){a instanceof SVGSVGElement&&(a.update&&a.update(),e.refresh(a),f.refresh(a))})},n=function(){i.debug&&console.time&&console.time("autoInjectSelector - "+i.autoInjectSelector);var a=k;l(i.autoInjectSelector,{},function(){if(i.debug&&console.timeEnd&&console.timeEnd("autoInjectSelector - "+i.autoInjectSelector),h.debug("AutoInjected: "+(k-a)),e.refreshAll(),i.autoInjectDone&&"function"==typeof i.autoInjectDone){var b=k-a;i.autoInjectDone(b)}})},o=function(a){a&&""!==a&&"complete"!==document.readyState?document.addEventListener("DOMContentLoaded",n):document.removeEventListener("DOMContentLoaded",n)},p=function(a){return a=a||{},d(i,a),o(i.autoInjectSelector),h.enableDebug(i.debug),window._Iconic?window._Iconic:{inject:l,update:m,smartIconApis:j,svgInjectedCount:k}};b.exports=p,window._Iconic=new p({autoInjectSelector:"img.iconic",evalScripts:"once",pngFallback:!1,each:null,autoInjectDone:null,debug:!1})},{"./modules/container":2,"./modules/extend":3,"./modules/log":4,"./modules/polyfills":5,"./modules/position":6,"./modules/responsive":7,"./modules/svg-injector":8}],2:[function(a,b){var c=function(a){var b=a.getAttribute("class").split(" "),c=-1!==b.indexOf("iconic-fluid"),d=[],e=["iconic-bg"];Array.prototype.forEach.call(b,function(a){switch(a){case"iconic-sm":case"iconic-md":case"iconic-lg":d.push(a),c||e.push(a.replace(/-/,"-bg-"));break;case"iconic-fluid":d.push(a),e.push(a.replace(/-/,"-bg-"));break;case"iconic-bg-circle":case"iconic-bg-rounded-rect":case"iconic-bg-badge":e.push(a);break;default:d.push(a)}}),a.setAttribute("class",d.join(" "));var f=a.parentNode,g=Array.prototype.indexOf.call(f.childNodes,a),h=document.createElement("span");h.setAttribute("class",e.join(" ")),h.appendChild(a),f.insertBefore(h,f.childNodes[g])};b.exports={addBackground:c}},{}],3:[function(a,b){b.exports=function(a){return Array.prototype.forEach.call(Array.prototype.slice.call(arguments,1),function(b){if(b)for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}),a}},{}],4:[function(a,b){var c=!1,d=function(a){console&&console.log&&console.log(a)},e=function(a){d("Iconic INFO: "+a)},f=function(a){d("Iconic WARNING: "+a)},g=function(a){c&&d("Iconic DEBUG: "+a)},h=function(a){c=a};b.exports={info:e,warn:f,debug:g,enableDebug:h}},{}],5:[function(){Array.prototype.forEach||(Array.prototype.forEach=function(a,b){"use strict";if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)}),function(){if(Event.prototype.preventDefault||(Event.prototype.preventDefault=function(){this.returnValue=!1}),Event.prototype.stopPropagation||(Event.prototype.stopPropagation=function(){this.cancelBubble=!0}),!Element.prototype.addEventListener){var a=[],b=function(b,c){var d=this,e=function(a){a.target=a.srcElement,a.currentTarget=d,c.handleEvent?c.handleEvent(a):c.call(d,a)};if("DOMContentLoaded"==b){var f=function(a){"complete"==document.readyState&&e(a)};if(document.attachEvent("onreadystatechange",f),a.push({object:this,type:b,listener:c,wrapper:f}),"complete"==document.readyState){var g=new Event;g.srcElement=window,f(g)}}else this.attachEvent("on"+b,e),a.push({object:this,type:b,listener:c,wrapper:e})},c=function(b,c){for(var d=0;d<a.length;){var e=a[d];if(e.object==this&&e.type==b&&e.listener==c){"DOMContentLoaded"==b?this.detachEvent("onreadystatechange",e.wrapper):this.detachEvent("on"+b,e.wrapper);break}++d}};Element.prototype.addEventListener=b,Element.prototype.removeEventListener=c,HTMLDocument&&(HTMLDocument.prototype.addEventListener=b,HTMLDocument.prototype.removeEventListener=c),Window&&(Window.prototype.addEventListener=b,Window.prototype.removeEventListener=c)}}()},{}],6:[function(a,b){var c=function(a){var b=a.getAttribute("data-position");if(b&&""!==b){var c,d,e,f,g,h,i,j=a.getAttribute("width"),k=a.getAttribute("height"),l=b.split("-"),m=a.querySelectorAll("g.iconic-container");Array.prototype.forEach.call(m,function(a){if(c=a.getAttribute("data-width"),d=a.getAttribute("data-height"),c!==j||d!==k){if(e=a.getAttribute("transform"),f=1,e){var b=e.match(/scale\((\d)/);f=b&&b[1]?b[1]:1}g=Math.floor((j/f-c)/2),h=Math.floor((k/f-d)/2),Array.prototype.forEach.call(l,function(a){switch(a){case"top":h=0;break;case"bottom":h=k/f-d;break;case"left":g=0;break;case"right":g=j/f-c;break;case"center":break;default:console&&console.log&&console.log("Unknown position: "+a)}}),i=0===h?g:g+" "+h,i="translate("+i+")",e?/translate/.test(e)?e=e.replace(/translate\(.*?\)/,i):e+=" "+i:e=i,a.setAttribute("transform",e)}})}};b.exports={refresh:c}},{}],7:[function(a,b){var c=/(iconic-sm\b|iconic-md\b|iconic-lg\b)/,d=function(a,b){var c="undefined"!=typeof window.getComputedStyle&&window.getComputedStyle(a,null).getPropertyValue(b);return!c&&a.currentStyle&&(c=a.currentStyle[b.replace(/([a-z])\-([a-z])/,function(a,b,c){return b+c.toUpperCase()})]||a.currentStyle[b]),c},e=function(a){var b=a.style.display;a.style.display="block";var c=parseFloat(d(a,"width").slice(0,-2)),e=parseFloat(d(a,"height").slice(0,-2));return a.style.display=b,{width:c,height:e}},f=function(){var a="/* Iconic Responsive Support Styles */\n.iconic-property-fill, .iconic-property-text {stroke: none !important;}\n.iconic-property-stroke {fill: none !important;}\nsvg.iconic.iconic-fluid {height:100% !important;width:100% !important;}\nsvg.iconic.iconic-sm:not(.iconic-size-md):not(.iconic-size-lg), svg.iconic.iconic-size-sm{width:16px;height:16px;}\nsvg.iconic.iconic-md:not(.iconic-size-sm):not(.iconic-size-lg), svg.iconic.iconic-size-md{width:32px;height:32px;}\nsvg.iconic.iconic-lg:not(.iconic-size-sm):not(.iconic-size-md), svg.iconic.iconic-size-lg{width:128px;height:128px;}\nsvg.iconic-sm > g.iconic-md, svg.iconic-sm > g.iconic-lg, svg.iconic-md > g.iconic-sm, svg.iconic-md > g.iconic-lg, svg.iconic-lg > g.iconic-sm, svg.iconic-lg > g.iconic-md {display: none;}\nsvg.iconic.iconic-icon-sm > g.iconic-lg, svg.iconic.iconic-icon-md > g.iconic-lg {display:none;}\nsvg.iconic-sm:not(.iconic-icon-md):not(.iconic-icon-lg) > g.iconic-sm, svg.iconic-md.iconic-icon-sm > g.iconic-sm, svg.iconic-lg.iconic-icon-sm > g.iconic-sm {display:inline;}\nsvg.iconic-md:not(.iconic-icon-sm):not(.iconic-icon-lg) > g.iconic-md, svg.iconic-sm.iconic-icon-md > g.iconic-md, svg.iconic-lg.iconic-icon-md > g.iconic-md {display:inline;}\nsvg.iconic-lg:not(.iconic-icon-sm):not(.iconic-icon-md) > g.iconic-lg, svg.iconic-sm.iconic-icon-lg > g.iconic-lg, svg.iconic-md.iconic-icon-lg > g.iconic-lg {display:inline;}";navigator&&navigator.userAgent&&/MSIE 10\.0/.test(navigator.userAgent)&&(a+="svg.iconic{zoom:1.0001;}");var b=document.createElement("style");b.id="iconic-responsive-css",b.type="text/css",b.styleSheet?b.styleSheet.cssText=a:b.appendChild(document.createTextNode(a)),(document.head||document.getElementsByTagName("head")[0]).appendChild(b)},g=function(a){if(/iconic-fluid/.test(a.getAttribute("class"))){var b,d=e(a),f=a.viewBox.baseVal.width/a.viewBox.baseVal.height;b=1===f?Math.min(d.width,d.height):1>f?d.width:d.height;var g;g=32>b?"iconic-sm":b>=32&&128>b?"iconic-md":"iconic-lg";var h=a.getAttribute("class"),i=c.test(h)?h.replace(c,g):h+" "+g;a.setAttribute("class",i)}},h=function(){var a=document.querySelectorAll(".injected-svg.iconic-fluid");Array.prototype.forEach.call(a,function(a){g(a)})};document.addEventListener("DOMContentLoaded",function(){f()}),window.addEventListener("resize",function(){h()}),b.exports={refresh:g,refreshAll:h}},{}],8:[function(b,c,d){!function(b,e){"use strict";function f(a){a=a.split(" ");for(var b={},c=a.length,d=[];c--;)b.hasOwnProperty(a[c])||(b[a[c]]=1,d.unshift(a[c]));return d.join(" ")}var g="file:"===b.location.protocol,h=e.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1"),i=Array.prototype.forEach||function(a,b){if(void 0===this||null===this||"function"!=typeof a)throw new TypeError;var c,d=this.length>>>0;for(c=0;d>c;++c)c in this&&a.call(b,this[c],c,this)},j={},k=0,l=[],m=[],n={},o=function(a){return a.cloneNode(!0)},p=function(a,b){m[a]=m[a]||[],m[a].push(b)},q=function(a){for(var b=0,c=m[a].length;c>b;b++)!function(b){setTimeout(function(){m[a][b](o(j[a]))},0)}(b)},r=function(a,c){if(void 0!==j[a])j[a]instanceof SVGSVGElement?c(o(j[a])):p(a,c);else{if(!b.XMLHttpRequest)return c("Browser does not support XMLHttpRequest"),!1;j[a]={},p(a,c);var d=new XMLHttpRequest;d.onreadystatechange=function(){if(4===d.readyState){if(404===d.status||null===d.responseXML)return c("Unable to load SVG file: "+a),g&&c("Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver."),c(),!1;if(!(200===d.status||g&&0===d.status))return c("There was a problem injecting the SVG: "+d.status+" "+d.statusText),!1;if(d.responseXML instanceof Document)j[a]=d.responseXML.documentElement;else if(DOMParser&&DOMParser instanceof Function){var b;try{var e=new DOMParser;b=e.parseFromString(d.responseText,"text/xml")}catch(f){b=void 0}if(!b||b.getElementsByTagName("parsererror").length)return c("Unable to parse SVG file: "+a),!1;j[a]=b.documentElement}q(a)}},d.open("GET",a),d.overrideMimeType&&d.overrideMimeType("text/xml"),d.send()}},s=function(a,c,d,e){var g=a.getAttribute("data-src")||a.getAttribute("src");if(!/svg$/i.test(g))return e("Attempted to inject a file with a non-svg extension: "+g),void 0;if(!h){var j=a.getAttribute("data-fallback")||a.getAttribute("data-png");return j?(a.setAttribute("src",j),e(null)):d?(a.setAttribute("src",d+"/"+g.split("/").pop().replace(".svg",".png")),e(null)):e("This browser does not support SVG and no PNG fallback was defined."),void 0}-1===l.indexOf(a)&&(l.push(a),a.setAttribute("src",""),r(g,function(d){if("undefined"==typeof d||"string"==typeof d)return e(d),!1;var h=a.getAttribute("id");h&&d.setAttribute("id",h);var j=a.getAttribute("title");j&&d.setAttribute("title",j);var m=[].concat(d.getAttribute("class")||[],"injected-svg",a.getAttribute("class")||[]).join(" ");d.setAttribute("class",f(m));var o=a.getAttribute("style");o&&d.setAttribute("style",o);var p=[].filter.call(a.attributes,function(a){return/^data-\w[\w\-]*$/.test(a.name)});i.call(p,function(a){a.name&&a.value&&d.setAttribute(a.name,a.value)});for(var q,r=d.querySelectorAll("defs clipPath[id]"),s=0,t=r.length;t>s;s++){q=r[s].id+"-"+k;for(var u=d.querySelectorAll('[clip-path*="'+r[s].id+'"]'),v=0,w=u.length;w>v;v++)u[v].setAttribute("clip-path","url(#"+q+")");r[s].id=q}d.removeAttribute("xmlns:a");for(var x,y,z=d.querySelectorAll("script"),A=[],B=0,C=z.length;C>B;B++)y=z[B].getAttribute("type"),y&&"application/ecmascript"!==y&&"application/javascript"!==y||(x=z[B].innerText||z[B].textContent,A.push(x),d.removeChild(z[B]));if(A.length>0&&("always"===c||"once"===c&&!n[g])){for(var D=0,E=A.length;E>D;D++)new Function(A[D])(b);n[g]=!0}a.parentNode.replaceChild(d,a),delete l[l.indexOf(a)],a=null,k++,e(d)}))},t=function(a,b,c){b=b||{};var d=b.evalScripts||"always",e=b.pngFallback||!1,f=b.each;if(void 0!==a.length){var g=0;i.call(a,function(b){s(b,d,e,function(b){f&&"function"==typeof f&&f(b),c&&a.length===++g&&c(g)})})}else a?s(a,d,e,function(b){f&&"function"==typeof f&&f(b),c&&c(1),a=null}):c&&c(0)};"object"==typeof c&&"object"==typeof c.exports?c.exports=d=t:"function"==typeof a&&a.amd?a(function(){return t}):"object"==typeof b&&(b.SVGInjector=t)}(window,document)},{}]},{},[1])(1)});
(function() {
'use strict';
angular.module('foundation.core.animation', [])
.service('FoundationAnimation', FoundationAnimation)
;
FoundationAnimation.$inject = ['$q'];
function FoundationAnimation($q) {
var animations = [];
var service = {};
var initClasses = ['ng-enter', 'ng-leave'];
var activeClasses = ['ng-enter-active', 'ng-leave-active'];
var activeGenericClass = 'is-active';
var events = [
'webkitAnimationEnd', 'mozAnimationEnd',
'MSAnimationEnd', 'oanimationend',
'animationend', 'webkitTransitionEnd',
'otransitionend', 'transitionend'
];
service.animate = animate;
service.toggleAnimation = toggleAnimation;
return service;
function toggleAnimation(element, futureState) {
if(futureState) {
element.addClass(activeGenericClass);
} else {
element.removeClass(activeGenericClass);
}
}
function animate(element, futureState, animationIn, animationOut) {
var animationTimeout;
var deferred = $q.defer();
var timedOut = true;
var self = this;
self.cancelAnimation = cancelAnimation;
var animationClass = futureState ? animationIn: animationOut;
var activation = futureState;
var initClass = activation ? initClasses[0] : initClasses[1];
var activeClass = activation ? activeClasses[0] : activeClasses[1];
run();
return deferred.promise;
function run() {
//stop animation
registerElement(element);
reset();
element.addClass(animationClass);
element.addClass(initClass);
element.addClass(activeGenericClass);
//force a "tick"
reflow();
//activate
element[0].style.transitionDuration = '';
element.addClass(activeClass);
element.on(events.join(' '), eventHandler);
animationTimeout = setTimeout(function() {
if(timedOut) {
finishAnimation();
}
}, 3000);
}
function eventHandler(e) {
if (element[0] === e.target) {
clearTimeout(animationTimeout);
finishAnimation();
}
}
function finishAnimation() {
deregisterElement(element);
reset(); //reset all classes
element[0].style.transitionDuration = '';
element.removeClass(!activation ? activeGenericClass : ''); //if not active, remove active class
reflow();
timedOut = false;
element.off(events.join(' '), eventHandler);
deferred.resolve({element: element, active: activation});
}
function cancelAnimation(element) {
deregisterElement(element);
angular.element(element).off(events.join(' ')); //kill all animation event handlers
timedOut = false;
deferred.reject();
}
function registerElement(el) {
var elObj = {
el: el,
animation: self
};
//kill in progress animations
var inProgress = animations.filter(function(obj) {
return obj.el === el;
});
if(inProgress.length > 0) {
var target = inProgress[0].el[0];
inProgress[0].animation.cancelAnimation(target);
}
animations.push(elObj);
}
function deregisterElement(el) {
var index;
var currentAnimation = animations.filter(function(obj, ind) {
if(obj.el === el) {
index = ind;
}
});
if(index >= 0) {
animations.splice(index, 1);
}
}
function reflow() {
return element[0].offsetWidth;
}
function reset() {
element[0].style.transitionDuration = 0;
element.removeClass(initClasses.join(' ') + ' ' + activeClasses.join(' ') + ' ' + animationIn + ' ' + animationOut);
}
}
}
})();
(function() {
'use strict';
angular.module('foundation.core', [
'foundation.core.animation'
])
.service('FoundationApi', FoundationApi)
.service('FoundationAdapter', FoundationAdapter)
.factory('Utils', Utils)
.run(Setup);
;
FoundationApi.$inject = ['FoundationAnimation'];
function FoundationApi(FoundationAnimation) {
var listeners = {};
var settings = {};
var uniqueIds = [];
var service = {};
service.subscribe = subscribe;
service.unsubscribe = unsubscribe;
service.publish = publish;
service.getSettings = getSettings;
service.modifySettings = modifySettings;
service.generateUuid = generateUuid;
service.toggleAnimate = toggleAnimate;
service.closeActiveElements = closeActiveElements;
service.animate = animate;
service.animateAndAdvise = animateAndAdvise;
return service;
function subscribe(name, callback) {
if (!listeners[name]) {
listeners[name] = [];
}
listeners[name].push(callback);
return true;
}
function unsubscribe(name, callback) {
if (listeners[name] !== undefined) {
delete listeners[name];
}
if (typeof callback == 'function') {
callback.call(this);
}
}
function publish(name, msg) {
if (!listeners[name]) {
listeners[name] = [];
}
listeners[name].forEach(function(cb) {
cb(msg);
});
return;
}
function getSettings() {
return settings;
}
function modifySettings(tree) {
settings = angular.extend(settings, tree);
return settings;
}
function generateUuid() {
var uuid = '';
//little trick to produce semi-random IDs
do {
uuid += 'zf-uuid-';
for (var i=0; i<15; i++) {
uuid += Math.floor(Math.random()*16).toString(16);
}
} while(!uniqueIds.indexOf(uuid));
uniqueIds.push(uuid);
return uuid;
}
function toggleAnimate(element, futureState) {
FoundationAnimation.toggleAnimate(element, futureState);
}
function closeActiveElements(options) {
var self = this;
options = options || {};
var activeElements = document.querySelectorAll('.is-active[zf-closable]');
// action sheets are nested zf-closable elements, so we have to target the parent
var nestedActiveElements = document.querySelectorAll('[zf-closable] > .is-active');
if (activeElements.length) {
angular.forEach(activeElements, function(el) {
if (options.exclude !== el.id) {
self.publish(el.id, 'close');
}
});
}
if (nestedActiveElements.length) {
angular.forEach(nestedActiveElements, function(el) {
var parentId = el.parentNode.id;
if (options.exclude !== parentId) {
self.publish(parentId, 'close');
}
});
}
}
function animate(element, futureState, animationIn, animationOut) {
return FoundationAnimation.animate(element, futureState, animationIn, animationOut);
}
function animateAndAdvise(element, futureState, animationIn, animationOut) {
var promise = FoundationAnimation.animate(element, futureState, animationIn, animationOut);
promise.then(function() {
publish(element[0].id, futureState ? 'active-true' : 'active-false');
}, function() {
publish(element[0].id, 'active-aborted');
});
return promise;
}
}
FoundationAdapter.$inject = ['FoundationApi'];
function FoundationAdapter(foundationApi) {
var service = {};
service.activate = activate;
service.deactivate = deactivate;
return service;
function activate(target) {
foundationApi.publish(target, 'show');
}
function deactivate(target) {
foundationApi.publish(target, 'hide');
}
}
function Utils() {
var utils = {};
utils.throttle = throttleUtil;
return utils;
function throttleUtil(func, delay) {
var timer = null;
return function () {
var context = this, args = arguments;
if (timer === null) {
timer = setTimeout(function () {
func.apply(context, args);
timer = null;
}, delay);
}
};
}
}
function Setup() {
// Attach FastClick
if (typeof(FastClick) !== 'undefined') {
FastClick.attach(document.body);
}
// Attach viewport units buggyfill
if (typeof(viewportUnitsBuggyfill) !== 'undefined') {
viewportUnitsBuggyfill.init();
}
}
})();
(function() {
'use strict';
angular.module('foundation.dynamicRouting.animations', ['foundation.dynamicRouting'])
.directive('uiView', uiView)
;
uiView.$inject = ['$rootScope', '$state'];
function uiView($rootScope, $state) {
var directive = {
restrict : 'ECA',
priority : -400,
link : link
};
return directive;
function link(scope, element) {
var animation = {};
var animationEnded = false;
var presetHeight;
var cleanup = [
$rootScope.$on('$stateChangeStart', onStateChangeStart),
$rootScope.$on('$stateChangeError', onStateChangeError),
scope.$on('$stateChangeSuccess', onStateChangeSuccess),
scope.$on('$viewContentAnimationEnded', onViewContentAnimationEnded)
];
var destroyed = scope.$on('$destroy', function onDestroy() {
angular.forEach(cleanup, function (cb) {
if (angular.isFunction(cb)) {
cb();
}
});
destroyed();
});
function onStateChangeStart(event, toState, toParams, fromState, fromParams) {
if (fromState.animation) {
if (!fromState.animation.leave && !toState.animation.leave) {
return;
}
else {
animationRouter(event, toState, fromState);
}
}
}
function animationRouter(event, toState, fromState) {
if (!animationEnded) {
resetParent();
prepareParent();
element.removeClass(fromState.animation.leave);
}
else {
prepareParent();
element.addClass(fromState.animation.leave);
}
}
function onStateChangeError() {
if(animation.leave) {
element.removeClass(animation.leave);
}
resetParent(); //reset parent if state change fails
}
function onStateChangeSuccess() {
resetParent();
if ($state.includes(getState()) && animation.enter) {
element.addClass(animation.enter);
}
}
function onViewContentAnimationEnded(event) {
if (event.targetScope === scope && animation.enter) {
element.removeClass(animation.enter);
}
animationEnded = true;
}
function getState() {
var view = element.data('$uiView');
var state = view && view.state && view.state.self;
if (state) {
angular.extend(animation, state.animation);
}
return state;
}
function resetParent() {
element.parent().removeClass('position-absolute');
if(presetHeight !== true) {
element.parent()[0].style.height = null;
}
}
function prepareParent() {
var parentHeight = parseInt(element.parent()[0].style.height);
var elHeight = parseInt(window.getComputedStyle(element[0], null).getPropertyValue('height'));
var tempHeight = parentHeight > 0 ? parentHeight : elHeight > 0 ? elHeight : '';
if(parentHeight > 0) {
presetHeight = true;
}
element.parent()[0].style.height = tempHeight + 'px';
element.parent().addClass('position-absolute');
}
}
}
})();
(function() {
'use strict';
angular.module('foundation.dynamicRouting', ['ui.router'])
.provider('$FoundationState', FoundationState)
.controller('DefaultController', DefaultController)
.config(DynamicRoutingConfig)
.run(DynamicRoutingRun)
;
FoundationState.$inject = ['$stateProvider'];
function FoundationState($stateProvider) {
var complexViews = {};
this.registerDynamicRoutes = function(routes) {
var dynamicRoutes = routes || foundationRoutes;
angular.forEach(dynamicRoutes, function(page) {
if (page.hasComposed) {
if (!angular.isDefined(complexViews[page.parent])) {
complexViews[page.parent] = { children: {} };
}
if (page.controller) {
page.controller = getController(page);
}
complexViews[page.parent].children[page.name] = page;
} else if (page.composed) {
if(!angular.isDefined(complexViews[page.name])) {
complexViews[page.name] = { children: {} };
}
if (page.controller) {
page.controller = getController(page);
}
angular.extend(complexViews[page.name], page);
} else {
var state = {
url: page.url,
templateUrl: page.path,
abstract: page.abstract || false,
parent: page.parent || '',
controller: getController(page),
data: getData(page),
animation: buildAnimations(page),
};
$stateProvider.state(page.name, state);
}
});
angular.forEach(complexViews, function(page) {
var state = {
url: page.url,
parent: page.parent || '',
abstract: page.abstract || false,
data: getData(page),
animation: buildAnimations(page),
views: {
'': buildState(page.path, page)
}
};
angular.forEach(page.children, function(sub) {
state.views[sub.name + '@' + page.name] = buildState(sub.path, page);
});
$stateProvider.state(page.name, state);
});
};
this.$get = angular.noop;
function getData(page) {
var data = { vars: {} };
if (page.data) {
if (typeof page.data.vars === "object") {
data.vars = page.data.vars;
}
delete page.data.vars;
angular.extend(data, page.data);
}
delete page.data;
angular.extend(data.vars, page);
return data;
}
function buildState(path, state) {
return {
templateUrl: path,
controller: getController(state),
};
}
function getController(state) {
var ctrl = state.controller || 'DefaultController';
if (!/\w\s+as\s+\w/.test(ctrl)) {
ctrl += ' as PageCtrl';
}
return ctrl;
}
function buildAnimations(state) {
var animations = {};
if (state.animationIn) {
animations.enter = state.animationIn;
}
if (state.animationOut) {
animations.leave = state.animationOut;
}
return animations;
}
}
DefaultController.$inject = ['$scope', '$stateParams', '$state'];
function DefaultController($scope, $stateParams, $state) {
var params = {};
angular.forEach($stateParams, function(value, key) {
params[key] = value;
});
$scope.params = params;
$scope.current = $state.current.name;
if($state.current.views) {
$scope.vars = $state.current.data.vars;
$scope.composed = $state.current.data.vars.children;
} else {
$scope.vars = $state.current.data.vars;
}
}
DynamicRoutingConfig.$inject = ['$FoundationStateProvider'];
function DynamicRoutingConfig(FoundationStateProvider) {
// Don't error out if Front Router is not being used
var foundationRoutes = window.foundationRoutes || [];
FoundationStateProvider.registerDynamicRoutes(foundationRoutes);
}
DynamicRoutingRun.$inject = ['$rootScope', '$state', '$stateParams'];
function DynamicRoutingRun($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}
})();
(function() {
'use strict';
angular.module('foundation.mediaquery', ['foundation.core'])
.run(mqInitRun)
.factory('FoundationMQInit', FoundationMQInit)
.factory('mqHelpers', mqHelpers)
.service('FoundationMQ', FoundationMQ)
;
mqInitRun.$inject = ['FoundationMQInit'];
function mqInitRun(mqInit) {
mqInit.init();
}
FoundationMQInit.$inject = ['mqHelpers', 'FoundationApi', 'Utils'];
function FoundationMQInit(helpers, foundationApi, u){
var factory = {};
var namedQueries = {
'default' : 'only screen',
landscape : 'only screen and (orientation: landscape)',
portrait : 'only screen and (orientation: portrait)',
retina : 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
'only screen and (min--moz-device-pixel-ratio: 2),' +
'only screen and (-o-min-device-pixel-ratio: 2/1),' +
'only screen and (min-device-pixel-ratio: 2),' +
'only screen and (min-resolution: 192dpi),' +
'only screen and (min-resolution: 2dppx)'
};
factory.init = init;
return factory;
function init() {
var mediaQueries;
var extractedMedia;
var mediaQuerySizes;
var mediaMap;
var key;
helpers.headerHelper(['foundation-mq']);
extractedMedia = helpers.getStyle('.foundation-mq', 'font-family');
if (!extractedMedia.match(/([\w]+=[\d]+[a-z]*&?)+/)) {
extractedMedia = 'small=0&medium=40rem&large=75rem&xlarge=90rem&xxlarge=120rem';
}
mediaQueries = helpers.parseStyleToObject((extractedMedia));
mediaQuerySizes = [];
for(key in mediaQueries) {
mediaQuerySizes.push({ query: key, size: parseInt(mediaQueries[key].replace('rem', '')) });
mediaQueries[key] = 'only screen and (min-width: ' + mediaQueries[key].replace('rem', 'em') + ')';
}
// sort by increasing size
mediaQuerySizes.sort(function(a,b) {
return a.size > b.size ? 1 : (a.size < b.size ? -1 : 0);
});
mediaMap = {};
for (key = 0; key < mediaQuerySizes.length; key++) {
mediaMap[mediaQuerySizes[key].query] = {
up: null,
down: null
};
if (key+1 < mediaQuerySizes.length) {
mediaMap[mediaQuerySizes[key].query].up = mediaQuerySizes[key+1].query;
}
if (key !== 0) {
mediaMap[mediaQuerySizes[key].query].down = mediaQuerySizes[key-1].query;
}
}
foundationApi.modifySettings({
mediaQueries: angular.extend(mediaQueries, namedQueries),
mediaMap: mediaMap
});
window.addEventListener('resize', u.throttle(function() {
foundationApi.publish('resize', 'window resized');
}, 50));
}
}
function mqHelpers() {
var factory = {};
factory.headerHelper = headerHelper;
factory.getStyle = getStyle;
factory.parseStyleToObject = parseStyleToObject;
return factory;
function headerHelper(classArray) {
var i = classArray.length;
var head = angular.element(document.querySelectorAll('head'));
while(i--) {
head.append('<meta class="' + classArray[i] + '" />');
}
return;
}
function getStyle(selector, styleName) {
var elem = document.querySelectorAll(selector)[0];
var style = window.getComputedStyle(elem, null);
return style.getPropertyValue('font-family');
}
// https://github.com/sindresorhus/query-string
function parseStyleToObject(str) {
var styleObject = {};
if (typeof str !== 'string') {
return styleObject;
}
if ((str[0] === '"' && str[str.length - 1] === '"') || (str[0] === '\'' && str[str.length - 1] === '\'')) {
str = str.trim().slice(1, -1); // some browsers re-quote string style values
}
if (!str) {
return styleObject;
}
styleObject = str.split('&').reduce(function(ret, param) {
var parts = param.replace(/\+/g, ' ').split('=');
var key = parts[0];
var val = parts[1];
key = decodeURIComponent(key);
// missing `=` should be `null`:
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
val = val === undefined ? null : decodeURIComponent(val);
if (!ret.hasOwnProperty(key)) {
ret[key] = val;
} else if (Array.isArray(ret[key])) {
ret[key].push(val);
} else {
ret[key] = [ret[key], val];
}
return ret;
}, {});
return styleObject;
}
}
FoundationMQ.$inject = ['FoundationApi'];
function FoundationMQ(foundationApi) {
var service = [],
mediaQueryResultCache = {},
queryMinWidthCache = {};
foundationApi.subscribe('resize', function() {
// any new resize event causes a clearing of the media cache
mediaQueryResultCache = {};
});
service.getMediaQueries = getMediaQueries;
service.match = match;
service.matchesMedia = matchesMedia;
service.matchesMediaOrSmaller = matchesMediaOrSmaller;
service.matchesMediaOnly = matchesMediaOnly;
service.collectScenariosFromElement = collectScenariosFromElement;
return service;
function getMediaQueries() {
return foundationApi.getSettings().mediaQueries;
}
function getNextLargestMediaQuery(media) {
var mediaMapEntry = foundationApi.getSettings().mediaMap[media];
if (mediaMapEntry) {
return mediaMapEntry.up;
} else {
return null;
}
}
function getNextSmallestMediaQuery(media) {
var mediaMapEntry = foundationApi.getSettings().mediaMap[media];
if (mediaMapEntry) {
return mediaMapEntry.down;
} else {
return null;
}
}
function match(scenarios) {
var count = scenarios.length;
var queries = service.getMediaQueries();
var matches = [];
if (count > 0) {
while (count--) {
var mq;
var rule = scenarios[count].media;
if (queries[rule]) {
mq = matchMedia(queries[rule]);
} else {
mq = matchMedia(rule);
}
if (mq.matches) {
matches.push({ ind: count});
}
}
}
return matches;
}
function matchesMedia(query) {
if (angular.isUndefined(mediaQueryResultCache[query])) {
// cache miss, run media query
mediaQueryResultCache[query] = match([{media: query}]).length > 0;
}
return mediaQueryResultCache[query];
}
function matchesMediaOrSmaller(query) {
// In order to match the named breakpoint or smaller,
// the next largest named breakpoint cannot be matched
var nextLargestMedia = getNextLargestMediaQuery(query);
if (nextLargestMedia && matchesMedia(nextLargestMedia)) {
return false;
}
// Check to see if any smaller named breakpoint is matched
return matchesSmallerRecursive(query);
function matchesSmallerRecursive(query) {
var nextSmallestMedia;
if (matchesMedia(query)) {
// matches breakpoint
return true;
} else {
// check if matches smaller media
nextSmallestMedia = getNextSmallestMediaQuery(query);
if (!nextSmallestMedia) {
// no more smaller breakpoints
return false;
} else {
return matchesSmallerRecursive(nextSmallestMedia);
}
}
}
}
function matchesMediaOnly(query) {
// Check that media ONLY matches named breakpoint and nothing else
var nextLargestMedia = getNextLargestMediaQuery(query);
if (!nextLargestMedia) {
// reached max media size, run query for current media
return matchesMedia(query);
} else {
// must match named breakpoint, but not next largest
return matchesMedia(query) && !matchesMedia(nextLargestMedia);
}
}
// Collects a scenario object and templates from element
function collectScenariosFromElement(parentElement) {
var scenarios = [];
var templates = [];
var elements = parentElement.children();
var i = 0;
angular.forEach(elements, function(el) {
var elem = angular.element(el);
//if no source or no html, capture element itself
if (!elem.attr('src') || !elem.attr('src').match(/.html$/)) {
templates[i] = elem;
scenarios[i] = { media: elem.attr('media'), templ: i };
} else {
scenarios[i] = { media: elem.attr('media'), src: elem.attr('src') };
}
i++;
});
return {
scenarios: scenarios,
templates: templates
};
}
}
})();
angular.module('markdown', [])
.directive('markdown', function() {
return {
restrict: 'A',
link: function(scope, element, attrs, controller) {
element.html(marked(element.html()));
}
};
});
'use strict';
(function(){
var svgDirectives = {};
angular.forEach([
'clipPath',
'colorProfile',
'src',
'cursor',
'fill',
'filter',
'marker',
'markerStart',
'markerMid',
'markerEnd',
'mask',
'stroke'
],
function(attr) {
svgDirectives[attr] = [
'$rootScope',
'$location',
'$interpolate',
'$sniffer',
'urlResolve',
'computeSVGAttrValue',
'svgAttrExpressions',
function(
$rootScope,
$location,
$interpolate,
$sniffer,
urlResolve,
computeSVGAttrValue,
svgAttrExpressions) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var initialUrl;
//Only apply to svg elements to avoid unnecessary observing
//Check that is in html5Mode and that history is supported
if ((!svgAttrExpressions.SVG_ELEMENT.test(element[0] &&
element[0].toString())) ||
!$location.$$html5 ||
!$sniffer.history) return;
//Assumes no expressions, since svg is unforgiving of xml violations
initialUrl = attrs[attr];
attrs.$observe(attr, updateValue);
$rootScope.$on('$locationChangeSuccess', updateValue);
function updateValue () {
var newVal = computeSVGAttrValue(initialUrl);
//Prevent recursive updating
if (newVal && attrs[attr] !== newVal) attrs.$set(attr, newVal);
}
}
};
}];
});
angular.module('ngSVGAttributes', []).
factory('urlResolve', [function() {
//Duplicate of urlResolve & urlParsingNode in angular core
var urlParsingNode = document.createElement('a');
return function urlResolve(url) {
urlParsingNode.setAttribute('href', url);
return urlParsingNode;
};
}]).
value('svgAttrExpressions', {
FUNC_URI: /^url\((.*)\)$/,
SVG_ELEMENT: /SVG[a-zA-Z]*Element/,
HASH_PART: /#.*/
}).
factory('computeSVGAttrValue', [
'$location', '$sniffer', 'svgAttrExpressions', 'urlResolve',
function($location, $sniffer, svgAttrExpressions, urlResolve) {
return function computeSVGAttrValue(url) {
var match, fullUrl;
if (match = svgAttrExpressions.FUNC_URI.exec(url)) {
//hash in html5Mode, forces to be relative to current url instead of base
if (match[1].indexOf('#') === 0) {
fullUrl = $location.absUrl().
replace(svgAttrExpressions.HASH_PART, '') +
match[1];
}
//Presumably links to external SVG document
else {
fullUrl = urlResolve(match[1]);
}
}
return fullUrl ? 'url(' + fullUrl + ')' : null;
};
}
]
).
directive(svgDirectives);
}());
(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);
};
}
}
})();
(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.show = show;
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();
if (!$scope.$$phase) {
content.$apply();
container.$apply();
}
}
function toggle() {
content.toggle();
container.toggle();
if (!$scope.$$phase) {
content.$apply();
container.$apply();
}
}
function show() {
content.show();
container.show();
if (!$scope.$$phase) {
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();
}
if (msg === 'show' || msg === 'open') {
controller.show();
}
});
controller.registerContainer(scope);
scope.toggle = function() {
scope.active = !scope.active;
return;
};
scope.hide = function() {
scope.active = false;
return;
};
scope.show = function() {
scope.active = true;
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;
};
scope.show = function() {
scope.active = true;
controller.registerListener();
return;
};
}
}
zfAsButton.$inject = ['FoundationApi'];
function zfAsButton(foundationApi) {
var directi