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

19
tests/Ply.stack.tests.js

@ -2,12 +2,19 @@
module('Ply.stack');
asyncTest('2x', function () {
new Ply({ el: '1', effect: 'fade' }).open().then(function () {
new Ply({ el: '2', effect: 'fade' }).open().then(function () {
// Ply.stack.last.close();
// Ply.stack.last.close().then(function () {
// start();
// });
new Ply('foo', { effect: 'slide' }).open().then(function (foo) {
new Ply('bar', { effect: 'fall' }).open().then(function (bar) {
ok(!foo.layerEl.parentNode, 'foo.parent == null');
ok(!bar.overlayBoxEl.parentNode, 'bar.parent == null');
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();
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');
@ -39,17 +39,17 @@
// Overlay 1
layer = new Ply({ overlay: { opacity: 1 } });
equal(layer.overlayEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayEl.style.backgroundColor, "", 'backgroundColor: ""');
equal(layer.overlayBoxEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayBoxEl.style.backgroundColor, "", 'backgroundColor: ""');
// Overlay 2
layer = new Ply({ overlay: { opacity: 1, backgroundColor: 'rgb(255, 0, 0)' } });
equal(layer.overlayEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayEl.style.backgroundColor, 'rgb(255, 0, 0)', 'backgroundColor: red');
equal(layer.overlayBoxEl.style.opacity, 1, 'opacity: 1');
equal(layer.overlayBoxEl.style.backgroundColor, 'rgb(255, 0, 0)', 'backgroundColor: red');
// Overlay 3
layer = new Ply({ overlay: null });
notEqual(layer.overlayEl.style.position, 'fixed', 'overlay: null');
notEqual(layer.overlayBoxEl.style.position, 'fixed', 'overlay: null');
// Layer
layer = new Ply({ layer: { textAlign: 'center' } });
@ -75,7 +75,10 @@
var content = document.createElement('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: content }).contentEl.innerHTML, '<b>!</b>');
});
@ -223,11 +226,11 @@
simulateEvent(layer.contentEl.getElementsByTagName('em')[1], 'click');
equal(log.join('\n'), [
'layer:DIV.click->layer',
'layer:DIV.click->:layer',
'foo:I.click->foo',
'bar:B.click->bar',
'bar:B.click->bar',
'layer:DIV.click->layer'
'layer:DIV.click->:layer'
].join('\n'));
return layer.close();

Loading…
Cancel
Save