|
1 /* |
|
2 YUI 3.10.3 (build 2fb5187) |
|
3 Copyright 2013 Yahoo! Inc. All rights reserved. |
|
4 Licensed under the BSD License. |
|
5 http://yuilibrary.com/license/ |
|
6 */ |
|
7 |
|
8 YUI.add('transition', function (Y, NAME) { |
|
9 |
|
10 /** |
|
11 * Provides the transition method for Node. |
|
12 * Transition has no API of its own, but adds the transition method to Node. |
|
13 * |
|
14 * @module transition |
|
15 * @requires node-style |
|
16 */ |
|
17 |
|
18 var CAMEL_VENDOR_PREFIX = '', |
|
19 VENDOR_PREFIX = '', |
|
20 DOCUMENT = Y.config.doc, |
|
21 DOCUMENT_ELEMENT = 'documentElement', |
|
22 DOCUMENT_STYLE = DOCUMENT[DOCUMENT_ELEMENT].style, |
|
23 TRANSITION_CAMEL = 'transition', |
|
24 TRANSITION_PROPERTY_CAMEL = 'transitionProperty', |
|
25 TRANSITION_PROPERTY, |
|
26 TRANSITION_DURATION, |
|
27 TRANSITION_TIMING_FUNCTION, |
|
28 TRANSITION_DELAY, |
|
29 TRANSITION_END, |
|
30 ON_TRANSITION_END, |
|
31 |
|
32 EMPTY_OBJ = {}, |
|
33 |
|
34 VENDORS = [ |
|
35 'Webkit', |
|
36 'Moz' |
|
37 ], |
|
38 |
|
39 VENDOR_TRANSITION_END = { |
|
40 Webkit: 'webkitTransitionEnd' |
|
41 }, |
|
42 |
|
43 /** |
|
44 * A class for constructing transition instances. |
|
45 * Adds the "transition" method to Node. |
|
46 * @class Transition |
|
47 * @constructor |
|
48 */ |
|
49 |
|
50 Transition = function() { |
|
51 this.init.apply(this, arguments); |
|
52 }; |
|
53 |
|
54 // One off handling of transform-prefixing. |
|
55 Transition._TRANSFORM = 'transform'; |
|
56 |
|
57 Transition._toCamel = function(property) { |
|
58 property = property.replace(/-([a-z])/gi, function(m0, m1) { |
|
59 return m1.toUpperCase(); |
|
60 }); |
|
61 |
|
62 return property; |
|
63 }; |
|
64 |
|
65 Transition._toHyphen = function(property) { |
|
66 property = property.replace(/([A-Z]?)([a-z]+)([A-Z]?)/g, function(m0, m1, m2, m3) { |
|
67 var str = ((m1) ? '-' + m1.toLowerCase() : '') + m2; |
|
68 |
|
69 if (m3) { |
|
70 str += '-' + m3.toLowerCase(); |
|
71 } |
|
72 |
|
73 return str; |
|
74 }); |
|
75 |
|
76 return property; |
|
77 }; |
|
78 |
|
79 Transition.SHOW_TRANSITION = 'fadeIn'; |
|
80 Transition.HIDE_TRANSITION = 'fadeOut'; |
|
81 |
|
82 Transition.useNative = false; |
|
83 |
|
84 // Map transition properties to vendor-specific versions. |
|
85 if ('transition' in DOCUMENT_STYLE |
|
86 && 'transitionProperty' in DOCUMENT_STYLE |
|
87 && 'transitionDuration' in DOCUMENT_STYLE |
|
88 && 'transitionTimingFunction' in DOCUMENT_STYLE |
|
89 && 'transitionDelay' in DOCUMENT_STYLE) { |
|
90 Transition.useNative = true; |
|
91 Transition.supported = true; // TODO: remove |
|
92 } else { |
|
93 Y.Array.each(VENDORS, function(val) { // then vendor specific |
|
94 var property = val + 'Transition'; |
|
95 if (property in DOCUMENT[DOCUMENT_ELEMENT].style) { |
|
96 CAMEL_VENDOR_PREFIX = val; |
|
97 VENDOR_PREFIX = Transition._toHyphen(val) + '-'; |
|
98 |
|
99 Transition.useNative = true; |
|
100 Transition.supported = true; // TODO: remove |
|
101 Transition._VENDOR_PREFIX = val; |
|
102 } |
|
103 }); |
|
104 } |
|
105 |
|
106 // Map transform property to vendor-specific versions. |
|
107 // One-off required for cssText injection. |
|
108 if (typeof DOCUMENT_STYLE.transform === 'undefined') { |
|
109 Y.Array.each(VENDORS, function(val) { // then vendor specific |
|
110 var property = val + 'Transform'; |
|
111 if (typeof DOCUMENT_STYLE[property] !== 'undefined') { |
|
112 Transition._TRANSFORM = property; |
|
113 } |
|
114 }); |
|
115 } |
|
116 |
|
117 if (CAMEL_VENDOR_PREFIX) { |
|
118 TRANSITION_CAMEL = CAMEL_VENDOR_PREFIX + 'Transition'; |
|
119 TRANSITION_PROPERTY_CAMEL = CAMEL_VENDOR_PREFIX + 'TransitionProperty'; |
|
120 } |
|
121 |
|
122 TRANSITION_PROPERTY = VENDOR_PREFIX + 'transition-property'; |
|
123 TRANSITION_DURATION = VENDOR_PREFIX + 'transition-duration'; |
|
124 TRANSITION_TIMING_FUNCTION = VENDOR_PREFIX + 'transition-timing-function'; |
|
125 TRANSITION_DELAY = VENDOR_PREFIX + 'transition-delay'; |
|
126 |
|
127 TRANSITION_END = 'transitionend'; |
|
128 ON_TRANSITION_END = 'on' + CAMEL_VENDOR_PREFIX.toLowerCase() + 'transitionend'; |
|
129 TRANSITION_END = VENDOR_TRANSITION_END[CAMEL_VENDOR_PREFIX] || TRANSITION_END; |
|
130 |
|
131 Transition.fx = {}; |
|
132 Transition.toggles = {}; |
|
133 |
|
134 Transition._hasEnd = {}; |
|
135 |
|
136 Transition._reKeywords = /^(?:node|duration|iterations|easing|delay|on|onstart|onend)$/i; |
|
137 |
|
138 Y.Node.DOM_EVENTS[TRANSITION_END] = 1; |
|
139 |
|
140 Transition.NAME = 'transition'; |
|
141 |
|
142 Transition.DEFAULT_EASING = 'ease'; |
|
143 Transition.DEFAULT_DURATION = 0.5; |
|
144 Transition.DEFAULT_DELAY = 0; |
|
145 |
|
146 Transition._nodeAttrs = {}; |
|
147 |
|
148 Transition.prototype = { |
|
149 constructor: Transition, |
|
150 init: function(node, config) { |
|
151 var anim = this; |
|
152 anim._node = node; |
|
153 if (!anim._running && config) { |
|
154 anim._config = config; |
|
155 node._transition = anim; // cache for reuse |
|
156 |
|
157 anim._duration = ('duration' in config) ? |
|
158 config.duration: anim.constructor.DEFAULT_DURATION; |
|
159 |
|
160 anim._delay = ('delay' in config) ? |
|
161 config.delay: anim.constructor.DEFAULT_DELAY; |
|
162 |
|
163 anim._easing = config.easing || anim.constructor.DEFAULT_EASING; |
|
164 anim._count = 0; // track number of animated properties |
|
165 anim._running = false; |
|
166 |
|
167 } |
|
168 |
|
169 return anim; |
|
170 }, |
|
171 |
|
172 addProperty: function(prop, config) { |
|
173 var anim = this, |
|
174 node = this._node, |
|
175 uid = Y.stamp(node), |
|
176 nodeInstance = Y.one(node), |
|
177 attrs = Transition._nodeAttrs[uid], |
|
178 computed, |
|
179 compareVal, |
|
180 dur, |
|
181 attr, |
|
182 val; |
|
183 |
|
184 if (!attrs) { |
|
185 attrs = Transition._nodeAttrs[uid] = {}; |
|
186 } |
|
187 |
|
188 attr = attrs[prop]; |
|
189 |
|
190 // might just be a value |
|
191 if (config && config.value !== undefined) { |
|
192 val = config.value; |
|
193 } else if (config !== undefined) { |
|
194 val = config; |
|
195 config = EMPTY_OBJ; |
|
196 } |
|
197 |
|
198 if (typeof val === 'function') { |
|
199 val = val.call(nodeInstance, nodeInstance); |
|
200 } |
|
201 |
|
202 if (attr && attr.transition) { |
|
203 // take control if another transition owns this property |
|
204 if (attr.transition !== anim) { |
|
205 attr.transition._count--; // remapping attr to this transition |
|
206 } |
|
207 } |
|
208 |
|
209 anim._count++; // properties per transition |
|
210 |
|
211 // make 0 async and fire events |
|
212 dur = ((typeof config.duration !== 'undefined') ? config.duration : |
|
213 anim._duration) || 0.0001; |
|
214 |
|
215 attrs[prop] = { |
|
216 value: val, |
|
217 duration: dur, |
|
218 delay: (typeof config.delay !== 'undefined') ? config.delay : |
|
219 anim._delay, |
|
220 |
|
221 easing: config.easing || anim._easing, |
|
222 |
|
223 transition: anim |
|
224 }; |
|
225 |
|
226 // native end event doesnt fire when setting to same value |
|
227 // supplementing with timer |
|
228 // val may be a string or number (height: 0, etc), but computedStyle is always string |
|
229 computed = Y.DOM.getComputedStyle(node, prop); |
|
230 compareVal = (typeof val === 'string') ? computed : parseFloat(computed); |
|
231 |
|
232 if (Transition.useNative && compareVal === val) { |
|
233 setTimeout(function() { |
|
234 anim._onNativeEnd.call(node, { |
|
235 propertyName: prop, |
|
236 elapsedTime: dur |
|
237 }); |
|
238 }, dur * 1000); |
|
239 } |
|
240 }, |
|
241 |
|
242 removeProperty: function(prop) { |
|
243 var anim = this, |
|
244 attrs = Transition._nodeAttrs[Y.stamp(anim._node)]; |
|
245 |
|
246 if (attrs && attrs[prop]) { |
|
247 delete attrs[prop]; |
|
248 anim._count--; |
|
249 } |
|
250 |
|
251 }, |
|
252 |
|
253 initAttrs: function(config) { |
|
254 var attr, |
|
255 node = this._node; |
|
256 |
|
257 if (config.transform && !config[Transition._TRANSFORM]) { |
|
258 config[Transition._TRANSFORM] = config.transform; |
|
259 delete config.transform; // TODO: copy |
|
260 } |
|
261 |
|
262 for (attr in config) { |
|
263 if (config.hasOwnProperty(attr) && !Transition._reKeywords.test(attr)) { |
|
264 this.addProperty(attr, config[attr]); |
|
265 |
|
266 // when size is auto or % webkit starts from zero instead of computed |
|
267 // (https://bugs.webkit.org/show_bug.cgi?id=16020) |
|
268 // TODO: selective set |
|
269 if (node.style[attr] === '') { |
|
270 Y.DOM.setStyle(node, attr, Y.DOM.getComputedStyle(node, attr)); |
|
271 } |
|
272 } |
|
273 } |
|
274 }, |
|
275 |
|
276 /** |
|
277 * Starts or an animation. |
|
278 * @method run |
|
279 * @chainable |
|
280 * @private |
|
281 */ |
|
282 run: function(callback) { |
|
283 var anim = this, |
|
284 node = anim._node, |
|
285 config = anim._config, |
|
286 data = { |
|
287 type: 'transition:start', |
|
288 config: config |
|
289 }; |
|
290 |
|
291 |
|
292 if (!anim._running) { |
|
293 anim._running = true; |
|
294 |
|
295 if (config.on && config.on.start) { |
|
296 config.on.start.call(Y.one(node), data); |
|
297 } |
|
298 |
|
299 anim.initAttrs(anim._config); |
|
300 |
|
301 anim._callback = callback; |
|
302 anim._start(); |
|
303 } |
|
304 |
|
305 |
|
306 return anim; |
|
307 }, |
|
308 |
|
309 _start: function() { |
|
310 this._runNative(); |
|
311 }, |
|
312 |
|
313 _prepDur: function(dur) { |
|
314 dur = parseFloat(dur) * 1000; |
|
315 |
|
316 return dur + 'ms'; |
|
317 }, |
|
318 |
|
319 _runNative: function() { |
|
320 var anim = this, |
|
321 node = anim._node, |
|
322 uid = Y.stamp(node), |
|
323 style = node.style, |
|
324 computed = node.ownerDocument.defaultView.getComputedStyle(node), |
|
325 attrs = Transition._nodeAttrs[uid], |
|
326 cssText = '', |
|
327 cssTransition = computed[Transition._toCamel(TRANSITION_PROPERTY)], |
|
328 |
|
329 transitionText = TRANSITION_PROPERTY + ': ', |
|
330 duration = TRANSITION_DURATION + ': ', |
|
331 easing = TRANSITION_TIMING_FUNCTION + ': ', |
|
332 delay = TRANSITION_DELAY + ': ', |
|
333 hyphy, |
|
334 attr, |
|
335 name; |
|
336 |
|
337 // preserve existing transitions |
|
338 if (cssTransition !== 'all') { |
|
339 transitionText += cssTransition + ','; |
|
340 duration += computed[Transition._toCamel(TRANSITION_DURATION)] + ','; |
|
341 easing += computed[Transition._toCamel(TRANSITION_TIMING_FUNCTION)] + ','; |
|
342 delay += computed[Transition._toCamel(TRANSITION_DELAY)] + ','; |
|
343 |
|
344 } |
|
345 |
|
346 // run transitions mapped to this instance |
|
347 for (name in attrs) { |
|
348 hyphy = Transition._toHyphen(name); |
|
349 attr = attrs[name]; |
|
350 if ((attr = attrs[name]) && attr.transition === anim) { |
|
351 if (name in node.style) { // only native styles allowed |
|
352 duration += anim._prepDur(attr.duration) + ','; |
|
353 delay += anim._prepDur(attr.delay) + ','; |
|
354 easing += (attr.easing) + ','; |
|
355 |
|
356 transitionText += hyphy + ','; |
|
357 cssText += hyphy + ': ' + attr.value + '; '; |
|
358 } else { |
|
359 this.removeProperty(name); |
|
360 } |
|
361 } |
|
362 } |
|
363 |
|
364 transitionText = transitionText.replace(/,$/, ';'); |
|
365 duration = duration.replace(/,$/, ';'); |
|
366 easing = easing.replace(/,$/, ';'); |
|
367 delay = delay.replace(/,$/, ';'); |
|
368 |
|
369 // only one native end event per node |
|
370 if (!Transition._hasEnd[uid]) { |
|
371 node.addEventListener(TRANSITION_END, anim._onNativeEnd, ''); |
|
372 Transition._hasEnd[uid] = true; |
|
373 |
|
374 } |
|
375 |
|
376 style.cssText += transitionText + duration + easing + delay + cssText; |
|
377 |
|
378 }, |
|
379 |
|
380 _end: function(elapsed) { |
|
381 var anim = this, |
|
382 node = anim._node, |
|
383 callback = anim._callback, |
|
384 config = anim._config, |
|
385 data = { |
|
386 type: 'transition:end', |
|
387 config: config, |
|
388 elapsedTime: elapsed |
|
389 }, |
|
390 |
|
391 nodeInstance = Y.one(node); |
|
392 |
|
393 anim._running = false; |
|
394 anim._callback = null; |
|
395 |
|
396 if (node) { |
|
397 if (config.on && config.on.end) { |
|
398 setTimeout(function() { // IE: allow previous update to finish |
|
399 config.on.end.call(nodeInstance, data); |
|
400 |
|
401 // nested to ensure proper fire order |
|
402 if (callback) { |
|
403 callback.call(nodeInstance, data); |
|
404 } |
|
405 |
|
406 }, 1); |
|
407 } else if (callback) { |
|
408 setTimeout(function() { // IE: allow previous update to finish |
|
409 callback.call(nodeInstance, data); |
|
410 }, 1); |
|
411 } |
|
412 } |
|
413 |
|
414 }, |
|
415 |
|
416 _endNative: function(name) { |
|
417 var node = this._node, |
|
418 value = node.ownerDocument.defaultView.getComputedStyle(node, '')[Transition._toCamel(TRANSITION_PROPERTY)]; |
|
419 |
|
420 name = Transition._toHyphen(name); |
|
421 if (typeof value === 'string') { |
|
422 value = value.replace(new RegExp('(?:^|,\\s)' + name + ',?'), ','); |
|
423 value = value.replace(/^,|,$/, ''); |
|
424 node.style[TRANSITION_CAMEL] = value; |
|
425 } |
|
426 }, |
|
427 |
|
428 _onNativeEnd: function(e) { |
|
429 var node = this, |
|
430 uid = Y.stamp(node), |
|
431 event = e,//e._event, |
|
432 name = Transition._toCamel(event.propertyName), |
|
433 elapsed = event.elapsedTime, |
|
434 attrs = Transition._nodeAttrs[uid], |
|
435 attr = attrs[name], |
|
436 anim = (attr) ? attr.transition : null, |
|
437 data, |
|
438 config; |
|
439 |
|
440 if (anim) { |
|
441 anim.removeProperty(name); |
|
442 anim._endNative(name); |
|
443 config = anim._config[name]; |
|
444 |
|
445 data = { |
|
446 type: 'propertyEnd', |
|
447 propertyName: name, |
|
448 elapsedTime: elapsed, |
|
449 config: config |
|
450 }; |
|
451 |
|
452 if (config && config.on && config.on.end) { |
|
453 config.on.end.call(Y.one(node), data); |
|
454 } |
|
455 |
|
456 if (anim._count <= 0) { // after propertyEnd fires |
|
457 anim._end(elapsed); |
|
458 node.style[TRANSITION_PROPERTY_CAMEL] = ''; // clean up style |
|
459 } |
|
460 } |
|
461 }, |
|
462 |
|
463 destroy: function() { |
|
464 var anim = this, |
|
465 node = anim._node; |
|
466 |
|
467 if (node) { |
|
468 node.removeEventListener(TRANSITION_END, anim._onNativeEnd, false); |
|
469 anim._node = null; |
|
470 } |
|
471 } |
|
472 }; |
|
473 |
|
474 Y.Transition = Transition; |
|
475 Y.TransitionNative = Transition; // TODO: remove |
|
476 |
|
477 /** |
|
478 * Animate one or more css properties to a given value. Requires the "transition" module. |
|
479 * <pre>example usage: |
|
480 * Y.one('#demo').transition({ |
|
481 * duration: 1, // in seconds, default is 0.5 |
|
482 * easing: 'ease-out', // default is 'ease' |
|
483 * delay: '1', // delay start for 1 second, default is 0 |
|
484 * |
|
485 * height: '10px', |
|
486 * width: '10px', |
|
487 * |
|
488 * opacity: { // per property |
|
489 * value: 0, |
|
490 * duration: 2, |
|
491 * delay: 2, |
|
492 * easing: 'ease-in' |
|
493 * } |
|
494 * }); |
|
495 * </pre> |
|
496 * @for Node |
|
497 * @method transition |
|
498 * @param {Object} config An object containing one or more style properties, a duration and an easing. |
|
499 * @param {Function} callback A function to run after the transition has completed. |
|
500 * @chainable |
|
501 */ |
|
502 Y.Node.prototype.transition = function(name, config, callback) { |
|
503 var |
|
504 transitionAttrs = Transition._nodeAttrs[Y.stamp(this._node)], |
|
505 anim = (transitionAttrs) ? transitionAttrs.transition || null : null, |
|
506 fxConfig, |
|
507 prop; |
|
508 |
|
509 if (typeof name === 'string') { // named effect, pull config from registry |
|
510 if (typeof config === 'function') { |
|
511 callback = config; |
|
512 config = null; |
|
513 } |
|
514 |
|
515 fxConfig = Transition.fx[name]; |
|
516 |
|
517 if (config && typeof config !== 'boolean') { |
|
518 config = Y.clone(config); |
|
519 |
|
520 for (prop in fxConfig) { |
|
521 if (fxConfig.hasOwnProperty(prop)) { |
|
522 if (! (prop in config)) { |
|
523 config[prop] = fxConfig[prop]; |
|
524 } |
|
525 } |
|
526 } |
|
527 } else { |
|
528 config = fxConfig; |
|
529 } |
|
530 |
|
531 } else { // name is a config, config is a callback or undefined |
|
532 callback = config; |
|
533 config = name; |
|
534 } |
|
535 |
|
536 if (anim && !anim._running) { |
|
537 anim.init(this, config); |
|
538 } else { |
|
539 anim = new Transition(this._node, config); |
|
540 } |
|
541 |
|
542 anim.run(callback); |
|
543 return this; |
|
544 }; |
|
545 |
|
546 Y.Node.prototype.show = function(name, config, callback) { |
|
547 this._show(); // show prior to transition |
|
548 if (name && Y.Transition) { |
|
549 if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default |
|
550 if (typeof config === 'function') { |
|
551 callback = config; |
|
552 config = name; |
|
553 } |
|
554 name = Transition.SHOW_TRANSITION; |
|
555 } |
|
556 this.transition(name, config, callback); |
|
557 } |
|
558 else if (name && !Y.Transition) { Y.log('unable to transition show; missing transition module', 'warn', 'node'); } |
|
559 return this; |
|
560 }; |
|
561 |
|
562 Y.NodeList.prototype.show = function(name, config, callback) { |
|
563 var nodes = this._nodes, |
|
564 i = 0, |
|
565 node; |
|
566 |
|
567 while ((node = nodes[i++])) { |
|
568 Y.one(node).show(name, config, callback); |
|
569 } |
|
570 |
|
571 return this; |
|
572 }; |
|
573 |
|
574 |
|
575 |
|
576 var _wrapCallBack = function(anim, fn, callback) { |
|
577 return function() { |
|
578 if (fn) { |
|
579 fn.call(anim); |
|
580 } |
|
581 if (callback && typeof callback === 'function') { |
|
582 callback.apply(anim._node, arguments); |
|
583 } |
|
584 }; |
|
585 }; |
|
586 |
|
587 Y.Node.prototype.hide = function(name, config, callback) { |
|
588 if (name && Y.Transition) { |
|
589 if (typeof config === 'function') { |
|
590 callback = config; |
|
591 config = null; |
|
592 } |
|
593 |
|
594 callback = _wrapCallBack(this, this._hide, callback); // wrap with existing callback |
|
595 if (typeof name !== 'string' && !name.push) { // named effect or array of effects supercedes default |
|
596 if (typeof config === 'function') { |
|
597 callback = config; |
|
598 config = name; |
|
599 } |
|
600 name = Transition.HIDE_TRANSITION; |
|
601 } |
|
602 this.transition(name, config, callback); |
|
603 } else if (name && !Y.Transition) { Y.log('unable to transition hide; missing transition module', 'warn', 'node'); |
|
604 } else { |
|
605 this._hide(); |
|
606 } |
|
607 return this; |
|
608 }; |
|
609 |
|
610 Y.NodeList.prototype.hide = function(name, config, callback) { |
|
611 var nodes = this._nodes, |
|
612 i = 0, |
|
613 node; |
|
614 |
|
615 while ((node = nodes[i++])) { |
|
616 Y.one(node).hide(name, config, callback); |
|
617 } |
|
618 |
|
619 return this; |
|
620 }; |
|
621 |
|
622 /** |
|
623 * Animate one or more css properties to a given value. Requires the "transition" module. |
|
624 * <pre>example usage: |
|
625 * Y.all('.demo').transition({ |
|
626 * duration: 1, // in seconds, default is 0.5 |
|
627 * easing: 'ease-out', // default is 'ease' |
|
628 * delay: '1', // delay start for 1 second, default is 0 |
|
629 * |
|
630 * height: '10px', |
|
631 * width: '10px', |
|
632 * |
|
633 * opacity: { // per property |
|
634 * value: 0, |
|
635 * duration: 2, |
|
636 * delay: 2, |
|
637 * easing: 'ease-in' |
|
638 * } |
|
639 * }); |
|
640 * </pre> |
|
641 * @for NodeList |
|
642 * @method transition |
|
643 * @param {Object} config An object containing one or more style properties, a duration and an easing. |
|
644 * @param {Function} callback A function to run after the transition has completed. The callback fires |
|
645 * once per item in the NodeList. |
|
646 * @chainable |
|
647 */ |
|
648 Y.NodeList.prototype.transition = function(config, callback) { |
|
649 var nodes = this._nodes, |
|
650 i = 0, |
|
651 node; |
|
652 |
|
653 while ((node = nodes[i++])) { |
|
654 Y.one(node).transition(config, callback); |
|
655 } |
|
656 |
|
657 return this; |
|
658 }; |
|
659 |
|
660 Y.Node.prototype.toggleView = function(name, on, callback) { |
|
661 this._toggles = this._toggles || []; |
|
662 callback = arguments[arguments.length - 1]; |
|
663 |
|
664 if (typeof name !== 'string') { // no transition, just toggle |
|
665 on = name; |
|
666 this._toggleView(on, callback); // call original _toggleView in Y.Node |
|
667 return; |
|
668 } |
|
669 |
|
670 if (typeof on === 'function') { // Ignore "on" if used for callback argument. |
|
671 on = undefined; |
|
672 } |
|
673 |
|
674 if (typeof on === 'undefined' && name in this._toggles) { // reverse current toggle |
|
675 on = ! this._toggles[name]; |
|
676 } |
|
677 |
|
678 on = (on) ? 1 : 0; |
|
679 if (on) { |
|
680 this._show(); |
|
681 } else { |
|
682 callback = _wrapCallBack(this, this._hide, callback); |
|
683 } |
|
684 |
|
685 this._toggles[name] = on; |
|
686 this.transition(Y.Transition.toggles[name][on], callback); |
|
687 |
|
688 return this; |
|
689 }; |
|
690 |
|
691 Y.NodeList.prototype.toggleView = function(name, on, callback) { |
|
692 var nodes = this._nodes, |
|
693 i = 0, |
|
694 node; |
|
695 |
|
696 while ((node = nodes[i++])) { |
|
697 node = Y.one(node); |
|
698 node.toggleView.apply(node, arguments); |
|
699 } |
|
700 |
|
701 return this; |
|
702 }; |
|
703 |
|
704 Y.mix(Transition.fx, { |
|
705 fadeOut: { |
|
706 opacity: 0, |
|
707 duration: 0.5, |
|
708 easing: 'ease-out' |
|
709 }, |
|
710 |
|
711 fadeIn: { |
|
712 opacity: 1, |
|
713 duration: 0.5, |
|
714 easing: 'ease-in' |
|
715 }, |
|
716 |
|
717 sizeOut: { |
|
718 height: 0, |
|
719 width: 0, |
|
720 duration: 0.75, |
|
721 easing: 'ease-out' |
|
722 }, |
|
723 |
|
724 sizeIn: { |
|
725 height: function(node) { |
|
726 return node.get('scrollHeight') + 'px'; |
|
727 }, |
|
728 width: function(node) { |
|
729 return node.get('scrollWidth') + 'px'; |
|
730 }, |
|
731 duration: 0.5, |
|
732 easing: 'ease-in', |
|
733 |
|
734 on: { |
|
735 start: function() { |
|
736 var overflow = this.getStyle('overflow'); |
|
737 if (overflow !== 'hidden') { // enable scrollHeight/Width |
|
738 this.setStyle('overflow', 'hidden'); |
|
739 this._transitionOverflow = overflow; |
|
740 } |
|
741 }, |
|
742 |
|
743 end: function() { |
|
744 if (this._transitionOverflow) { // revert overridden value |
|
745 this.setStyle('overflow', this._transitionOverflow); |
|
746 delete this._transitionOverflow; |
|
747 } |
|
748 } |
|
749 } |
|
750 } |
|
751 }); |
|
752 |
|
753 Y.mix(Transition.toggles, { |
|
754 size: ['sizeOut', 'sizeIn'], |
|
755 fade: ['fadeOut', 'fadeIn'] |
|
756 }); |
|
757 |
|
758 |
|
759 }, '3.10.3', {"requires": ["node-style"]}); |