',
parentScope: scope,
tether: {
@@ -65,154 +52,139 @@ angular.module('ngTetherTooltip', ['ngTether']).directive('tetherTooltip', [
tooltip.enter();
});
elem.on('mouseleave', function () {
- tooltip.leave();
- });
- scope.$on('$destroy', function () {
- elem.unbind('hover');
- elem.unbind('mouseleave');
+ scope.$apply(tooltip.leave);
});
}
};
}
-]);
-angular.module('ngTether', []).factory('Utils', [
- '$compile',
- function ($compile) {
+}());
+(function (Tether, angular) {
+ angular.module('ngTether', []).factory('TetherUtils', tetherUtils).factory('Tether', tetherInstanceDirective);
+ function tetherUtils() {
var Utils = {};
Utils.extendDeep = function deepExtend(target, source) {
- for (var prop in source)
- if (prop in target)
- angular.extend(target[prop], source[prop]);
- else
- target[prop] = source[prop];
+ for (var key in source) {
+ if (key in target) {
+ angular.extend(target[key], source[key]);
+ } else {
+ target[key] = source[key];
+ }
+ }
return target;
};
return Utils;
}
-]).factory('Tether', [
- '$compile',
- '$rootScope',
- '$log',
- '$window',
- '$animate',
- '$controller',
- '$timeout',
- '$q',
- '$http',
- '$templateCache',
- function ($compile, $rootScope, $log, $window, $animate, $controller, $timeout, $q, $http, $templateCache) {
+ tetherInstanceDirective.$inject = [
+ '$compile',
+ '$rootScope',
+ '$document',
+ '$templateCache',
+ '$animate',
+ '$controller',
+ '$q',
+ '$http'
+ ];
+ function tetherInstanceDirective($compile, $rootScope, $document, $templateCache, $animate, $controller, $q, $http) {
return function (config) {
'use strict';
- if (!(!config.template ^ !config.templateUrl)) {
+ if (!(config.template || config.templateUrl)) {
throw new Error('Expected one of either `template` or `templateUrl`');
}
- config.tether = config.tether || {};
- var controller = config.controller || angular.noop, controllerAs = config.controllerAs, parentScope = config.parentScope || $rootScope, extend = angular.extend, element = null, scope, html, tether, bodyEl = angular.element($window.document.body);
- // Attach a tether element and the target element.
- function attachTether() {
- tether = new Tether(extend({ element: element[0] }, config.tether));
+ if (!Tether) {
+ throw new Error('Tether is required`');
}
- function templateDfd() {
- var template = config.template ? $templateCache.get(config.template) || config.template : $http.get(config.templateUrl, { cache: $templateCache }).then(function (resp) {
+ config.tether = config.tether || {};
+ var controller = config.controller || angular.noop, controllerAs = config.controllerAs, parentScope = config.parentScope || $rootScope, extend = angular.extend, element = null, scope, activeAnimatePromise;
+ var tether = {
+ enter: enter,
+ leave: leave,
+ active: false,
+ config: config.tether
+ };
+ // backward compatible method until next major version is released
+ tether.isActive = function () {
+ return tether.active;
+ };
+ function templateDeferred() {
+ var template;
+ if (config.template) {
+ template = $templateCache.get(config.template) || config.template;
+ } else {
+ template = $http.get(config.templateUrl, { cache: $templateCache }).then(function (resp) {
return resp.data;
});
+ }
return $q.when(template);
}
function create(html, locals) {
+ var ctrl;
element = angular.element(html.trim());
+ tether.tetherInstance = new Tether(extend({ element: element[0] }, config.tether));
scope = parentScope.$new();
// assign locals being passed on enter method.
if (locals) {
- for (var prop in locals) {
- scope[prop] = locals[prop];
+ for (var key in locals) {
+ if (locals.hasOwnProperty(key)) {
+ scope[key] = locals[key];
+ }
}
}
if (config.controller) {
- var ctrl = $controller(controller, { $scope: scope });
+ ctrl = $controller(controller, { $scope: scope });
}
if (controllerAs) {
scope[controllerAs] = ctrl;
}
$compile(element)(scope);
- scope.$on('$destroy', destroy);
- // Hack. html is being compiled asynchronously the dimensions of the element
- // would most likley have a different dimensions after compilation
- $timeout(function () {
- if (!element)
- return;
- $animate.enter(element, bodyEl);
- attachTether();
- tether.position();
+ tether.active = true;
+ scope.$watch(function () {
+ tether.tetherInstance.position();
+ });
+ // prevents document instant click fire. there's no need to run digest cycle.
+ setTimeout(function () {
if (config.leaveOnBlur) {
- bodyEl.on('click touchend', leaveOnBlur);
+ $document.on('click touchend', leaveOnBlur);
}
- }, 15);
+ }, 0);
+ activeAnimatePromise = $animate.enter(element, $document.find('body'));
+ return activeAnimatePromise;
}
function leaveOnBlur(evt) {
var target = evt.target;
- if (!element || target === element[0]) {
+ if (tether.active === false || target === element[0]) {
return;
}
while (target.parentElement !== null) {
- if (target.parentElement == element[0]) {
+ if (target.parentElement === element[0]) {
return;
}
target = target.parentElement;
}
- return leave();
+ scope.$applyAsync(leave);
}
// Attach tether and add it to the dom
function enter(locals) {
- if (element) {
- return $log.debug('Tethered instance is already active; now toggling');
+ if (tether.active) {
+ leave();
}
- templateDfd().then(function (html) {
- create(html, locals);
+ return templateDeferred().then(function (html) {
+ return create(html, locals);
});
}
// Detach the tether and remove it from the dom
function leave() {
- if (config.leaveOnBlur) {
- bodyEl.off('click touchend', leaveOnBlur);
- }
- if (!isActive()) {
- if (element) {
- element = null;
- }
- return false;
- }
- tether.destroy();
- $timeout(function () {
- element && $animate.leave(element, function () {
- destroy();
- });
- });
- }
- function destroy() {
- if (!element) {
- return;
+ if (tether.active === false) {
+ return $q.when(tether.active);
}
- element.remove();
- element = null;
- }
- function position() {
- if (element) {
- $animate.move(element, bodyEl);
- attachTether();
+ if (config.leaveOnBlur) {
+ $document.off('click touchend', leaveOnBlur);
}
+ tether.active = false;
+ tether.tetherInstance.destroy();
+ scope.$destroy();
+ return $animate.leave(element);
}
- // bool. is tethered instance got destroyed
- function isActive() {
- return tether && tether.enabled;
- }
- return {
- enter: enter,
- leave: leave,
- position: position,
- isActive: isActive,
- tether: html,
- config: config.tether
- };
+ return tether;
};
}
-]);}));
\ No newline at end of file
+}(Tether, angular));
\ No newline at end of file
diff --git a/dist/angular-tether.min.js b/dist/angular-tether.min.js
index a61a3cb..747843e 100644
--- a/dist/angular-tether.min.js
+++ b/dist/angular-tether.min.js
@@ -1 +1 @@
-/*! angular-tether - v0.1.5 - 2014-07-15 */!function(a,b){"function"==typeof define&&define.amd?define(["tether"],b):"object"==typeof exports?module.exports=b(require("tether")):a.test=b(a.Tether)}(this,function(a){angular.module("ngTetherPopover",["ngTether"]).directive("tetherPopover",["Tether","$parse","Utils",function(a,b,c){return{restrict:"A",scope:{tetherPopover:"=",config:"="},link:function(b,d){b.tetherPopover=new a(c.extendDeep({parentScope:b.$parent,leaveOnBlur:!0,tether:{target:d[0],attachment:"top center",targetAttachment:"bottom center",constraints:[{to:"window",attachment:"together"}]}},b.config)),b.$watch("tetherPopover.config.targetAttachment",function(){b.tetherPopover.isActive()&&b.tetherPopover.position()},!0),b.$watch("tetherPopover.config.attachment",function(){b.tetherPopover.isActive()&&b.tetherPopover.position()},!0)}}}]),angular.module("ngTetherTooltip",["ngTether"]).directive("tetherTooltip",["Tether","Utils",function(a,b){return{scope:{content:"@tetherTooltip",config:"=config"},link:function(c,d){var e=new a(b.extendDeep({template:'
{{ content }}
',parentScope:c,tether:{target:d[0],attachment:"top center",targetAttachment:"bottom center",constraints:[{to:"window",attachment:"together",pin:!0}]}},c.config));d.on("mouseenter",function(){e.enter()}),d.on("mouseleave",function(){e.leave()}),c.$on("$destroy",function(){d.unbind("hover"),d.unbind("mouseleave")})}}}]),angular.module("ngTether",[]).factory("Utils",["$compile",function(){var a={};return a.extendDeep=function(a,b){for(var c in b)c in a?angular.extend(a[c],b[c]):a[c]=b[c];return a},a}]).factory("Tether",["$compile","$rootScope","$log","$window","$animate","$controller","$timeout","$q","$http","$templateCache",function(b,c,d,e,f,g,h,i,j,k){return function(l){"use strict";function m(){x=new a(B({element:C[0]},l.tether))}function n(){var a=l.template?k.get(l.template)||l.template:j.get(l.templateUrl,{cache:k}).then(function(a){return a.data});return i.when(a)}function o(a,c){if(C=angular.element(a.trim()),v=A.$new(),c)for(var d in c)v[d]=c[d];if(l.controller)var e=g(y,{$scope:v});z&&(v[z]=e),b(C)(v),v.$on("$destroy",s),h(function(){C&&(f.enter(C,D),m(),x.position(),l.leaveOnBlur&&D.on("click touchend",p))},15)}function p(a){var b=a.target;if(C&&b!==C[0]){for(;null!==b.parentElement;){if(b.parentElement==C[0])return;b=b.parentElement}return r()}}function q(a){return C?d.debug("Tethered instance is already active; now toggling"):void n().then(function(b){o(b,a)})}function r(){return l.leaveOnBlur&&D.off("click touchend",p),u()?(x.destroy(),void h(function(){C&&f.leave(C,function(){s()})})):(C&&(C=null),!1)}function s(){C&&(C.remove(),C=null)}function t(){C&&(f.move(C,D),m())}function u(){return x&&x.enabled}if(!(!l.template^!l.templateUrl))throw new Error("Expected one of either `template` or `templateUrl`");l.tether=l.tether||{};var v,w,x,y=l.controller||angular.noop,z=l.controllerAs,A=l.parentScope||c,B=angular.extend,C=null,D=angular.element(e.document.body);return{enter:q,leave:r,position:t,isActive:u,tether:w,config:l.tether}}}])});
\ No newline at end of file
+!function(){function a(a,b){return{restrict:"A",scope:{tetherPopover:"=",config:"="},link:function(c,d){c.tetherPopover=new a(b.extendDeep({parentScope:c.$parent,leaveOnBlur:!0,tether:{target:d[0],attachment:"top center",targetAttachment:"bottom center",constraints:[{to:"window",attachment:"together"}]}},c.config))}}}angular.module("ngTetherPopover",["ngTether"]).directive("tetherPopover",a)}(),function(){function a(a,b){return{scope:{content:"@tetherTooltip",config:"=config"},link:function(c,d){var e=new a(b.extendDeep({template:'
{{ content }}
',parentScope:c,tether:{target:d[0],attachment:"top center",targetAttachment:"bottom center",constraints:[{to:"window",attachment:"together",pin:!0}]}},c.config));d.on("mouseenter",function(){e.enter()}),d.on("mouseleave",function(){c.$apply(e.leave)})}}}angular.module("ngTetherTooltip",["ngTether"]).directive("tetherTooltip",a)}(),function(a,b){function c(){var a={};return a.extendDeep=function(a,c){for(var d in c)d in a?b.extend(a[d],c[d]):a[d]=c[d];return a},a}function d(c,d,e,f,g,h,i,j){return function(k){"use strict";function l(){var a;return a=k.template?f.get(k.template)||k.template:j.get(k.templateUrl,{cache:f}).then(function(a){return a.data}),i.when(a)}function m(d,f){var i;if(w=b.element(d.trim()),x.tetherInstance=new a(v({element:w[0]},k.tether)),q=u.$new(),f)for(var j in f)f.hasOwnProperty(j)&&(q[j]=f[j]);return k.controller&&(i=h(s,{$scope:q})),t&&(q[t]=i),c(w)(q),x.active=!0,q.$watch(function(){x.tetherInstance.position()}),setTimeout(function(){k.leaveOnBlur&&e.on("click touchend",n)},0),r=g.enter(w,e.find("body"))}function n(a){var b=a.target;if(x.active!==!1&&b!==w[0]){for(;null!==b.parentElement;){if(b.parentElement===w[0])return;b=b.parentElement}q.$applyAsync(p)}}function o(a){return x.active&&p(),l().then(function(b){return m(b,a)})}function p(){return x.active===!1?i.when(x.active):(k.leaveOnBlur&&e.off("click touchend",n),x.active=!1,x.tetherInstance.destroy(),q.$destroy(),g.leave(w))}if(!k.template&&!k.templateUrl)throw new Error("Expected one of either `template` or `templateUrl`");if(!a)throw new Error("Tether is required`");k.tether=k.tether||{};var q,r,s=k.controller||b.noop,t=k.controllerAs,u=k.parentScope||d,v=b.extend,w=null,x={enter:o,leave:p,active:!1,config:k.tether};return x.isActive=function(){return x.active},x}}b.module("ngTether",[]).factory("TetherUtils",c).factory("Tether",d),d.$inject=["$compile","$rootScope","$document","$templateCache","$animate","$controller","$q","$http"]}(Tether,angular);
\ No newline at end of file
diff --git a/examples/appctrl.js b/examples/appctrl.js
index 74b2f9f..734bced 100644
--- a/examples/appctrl.js
+++ b/examples/appctrl.js
@@ -1,634 +1,85 @@
-var app = angular.module('app', ['ng', 'ngAnimate', 'ngTetherTooltip', 'ngTetherPopover', 'ui.ace']);
+angular.module('app', ['ng', 'ngAnimate', 'ngTetherTooltip', 'ngTetherPopover', 'ui.ace'])
+ .controller('appCtrl', function($scope, Tether, $templateCache) {
-app.controller('appCtrl', function($scope, Tether, $templateCache){
-
- $scope.aceLoaded = function(_editor) {
- _editor.renderer.setShowGutter(false);
- _editor.renderer.setHighlightGutterLine(false);
- _editor.getSession().setValue($templateCache.get('popoverDemo.html'));
+ $scope.aceLoaded = function(_editor) {
+ _editor.renderer.setShowGutter(false);
+ _editor.renderer.setHighlightGutterLine(false);
+ _editor.getSession().setValue($templateCache.get('popoverDemo.html'));
// _editor.setReadOnly(true);
- };
-
- $scope.getTemplate = function(){
- return 'popoverDemo.html'
- };
-
- $scope.aceChanged = function(args) {
- var changed = args[0];
- var _editor = args[1];
- $templateCache.put('popoverDemo.html', _editor.getSession().getValue());
-
- };
-
- $scope.editorConfig = {
- showLineNumbers: false,
- mode: 'html',
- onLoad: $scope.aceLoaded,
- onChange: $scope.aceChanged
- };
-
-
- $scope.intro = Tether({
- templateUrl: 'intro.html',
- tether : {
- target: '#intro',
- attachment: 'bottom center',
- targetAttachment: 'middle center',
- targetModifier: 'visible',
- constraints: [
- {
- to: '#intro',
- pin: true
- }
- ]
- }
- });
-
- $scope.intro.enter();
-
- $scope.footer = Tether({
- templateUrl: 'intro.html',
- tether : {
- target: '#footer',
- attachment: 'top center',
- targetAttachment: 'middle center',
- targetModifier: 'visible',
- constraints: [
- {
- to: '#footer',
- pin: true
- }
- ]
- }
- });
-
- $scope.footer.enter();
-
-
- $scope.MIRROR_ATTACH = [
- 'top', 'right', 'bottom', 'left',
- 'center', 'middle'
- ];
-
- $scope.popoverConfig = {
- template: 'popover.html',
- tether: {
- attachment: 'middle right',
- targetAttachment: 'middle left'
- }
- };
-
- $scope.posX = [
- 'left',
- 'right',
- 'center'
- ];
- $scope.posY = [
- 'top',
- 'bottom',
- 'middle'
- ];
-
-
-// $scope.tetherConfig = {
-// attachment: 'bottom center',
-// targetAttachment: 'top center',
-// constraints: [
-// {
-// to: 'window',
-// attachment: 'together'
-// }
-// ]
-// };
-
-});
-
-
-// SmoothScroll for websites v1.2.1
-// Licensed under the terms of the MIT license.
-
-// People involved
-// - Balazs Galambosi (maintainer)
-// - Michael Herf (Pulse Algorithm)
-
-// SmoothScroll for websites v1.2.1
-// Licensed under the terms of the MIT license.
-
-// People involved
-// - Balazs Galambosi (maintainer)
-// - Michael Herf (Pulse Algorithm)
-
-(function(){
-
-// Scroll Variables (tweakable)
- var defaultOptions = {
-
- // Scrolling Core
- frameRate : 150, // [Hz]
- animationTime : 500, // [px]
- stepSize : 150, // [px]
-
- // Pulse (less tweakable)
- // ratio of "tail" to "acceleration"
- pulseAlgorithm : true,
- pulseScale : 6,
- pulseNormalize : 1,
-
- // Acceleration
- accelerationDelta : 20, // 20
- accelerationMax : 1, // 1
-
- // Keyboard Settings
- keyboardSupport : true, // option
- arrowScroll : 50, // [px]
-
- // Other
- touchpadSupport : true,
- fixedBackground : true,
- excluded : ""
- };
-
- var options = defaultOptions;
-
-
-// Other Variables
- var isExcluded = false;
- var isFrame = false;
- var direction = { x: 0, y: 0 };
- var initDone = false;
- var root = document.documentElement;
- var activeElement;
- var observer;
- var deltaBuffer = [ 120, 120, 120 ];
-
- var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32,
- pageup: 33, pagedown: 34, end: 35, home: 36 };
-
-
- /***********************************************
- * SETTINGS
- ***********************************************/
-
- var options = defaultOptions;
-
-
- /***********************************************
- * INITIALIZE
- ***********************************************/
-
- /**
- * Tests if smooth scrolling is allowed. Shuts down everything if not.
- */
- function initTest() {
-
- var disableKeyboard = false;
-
- // disable keyboard support if anything above requested it
- if (disableKeyboard) {
- removeEvent("keydown", keydown);
- }
-
- if (options.keyboardSupport && !disableKeyboard) {
- addEvent("keydown", keydown);
- }
- }
-
- /**
- * Sets up scrolls array, determines if frames are involved.
- */
- function init() {
-
- if (!document.body) return;
-
- var body = document.body;
- var html = document.documentElement;
- var windowHeight = window.innerHeight;
- var scrollHeight = body.scrollHeight;
-
- // check compat mode for root element
- root = (document.compatMode.indexOf('CSS') >= 0) ? html : body;
- activeElement = body;
-
- initTest();
- initDone = true;
-
- // Checks if this script is running in a frame
- if (top != self) {
- isFrame = true;
- }
-
- /**
- * This fixes a bug where the areas left and right to
- * the content does not trigger the onmousewheel event
- * on some pages. e.g.: html, body { height: 100% }
- */
- else if (scrollHeight > windowHeight &&
- (body.offsetHeight <= windowHeight ||
- html.offsetHeight <= windowHeight)) {
-
- // clearfix
- if (root.offsetHeight <= windowHeight) {
- var underlay = document.createElement("div");
- underlay.style.clear = "both";
- body.appendChild(underlay);
- }
- }
-
- // disable fixed background
- if (!options.fixedBackground && !isExcluded) {
- body.style.backgroundAttachment = "scroll";
- html.style.backgroundAttachment = "scroll";
- }
- }
-
-
- /************************************************
- * SCROLLING
- ************************************************/
-
- var que = [];
- var pending = false;
- var lastScroll = +new Date;
-
- /**
- * Pushes scroll actions to the scrolling queue.
- */
- function scrollArray(elem, left, top, delay) {
-
- delay || (delay = 1000);
- directionCheck(left, top);
-
- if (options.accelerationMax != 1) {
- var now = +new Date;
- var elapsed = now - lastScroll;
- if (elapsed < options.accelerationDelta) {
- var factor = (1 + (30 / elapsed)) / 2;
- if (factor > 1) {
- factor = Math.min(factor, options.accelerationMax);
- left *= factor;
- top *= factor;
- }
- }
- lastScroll = +new Date;
- }
-
- // push a scroll command
- que.push({
- x: left,
- y: top,
- lastX: (left < 0) ? 0.99 : -0.99,
- lastY: (top < 0) ? 0.99 : -0.99,
- start: +new Date
- });
-
- // don't act if there's a pending queue
- if (pending) {
- return;
- }
-
- var scrollWindow = (elem === document.body);
-
- var step = function (time) {
-
- var now = +new Date;
- var scrollX = 0;
- var scrollY = 0;
-
- for (var i = 0; i < que.length; i++) {
-
- var item = que[i];
- var elapsed = now - item.start;
- var finished = (elapsed >= options.animationTime);
+ };
- // scroll position: [0, 1]
- var position = (finished) ? 1 : elapsed / options.animationTime;
+ $scope.getTemplate = function() {
+ return 'popoverDemo.html';
+ };
- // easing [optional]
- if (options.pulseAlgorithm) {
- position = pulse(position);
- }
+ $scope.aceChanged = function(args) {
+ var changed = args[0];
+ var _editor = args[1];
+ $templateCache.put('popoverDemo.html', _editor.getSession().getValue());
- // only need the difference
- var x = (item.x * position - item.lastX) >> 0;
- var y = (item.y * position - item.lastY) >> 0;
+ };
- // add this to the total scrolling
- scrollX += x;
- scrollY += y;
+ $scope.editorConfig = {
+ showLineNumbers: false,
+ mode: 'html',
+ onLoad: $scope.aceLoaded,
+ onChange: $scope.aceChanged
+ };
- // update last values
- item.lastX += x;
- item.lastY += y;
+ $scope.MIRROR_ATTACH = [
+ 'top', 'right', 'bottom', 'left',
+ 'center', 'middle'
+ ];
- // delete and step back if it's over
- if (finished) {
- que.splice(i, 1); i--;
+ $scope.popoverConfig = {
+ template: 'popover.html',
+ tether: {
+ attachment: 'middle right',
+ targetAttachment: 'middle left'
}
- }
-
- // scroll left and top
- if (scrollWindow) {
- window.scrollBy(scrollX, scrollY);
- }
- else {
- if (scrollX) elem.scrollLeft += scrollX;
- if (scrollY) elem.scrollTop += scrollY;
- }
-
- // clean up if there's nothing left to do
- if (!left && !top) {
- que = [];
- }
-
- if (que.length) {
- requestFrame(step, elem, (delay / options.frameRate + 1));
- } else {
- pending = false;
- }
- };
-
- // start a new queue of actions
- requestFrame(step, elem, 0);
- pending = true;
- }
-
-
- /***********************************************
- * EVENTS
- ***********************************************/
-
- /**
- * Mouse wheel handler.
- * @param {Object} event
- */
- function wheel(event) {
-
- if (!initDone) {
- init();
- }
-
- var target = event.target;
- var overflowing = overflowingAncestor(target);
-
- // use default if there's no overflowing
- // element or default action is prevented
- if (!overflowing || event.defaultPrevented ||
- isNodeName(activeElement, "embed") ||
- (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
- return true;
- }
-
- var deltaX = event.wheelDeltaX || 0;
- var deltaY = event.wheelDeltaY || 0;
-
- // use wheelDelta if deltaX/Y is not available
- if (!deltaX && !deltaY) {
- deltaY = event.wheelDelta || 0;
- }
-
- // check if it's a touchpad scroll that should be ignored
- if (!options.touchpadSupport && isTouchpad(deltaY)) {
- return true;
- }
-
- // scale by step size
- // delta is 120 most of the time
- // synaptics seems to send 1 sometimes
- if (Math.abs(deltaX) > 1.2) {
- deltaX *= options.stepSize / 120;
- }
- if (Math.abs(deltaY) > 1.2) {
- deltaY *= options.stepSize / 120;
- }
-
- scrollArray(overflowing, -deltaX, -deltaY);
- event.preventDefault();
- }
-
- /**
- * Keydown event handler.
- * @param {Object} event
- */
- function keydown(event) {
-
- var target = event.target;
- var modifier = event.ctrlKey || event.altKey || event.metaKey ||
- (event.shiftKey && event.keyCode !== key.spacebar);
-
- // do nothing if user is editing text
- // or using a modifier key (except shift)
- // or in a dropdown
- if ( /input|textarea|select|embed/i.test(target.nodeName) ||
- target.isContentEditable ||
- event.defaultPrevented ||
- modifier ) {
- return true;
- }
- // spacebar should trigger button press
- if (isNodeName(target, "button") &&
- event.keyCode === key.spacebar) {
- return true;
- }
-
- var shift, x = 0, y = 0;
- var elem = overflowingAncestor(activeElement);
- var clientHeight = elem.clientHeight;
-
- if (elem == document.body) {
- clientHeight = window.innerHeight;
- }
-
- switch (event.keyCode) {
- case key.up:
- y = -options.arrowScroll;
- break;
- case key.down:
- y = options.arrowScroll;
- break;
- case key.spacebar: // (+ shift)
- shift = event.shiftKey ? 1 : -1;
- y = -shift * clientHeight * 0.9;
- break;
- case key.pageup:
- y = -clientHeight * 0.9;
- break;
- case key.pagedown:
- y = clientHeight * 0.9;
- break;
- case key.home:
- y = -elem.scrollTop;
- break;
- case key.end:
- var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
- y = (damt > 0) ? damt+10 : 0;
- break;
- case key.left:
- x = -options.arrowScroll;
- break;
- case key.right:
- x = options.arrowScroll;
- break;
- default:
- return true; // a key we don't care about
- }
-
- scrollArray(elem, x, y);
- event.preventDefault();
- }
-
- /**
- * Mousedown event only for updating activeElement
- */
- function mousedown(event) {
- activeElement = event.target;
- }
-
-
- /***********************************************
- * OVERFLOW
- ***********************************************/
-
- var cache = {}; // cleared out every once in while
- setInterval(function () { cache = {}; }, 10 * 1000);
-
- var uniqueID = (function () {
- var i = 0;
- return function (el) {
- return el.uniqueID || (el.uniqueID = i++);
- };
- })();
-
- function setCache(elems, overflowing) {
- for (var i = elems.length; i--;)
- cache[uniqueID(elems[i])] = overflowing;
- return overflowing;
- }
+ };
- function overflowingAncestor(el) {
- var elems = [];
- var rootScrollHeight = root.scrollHeight;
- do {
- var cached = cache[uniqueID(el)];
- if (cached) {
- return setCache(elems, cached);
- }
- elems.push(el);
- if (rootScrollHeight === el.scrollHeight) {
- if (!isFrame || root.clientHeight + 10 < rootScrollHeight) {
- return setCache(elems, document.body); // scrolling root in WebKit
- }
- } else if (el.clientHeight + 10 < el.scrollHeight) {
- overflow = getComputedStyle(el, "").getPropertyValue("overflow-y");
- if (overflow === "scroll" || overflow === "auto") {
- return setCache(elems, el);
+ $scope.posX = [
+ 'left',
+ 'right',
+ 'center'
+ ];
+ $scope.posY = [
+ 'top',
+ 'bottom',
+ 'middle'
+ ];
+
+ })
+
+ .directive('tetherBlock', function(Tether){
+ return {
+ scope: {
+ options : '=',
+ tetherOptions: '='
+ },
+ link: function(scope, elm){
+ Tether({
+ templateUrl: 'intro.html',
+ tether: angular.extend({
+ target: elm[0],
+ attachment: 'bottom center',
+ targetAttachment: 'middle center',
+ targetModifier: 'visible',
+ constraints: [
+ {
+ to: elm,
+ pin: true
+ }
+ ]
+ }, scope.tetherOptions)
+ }).enter();
}
- }
- } while (el = el.parentNode);
- }
-
-
- /***********************************************
- * HELPERS
- ***********************************************/
-
- function addEvent(type, fn, bubble) {
- window.addEventListener(type, fn, (bubble||false));
- }
-
- function removeEvent(type, fn, bubble) {
- window.removeEventListener(type, fn, (bubble||false));
- }
-
- function isNodeName(el, tag) {
- return (el.nodeName||"").toLowerCase() === tag.toLowerCase();
- }
-
- function directionCheck(x, y) {
- x = (x > 0) ? 1 : -1;
- y = (y > 0) ? 1 : -1;
- if (direction.x !== x || direction.y !== y) {
- direction.x = x;
- direction.y = y;
- que = [];
- lastScroll = 0;
- }
- }
-
- var deltaBufferTimer;
-
- function isTouchpad(deltaY) {
- if (!deltaY) return;
- deltaY = Math.abs(deltaY)
- deltaBuffer.push(deltaY);
- deltaBuffer.shift();
- clearTimeout(deltaBufferTimer);
- deltaBufferTimer = setTimeout(function () {
- chrome.storage.local.set({ deltaBuffer: deltaBuffer });
- }, 1000);
- var allDivisable = (isDivisible(deltaBuffer[0], 120) &&
- isDivisible(deltaBuffer[1], 120) &&
- isDivisible(deltaBuffer[2], 120));
- return !allDivisable;
- }
-
- function isDivisible(n, divisor) {
- return (Math.floor(n / divisor) == n / divisor);
- }
-
- var requestFrame = (function () {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- function (callback, element, delay) {
- window.setTimeout(callback, delay || (1000/60));
};
- })();
-
-
- /***********************************************
- * PULSE
- ***********************************************/
-
- /**
- * Viscous fluid with a pulse for part and decay for the rest.
- * - Applies a fixed force over an interval (a damped acceleration), and
- * - Lets the exponential bleed away the velocity over a longer interval
- * - Michael Herf, http://stereopsis.com/stopping/
- */
- function pulse_(x) {
- var val, start, expx;
- // test
- x = x * options.pulseScale;
- if (x < 1) { // acceleartion
- val = x - (1 - Math.exp(-x));
- } else { // tail
- // the previous animation ended here:
- start = Math.exp(-1);
- // simple viscous drag
- x -= 1;
- expx = 1 - Math.exp(-x);
- val = start + (expx * (1 - start));
- }
- return val * options.pulseNormalize;
- }
-
- function pulse(x) {
- if (x >= 1) return 1;
- if (x <= 0) return 0;
+ })
- if (options.pulseNormalize == 1) {
- options.pulseNormalize /= pulse_(1);
- }
- return pulse_(x);
- }
+;
- var isChrome = /chrome/i.test(window.navigator.userAgent);
- var isMouseWheelSupported = 'onmousewheel' in document;
- if (isMouseWheelSupported && isChrome) {
- addEvent("mousedown", mousedown);
- addEvent("mousewheel", wheel);
- addEvent("load", init);
- }
-})();
\ No newline at end of file
diff --git a/examples/index.html b/examples/index.html
index 9ce6b53..c6faefd 100755
--- a/examples/index.html
+++ b/examples/index.html
@@ -17,10 +17,544 @@
+
+
-
+