<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script data-require="angular-route@*" data-semver="1.4.8" src="https://code.angularjs.org/1.4.8/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.1/TweenLite.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.1/easing/EasePack.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.1/plugins/ScrollToPlugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/ScrollMagic.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/plugins/debug.addIndicators.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.5/plugins/animation.gsap.js"></script>
<script src="ng-magics.js"></script>
<script src="script.js"></script>
<link href="style.css" rel="stylesheet" />
</head>
<body ng-app="app" ng-controller="AppController as app">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<ul class="nav navbar-nav">
<li ng-class="{ active: (route == 'a') }">
<a href="#"><em>a</em> Scene</a>
</li>
<li ng-class="{ active: (route == 'b') }">
<a href="#"><em>b</em> Scene</a>
</li>
<li ng-class="{ active: (route == 'c') }">
<a href="#"><em>c</em> Scene</a>
</li>
<li ng-class="{ active: (route == 'd') }">
<a href="#"><em>d</em> Scene</a>
</li>
</ul>
<p class="navbar-brand pull-right">ng-magics</p>
</div>
</nav>
<section magics-scene="a">
<div class="container">
<div class="row">
<div class="col-md-12">
<h1><em>a</em> Scene</h1>
<p class="lead">Entry scene that got no special treatment.</p>
<p>It got no parent <em>magics-stage</em> directive, so it is defined on <em>default</em> stage, which just a basic vertical stage that uses window as the container.</p>
<p>Even though it doesn't define scene spies, top bar can reflects its activity because of <em>sceneEnter</em> event listeners on root scope.</p>
</div>
</div>
</div>
</section>
<section magics-scene="b">
<div class="container" ng-controller="GalleryController as gallery">
<div class="row">
<div class="col-md-12">
<h1><em>b</em> Scene</h1>
<p class="lead">It got a nested stage.</p>
<p class="text-center">
<span class="btn btn-default" ng-class="{ 'btn-success': gallery.five }">Five</span>
<span class="btn btn-default" ng-class="{ 'btn-warning': gallery.ten }">Ten</span>
</p>
<div class="progress">
<div ng-style="{ 'width': gallery.progress }" ng-class="{ 'reverse': gallery.reverse }">
<span>{{ gallery.progress }}</span>
</div>
</div>
<h2><em>gallery</em> Horizontal Stage</h2>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div>
<div magics-stage="gallery" magics-stage-options="{ vertical: false, globalSceneOptions: { triggerHook: 0.3 } }" class="gallery">
<ul magics-scene="gallery" magics-spy magics-spy-progress="gallery.progressHandler">
<li></li>
<li></li>
<li></li>
<li></li>
<li magics-scene="galleryFive" magics-spy="gallery.five" magics-spy-progress="gallery.fiveProgressHandler">
<div id="galleryFive">5</div>
</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li magics-scene="galleryTen" magics-spy="gallery.ten">
<div>10</div>
</li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</div>
<p></p>
</div>
</div>
</div>
</section>
<section magics-scene="c" parallax parallax-distance="0.66">
<div class="container">
<div class="row">
<div class="col-md-12">
<h1><em>c</em> Scene</h1>
<h2><em>parallax</em> directive</h2>
<p class="lead">An example of parallax directive that enables fancy effects with just a tiny bit of code and some scroll sorcery.</p>
</div>
</div>
</div>
</section>
<section magics-scene="d">
<h1><em>d</em> Scene</h1>
<p class="lead">Another dull empty scene.</p>
</section>
</body>
</html>
var app = angular.module('app', ['ngRoute', 'ngMagics']);
app.config(function (magicsProvider) {
// magicsProvider.stageOptions = { vertical: false };
magicsProvider.debug = true;
magicsProvider.debugOptions = {
colorStart: '#00bc8c',
colorEnd: '#e74c3c',
colorTrigger: '#3498db'
};
});
app.constant('routes', ['a', 'b', 'c', 'd']);
app.config(function ($locationProvider, $routeProvider, routes) {
angular.forEach(routes, function (route) {
$routeProvider.when('/' + route, {});
});
$routeProvider.otherwise({
redirectTo: '/a'
});
});
app.run(function ($compile, $rootScope, $location, magics, routes) {
// dummy ng-view
$compile('<ng-view>')($rootScope);
$rootScope.$on('sceneEnter', function (e, sceneName) {
console.log('sceneEnter', sceneName, e);
if (routes.indexOf(sceneName) >= 0) {
// 'sceneEnter' can be triggered inside or outside the digest this way
$rootScope.$evalAsync(function () {
$location.path('/' + sceneName);
});
}
});
// current route as single source of truth for active scene state
$rootScope.$on('$routeChangeSuccess', function (e, current) {
try {
var route = current.$$route.originalPath.replace(/(^\/)/, '');
} catch (e) {}
// should be a service, but global scope variable
// can do the job for 1-way bindings on children scopes,
// as long as its value is changed only on root scope
$rootScope.route = route;
console.debug('route', route);
});
});
app.controller('AppController', function ($scope, throttle, magics) {
this.progressHandler = throttle(function (e) {
$scope.$apply(function () {
self.progress = Math.round(e.progress * 100) + '%';
});
console.debug('app.progress', e);
}, 50);
});
app.controller('GalleryController', function ($scope, throttle) {
var self = this;
// generic throttle/debounce functions are bundled with ngMagics,
// scope manipulations have to be reasonably braked
this.progressHandler = throttle(function (e) {
$scope.$apply(function () {
self.reverse = (e.scrollDirection === 'REVERSE');
self.progress = Math.round(e.progress * 100) + '%';
});
console.debug('gallery.progress', e);
}, 50);
this.fiveProgressHandler = function (e) {
var scale = 1 + 0.5 * e.progress;
// directive is the proper place for that
if (!this.fiveElement)
this.fiveElement = angular.element(e.target.triggerElement()).find('div');
// unthrottled progress handler is a good place for realtime animations
this.fiveElement.css('transform', 'scale(' + scale + ',' + scale + ')');
}
});
app.controller('ParallaxController', function ($element, $scope) {
// extra pixels that the background height has off-canvas
this.extra = 42;
this.distance = 1;
this.progress = 0;
this.scale = function () {
return 1 / this.distance();
}
this.distance = function () {
return $scope.distance || 1;
}
this.height = function () {
return $element[0].offsetHeight;
}
this.offset = function () {
var offsetMax = Math.max(this.height() * (this.scale() - 1) - this.extra, 0);
return (this.progress - 0.5) * offsetMax * -1;
}
this.progressHandler = function () {}
});
app.directive('parallax', function (magics, debounce) {
return {
scope: {
distance: '=parallaxDistance'
},
transclude: true,
template:
'<div magics-scene="parallax" class="parallax-container">' +
' <div parallax-background></div>' +
' <div ng-transclude></div>' +
'</div>',
controller: 'ParallaxController',
controllerAs: 'parallax',
link: function (scope, element, attrs, ctrl) {
var self = ctrl;
var scene = magics.scene('parallax');
scene.on('shift', debounce(function () {
scope.$broadcast('parallax:refresh');
}, 50));
scene.on('progress', function (e) {
self.progress = e.progress;
scope.$broadcast('parallax:progress');
});
}
};
});
app.directive('parallaxBackground', function (tweenEasing) {
return {
require: ['parallaxBackground', '^parallax'],
controller: function () {
},
link: function (scope, element, attrs, ctrls) {
var parallaxCtrl = ctrls[1];
var blurRadius = 20;
scope.$on('parallax:refresh', refresh);
scope.$on('parallax:progress', progress);
function refresh() {
console.log('parallax refresh', parallaxCtrl.scale())
var scale = parallaxCtrl.scale();
element.css('transform', 'scale(' + scale + ',' + scale + ')');
progress();
}
function progress() {
console.log('parallax progress', parallaxCtrl.offset())
element.css('margin-top', parallaxCtrl.offset() + 'px');
var amount = ease(Math.abs((parallaxCtrl.progress * 2 - 1)));
var blur = Math.round(amount * blurRadius + 1) + 'px';
element.css('filter', 'blur(' + blur + ')');
}
function ease(val) {
return tweenEasing.Power2.easeIn.getRatio(val);
}
}
}
});
@import (less) "http://cdn.rawgit.com/twbs/bootstrap/v3.3.6/less/bootstrap.less";
@import (less) "http://cdn.rawgit.com/thomaspark/bootswatch/gh-pages/darkly/bootswatch.less";
@import (less) "http://cdn.rawgit.com/thomaspark/bootswatch/gh-pages/darkly/variables.less";
.for(@i, @n) {
.-each(@i);
}
.for(@n) when (isnumber(@n)) {
.for(1, @n);
}
.for(@i, @n) when not (@i = @n) {
.for((@i + (@n - @i) / abs(@n - @i)), @n);
}
@color_a: #264653;
@color_b: #2a9d8f;
@color_c: #e9c46a;
@color_d: #f4a261;
@color_e: #e76f51;
@grid-float-breakpoint: 0;
section {
&:first-of-type {
padding-top: @navbar-height;
}
&:nth-of-type(2) {
background: @color_a;
}
&:nth-of-type(3) {
background: @color_b;
}
&:nth-of-type(3) {
background: @color_b;
}
min-height: 100vh;
}
h1, h2 {
text-align: center;
}
nav {
& ul a {
cursor: default;
}
.navbar-brand {
height: auto;
padding-bottom: 0;
}
}
.lead {
text-align: center;
}
.gallery {
& ul {
.list-inline();
float: left;
display: inline-block;
font-size: 0rem;
white-space: nowrap;
}
& ul > li {
.for(15); .-each(@i) {
&:nth-of-type(@{i}) {
background: url('http://placeimg.com/300/300/nature/@{i}') no-repeat center;
}
}
vertical-align: middle;
padding: 0;
font-size: 1rem;
width: 300px;
height: 300px;
}
& li div {
.text-center();
line-height: 300px;
font-size: 15em;
}
overflow-x: scroll;
overflow-y: hidden;
}
.progress {
& div {
.progress-bar();
.progress-bar-success();
min-width: 2em;
line-height: @line-height-computed * 1.25;
font-size:@font-size-base;
}
& div.reverse {
.progress-bar-danger();
}
height: @line-height-computed * 1.25
}
[parallax] {
overflow: hidden;
height: 100vh;
& .parallax-container {
height: 100vh;
position: relative;
}
}
[parallax-background] {
background: url('http://placeimg.com/2000/2000/nature/1') no-repeat center;
background-size: cover;
width: 100%;
height: 100vh;
position: absolute;
}
(function(__root, __factory) { if (typeof define === "function" && define.amd) { define("ng-magics", ["angular"], __factory);} else if (typeof exports === "object") {module.exports = __factory(require("angular"));} else {__root["ng-magics"] = __factory(angular);}})(this, (function(__small$_mod_0) {
var exports = {};
var __small$_4 = (function() {
var exports = {};
/// <reference path="../typings/globals.d.ts"/>
/// <reference path="../typings/lib.d.ts"/>
var angular = __small$_mod_0;
var debottle_1 = ((function() {
var exports = {};
var apply = ((function() {
var exports = {};
function apply(self, fn, args) {
var selfless = (self === undefined) || (self === null);
var length = args ? args.length : 0;
switch (length) {
case 0:
return selfless ? fn() : fn.call(self);
case 1:
return selfless ? fn(args[0]) : fn.call(self, args[0]);
case 2:
return selfless ? fn(args[0], args[1]) : fn.call(self, args[0], args[1]);
case 3:
return selfless ? fn(args[0], args[1], args[2]) : fn.call(self, args[0], args[1], args[2]);
case 4:
return selfless ? fn(args[0], args[1], args[2], args[3]) : fn.call(self, args[0], args[1], args[2], args[3]);
case 5:
return selfless ? fn(args[0], args[1], args[2], args[3], args[4]) : fn.call(self, args[0], args[1], args[2], args[3], args[4]);
case 6:
return selfless ? fn(args[0], args[1], args[2], args[3], args[4], args[5]) : fn.call(self, args[0], args[1], args[2], args[3], args[4], args[5]);
// the crucial point
case 7:
return selfless ? fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]) : fn.call(self, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
default:
return selfless ? fn.apply(null, args) : fn.apply(self, args);
}
}
exports = apply;
return exports;
})());
function Debottle(delay) {
this.$delay = delay;
this.$cancel = function () {
return clearTimeout(this.$timeout);
}
}
function debounce(fn, delay, cb) {
if (arguments.length === 2 && typeof delay === 'function') {
cb = delay;
delay = undefined;
}
var self = debouncedFn;
Debottle.call(self, delay);
function debouncedFn() {
var args = arguments;
if (self.$timeout !== undefined)
self.$cancel();
self.$timeout = setTimeout(function () {
if (typeof cb !== 'function')
return apply(null, fn, args);
try {
cb(null, apply(null, fn, args));
} catch (e) {
cb(e);
}
}, self.$delay);
};
return self;
}
function throttle(fn, delay, cb) {
if (arguments.length === 2 && typeof delay === 'function') {
cb = delay;
delay = undefined;
}
var self = throttledFn;
Debottle.call(self, delay);
function throttledFn() {
var args = arguments;
if (self.$timeout !== undefined)
return;
self.$timeout = setTimeout(function () {
self.$timeout = undefined;
}, self.$delay);
if (typeof cb !== 'function')
return apply(null, fn, args);
try {
cb(null, apply(null, fn, args));
} catch (e) {
cb(e);
}
};
return self;
}
exports.debounce = debounce;
exports.throttle = throttle;
return exports;
})());
exports.__esModule = true;
exports["default"] = angular.module('ngMagics.constants', [])
.constant('debounce', debottle_1.debounce)
.constant('throttle', debottle_1.throttle)
.constant('scrollMagic', (function () {
if (typeof ScrollMagic !== 'undefined') {
return ScrollMagic;
}
})())
.constant('Tween', (function () {
var Tween;
// module bundler global substitution
if (typeof TweenMax !== 'undefined') {
Tween = TweenMax;
}
else if (typeof TweenLite !== 'undefined') {
Tween = TweenLite;
}
else if (typeof GreenSockGlobals !== 'undefined') {
Tween = GreenSockGlobals.TweenMax || GreenSockGlobals.TweenLite;
}
return Tween;
})())
.constant('tweenEasing', (function () {
if (typeof GreenSockGlobals !== 'undefined') {
return GreenSockGlobals.com.greensock.easing;
}
})())
.name;
return exports;
})();
var __small$_5 = (function() {
var exports = {};
/// <reference path="../typings/globals.d.ts"/>
/// <reference path="../typings/lib.d.ts"/>
var angular = __small$_mod_0;
var constants_1 = __small$_4;
var MagicsProvider = (function () {
function MagicsProvider() {
var _this = this;
var deps = [];
for (var _i = 0; _i < arguments.length; _i++) {
deps[_i - 0] = arguments[_i];
}
this.$ = {};
this.debug = false;
this.debugOptions = {};
this.sceneOptions = {};
this.stageOptions = {};
this.pinOptions = {};
this.performanceOptions = {
brake: 'debounce',
delay: 50
};
var self = this.constructor;
angular.forEach(self.$inject, function (depName, i) {
_this.$[depName] = deps[i];
});
// TODO: proper typing
this.$get.$inject = MagicsInstance.$inject;
this.scrollOptions = {
y: true,
duration: 0.75,
ease: this.$.tweenEasing.Power2.easeInOut
};
}
MagicsProvider.prototype.$get = function () {
var deps = [];
for (var _i = 0; _i < arguments.length; _i++) {
deps[_i - 0] = arguments[_i];
}
var instance = Object.create(MagicsInstance.prototype);
MagicsInstance.apply(instance, [this].concat(deps));
return instance;
};
MagicsProvider.$inject = ['tweenEasing'];
return MagicsProvider;
})();
var MagicsInstance = (function () {
function MagicsInstance(provider) {
var _this = this;
var deps = [];
for (var _i = 1; _i < arguments.length; _i++) {
deps[_i - 1] = arguments[_i];
}
this.$ = {};
// stage.scrollTo accepts 1 optional argument
// TODO: swappable method
this._scrollHandler = function (target, _a) {
var container = _a[0], deferred = _a[1];
var _b = _this.$, $rootScope = _b.$rootScope, Tween = _b.Tween;
var scrollOptions = _this._provider.scrollOptions;
function completeHandler() {
deferred.resolve();
$rootScope.$apply();
}
function autoKillHandler() {
deferred.reject();
$rootScope.$apply();
}
var scrollToOptions = {
autoKill: true,
onAutoKill: autoKillHandler
};
if (scrollOptions.x) {
scrollToOptions.x = target;
}
if (scrollOptions.y) {
scrollToOptions.y = target;
}
Tween.to(container, scrollOptions.duration, {
scrollTo: scrollToOptions,
ease: scrollOptions.ease,
onComplete: completeHandler
});
};
var self = this.constructor;
angular.forEach(self.$inject, function (depName, i) {
_this.$[depName] = deps[i];
});
this._provider = provider;
//
var _a = this.$, $cacheFactory = _a.$cacheFactory, debounce = _a.debounce, throttle = _a.throttle;
this._brake = (this._provider.performanceOptions.brake === 'throttle')
? throttle
: debounce;
this._delay = this._provider.performanceOptions.delay;
var cache = $cacheFactory('magics');
this._scenes = cache.put('scenes', {});
this._stages = cache.put('stages', {});
this.stage('default', {});
}
MagicsInstance.prototype._isEmpty = function (val) {
return ([null, undefined, ''].indexOf(val) >= 0);
};
MagicsInstance.prototype._patch = function (name, storageName, instance) {
var _this = this;
if ('$$patched' in instance) {
return instance;
}
var destroy_ = instance.destroy;
instance.destroy = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i - 0] = arguments[_i];
}
if (name === 'default') {
return instance;
}
if (name in _this[storageName]) {
delete _this[storageName][name];
}
return destroy_.apply(instance, args);
};
instance.$$patched = true;
return instance;
};
MagicsInstance.prototype.stage = function (name, options) {
var _a = this.$, $window = _a.$window, scrollMagic = _a.scrollMagic;
if (this._isEmpty(name)) {
name = 'default';
}
// TODO: duplicate warning for 'options'
if (name in this._stages) {
return this._stages[name];
}
var stageOptions = angular.extend({}, this._provider.stageOptions, {
globalSceneOptions: this._provider.sceneOptions,
// TODO: custom container
container: this._provider.container || $window
}, options);
var stage = this._stages[name] = new scrollMagic.Controller(stageOptions);
stage.scrollTo(this._scrollHandler);
return this._patch(name, '_stages', stage);
};
MagicsInstance.prototype.scene = function (name, options, stageName) {
var _a = this.$, $rootScope = _a.$rootScope, scrollMagic = _a.scrollMagic;
// TODO: duplicate warning for 'options'
if (name in this._scenes) {
return this._scenes[name];
}
if (this._isEmpty(stageName)) {
stageName = 'default';
}
var stage = this._stages[stageName];
var scene = this._scenes[name] = (new scrollMagic.Scene(options)).addTo(stage);
if (this._provider.debug) {
scene.addIndicators(angular.extend({}, this._provider.debugOptions, {
name: name
}));
}
this.onSceneEnter(name, function (e) {
$rootScope.$broadcast('sceneEnter:' + name, e);
$rootScope.$broadcast('sceneEnter', name, e);
});
this.onSceneLeave(name, function (e) {
$rootScope.$broadcast('sceneLeave:' + name, e);
$rootScope.$broadcast('sceneLeave', name, e);
});
return this._patch(name, '_scenes', scene);
};
MagicsInstance.prototype.scrollToScene = function (scene, offset) {
var _a = this.$, $q = _a.$q, scrollMagic = _a.scrollMagic;
offset = offset || 0;
if (angular.isString(scene)) {
scene = this._scenes[scene];
}
if (!(scene instanceof scrollMagic.Scene)) {
return false;
}
var target = scene.scrollOffset() + offset;
var stage = scene.controller();
var container = stage.info('container');
var deferred = $q.defer();
// the proper use case for Deferred, one and only
stage.scrollTo(target, [container, deferred]);
return deferred.promise;
};
// TODO: ? stage namespacing, brake per stage
// TODO: additional params
MagicsInstance.prototype.onSceneEnter = function (name, handler) {
var _this = this;
var brakedHandler = this._brake(handler, this._delay);
this._scenes[name].on('enter', brakedHandler);
return function () {
var scene = _this._scenes[name];
if (scene) {
scene.off('enter', brakedHandler);
}
};
};
MagicsInstance.prototype.onSceneLeave = function (name, handler) {
var _this = this;
var brakedHandler = this._brake(handler, this._delay);
var scene = this._scenes[name];
scene.on('leave', brakedHandler);
return function () {
var scene = _this._scenes[name];
if (scene) {
scene.off('leave', brakedHandler);
}
};
};
// TODO: onScenePoint
MagicsInstance.prototype.onSceneProgress = function (name, handler) {
var _this = this;
var scene = this._scenes[name];
scene.on('progress', handler);
return function () {
var scene = _this._scenes[name];
if (scene) {
scene.off('progress', handler);
}
};
};
MagicsInstance.prototype.onSceneDestroy = function (name, handler) {
var _this = this;
var scene = this._scenes[name];
scene.on('destroy', handler);
return function () {
var scene = _this._scenes[name];
if (scene) {
scene.off('destroy', handler);
}
};
};
MagicsInstance.$inject = ['$cacheFactory', '$q', '$rootScope', '$window', 'debounce', 'throttle', 'scrollMagic', 'Tween'];
return MagicsInstance;
})();
exports.__esModule = true;
exports["default"] = angular.module('ngMagics.magics', [constants_1["default"]])
.provider('magics', MagicsProvider)
.name;
return exports;
})();
/// <reference path="./typings/globals.d.ts"/>
/// <reference path="./typings/lib.d.ts"/>
var angular = __small$_mod_0;
var magics_scene_1 = ((function() {
var exports = {};
/// <reference path="../typings/globals.d.ts"/>
/// <reference path="../typings/lib.d.ts"/>
var angular = __small$_mod_0;
var magics_1 = __small$_5;
var MagicsSceneDirectiveController = (function () {
function MagicsSceneDirectiveController() {
var _this = this;
var deps = [];
for (var _i = 0; _i < arguments.length; _i++) {
deps[_i - 0] = arguments[_i];
}
this.$ = {};
var self = this.constructor;
angular.forEach(self.$inject, function (depName, i) {
_this.$[depName] = deps[i];
});
//
var _a = this.$, $scope = _a.$scope, $element = _a.$element, $attrs = _a.$attrs;
var expando = angular.element.expando;
// TODO: global option to get scene name from 'id' attr
// uninterpolated attribute
this.sceneName = $attrs.magicsScene || (expando + '.' + $element[0][expando]);
// TODO: filter duration, offset, triggerHook, reverse
this.sceneOptions = $scope.$eval($attrs.magicsSceneOptions) || {};
}
MagicsSceneDirectiveController.prototype.init = function (stageName) {
var _this = this;
var _a = this.$, $element = _a.$element, magics = _a.magics;
// TODO: avoid _scenes check
// TODO: duplicate warning
if (this.sceneName in magics._scenes) {
this.scene = magics.scene(this.sceneName);
return;
}
this.scene = magics.scene(this.sceneName, this.sceneOptions, stageName);
if (!('duration' in this.sceneOptions)) {
// TODO: ? stage property
var stage = magics.stage(stageName);
var element = $element[0];
var isVertical = stage.info('vertical');
// TODO: ? separate method
this.scene.duration(function () {
// TODO: caching
return isVertical ? element.offsetHeight : element.offsetWidth;
});
// TODO: spec
this.scene.triggerElement(element);
}
$element.on('$destroy', function () {
magics.scene(_this.sceneName).destroy();
});
};
MagicsSceneDirectiveController.$inject = ['$scope', '$element', '$attrs', '$rootScope', 'magics'];
return MagicsSceneDirectiveController;
})();
exports.__esModule = true;
exports["default"] = angular.module('ngMagics.magicsScene', [magics_1["default"]])
.directive('magicsScene', function () { return ({
/**
* @ngdoc directive
* @name magicsScene
*
* @element ANY
* @restrict A
*
* @param {string=} magicsScene Scene name.
* @param {Object=} magicsSceneOptions Options that are used on scene creation.
*
* @description Creates a new scene or reuses the existing one on either the stage specified by `magicsStage` directive or 'default' stage.
*/
restrict: 'A',
require: ['magicsScene', '?^magicsStage'],
controller: MagicsSceneDirectiveController,
link: {
pre: function (scope, element, attrs, ctrls) {
var sceneCtrl = ctrls[0], stageCtrl = ctrls[1];
var stageName = (stageCtrl || {}).stageName;
sceneCtrl.init(stageName);
}
}
}); })
.name;
return exports;
})());
var magics_spy_1 = ((function() {
var exports = {};
/// <reference path="../typings/globals.d.ts"/>
/// <reference path="../typings/lib.d.ts"/>
var angular = __small$_mod_0;
var magics_1 = __small$_5;
var MagicsSpyDirectiveController = (function () {
function MagicsSpyDirectiveController() {
var _this = this;
var deps = [];
for (var _i = 0; _i < arguments.length; _i++) {
deps[_i - 0] = arguments[_i];
}
this.$ = {};
var self = this.constructor;
angular.forEach(self.$inject, function (depName, i) {
_this.$[depName] = deps[i];
});
//
var _a = this.$, $scope = _a.$scope, $attrs = _a.$attrs, $parse = _a.$parse;
// uninterpolated attribute
if ($attrs.magicsSpy) {
var setter = $parse($attrs.magicsSpy).assign;
if (setter) {
this._flagSetter = function (val) { return setter($scope, val); };
}
}
}
// TODO: get/set
MagicsSpyDirectiveController.prototype.flag = function (val) {
if (arguments.length) {
this._flag = val;
if (this._flagSetter) {
this._flagSetter(val);
}
}
return this._flag;
};
MagicsSpyDirectiveController.prototype.init = function (sceneName) {
var _this = this;
var _a = this.$, $scope = _a.$scope, $element = _a.$element, $attrs = _a.$attrs, magics = _a.magics;
var progressHandler = $scope.$eval($attrs.magicsSpyProgress);
if (progressHandler) {
var offSceneProgress = magics.onSceneProgress(sceneName, progressHandler);
$element.on('$destroy', function () { return offSceneProgress(); });
}
// TODO: ? $rootScope
$scope.$on('sceneEnter:' + sceneName, function (e) {
$scope.$apply(function () { return _this.flag(true); });
});
$scope.$on('sceneLeave:' + sceneName, function (e) {
$scope.$apply(function () { return _this.flag(false); });
});
};
MagicsSpyDirectiveController.$inject = ['$scope', '$element', '$attrs', '$parse', 'magics'];
return MagicsSpyDirectiveController;
})();
exports.__esModule = true;
exports["default"] = angular.module('ngMagics.magicsSpy', [magics_1["default"]])
.directive('magicsSpy', ['magics', function (magics) { return ({
/**
* @ngdoc directive
* @name magicsSpy
*
* @element ANY
* @restrict A
*
* @param {expression=} magicsSpy Scope variable flag *(read-only)*.
* @param {string=} magicsSpyScene Scene name.
* @param {expression=} magicsSpyProgress Scene progress callback function.
*
* @description Sets up a spy for the scene specified by either parent `magicsScene` directive or `magicsSpyScene` attribute.
*/
restrict: 'A',
require: ['magicsSpy', '?^magicsScene'],
controller: MagicsSpyDirectiveController,
link: {
pre: function (scope, element, attrs, ctrls) {
var spyCtrl = ctrls[0], sceneCtrl = ctrls[1];
var parentSceneName = (sceneCtrl || {}).sceneName;
var sceneName = attrs.magicsSpyScene || parentSceneName;
if (magics._isEmpty(sceneName)) {
return;
}
spyCtrl.init(sceneName);
}
}
}); }])
.name;
return exports;
})());
var magics_stage_1 = ((function() {
var exports = {};
/// <reference path="../typings/globals.d.ts"/>
/// <reference path="../typings/lib.d.ts"/>
var angular = __small$_mod_0;
var magics_1 = __small$_5;
var MagicsStageDirectiveController = (function () {
function MagicsStageDirectiveController() {
var _this = this;
var deps = [];
for (var _i = 0; _i < arguments.length; _i++) {
deps[_i - 0] = arguments[_i];
}
this.$ = {};
var self = this.constructor;
angular.forEach(self.$inject, function (depName, i) {
_this.$[depName] = deps[i];
});
//
var _a = this.$, $scope = _a.$scope, $attrs = _a.$attrs;
// uninterpolated attribute
this.stageName = $attrs.magicsStage || 'default';
// TODO: filter vertical, refreshInterval
this.stageOptions = $scope.$eval($attrs.magicsStageOptions) || {};
// TODO: custom scrollTo function
}
MagicsStageDirectiveController.prototype.init = function () {
var _this = this;
var _a = this.$, $element = _a.$element, magics = _a.magics;
// TODO: avoid _stages check
// TODO: duplicate warning
if (this.stageName in magics._stages) {
this.stage = magics.stage(this.stageName);
return;
}
var stageOptions = angular.extend({}, this.stageOptions, { container: $element[0] });
this.stage = magics.stage(this.stageName, stageOptions);
// TODO: ? scope on destroy
$element.on('$destroy', function () {
magics.stage(_this.stageName).destroy();
});
};
MagicsStageDirectiveController.$inject = ['$scope', '$element', '$attrs', 'magics'];
return MagicsStageDirectiveController;
})();
exports.__esModule = true;
exports["default"] = angular.module('ngMagics.magicsStage', [magics_1["default"]])
.directive('magicsStage', function () { return ({
/**
* @ngdoc directive
* @name magicsStage
*
* @element ANY
* @restrict A
*
* @param {string=} magicsStage Stage name.
* @param {Object=} magicsStageOptions Options that have to be passed to `magics.stage`.
*
* @description Creates a new stage or reuses the existing one.
*/
restrict: 'A',
controller: MagicsStageDirectiveController,
link: {
pre: function (scope, element, attrs, ctrl) {
ctrl.init();
}
}
}); })
.name;
return exports;
})());
var constants_1 = __small$_4;
var magics_1 = __small$_5;
exports.__esModule = true;
exports["default"] = angular.module('ngMagics', [
magics_scene_1["default"],
magics_spy_1["default"],
magics_stage_1["default"],
constants_1["default"],
magics_1["default"]
])
.name;
return exports;
}))