Browse Source

#2: + 'hideLayerInStack' & 'visibleOverlayInStack' flags

modules
RubaXa 11 years ago
parent
commit
b75b4bc0ee
  1. 2
      Ply.min.js
  2. 95
      src/Ply.es6
  3. 19
      tests/Ply.stack.tests.js
  4. 21
      tests/Ply.tests.js

2
Ply.min.js vendored

File diff suppressed because one or more lines are too long

95
src/Ply.es6

@ -103,7 +103,6 @@
function _promise(executor) { function _promise(executor) {
/* istanbul ignore if */ /* istanbul ignore if */
if (Promise) { if (Promise) {
// @todo: Поткрыть тестами
return new Promise(executor); return new Promise(executor);
} else { } else {
var dfd = $.Deferred(); var dfd = $.Deferred();
@ -559,7 +558,7 @@
/** /**
* Создать лаер с контентом * Создать слой с контентом
* @param {HTMLElement} contentEl * @param {HTMLElement} contentEl
* @param {Object} options * @param {Object} options
* @returns {HTMLElement} * @returns {HTMLElement}
@ -608,13 +607,14 @@
return _buildDOM({ return _buildDOM({
ply: ':overlay', ply: ':overlay',
tag: '.ply-overlay', tag: '.ply-overlay',
css: _extend({ css: {
top: 0, top: 0,
left: 0, left: 0,
right: 0, right: 0,
bottom: 0, bottom: 0,
position: 'fixed' position: 'fixed'
}, style) },
children: [{ tag: 'div', css: _extend({ width: '100%', height: '100%' }, style) }]
}); });
} }
@ -629,12 +629,13 @@
*/ */
function _createPly(target, options, onlyLayer) { function _createPly(target, options, onlyLayer) {
// Корневой слой // Корневой слой
target.wrapEl = _buildDOM({ css: { whiteSpace: 'nowrap' } }); target.wrapEl = _buildDOM({ css: { whiteSpace: 'nowrap', zIndex: options.zIndex } });
// Затемнение // Затемнение
if (!onlyLayer) { if (!onlyLayer) {
target.overlayEl = _createOverlay(options.overlay); target.overlayEl = _createOverlay(options.overlay);
target.overlayBoxEl = target.overlayEl.firstChild;
_appendChild(target.wrapEl, target.overlayEl); _appendChild(target.wrapEl, target.overlayEl);
} }
@ -698,8 +699,10 @@
// //
// Настройки по умолчанию // Настройки по умолчанию
// //
var defaults = { var _defaults = {
layer: {}, zIndex: 10000,
layer: {}, // css
overlay: { overlay: {
opacity: .6, opacity: .6,
@ -710,7 +713,9 @@
closeBtn: true, closeBtn: true,
bodyScroll: false, bodyScroll: false,
closeByEsc: true, closeByEsc: true,
closeByOverlay: true closeByOverlay: true,
hideLayerInStack: true,
visibleOverlayInStack: false
}, },
baseHtml: true, baseHtml: true,
@ -735,21 +740,30 @@
/** /**
* @class Ply * @class Ply
* @param {Object} options опции слоя * @param {HTMLElement|Object} el слой или опции
* @param {Object} [options] опции слоя
*/ */
function Ply(options) { function Ply(el, options) {
options = (el instanceof Object) ? el : (options || {});
options.el = options.el || el;
var _this = this; var _this = this;
// Локальный идентификатор // Локальный идентификатор
_this.cid = 'c' + gid++; _this.cid = 'c' + gid++;
// Увеличиваем глобальный zIndex
_defaults.zIndex++;
// Опции // Опции
_this.options = options = _extend({}, defaults, options); _this.options = options = _extend({}, _defaults, options);
// Флаги // Флаги
options.flags = _extend({}, defaults.flags, options.flags); options.flags = _extend({}, _defaults.flags, options.flags);
// Создаем Ply-элементы // Создаем Ply-элементы
@ -869,11 +883,16 @@
* @param {String} name * @param {String} name
* @param {String|Object} [effects] * @param {String|Object} [effects]
* @returns {Promise} * @returns {Promise}
* @private
*/ */
_applyEffect: function (el, name, effects) { applyEffect: function (el, name, effects) {
if (!el.nodeType) {
effects = name;
name = el;
el = this.layerEl;
}
effects = Ply.effects.get(effects || this.effects); effects = Ply.effects.get(effects || this.effects);
return Ply.effects.apply.call(effects, el, name); return Ply.effects.apply.call(effects, this[el] || el, name);
}, },
@ -973,9 +992,10 @@
* @returns {Promise} * @returns {Promise}
* @private * @private
*/ */
toggleState: function (state, effect) { _toggleState: function (state, effect) {
var _this = this, var _this = this,
mode = state ? 'open' : 'close' mode = state ? 'open' : 'close',
prevLayer = Ply.stack.last
; ;
/* istanbul ignore else */ /* istanbul ignore else */
@ -989,18 +1009,38 @@
// Очередь эффектов // Очередь эффектов
_this.fx(() => { _this.fx(() => {
return _preloadImage(_this.wrapEl).then(() => { return _preloadImage(_this.wrapEl).then(() => {
var isFirst = Ply.stack.length === (state ? 1 : 0),
hideLayer = prevLayer && prevLayer.hasFlag('hideLayerInStack'),
hasOverlay = isFirst || _this.hasFlag('visibleOverlayInStack');
if (state) { if (state) {
// Убрать «затемнение» если мы не первые в стеке
!hasOverlay && _removeElement(_this.overlayBoxEl);
_appendChild(_this.bodyEl, _this.wrapEl); _appendChild(_this.bodyEl, _this.wrapEl);
_this.wrapEl.focus(); _this.wrapEl.focus();
_autoFocus(_this.layerEl); _autoFocus(_this.layerEl);
if (hideLayer) {
// Скрыть слой «под»
prevLayer.applyEffect('close.layer', effect).then(() => {
_removeElement(prevLayer.layerEl);
});
}
} else if (prevLayer = Ply.stack.last) {
// Слой мог быть скрыт, нужно вернуть его
_appendChild(prevLayer.wrapEl, prevLayer.layerEl);
prevLayer.hasFlag('hideLayerInStack') && prevLayer.applyEffect('open.layer', effect);
} }
// Применяем основные эффекты
return _promiseAll([ return _promiseAll([
_this._applyEffect(_this.overlayEl, mode + '.overlay', effect), _this.applyEffect(mode + '.layer', effect),
_this._applyEffect(_this.layerEl, mode + '.layer', effect) hasOverlay && _this.applyEffect('overlayEl', mode + '.overlay', effect)
]).then(() => { ]).then(() => {
if (!state) { if (!state) {
_removeElement(_this.wrapEl); _removeElement(_this.wrapEl);
_appendChild(_this.overlayEl, _this.overlayBoxEl);
} }
_this.options[mode](_this); _this.options[mode](_this);
}); });
@ -1018,7 +1058,7 @@
* @returns {Promise} * @returns {Promise}
*/ */
open: function (effect) { open: function (effect) {
return this.toggleState(true, effect); return this._toggleState(true, effect);
}, },
@ -1028,7 +1068,7 @@
* @returns {Promise} * @returns {Promise}
*/ */
close: function (effect) { close: function (effect) {
return this.toggleState(false, effect); return this._toggleState(false, effect);
}, },
@ -1050,8 +1090,8 @@
prepare(); prepare();
return _promiseAll([ return _promiseAll([
_this._applyEffect(closeEl, 'close.layer', effects), _this.applyEffect(closeEl, 'close.layer', effects),
_this._applyEffect(openEl, 'open.layer', effects) _this.applyEffect(openEl, 'open.layer', effects)
]).then(() => { ]).then(() => {
_removeElement(closeEl); _removeElement(closeEl);
complete(); complete();
@ -1127,7 +1167,7 @@
/** /**
* Уничтожить лаер * Уничтожить слой
*/ */
destroy: function () { destroy: function () {
_removeElement(this.wrapEl); _removeElement(this.wrapEl);
@ -1159,7 +1199,7 @@
/** /**
* Удаить последний ply-лаер из стека * Удаить последний ply-слой из стека
* @param {Event} evt * @param {Event} evt
* @private * @private
*/ */
@ -1392,9 +1432,12 @@
// Возвращаем стили, именно на "then" с разрывом, т.к. «Обещания» могу быть ассинхронными // Возвращаем стили, именно на "then" с разрывом, т.к. «Обещания» могу быть ассинхронными
el.setAttribute('style', oldStyle[0]); el.setAttribute('style', oldStyle[0]);
firstEl && firstEl.setAttribute('style', oldStyle[1]); firstEl && firstEl.setAttribute('style', oldStyle[1]);
return el;
})); }));
} }
} }
return _promise((resolve) => { resolve(); });
}, },
@ -1609,7 +1652,7 @@
Ply.each = _each; Ply.each = _each;
Ply.extend = _extend; Ply.extend = _extend;
Ply.promise = _promise; Ply.promise = _promise;
Ply.defaults = defaults; Ply.defaults = _defaults;
Ply.attrName = _plyAttr; Ply.attrName = _plyAttr;
Ply.Context = Context; Ply.Context = Context;

19
tests/Ply.stack.tests.js

@ -2,12 +2,19 @@
module('Ply.stack'); module('Ply.stack');
asyncTest('2x', function () { asyncTest('2x', function () {
new Ply({ el: '1', effect: 'fade' }).open().then(function () { new Ply('foo', { effect: 'slide' }).open().then(function (foo) {
new Ply({ el: '2', effect: 'fade' }).open().then(function () { new Ply('bar', { effect: 'fall' }).open().then(function (bar) {
// Ply.stack.last.close(); ok(!foo.layerEl.parentNode, 'foo.parent == null');
// Ply.stack.last.close().then(function () { ok(!bar.overlayBoxEl.parentNode, 'bar.parent == null');
// start();
// }); Ply.stack.last.close().then(function () {
ok(!!foo.layerEl.parentNode, 'foo.parent != null');
ok(!!bar.overlayBoxEl.parentNode, 'bar.parent != null');
Ply.stack.last.close().then(function () {
start();
});
});
}); });
}); });
}); });

21
tests/Ply.tests.js

@ -29,7 +29,7 @@
layer = new Ply(); layer = new Ply();
for (var key in Ply.defaults.overlay) { for (var key in Ply.defaults.overlay) {
equal(layer.overlayEl.style[key], Ply.defaults.overlay[key], key); equal(layer.overlayBoxEl.style[key], Ply.defaults.overlay[key], key);
} }
equal(layer.bodyEl, document.body, 'body'); equal(layer.bodyEl, document.body, 'body');
@ -39,17 +39,17 @@
// Overlay 1 // Overlay 1
layer = new Ply({ overlay: { opacity: 1 } }); layer = new Ply({ overlay: { opacity: 1 } });
equal(layer.overlayEl.style.opacity, 1, 'opacity: 1'); equal(layer.overlayBoxEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayEl.style.backgroundColor, "", 'backgroundColor: ""'); equal(layer.overlayBoxEl.style.backgroundColor, "", 'backgroundColor: ""');
// Overlay 2 // Overlay 2
layer = new Ply({ overlay: { opacity: 1, backgroundColor: 'rgb(255, 0, 0)' } }); layer = new Ply({ overlay: { opacity: 1, backgroundColor: 'rgb(255, 0, 0)' } });
equal(layer.overlayEl.style.opacity, 1, 'opacity: 1'); equal(layer.overlayBoxEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayEl.style.backgroundColor, 'rgb(255, 0, 0)', 'backgroundColor: red'); equal(layer.overlayBoxEl.style.backgroundColor, 'rgb(255, 0, 0)', 'backgroundColor: red');
// Overlay 3 // Overlay 3
layer = new Ply({ overlay: null }); layer = new Ply({ overlay: null });
notEqual(layer.overlayEl.style.position, 'fixed', 'overlay: null'); notEqual(layer.overlayBoxEl.style.position, 'fixed', 'overlay: null');
// Layer // Layer
layer = new Ply({ layer: { textAlign: 'center' } }); layer = new Ply({ layer: { textAlign: 'center' } });
@ -75,7 +75,10 @@
var content = document.createElement('b'); var content = document.createElement('b');
content.innerHTML = '<b>!</b>'; content.innerHTML = '<b>!</b>';
equal(new Ply({ }).contentEl.innerHTML, '', 'conentEl'); equal(new Ply('').contentEl.innerHTML, '', 'conentEl');
equal(new Ply('Wow!').contentEl.innerHTML, 'Wow!', 'contentEl');
equal(new Ply(content).contentEl.innerHTML, '<b>!</b>');
equal(new Ply({ el: 'Wow!' }).contentEl.innerHTML, 'Wow!', 'contentEl'); equal(new Ply({ el: 'Wow!' }).contentEl.innerHTML, 'Wow!', 'contentEl');
equal(new Ply({ el: content }).contentEl.innerHTML, '<b>!</b>'); equal(new Ply({ el: content }).contentEl.innerHTML, '<b>!</b>');
}); });
@ -223,11 +226,11 @@
simulateEvent(layer.contentEl.getElementsByTagName('em')[1], 'click'); simulateEvent(layer.contentEl.getElementsByTagName('em')[1], 'click');
equal(log.join('\n'), [ equal(log.join('\n'), [
'layer:DIV.click->layer', 'layer:DIV.click->:layer',
'foo:I.click->foo', 'foo:I.click->foo',
'bar:B.click->bar', 'bar:B.click->bar',
'bar:B.click->bar', 'bar:B.click->bar',
'layer:DIV.click->layer' 'layer:DIV.click->:layer'
].join('\n')); ].join('\n'));
return layer.close(); return layer.close();

Loading…
Cancel
Save