/**
30 | * @const Framework
31 | * @description autogenerated with build script, holds current verison info
32 | * @property {string} version - the version
33 | * @property {string} build - the build number
34 | * @property {string} date - the date of the build
35 | */
36 | // DO NOT EDIT. Updated from version.json
37 | var Framework = {"version":"4","build":79,"date":"2015-11-03T00:22:52.407Z"}
A utility to handle requestAnimationFrame loops. It really only exists to eliminate a common but hard debug problem:
5 | * since RaF is sort of a recurent function, sometimes the code can accidentally start the loop twice (or even more times). This has diastrous
6 | * conseuences for perofrmance, but it is not easy to spot at all.
7 | *
8 |
With FrameImpulse you will not get into this kind of trouble easily.
9 | *
10 | * @example
11 | var render = function() {
12 | // Do some rendering logic in here
13 | }
14 |
15 | // When the loop needs to be activated
16 | FrameImpulse.on(render);
17 |
18 | // ...and when it needs to stop
19 | FrameImpulse.off(render);
20 | */
21 | var FrameImpulse = (function() {
22 |
23 | var vendors = ['webkit', 'moz'];
24 |
25 | var listeners = [], numListeners = 0, toRemove = [], numToRemove;
26 | var lastTime = 0;
27 |
28 | var provider = window;
29 |
30 | var r = {};
31 |
32 | // for(var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
33 | // window.requestAnimationFrame = window[vendors[i] + 'RequestAnimationFrame'];
34 | // }
35 |
36 | // if (!window.requestAnimationFrame) {
37 | // window.requestAnimationFrame = function(callback) {
38 | // var currTime = new Date().getTime();
39 | // var timeToCall = Math.max(0, 16 - (currTime - lastTime));
40 | // var id = window.setTimeout(function() {
41 | // callback(currTime + timeToCall);
42 | // }, timeToCall);
43 | // lastTime = currTime + timeToCall;
44 | // return id;
45 | // };
46 | // }
47 |
48 | var run = function(time, frame) {
49 | provider.requestAnimationFrame(run);
50 |
51 | if(numListeners == 0) return;
52 |
53 | for(var i = 0; i < numListeners; i++) {
54 | listeners[i].apply(null, arguments);
55 | }
56 |
57 | if(numToRemove > 0) {
58 | var indexToRemove = [];
59 | for (var i = listeners.length - 1; i >= 0; i--) {
60 | for (var j = 0; j < toRemove.length; j++) {
61 | if (listeners[i] === toRemove[j])
62 | indexToRemove.push(i);
63 | };
64 | };
65 |
66 | for (var i = 0; i < indexToRemove.length; i++) {
67 | listeners.splice(indexToRemove[i], 1);
68 | };
69 |
70 | numListeners = listeners.length;
71 | toRemove = [];
72 | numToRemove = 0;
73 | }
74 | }
75 |
76 | /**
77 | * @method on
78 | * @memberof FrameImpulse
79 | * @static
80 | *
81 | * @param {Function} callback - the function used as callback for the listener
82 | * @description Adds a listener to be called on every frame. The cool thing about this function,
83 | * is that the same function is added twice, it will not be called twice later on. However, this
84 | * does not work with anonymous functions, so we suggest to never use anonnymous functions with this.
85 | */
86 | r.on = function(f) {
87 | if(listeners.indexOf(f) > -1) { return; }
88 | listeners.push(f);
89 | numListeners = listeners.length;
90 | // console.log("FrameImpulse > new listener > total :", numListeners);
91 | }
92 |
93 | /**
94 | * @method off
95 | * @memberof FrameImpulse
96 | * @static
97 | *
98 | * @param {Function} callback - the function used as callback for the listener.
99 | * Needs to be the same function as passed to the on() when it was being registered.
100 | * @description Removes a listener to be called on every frame
101 | */
102 | r.off = function(f) {
103 |
104 |
105 | // At this point we think the "late" removal patttern was more harmful than helpful, so it's gone.
106 |
107 | // if(listeners.indexOf(f) == -1) { return; }
108 | // toRemove.push(f);
109 | // numToRemove = toRemove.length;
110 |
111 | var i = listeners.indexOf(f);
112 | if(i == -1) return;
113 | listeners.splice(i, 1);
114 | numListeners = listeners.length;
115 | }
116 |
117 | /**
118 | * @method getListeners
119 | * @memberof FrameImpulse
120 | * @static
121 | *
122 | * @description Returns a list of all currently registered functions. Useful for debugging.
123 | */
124 | r.getListeners = function() {
125 | return listeners;
126 | }
127 |
128 | r.setProvider = function(p) {
129 | var newprov = p && p != provider;
130 | provider = p || window;
131 | if(newprov) provider.requestAnimationFrame(run);
132 | }
133 |
134 | run();
135 | return r;
136 |
137 | })();
--------------------------------------------------------------------------------
/src/Gesture.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @class Gesture
3 | *
4 | * @param {Object=} options - object holding settings (see above)
5 | *
6 | * @description
7 | *
8 | *
A simple touch (or click/drag) gesture recognition class.
9 | *
10 | *
Works with touch gesture, mouse clik/drag gestures and key press (cursor keys), detects swipes in 4 directions.
11 | *
12 | *
For advanced scenarios Hammer.js can be used instead.
13 | *
14 | *
Options include:
15 | *
16 | *
maxTime - how long before swipe is not considered a swipe (default 300ms)
17 | *
minDistance - how much must the user move to consider this a swipe (default 30px)
18 | *
tolerance - how far off vertical or horizontal axis is considered as swipe
19 | * default: 0.1, don't make it larger than 0.25 (i.e. 45deg)
20 | *
noKeyboard - if set tu true, key listeners will not be activated
21 | * (use if cursor keys are used for something else and there's a conflict)
22 | *
23 | *
24 | *
25 | * @example
26 | var g = new Gesture();
27 | g.swipeUp.on(function() {
28 | console.log("User swiped up!");
29 | });
30 | */
31 | var Gesture = function(options) {
32 |
33 | options = options || {};
34 |
35 | var that = this;
36 | var cl;
37 |
38 | var isTouch = 'ontouchstart' in document;
39 | var downEvent = isTouch ? 'touchstart' : 'mousedown';
40 | var moveEvent = isTouch ? 'touchmove' : 'mousemove';
41 | var upEvent = isTouch ? 'touchend' : 'mouseup';
42 |
43 | /**
44 | * @member {Trigger} swipeUp
45 | * @memberof Gesture.prototype
46 | *
47 | * @description Triggered when a "swipe up" gesture is detected
48 | */
49 | this.swipeUp = new Trigger();
50 |
51 | /**
52 | * @member {Trigger} swipeDown
53 | * @memberof Gesture.prototype
54 | *
55 | * @description Triggered when a "swipe down" gesture is detected
56 | */
57 | this.swipeDown = new Trigger();
58 |
59 | /**
60 | * @member {Trigger} swipeLeft
61 | * @memberof Gesture.prototype
62 | *
63 | * @description Triggered when a "swipe left" gesture is detected
64 | */
65 | this.swipeLeft = new Trigger();
66 |
67 | /**
68 | * @member {Trigger} swipeRight
69 | * @memberof Gesture.prototype
70 | *
71 | * @description Triggered when a "swipe right" gesture is detected
72 | */
73 | this.swipeRight = new Trigger();
74 |
75 | var tolerance = options.tolerance || 0.1;
76 |
77 | var start = { x:0, y:0 },
78 | delta = { x: 0, y: 0 },
79 | startTime = 0,
80 | maxTime = options.maxTime || 300, minDistance = options.minDistance || 30;
81 | minDistance = minDistance * minDistance; // square it for faster math
82 |
83 | var onStart = function(e) {
84 | e = isTouch ? e.targetTouches[0] : e;
85 | start.x = e.pageX;
86 | start.y = e.pageY;
87 | delta.x = 0;
88 | delta.y = 0;
89 | startTime = new Date().getTime();
90 | }
91 |
92 | var onMove = function(e) {
93 | e = isTouch ? e.targetTouches[0] : e;
94 | delta.x = e.pageX - start.x;
95 | delta.y = e.pageY - start.y;
96 | }
97 |
98 | var onStop = function(e) {
99 | var ds = delta.x * delta.x + delta.y * delta.y;
100 | var dt = new Date().getTime() - startTime;
101 | var t = tolerance;
102 |
103 | if(dt > maxTime) return;
104 | if(ds < minDistance) return;
105 |
106 | var a = Math.atan2(delta.y, delta.x) / Math.PI;
107 | // up = -0.5, down = 0.5, left = 1, right = 0
108 | if(a > -0.5 - t && a < -0.5 + t) that.swipeUp.trigger();
109 | if(a > 0.5 - t && a < 0.5 + t) that.swipeDown.trigger();
110 | if(a > 0.0 - t && a < 0.0 + t) that.swipeRight.trigger();
111 | if(a < -1.0 + t || a > 1.0 - t) that.swipeLeft.trigger();
112 | }
113 |
114 | var onKeyDown = function(e) {
115 | // 37 left arrow, 38 up arrow, 39 right arrow, 40 down arrow
116 | delta.x = delta.y = 0;
117 | switch(e.keyCode) {
118 | case 39:
119 | that.swipeLeft.trigger();
120 | break;
121 | case 37:
122 | that.swipeRight.trigger();
123 | break;
124 | case 40:
125 | that.swipeUp.trigger();
126 | break;
127 | case 38:
128 | that.swipeDown.trigger();
129 | break;
130 | }
131 | }
132 |
133 | /**
134 | * @method create
135 | * @memberof Gesture.prototype
136 | *
137 | * @description registers all necessary listeners.
138 | * This is done automatically in the constructor,
139 | * so it doesn't need to be called, unless destroy()
140 | * was called before and we want to reuse the object.
141 | */
142 | this.create = function() {
143 | (options.element || document).addEventListener(downEvent, onStart);
144 | document.addEventListener(moveEvent, onMove);
145 | document.addEventListener(upEvent, onStop);
146 | if(!options.noKeyboard) document.addEventListener("keydown", onKeyDown);
147 | }
148 |
149 | /**
150 | * @method destroy
151 | * @memberof Gesture.prototype
152 | *
153 | * @description deregisters all listeners
154 | */
155 | this.destroy = function() {
156 | (options.element || document).removeEventListener(downEvent, onStart);
157 | document.removeEventListener(moveEvent, onMove);
158 | document.removeEventListener(upEvent, onStop);
159 | if(!options.noKeyboard) document.removeEventListener("keydown", onKeyDown);
160 | }
161 |
162 | this.create();
163 | }
--------------------------------------------------------------------------------
/src/HistoryRouter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @class HistoryRouter
3 | *
4 | * @description
A router that handles browser/app history.
5 | * Works with either the History API or just internally within the app.
6 | *
In most cases - NOT TO BE used directly, it is used internally by {@link Application} instead.
A Trigger can only send one type of event and it will always notify all of its listeners.
6 | *
In order to build a more robust event system, use multiple
7 | * Trigger objects as properties.
8 | *
9 | * @example
10 | // Simple usage for a single type of event
11 | var menuPress = new Trigger();
12 |
13 | var menuPressListener = function(params) {
14 | console.log("menuPress trigger fired");
15 | // params = whatever was passed to the trigger method (see below)
16 | console.log(params);
17 | }
18 |
19 | menuPress.on(menuPressListener);
20 |
21 | // ... then somewhere in the code:
22 | menuPress.trigger({ id: 5 });
23 |
24 | // ... and eventually
25 | menuPress.off(menuPressListener);
26 | *
27 | * @example
28 | // If there are multiple events to handle,
29 | // simply create multiple triggers
30 | var car = {
31 | engineStarted: new Trigger(),
32 | brakeApplied: new Trigger(),
33 | gearChanged: new Trigger()
34 | }
35 | */
36 | var Trigger = function() {
37 |
38 | var t = {};
39 |
40 | var listeners = [];
41 | var lock = false;
42 |
43 | var lateTriggers = [];
44 | var lateRemovals = [];
45 |
46 | /**
47 | * @method on
48 | * @memberof Trigger.prototype
49 | * @param {Function} callback - the function used as callback for the listener
50 | * @param {Object=} context - the context in which to invoke the function
51 | * @description Adds a listener to this trigger
52 | */
53 | t.on = function (callback, context, callOnInit) {
54 | if(listeners.indexOf(callback) > -1) { return; }
55 | callback.context = context;
56 | listeners.push(callback);
57 | if(callOnInit) callback();
58 | };
59 |
60 | /**
61 | * @method off
62 | * @memberof Trigger.prototype
63 | * @param {Function} callback - the function used as callback for the listener.
64 | * Needs to be the same function as passed to the on() when it was being registered.
65 | * @description Removes a listener from this trigger.
66 | *
If the passed callback is not a listener of this trigger,
67 | * this function will not throw any warnings, it will just return.
68 | *
If this function is called from within a function that is a listener for that trigger,
69 | * the callback will not be removed until all other listeners are called.
70 | */
71 | t.off = function (callback) {
72 | var i = listeners.indexOf(callback);
73 |
74 | if(i == -1) return;
75 |
76 | if(lock) {
77 | lateRemovals.push({ callback: callback });
78 | return;
79 | }
80 |
81 | listeners.splice(i, 1);
82 | };
83 |
84 | /**
85 | * @method trigger
86 | * @memberof Trigger.prototype
87 | * @param {Object=} data - An object specifying the events parameters. All listeners will receive this object as argument.
88 | * @description Fires this trigger passing data as srgument to all listeners.
89 | *
If this function is called from within a function that is a listener for that trigger,
90 | * the trigger will not be fired until all other listeners
91 | * are called for the previous one.
92 | */
93 | t.trigger = function (data) {
94 |
95 | if(lock) {
96 | lateTriggers.push({ data: data });
97 | return;
98 | }
99 |
100 | lock = true;
101 |
102 | var i = 0, nl = listeners.length;
103 | while(i < nl) {
104 | var f = listeners[i];
105 | f.call(f.context, data);
106 | i++;
107 | }
108 |
109 | lock = false;
110 |
111 | var d;
112 | while(d = lateTriggers.shift()) t.trigger(d.data);
113 | while(d = lateRemovals.shift()) t.off(d.callback);
114 | };
115 |
116 | return t;
117 |
118 | };
--------------------------------------------------------------------------------
/src/Version.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @const Framework
3 | * @description autogenerated with build script, holds current verison info
4 | * @property {string} version - the version
5 | * @property {string} build - the build number
6 | * @property {string} date - the date of the build
7 | */
8 | // DO NOT EDIT. Updated from version.json
9 | var Framework = {"version":"4","build":224,"date":"2022-06-27T21:09:39.716Z"}
--------------------------------------------------------------------------------
/src/domExtend/Animation.js:
--------------------------------------------------------------------------------
1 | var ExtAnimation = function(ext, element, globalExt) {
2 |
3 | var events = {
4 | 'animation': 'animationend',
5 | 'Moz': 'animationend',
6 | 'O': 'oanimationend',
7 | 'Webkit': 'webkitAnimationEnd',
8 | 'Ms': 'MSAnimationEnd'
9 | };
10 |
11 | var animStrigify = function(anim) {
12 | return [
13 | anim.name,
14 | anim.duration + 's',
15 | anim.ease,
16 | anim.delay + 's',
17 | anim.count,
18 | anim.direction,
19 | anim.fillMode//,
20 | // anim.playState // doesn't work on Safari 8.0, but it's not very useful anyway
21 | ].join(' ');
22 | }
23 |
24 | // animation: name duration timing-function delay iteration-count direction fill-mode (play-state - not-inplemented);
25 | var createAnimation = function(name, duration, ease, delay) {
26 | var a = {
27 | name: name,
28 | duration: duration || 1,
29 | ease: ease || 'ease',
30 | delay: delay || 0,
31 | count: 1,
32 | direction: 'normal',
33 | fillMode: 'backwards'//,
34 | // playState: 'running'
35 | };
36 |
37 | a.setTime = function(t) {
38 | a.time = t;
39 | return a;
40 | }
41 |
42 | a.setDelay = function(t) {
43 | a.delay = t;
44 | return a;
45 | }
46 |
47 | return a;
48 | }
49 |
50 | globalExt.createAnimation = createAnimation;
51 | ext.createAnimation = createAnimation;
52 |
53 | ext.animate = function(anim, callback, dontClear) {
54 |
55 | var a;
56 |
57 | if(anim instanceof Array) {
58 | var aa = [];
59 | anim.forEach(function(e) { aa.push(animStrigify(e)); });
60 | a = aa.join(', ');
61 | } else {
62 | a = animStrigify(anim);
63 | }
64 |
65 | var eventName = events[Simplrz.prefix.js];
66 |
67 | if(element._onEnded) element.removeEventListener(eventName, element._onEnded);
68 |
69 | element._onEnded = function() {
70 | element.removeEventListener(eventName, element._onEnded);
71 |
72 | if(dontClear == null) {
73 | element.style[Simplrz.prefix.js + "Animation"] = '';
74 | element.style["animation"] = '';
75 | }
76 |
77 | if(callback) callback();
78 | }
79 |
80 |
81 | element.style[Simplrz.prefix.js + "Animation"] = "";
82 | element.style["animation"] = "";
83 |
84 | setTimeout(function() {
85 | if(ext.show) ext.show();
86 | element.addEventListener(eventName, element._onEnded);
87 | element.style[Simplrz.prefix.js + "Animation"] = a;
88 | element.style["animation"] = a;
89 | }, 0);
90 | }
91 | };
--------------------------------------------------------------------------------
/src/domExtend/DomExtend.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace DomExtend
3 | */
4 | var DomExtend = (function() {
5 |
6 | var that = {};
7 |
8 | /**
9 | * @method create
10 | * @memberof DomExtend
11 | * @static
12 | * @param {string} tag - the name of the tag to create
13 | * @description Created a HTMLElement of type defined by the tag. It first calls document.createElement(tag)
14 | * and the extends this element with DomExtend functionality.
15 | */
16 | that.create = function(tag, cssclass) {
17 | var e = document.createElement(tag);
18 | if(cssclass) e.classList.add(cssclass);
19 | that.extend(e);
20 | return e;
21 | };
22 |
23 | /**
24 | * The equivalent of document.querySelector. It extends the object
25 | * with DomExtend functionality before returning the result.
26 | *
27 | * @method select
28 | * @memberof DomExtend
29 | * @static
30 | * @param {string} sel - the CSS selector to query
31 | * @param {HTMLElement=} element - the HTML element to query on, defaults to document
32 | */
33 | that.select = function(sel, element) {
34 | var e = (element || document).querySelector(sel);
35 | if(e && !e.ext) that.extend(e);
36 | return e;
37 | };
38 |
39 | /**
40 | * The equivalent of document.querySelectorAll. It extends the objects
41 | * with DomExtend functionality before returning the result and it returns them as regular Array (yay!)
42 | *
43 | * @method select
44 | * @memberof DomExtend
45 | * @static
46 | * @param {string} sel - the CSS selector to query
47 | * @param {HTMLElement=} element - the HTML element to query on, defaults to document
48 | */
49 | that.selectAll = function(sel, element) {
50 | var es = (element || document).querySelectorAll(sel);
51 | var nes = es.length, r = [];
52 | for(var i = 0; i < nes; i++) {
53 | var e = es[i]
54 | if(!e.ext) e = that.extend(e);
55 | r.push(e);
56 | }
57 | return r;
58 | };
59 |
60 | /**
61 | * @method extend
62 | * @memberof DomExtend
63 | * @static
64 | * @param {HTMLElement} element - the tag to extend
65 | * @description adds the .ext property to the element, with all the DomExtend functionality. This method should be rarely used and if you
66 | * find yourself using it a lot, you need to rethink the code. All element selected with EXT.select or element.ext.select
67 | * or created with EXT.create will be already extended.
68 | */
69 | that.extend = function(element) {
70 |
71 | if(element.ext) return element;
72 |
73 | var ext = {};
74 |
75 | /**
76 | * The equivalent of element.querySelector. It extends the object
77 | * with DomExtend functionality before returning the result.
78 | *
79 | * @method select
80 | * @memberof DomExtend.prototype
81 | * @param {string} sel - the CSS selector to query
82 | */
83 | ext.select = function(sel) {
84 | return that.select(sel, element);
85 | };
86 |
87 | /**
88 | * The equivalent of element.querySelectorAll. It extends the objects
89 | * with DomExtend functionality before returning the result and it returns them as regular Array (yay!)
90 | *
91 | * @method select
92 | * @memberof DomExtend.prototype
93 | * @param {string} sel - the CSS selector to query
94 | */
95 | ext.selectAll = function(sel) {
96 | return that.selectAll(sel, element);
97 | };
98 |
99 | /**
100 | * @method detach
101 | * @memberof DomExtend.prototype
102 | * @description Safely removes the element from it's parent node. It is the same as saying
103 | * element.parentNode.removeChild(element) but will not throw an error if parentNode is null.
104 | */
105 | ext.detach = function() {
106 | var p = element.parentNode;
107 | if(!p) return;
108 | p.removeChild(element);
109 | };
110 |
111 | /**
112 | * @method attachTo
113 | * @memberof DomExtend.prototype
114 | * @description Safely attaches the element to a parent node. It is the same as saying
115 | * parent.appednChild(element) but will not throw an error if child is already added to parent.
116 | */
117 | ext.attachTo = function(parent) {
118 | if(element.parentNode == parent) return;
119 | else parent.appendChild(element);
120 | }
121 |
122 | // Add State related functions (see State.js for details)
123 | if(window.ExtState) ExtState(ext, element);
124 |
125 | // Add Transform related functions (see Transform.js for details)
126 | if(window.ExtTransform) ExtTransform(ext, element);
127 |
128 | // Add Transition related functions (see Transition.js for details)
129 | if(window.ExtTransition) ExtTransition(ext, element);
130 |
131 | // Add Animation related functions (see Transition.js for details)
132 | if(window.ExtAnimation) ExtAnimation(ext, element, that);
133 |
134 | ext.element = element;
135 | element.ext = ext;
136 | return element;
137 | };
138 |
139 | window.EXT = that;
140 |
141 | return that;
142 |
143 | })();
--------------------------------------------------------------------------------
/src/domExtend/State.js:
--------------------------------------------------------------------------------
1 | var ExtState = function(ext, element) {
2 |
3 | var cc = function(p) {
4 | return p.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
5 | }
6 |
7 | ext.data = {};
8 |
9 | /**
10 | * @method show
11 | * @memberof DomExtend.prototype
12 | * @param {string} [display=block] the CSS property value to use.
13 | * @description Sets the display CSS property of the object to the display type specified in the argument. Defaults to "block".
14 | */
15 | ext.show = function(display) {
16 | element.style.display = display || element.ext.__defaultDisplay || "block";
17 | };
18 |
19 | /**
20 | * @method hide
21 | * @memberof DomExtend.prototype
22 | * @description Sets the display CSS property of the object to "none".
23 | */
24 | ext.hide = function() {
25 | if(!element.ext.__defaultDisplay) {
26 | var d = ext.readCss('display');
27 | element.ext.__defaultDisplay = d == 'none' ? 'block' : d;
28 | }
29 | element.style.display = "none";
30 | };
31 |
32 | /**
33 | * @method toggle
34 | * @memberof DomExtend.prototype
35 | * @description Toggle the display CSS between "none" and "block".
36 | */
37 | ext.toggle = function(show, display) {
38 | if(show) ext.show(display);
39 | else ext.hide();
40 | };
41 |
42 | /**
43 | * @method visible
44 | * @memberof DomExtend.prototype
45 | * @description Returns true if the CSS display property is set to none on this element.
46 | */
47 | ext.visible = function() {
48 | return ext.readCss('display') != "none";
49 | };
50 |
51 | /**
52 | * @method on
53 | * @memberof DomExtend.prototype
54 | * @description Equivalent of element.addEventListener but shorter and has a special touch handler for 'click' events.
55 | */
56 | ext.on = function(event, callback, options) {
57 | // if(Simplrz.touch && event == 'click') {
58 | // callback.___thProxy = Util.handleTap(element, callback);
59 | // return callback.___thProxy;
60 | // } else
61 | if(event == 'doubleclick') {
62 | callback.___dcProxy = Util.handleDC(element, callback);
63 | return callback.___dcProxy;
64 | } else {
65 | // if(!options) options = { passive: true };
66 | if(!options) options = { };
67 | return element.addEventListener(event, callback, options);
68 | }
69 | }
70 |
71 | /**
72 | * @method off
73 | * @memberof DomExtend.prototype
74 | * @description Equivalent of element.removeEventListener but shorter and works witht the special touch handler for 'click' events.
75 | */
76 | ext.off = function(event, callback, useCapture) {
77 | // if(callback.___thProxy) {
78 | // Util.clearTapHandler(element, callback.___thProxy);
79 | // callback.___thProxy = null;
80 | // } else
81 | if(callback.___dcProxy) {
82 | // callback.___dcProxy.clear = null;
83 | Util.clearDCHandler(element, callback.___dcProxy);
84 | } else {
85 | return element.removeEventListener(event, callback, useCapture);
86 | }
87 |
88 | };
89 |
90 | /**
91 | * @method readCss
92 | * @memberof DomExtend.prototype
93 | *
94 | * @param {string} property - the name of the CSS property
95 | * @param {Boolean} notCalculated - if true, grabs the value directly from the style property of the object.
96 | *
97 | * @description
Returns true if the value of a CSS property, fetched using computed styles.
98 | *
The CSS values of the object can be defined in multiple stylesheets, so it's not straightforward
99 | * to read them - i.e. in most cases just saying ex. var d = element.style.display will not return
100 | * expected results.
101 | *
This method uses computed styles to fetch the actual CSS value of a property.
102 | */
103 | ext.readCss = function(property, notCalculated) {
104 | if(notCalculated) {
105 | return element.style[property];
106 | } else {
107 | var s = getComputedStyle(element);
108 | if(!s) element.style[property]; // Bug in Firefox - this will be null if in iframe and it's set to display:none
109 | else return s.getPropertyValue(property);
110 | }
111 | }
112 |
113 | /**
114 | * @method bg
115 | * @memberof DomExtend.prototype
116 | * @description Loads and sets a backgroung image for the element. Passing the onLoad function allows to make
117 | * animated transitions (ex. fade in) when the background images are loaded.
118 | *
119 | * @param {string} path - the path to the image
120 | * @param {Function} onLoad - the load callback to be exectued. It is called after the image was loaded but before
121 | * it has been set as background image.
122 | */
123 | ext.bg = function(path, onLoad) {
124 |
125 | if(onLoad) {
126 | var i = new Image();
127 | i.addEventListener('load', function() {
128 | onLoad(element, i);
129 | element.style.backgroundImage = 'url(' + path + ')';
130 | });
131 | i.src = path;
132 | } else {
133 | element.style.backgroundImage = 'url(' + path + ')';
134 | }
135 | }
136 | };
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/src/domExtend/Transition.js:
--------------------------------------------------------------------------------
1 | var ExtTransition = function(ext, element) {
2 |
3 | var events = {
4 | 'transition': 'transitionEnd',
5 | 'Moz': 'transitionend',
6 | 'O': 'oTransitionEnd',
7 | 'Webkit': 'webkitTransitionEnd',
8 | 'Ms': 'MSTransitionEnd'
9 | };
10 |
11 | var trEvent = events[Simplrz.prefix.js];
12 | var TR = "transform";
13 |
14 | var now = function() {
15 | return new Date().getTime();
16 | }
17 |
18 | ext.createTransition = function() {
19 |
20 | var transition = {};
21 | var tr = [], ts = [];
22 | var cb, numTrans;
23 | var startTime, maxTime = 0, finalized;
24 |
25 | var onEnded = function(e) {
26 | numTrans--;
27 | if(numTrans <= 0) {
28 | var t = now() - startTime;
29 | if(t >= maxTime) {
30 | finalize();
31 | } else if(!finalized) {
32 | // console.log("Transition early end > ", t, maxTime);
33 | setTimeout(finalize, t);
34 | finalized = true;
35 | }
36 | }
37 | };
38 |
39 | var finalize = function() {
40 | transition.clear();
41 | if(cb) cb();
42 | }
43 |
44 | var setValues = function(vals) {
45 | var nv = vals.length;
46 |
47 | for(var i = 0; i < nv; i++) {
48 | var p = vals[i][0], v = vals[i][1];
49 | if(p == TR) ext.transform(v);
50 | else element.style[p] = v;
51 | }
52 |
53 | return transition;
54 | };
55 |
56 | function propToCss(str) {
57 | return str.replace(/([A-Z])/g, function(letter) { return '-' + letter.toLowerCase(); });
58 | }
59 |
60 | transition.add = function(property, to, time, ease, delay) {
61 | maxTime = Math.max(maxTime, time);
62 | ease = ease || Util.cssEase.ease;
63 | delay = delay || 0;
64 | tr.push([propToCss(property), time+'ms', ease, delay+'ms'].join(' '));
65 | ts.push([property, to]);
66 |
67 | return transition;
68 | }
69 |
70 | transition.trs = function(values, time, ease, delay) {
71 | maxTime = Math.max(maxTime, time);
72 | ease = ease || Util.cssEase.ease;
73 | delay = delay || 0;
74 | tr.push([Simplrz.prefix.css + "transform", time+'ms', ease, delay+'ms'].join(' '));
75 | ts.push([TR, values]);
76 |
77 | return transition;
78 | }
79 |
80 | transition.clear = function() {
81 | element.removeEventListener(trEvent, onEnded);
82 | tr = [];
83 | ts = [];
84 | element.style[Simplrz.prefix.js + "Transition"] = "";
85 | element.style["transition"] = "";
86 | }
87 |
88 | transition.start = function(callback) {
89 | cb = callback;
90 | numTrans = ts.length;
91 |
92 | // force repaint
93 | var w = element.offsetWidth;
94 |
95 | element.addEventListener(trEvent, onEnded);
96 | startTime = now();
97 | finalized = false;
98 | element.style[Simplrz.prefix.js + "Transition"] = tr;
99 | element.style["transition"] = tr;
100 | setValues(ts);
101 |
102 | return transition;
103 | };
104 |
105 | transition.then = function(callback) {
106 | var t = ext.createTransition();
107 |
108 | var c = function() {
109 | callback();
110 | t.start();
111 | }
112 |
113 | transition.start(c);
114 |
115 | return t;
116 | }
117 |
118 | return transition;
119 |
120 | };
121 |
122 | /**
123 | * @method transition
124 | * @memberof DomExtend.prototype
125 | * @description Creates and starts a CSS transition animation on the element.
126 | *
127 | * @param {Object} properties - the properties to animate, See examples below.
128 | * @param {Number} time - the duration of the animation in milliseconds
129 | * @param {string} ease - the ease. See Util.cssEase for list of easing functions available.
130 | * @param {Number=} delay - the delay before the animation starts in milliseconds, defaults to 0
131 | * @param {Function=} callback - the function to be invoked when the animation is finished
132 | *
133 | * @example
134 | // Animate the opacity property
135 | element.style.opacity = 0;
136 | element.ext.transtion({ opacity: 1 }, 1000, 'ease');
137 |
138 | // Animate the opacity with custom easing and listen for when the animation is over
139 | element.style.opacity = 0;
140 | element.ext.transtion({ opacity: 1 }, 1000, Util.cssEase.quadIn, 0, function() {
141 | console.log('Animation is over!');
142 | });
143 |
144 | // Animate the x, y position and z rotation
145 |
146 | // 1. Define start values
147 | // If this is omitted the transtions will start
148 | // from the current state of the object.
149 | element.ext.x = 0;
150 | element.ext.y = 0;
151 | element.ext.rotZ = 0;
152 | element.ext.transform();
153 |
154 | // 2. Start the animation
155 | // Note that the transform values are passed as object,
156 | // not as properties of the "properties" argument
157 | element.ext.transition({
158 | transform: {
159 | x: 100, y: 100, rotZ: 20
160 | }
161 | }, 1000, 'ease');
162 | */
163 | ext.transition = function(properties, time, ease, delay, callback) {
164 | var t = ext.createTransition();
165 |
166 | for(var p in properties) {
167 | var v = properties[p];
168 | if(p == TR) t.trs(v, time, ease, delay);
169 | else t.add(p, v, time, ease, delay);
170 | }
171 |
172 | t.start(callback);
173 | return t;
174 | }
175 | };
176 |
177 |
178 |
--------------------------------------------------------------------------------
/test/css-animation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |