diff --git a/assets/ActionCollection/ActionCollection.js b/assets/ActionCollection/ActionCollection.js index 1a007f4..45fdbd0 100644 --- a/assets/ActionCollection/ActionCollection.js +++ b/assets/ActionCollection/ActionCollection.js @@ -2,26 +2,30 @@ kit.PluginManager.register('ActionCollection', function(module, exports, require, global) { var Collection = require('Collection'); + var support = require('support'); /** + * @class ActionCollection + * @extends {kit.Collection} * @memberOf kit */ var ActionCollection = function (list = []) { - this.collection = new Collection(list); + Collection.prototype.constructor.apply(this, arguments); }; - ActionCollection.prototype.push = function (action) { - this.collection.push(action); - }; - ActionCollection.prototype.run = function (count = -1) { - this.collection.map(function (action) { + var proto = ActionCollection.prototype; + + proto.run = function (count = -1) { + this.map(function (action) { action.run(count); }) }; - ActionCollection.prototype.stop = function () { - this.collection.map(function (action) { + proto.stop = function () { + this.map(function (action) { action.stop(); }) }; + support.extend(ActionCollection.prototype, Collection.prototype); + return module.exports = ActionCollection; }); \ No newline at end of file diff --git a/assets/Viewer/Viewer.js b/assets/Viewer/Viewer.js index 6c5ff89..63e5a3f 100644 --- a/assets/Viewer/Viewer.js +++ b/assets/Viewer/Viewer.js @@ -10,12 +10,13 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) var AnimationTrap = function (node, callbackBefore = function(){}, callbackAfter = function(){}) { this.node = support.getNode(node); - this.active = 0; + this.active = false; this.__timeoutId = 0; + this.__callbackOptions = {}; this.callbackBefore = callbackBefore; this.callbackAfter = callbackAfter; this.__callbackAfterHandler = function () { - this.callbackAfter(); + this.callbackAfter(this.__callbackOptions); this.stop(); }.bind(this); this.__animationstart = false; @@ -28,30 +29,43 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) new Action(this.node, 'animationcancel', this.__callbackAfterHandler) ]); }; - AnimationTrap.prototype.run = function () { + AnimationTrap.prototype.run = function (options = {}) { - if(this.active === 1){ + if(this.active){ return; } - this.active = 1; + this.__callbackOptions = Object.assign({ + useAnim: true + }, options); + + + if(!this.__callbackOptions.useAnim){ + this.callbackBefore(this.__callbackOptions); + this.callbackAfter(this.__callbackOptions); + this.stop(); + return; + } + + this.active = true; this.__animationStartAction.run(1); - this.callbackBefore(); + this.callbackBefore(this.__callbackOptions); this.__animationEndAction.run(1); this.__timeoutId = setTimeout(function () { if(!this.__animationstart) { - this.__callbackAfterHandler(); + this.__callbackAfterHandler(this.__callbackOptions); } }.bind(this), 100); }; AnimationTrap.prototype.stop = function () { clearTimeout(this.__timeoutId); this.__timeoutId = 0; + this.__callbackOptions = {}; this.__animationstart = false; this.__animationStartAction.stop(); this.__animationEndAction.stop(); - this.active = 0; + this.active = false; }; @@ -76,26 +90,36 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) this.node = support.getNode(node); this.masterNode = support.getNode(masterNode); this.onShow = new Collection(); + this.onShowBefore = new Collection(); this.onHide = new Collection(); + this.onHideBefore = new Collection(); this.animShowClass = ''; this.animHideClass = ''; this.delayHide = 0; this.activeMasterClass = 'active'; - this.__aminationTrapHide = new AnimationTrap(this.node, function () { + this.__aminationTrapHide = new AnimationTrap(this.node, function (options) { + if(options.onHideBefore !== false) { + this.onHideBefore.eachCall(); + } removeAnimation.call(this, this.animShowClass); addAnimation.call(this, this.animHideClass); - }.bind(this), function () { + }.bind(this), function (options) { if(this.masterNode && this.activeMasterClass) { this.masterNode.classList.remove(this.activeMasterClass); } this.node.classList.add('hide'); this.node.classList.remove('show'); - this.onHide.eachCall(); + if(options.onHide !== false) { + this.onHide.eachCall(); + } this.node.style.display = 'none'; }.bind(this)); - this.__aminationTrapShow = new AnimationTrap(this.node, function () { + this.__aminationTrapShow = new AnimationTrap(this.node, function (options = {}) { + if(options.onShowBefore !== false) { + this.onShowBefore.eachCall(); + } this.node.classList.remove('hide'); this.node.classList.add('show'); if(this.node.style.display === 'none') { @@ -104,10 +128,13 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) if(this.masterNode && this.activeMasterClass) { this.masterNode.classList.add(this.activeMasterClass); } + removeAnimation.call(this, this.animHideClass); addAnimation.call(this, this.animShowClass); - this.onShow.eachCall(); - }.bind(this), function () { + if(options.onShow !== false) { + this.onShow.eachCall(); + } + }.bind(this), function (options = {}) { }.bind(this)); @@ -121,30 +148,42 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) }; var proto = Viewer.prototype; - proto.show = function(){ + proto.show = function(options = {}){ + if(this.isShown()) { return; } - deferredHideCancel.call(this); - this.__aminationTrapHide.stop(); - this.__aminationTrapShow.run(); + + options.useAnim = !!this.animHideClass; + + this.stop(); + + this.__aminationTrapShow.run(options); }; - proto.hide = function(){ + + proto.hide = function(options = {}){ if(this.isHidden()) { return; } + options.useAnim = !!this.animHideClass; + + this.__aminationTrapShow.stop(); + var hideDeferred = function () { deferredHideCancel.call(this); - this.__deferredHideID = setTimeout(hide.bind(this), this.delayHide); + if(this.delayHide) { + this.__deferredHideID = setTimeout(hide.bind(this), this.delayHide); + return; + } + hide(); }.bind(this); - var hide = function() { deferredHideCancel.call(this); - this.__aminationTrapShow.stop(); - this.__aminationTrapHide.run(); + this.__aminationTrapHide.run(options); }.bind(this); + hideDeferred(); }; proto.toggle = function(){ @@ -156,15 +195,22 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global) return false; }; proto.isShown = function(){ - return !this.isHidden() && !this.__aminationTrapHide.active; + return !this.isHidden(); }; proto.isHidden = function(){ var result = this.node.classList.contains('hide'); + result = result || getComputedStyle(this.node).display === 'none'; if(this.masterNode && this.activeMasterClass) { result = result || !this.masterNode.classList.contains(this.activeMasterClass); } - return result || this.__aminationTrapHide.active; + return result || this.__aminationTrapHide.active || this.__deferredHideID; + }; + proto.stop = function () { + this.__aminationTrapHide.stop(); + this.__aminationTrapShow.stop(); + deferredHideCancel.call(this); + // removeAnimation.call(this, this.animHideClass); + // removeAnimation.call(this, this.animShowClass); }; - return module.exports = Viewer; }); diff --git a/assets/align/align.js b/assets/align/align.js index 9156b5f..c03abe2 100644 --- a/assets/align/align.js +++ b/assets/align/align.js @@ -457,6 +457,11 @@ kit.PluginManager.register('align',function(module, exports, require) { }; + /** + * + * @param node + * @return {AlignClass} + */ AlignClass.prototype.setNode = function(node){ this.unset(); this.node = support.getNode(node); @@ -471,6 +476,10 @@ kit.PluginManager.register('align',function(module, exports, require) { return this; }; + /** + * @param node + * @return {AlignClass} + */ AlignClass.prototype.setParentNode = function(node){ this.parentNode = support.getNode(node); if(this.__calc) { @@ -478,6 +487,7 @@ kit.PluginManager.register('align',function(module, exports, require) { } return this; }; + AlignClass.prototype.setLimiterNode = function(node){ this.limiterNode = support.getNode(node) || window; if(this.__calc) { @@ -520,18 +530,27 @@ kit.PluginManager.register('align',function(module, exports, require) { return this; }; + /** + * + * @param hAlign + * @param vAlign + * @param hDirection + * @param vDirection + * @return {AlignClass} + */ AlignClass.prototype.set = function(hAlign, vAlign, hDirection, vDirection){ - this.setEx('vertical', vDirection, vAlign); - this.setEx('horizontal', hDirection, hAlign); - return this; - }; - AlignClass.prototype.setVertical = function(direction, align){ - this.setEx('vertical', direction, align); + this.setEx('vertical', vAlign, vDirection); + this.setEx('horizontal', hAlign, hDirection); return this; }; - AlignClass.prototype.setHorizontal = function(direction, align){ - this.setEx('horizontal', direction, align); + AlignClass.prototype.setVertical = function(align, direction){ + this.setEx('vertical', align, direction); + return this; + }; + + AlignClass.prototype.setHorizontal = function(align, direction){ + this.setEx('horizontal', align, direction); return this; }; @@ -544,7 +563,7 @@ kit.PluginManager.register('align',function(module, exports, require) { } }; - AlignClass.prototype.setEx = function(axis, direction, align){ + AlignClass.prototype.setEx = function(axis, align, direction){ this.reset(axis === 'horizontal', axis === 'vertical'); diff --git a/assets/collection/collection.js b/assets/collection/collection.js index c476637..4fc35d3 100644 --- a/assets/collection/collection.js +++ b/assets/collection/collection.js @@ -91,13 +91,16 @@ kit.PluginManager.register('Collection', function(module, exports, require, glob return ob; }; Collection.prototype.serialize = function () { - return JSON.stringify(this.all()); + return JSON.stringify(this.toObject()); + }; + Collection.prototype.serializeArray = function () { + return JSON.stringify(this.toArray()); }; Collection.prototype.has = function (key) { - return this.data.hasOwnProperty(key) && this.__keys.includes(safeArrayKey(key)); + return this.__keys.includes(safeArrayKey(key)); }; Collection.prototype.indexKey = function (key) { - return this.__keys.indexOf(key); + return this.__keys.indexOf(safeArrayKey(key)); }; /** * @param key @@ -157,17 +160,13 @@ kit.PluginManager.register('Collection', function(module, exports, require, glob * @return {kit.Collection} */ Collection.prototype.each = function (callback = true) { - var BreakException = {}, i; - try { - if(this.__keys.length) - for (i = 0; i < this.__keys.length; i++) { - if(valueEx(callback, this.__values[i], this.__keys[i], this.data) === false) { - throw BreakException; - } + var i; + if(this.__keys.length) + for (i = 0; i < this.__keys.length; i++) { + if(valueEx(callback, this.__values[i], this.__keys[i], this.data) === false) { + break; } - } catch (e) { - if (e !== BreakException) throw e; - } + } return this; }; /** @@ -175,17 +174,13 @@ kit.PluginManager.register('Collection', function(module, exports, require, glob * @return {kit.Collection} */ Collection.prototype.eachReverse = function (callback = true) { - var BreakException = {}, i; - try { - if(this.__keys.length) - for (i = this.__keys.length - 1; i >= 0; i--) { - if(valueEx(callback, this.__values[i], this.__keys[i], this.data) === false) { - throw BreakException; - } + var i; + if(this.__keys.length) + for (i = this.__keys.length - 1; i >= 0; i--) { + if(valueEx(callback, this.__values[i], this.__keys[i], this.data) === false) { + break; } - } catch (e) { - if (e !== BreakException) throw e; - } + } return this; }; /** @@ -328,7 +323,7 @@ kit.PluginManager.register('Collection', function(module, exports, require, glob * Method removes and returns the last item from the collection */ Collection.prototype.pop = function(){ - var index = this.length - 1; + var index = this.__keys.length - 1; if(index < 0) { return undefined; } @@ -381,23 +376,19 @@ kit.PluginManager.register('Collection', function(module, exports, require, glob * @return {kit.Collection} */ Collection.prototype.eachCall = function (context, args1, args2) { - var args = []; + var args = [], i; if(arguments.length > 1) - for(var i = 1; arguments.length - 1 >= i;i++) { + for(i = 1; arguments.length - 1 >= i;i++) { args.push(arguments[i]); } - var BreakException = {}, i; - try { - if(this.__keys.length) - for (i = 0; i < this.__keys.length; i++) { - if(typeof this.__values[i] === 'function' && - this.__values[i].apply(context, [].concat(args, this.__keys[i])) === false) { - throw BreakException; - } + + if(this.__keys.length) + for (i = 0; i < this.__keys.length; i++) { + if(typeof this.__values[i] === 'function' && + this.__values[i].apply(context, [].concat(args, this.__keys[i])) === false) { + throw BreakException; } - } catch (e) { - if (e !== BreakException) throw e; - } + } return this; }; diff --git a/assets/config/config.js b/assets/config/config.js index e807179..e6c4b34 100644 --- a/assets/config/config.js +++ b/assets/config/config.js @@ -8,8 +8,12 @@ window.kit = window.kit || {}; */ kit.config = kit.config || {}; +// [PluginManager] + kit.config.assetsPath = '/local/templater.dev/kit/assets'; kit.config.requiredDependencies = ['bsCore', 'toolkit', 'support']; kit.config.autoloadPluginList = ['tooltip', 'support']; kit.config.debug = true; -kit.config.defaultPhoneMask = '+7 (999) 999-99-99'; \ No newline at end of file +kit.config.defaultPhoneMask = '+7 (999) 999-99-99'; + +// [OtherPlugins] \ No newline at end of file diff --git a/assets/menu/menu.css b/assets/menu/menu.css index 81f3927..df555e9 100644 --- a/assets/menu/menu.css +++ b/assets/menu/menu.css @@ -29,12 +29,20 @@ border-right: var(--kit-menu-border-width) solid var(--kit-color-primary, #3c9cdd); box-shadow: 0 0 10px 0 #00000033, inset -5px 0 5px -5px var(--kit-color-primary-b2, #2283c3); } -.kit-menu.active { +.kit-menu.active, .kit-menu.show { display: block; z-index: 1000; } - +.kit-text-debug { + position: absolute; + background-color: #363636; + pointer-events: none; + color: #dddddd; + font-size: 12px; + font-family: monospace; + line-height: 1.1em; +} diff --git a/assets/menu/menu.js b/assets/menu/menu.js index 52114d1..2973e24 100644 --- a/assets/menu/menu.js +++ b/assets/menu/menu.js @@ -1,11 +1,11 @@ /** @module menu */ //todo: instance, options, auto-options-by-node -__PluginManager__.register('menu',function(module, exports, require) { +__PluginManager__.register('menu',function(module, exports, require, global) { - var userAction = require('userAction'); var Collection = require('Collection'); var Action = require('Action'); + var userAction = require('userAction'); var ActionCollection = require('ActionCollection'); var support = require('support'); var Viewer = require('Viewer'); @@ -13,14 +13,18 @@ __PluginManager__.register('menu',function(module, exports, require) { var libModule = require('lib'); var dataStructures = require('dataStructures'); + + const MENU_PLUGIN_NAME = 'menu'; + const MENU_ITEM_PLUGIN_NAME = 'menuItem'; + const MENU_CLASS = 'kit-menu'; + const MENU_ITEM_CLASS = 'kit-menu-item'; + /** * @class kitMenuClassDefaultOptions */ var defaultMenuOptions = { parent: null, - nodeProperty: 'menu', - class: 'kit-menu', - eventType: 'hover', + eventType: 'hint', animation: '', hideDelay: 200, alignOffset: [0, 0], @@ -42,762 +46,593 @@ __PluginManager__.register('menu',function(module, exports, require) { var MenuList = []; var MenuListIncrement = 0; - var MenuClass = (function () { + /** + * @typedef kitMenuItemHandler + * @param event {MouseEvent} + * @param menuItem {MenuItem} + * @param menu {Menu} + */ + + + /** + * @class kit.menu.Class + * @param options + * @param items + */ + var Menu = function(options = {}, items = []) + { + this.id = ++MenuListIncrement; + MenuList[this.id] = this; + + this.itemList = {}; + this.node = null; + this.bInit = false; + this.bActive = false; + this.options = defaultMenuOptions; + this.createNode(); //с пула нужна базовая нода + this.setOptions(options); + this.addItemList(items); + }; + + Menu.prototype.getItemById = function(itemId) { + if(this.itemList.hasOwnProperty(itemId)) { + return this.itemList[itemId]; + } + return false; + }; + /** + * хуета + * @return {null} + */ + Menu.prototype.getNode = function () { + return this.node; + }; + Menu.prototype.getParent = function () { + return this.options.parent; + }; + Menu.prototype.createNode = function () { + this.node = document.createElement('div'); + this.node.classList.add(MENU_CLASS); + this.node.style.display = 'none'; + this.node.setAttribute('data-menu-id', this.id); + this.node.kit = this.node.kit || {}; + this.node.kit[MENU_PLUGIN_NAME] = this; + }; + + + Menu.prototype.hide = function () { + if(this.viewer) { + this.viewer.hide(); + } + return this; + }; + Menu.prototype.show = function () { + if(this.viewer) { + this.viewer.show(); + } + return this; + }; + + Menu.prototype.setPosition = function () { + // console.log('setPosition ' + this.id); + if(!(this.getParent() instanceof Element)) { + console.warn('Menu.options.parent NOT instanceof Element'); + return false; + } + + this.node.style.position = 'absolute'; + this.node.style.width = 'fit-content'; + + //var parentNode = this.getParentMenuNode() || this.getParent(); + var parentNode = this.getParent(); + + var hAlign = 'right'; + var hDirection = 'right'; + var parentMenu = this.getParentMenu(); + if(parentMenu && parentMenu instanceof Menu) { + hDirection = parentMenu.align.condition.horizontal.direction; + hAlign = parentMenu.align.condition.horizontal.align; + } + + this.align.offset = this.options.alignOffset; + this.align + .setNode(this.node) + .setParentNode(parentNode) + .set(hAlign, 'top', hDirection, 'bottom'); + }; + + Menu.prototype.setPositionRecursive = function(){ + var list = getChainActiveMenuDataList(this.id); + list.forEach(function (data) { + data.menu.setPosition(); + }) + }; + + /** + * под сомнением + * рассмотреть под призмой нескольких меню для родительской ноды + * @return {Menu} | null + */ + Menu.prototype.getParentMenu = function() { + var p = this.getParent(); + if(p instanceof Element && p.hasOwnProperty('kit') && p.kit[MENU_ITEM_PLUGIN_NAME] instanceof MenuItemClass) { + return p.kit[MENU_ITEM_PLUGIN_NAME].getMenu(); + } + }; + Menu.prototype.getParentMenuNode = function() { + var parentMenu = this.getParentMenu(), + parentMenuNode; + if(parentMenu) { + parentMenuNode = parentMenu.node; + } + return parentMenuNode; + }; + + /** + * + * @param options {kitMenuItemOptions} + * @return {MenuItem} + */ + Menu.prototype.addItem = function (options = {}) { + var id; + if(options instanceof MenuItemClass) { + options.parentId = this.id; + id = options.options.id; + this.itemList[id] = options; + } else if(options instanceof Object){ + if(!options.id) { + options.id = support.uniqueId(8); + } + id = options.id; + this.itemList[id] = (new this.MenuItem(this.id)).setOptions(options).init(); + } + return this.itemList[id]; + }; + Menu.prototype.addItemList = function(itemList = []){ + itemList.forEach((function(element, index, array){ + this.addItem(element); + }).bind(this)); + return this; + }; + Menu.prototype.sortItems = function() { + this.itemList = Object.entries(this.itemList) + .sort(function(a, b){ + return a[1].options.sort >>> 0 - b[1].options.sort >>> 0; + }) + .reduce((r, [k, v]) => ({ ...r, [k]: v }), {}); + }; + Menu.prototype.render = function() { + //console.log('Menu: render'); + this.sortItems(); + this.node.innerHTML = ''; + if(global.config.debug) { + this.node.innerHTML = '
'+this.id+'
'; + } + for (var i in this.itemList) { + if(this.itemList.hasOwnProperty(i)) { + this.node.append(this.itemList[i].getNode()); + } + } + return this; + }; + + /** + * @param parentNode + * @return {boolean} + */ + Menu.prototype.setParent = function(parentNode) { + // console.log('Menu: setParent ' + parentNode); + parentNode = support.getNode(parentNode); + + if(!(parentNode instanceof Element)) { + //console.warn('Menu.setParent: Не удалось получить parent. ' + parentNode); + return false; + } + if(this.viewer instanceof Viewer) { + this.bActive = this.viewer.isShown(); + this.viewer.stop(); + } + + this.options.parent = parentNode; + + if(this.bInit) { + this.init(true); + } + }; + Menu.prototype.setEventType = function(type = 'hint') { + this.options.eventType = type; + if(this.bInit) { + this.init(); + } + }; + + Menu.prototype.init = function (setPositionRecursive = false) { + var self = this; + + if(!(this.options.parent instanceof Element)) { + console.warn('Menu.init: Не установлен parent'); + return false; + } + + this.render(); + if(this.node.parentElement !== this.options.parent) { + this.node.remove(); + this.options.parent.prepend(this.node); + } + + if(this.align instanceof align.Class) { + this.align.unset(); + } + this.align = new align.Class(this.node, this.options.parent); + + + if(this.actions instanceof ActionCollection) { + this.actions.stop(); + } + + var ua = new userAction[support.str.ucFirst(this.options.eventType)](this.options.parent, this.node); + if(ua.viewer instanceof Viewer) { + this.viewer = ua.viewer; + ua.viewer.onHideBefore.push(function () { + var list = getChainActiveMenuDataList(self.id); + list.shift(); + list.reverse().forEach(function (data) { + if(data.menu.viewer) { + data.menu.viewer.hide({onHideBefore: false}); + } + }); + }); + ua.viewer.onHide.push(function () { + self.bActive = self.viewer.isShown(); + }); + ua.viewer.onShow.push(function () { + self.setPosition.call(self); + self.bActive = self.viewer.isShown(); + }); + } + this.actions = new ActionCollection([ua]); + this.actions.run(); + + if(this.bActive) { + if(setPositionRecursive) { + this.setPositionRecursive(); + } else { + this.setPosition(); + } + this.show(); + } else { + this.hide(); + } + + this.node.setAttribute('data-kit-menu-init', 1); + this.bInit = true; + }; + + + + /** + * @param options {kitMenuClassDefaultOptions} + * @return {Menu} + */ + Menu.prototype.setOptions = function (options = {}) { + this.options = Object.assign({}, this.options, options); + this.setParent(this.options.parent); + return this; + }; + + var MenuItemClass = function () { + + function MenuItem(parentId) { + var _thisMenuItem = this; + this.parentId = Number(parentId); + this.node = Element; + this.bInit = false; + this.bActive = false; + this.child = null; + + /** + * @class kitMenuItemOptions + */ + this.options = { + id: '', + icon: libModule.svg.options, + arrow: libModule.svg.arrowMenu, + label: 'menu', + href: 'javascript:void(0);', + class: '', + sort: 500, + visible: true, + /** @type {kitMenuItemHandler} */ + hover: this.defaultHoverHandler, + /** @type {kitMenuItemHandler} */ + click: this.defaultClickHandler, + dblclick: this.defaultDblClickHandler, + }; + + this.handleEvent = function(event) { + event.stopPropagation(); + switch(event.type) { + case 'mouseover': + this.options.hover(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); + break; + case 'click': + this.options.click(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); + break; + case 'dblclick': + this.options.dblclick(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); + break; + } + }; + this.createNode(); + } + /** - * @typedef kitMenuItemHandler * @param event {MouseEvent} * @param menuItem {MenuItem} * @param menu {Menu} */ + MenuItem.prototype.defaultHoverHandler = function (event, menuItem, menu) { + console.log('hover: ' + menuItem.options.label); + }; + /** + * @param event {MouseEvent} + * @param menuItem {MenuItem} + * @param menu {Menu} + */ + MenuItem.prototype.defaultClickHandler = function (event, menuItem, menu) { + console.log('click: ' + menuItem.options.label); + menu.hide(); + }; + /** + * @param event {MouseEvent} + * @param menuItem {MenuItem} + * @param menu {Menu} + */ + MenuItem.prototype.defaultDblClickHandler = function (event, menuItem, menu) { + console.log('dblclick: ' + menuItem.options.label); + }; + MenuItem.prototype.getMenu = function () { + return MenuList[this.parentId]; + }; + + MenuItem.prototype.getParent = function () { + if(MenuList[this.parentId] instanceof Menu) { + return MenuList[this.parentId].node; + } + return null; + }; + + MenuItem.prototype.getId = function () { + return this.options.id; + }; /** - * @param options - * @param items - * @constructor + * @returns HTMLElement */ - function Menu(options = {}, items = []) - { - //console.log('Menu: constructor'); - var _this = this; - this.parentActionHandler = this.parentAction.bind(this); - this.documentListenerHandler = this.documentListener.bind(this); - this.nodeActionHandler = this.nodeAction.bind(this); - - this.id = ++MenuListIncrement; - MenuList[this.id] = this; - - this.itemList = {}; - this.align = new align.Class(); - this.node = null; - this.bInit = false; - this.deferredHideID = 0; - this.bActive = false; - this.options = defaultMenuOptions; - this.createNode(); //с пула нужна базовая нода - this.setOptions(options); - this.addItemList(items); - this.handleEvent = function(event) { - // console.log('Menu handleEvent'); - // console.log(event.type); - switch(event.type) { - case 'click': - this.options.click(event, _this); - break; - case 'mouseover': - this.options.hover(event, _this); - break; - } - }; - } - Menu.prototype.getItemById = function(itemId) { - if(this.itemList.hasOwnProperty(itemId)) { - return this.itemList[itemId]; - } - return false; - }; - Menu.prototype.getNode = function () { - if(this.node.innerHTML === '') { - this.render(); - } + MenuItem.prototype.getNode = function () { return this.node; }; - Menu.prototype.getParent = function () { - return this.options.parent; - }; - Menu.prototype.createNode = function () { - this.node = document.createElement('div'); - this.node.classList.add(this.options.class); - this.node.style.display = 'none'; - this.node.setAttribute('data-menu-id', this.id); + + MenuItem.prototype.createNode = function () { + this.node = document.createElement('a'); + this.node.style.position = 'relative'; + this.node.dataset.parentId = this.parentId; this.node.kit = this.node.kit || {}; - this.node.kit[this.options.nodeProperty] = this; - }; - Menu.prototype.showNode = function () { - // console.log('Menu: showNode ' + this.id, this.bActive); - this.deferredHideCancel(); - if(!this.bActive) { - this.node.style.display = ''; - this.node.classList.add('active'); - this.options.parent.classList.add('active'); - this.calcStyle(); - this.bActive = true; - this.addDocumentEventListener(); - } - this.addAnimation(); - }; - - Menu.prototype.hide = function () { - getChainActiveMenuDataList(this.id).reverse().forEach(function (data) { - data.menu.hideNodeNow(); - }); - return this; - }; - Menu.prototype.hideNode = function () { - this.hideNodeNow(); - }; - Menu.prototype.hideNodeDeferred = function () { - this.deferredHideCancel(); - this.deferredHideID = setTimeout(this.hideNodeNow.bind(this), this.options.hideDelay); - }; - Menu.prototype.deferredHideCancel = function () { - if(this.deferredHideID) { - clearTimeout(this.deferredHideID); - this.deferredHideID = 0; - } - return this; - }; - Menu.prototype.hideNodeNow = function () { - // console.log('Menu: hideNodeNow'); - this.deferredHideCancel(); - this.node.style.display = 'none'; - this.removeAnimation(); - this.node.classList.remove('active'); - this.options.parent.classList.remove('active'); - this.bActive = false; - this.removeDocumentEventListener(); - return this; - }; - - Menu.prototype.removeAnimation = function(){ - if(this.options.animation && this.node && this.node.classList.contains(this.options.animation)){ - this.node.classList.remove(this.options.animation); - } - }; - Menu.prototype.addAnimation = function(){ - if(this.options.animation && this.node && !this.node.classList.contains(this.options.animation)){ - this.node.classList.add(this.options.animation); - } - }; - - Menu.prototype.calcStyle = function () { - // console.log('calcStyle ' + this.id); - if(!(this.options.parent instanceof Element)) { - console.warn('Menu.options.parent NOT instanceof Element'); - return false; - } - - this.node.style.position = 'absolute'; - this.node.style.width = 'fit-content'; - - //var parentNode = this.getParentMenuNode() || this.getParent(); - var parentNode = this.getParent(); - - var hDirection = 'right'; - var parentMenu = this.getParentMenu(); - if(parentMenu && parentMenu instanceof Menu) { - hDirection = parentMenu.align.condition.horizontal.direction; - } - var hAlign = 'right'; - if(parentMenu && parentMenu instanceof Menu) { - hAlign = parentMenu.align.condition.horizontal.align; - } - - this.align.offset = this.options.alignOffset; - this.align - .setNode(this.node) - .setParentNode(parentNode) - .setHorizontal(hDirection, hAlign) - .setVertical('bottom', 'top'); - - }; - - Menu.prototype.calcStyleChain = function(){ - getChainActiveMenuDataList(this.id).forEach(function (data) { - data.menu.calcStyle(); - }) + this.node.kit.menuItem = this; }; /** - * @return {Menu} | null + * @param content HTMLElement | string + * @returns {MenuItem} */ - Menu.prototype.getParentMenu = function() { - var p = this.getParent(); - if(p instanceof Element && p.hasOwnProperty('kit') && p.kit.menuItem instanceof MenuItemClass) { - return p.kit.menuItem.getMenu(); - } - }; - Menu.prototype.getParentMenuNode = function() { - var parentMenu = this.getParentMenu(), - parentMenuNode; - if(parentMenu) { - parentMenuNode = parentMenu.getNode(); - } - return parentMenuNode; + MenuItem.prototype.setLabel = function (content = '') { + this.options.label = content; + var wrap = this.getNodeScopeElementByClassName('kit-menu-item__label'); + this.setContent(wrap, content); + return this; }; /** - * - * @param options {kitMenuItemOptions} - * @param returnItem - * @return {Menu} + * @param href + * @returns {MenuItem} */ - Menu.prototype.addItem = function (options = {}, returnItem = false) { - var listIndex; - if(options instanceof MenuItemClass) { - options.parentId = this.id; - listIndex = options.options.id; - this.itemList[listIndex] = options; - } else if(options instanceof Object){ - if(!options.id) { - options.id = this.uniqueId(8); - } - listIndex = options.id; - this.itemList[listIndex] = (new this.MenuItem(this.id)).setOptions(options).init(); - } - if(returnItem) { - return this.itemList[listIndex]; - } + MenuItem.prototype.setHref = function (href = 'javascript:void(0);') { + this.options.href = href; + this.getNode().setAttribute('href', href); return this; }; - Menu.prototype.addItemList = function(itemList = []){ - itemList.forEach((function(element, index, array){ - this.addItem(element); - }).bind(this)); - return this; - }; - Menu.prototype.sortItems = function() { - this.itemList = Object.entries(this.itemList) - .sort(function(a, b){ - return a[1].options.sort - b[1].options.sort; - }) - .reduce((r, [k, v]) => ({ ...r, [k]: v }), {}); - }; - Menu.prototype.render = function() { - //console.log('Menu: render'); - this.sortItems(); - this.node.innerHTML = ''; - for (var i in this.itemList) { - if(this.itemList.hasOwnProperty(i)) { - this.node.append(this.itemList[i].getNode()); - } - } - return this; - }; - Menu.prototype.uniqueId = function (idStrLen = 32) { - var idStr = ''; - idStrLen && (idStr = (Math.floor((Math.random() * 25)) + 10).toString(36)); - do { - idStr += (Math.floor((Math.random() * 35))).toString(36); - } while (idStr.length < idStrLen); - return (idStr); - }; - Menu.prototype.setParent = function(parentNode) { - // console.log('Menu: setParent ' + parentNode); - - if(typeof parentNode === 'string') { - parentNode = document.querySelector(parentNode); - } - - if(!(parentNode instanceof Element)) { - //console.warn('Menu.setParent: Не удалось получить parent. ' + parentNode); - return false; - } - - this.removeParentEventListener(); - - this.options.parent = parentNode; - - if(this.bInit) { - this.reInit(true); - } - }; - Menu.prototype.setEventType = function(type = 'hover') { - - this.options.eventType = type; - - if(this.bInit) { - this.reInit(); - } - }; - Menu.prototype.addDocumentEventListener = function() { - document.addEventListener('click', this.documentListenerHandler, false); - }; - Menu.prototype.removeDocumentEventListener = function() { - document.removeEventListener('click', this.documentListenerHandler, false); - }; - Menu.prototype.removeParentEventListener = function() { - // console.log('Menu: removeParentEventListener'); - if(this.options.parent instanceof Element) { - this.options.parent.classList.remove('active'); - this.options.parent.removeEventListener('click', this.parentActionHandler, false); - this.options.parent.removeEventListener('mouseover', this.parentActionHandler, false); - this.options.parent.removeEventListener('mouseout', this.parentActionHandler, false); - } - }; - Menu.prototype.addParentEventListener = function() { - if(this.options.parent instanceof Element) { - if(this.options.eventType === 'hover') { - this.options.parent.addEventListener('mouseover', this.parentActionHandler, false); - this.options.parent.addEventListener('mouseout', this.parentActionHandler, false); - } - if(this.options.eventType === 'click') { - this.options.parent.addEventListener(this.options.eventType, this.parentActionHandler, false); - } - } - }; - Menu.prototype.addNodeEventListener = function() { - if(!this.node) { - return; - } - - this.node.addEventListener('mouseenter', this.nodeActionHandler, false); - this.node.addEventListener('mouseleave', this.nodeActionHandler, false); - }; - Menu.prototype.removeNodeEventListener = function() { - if(!this.node) { - return; - } - - this.node.removeEventListener('mouseenter', this.nodeActionHandler, false); - this.node.removeEventListener('mouseleave', this.nodeActionHandler, false); - }; - Menu.prototype.insertToNode = function (parent) { - if(!(parent instanceof Element)) { - console.warn('Menu.insertToNode - node NOT instanceof Element'); - return false; - } - this.setParent(parent); - this.options.parent.prepend(this.getNode()); - }; - Menu.prototype.init = function () { - if(this.bInit === true) { - return; - } - if(!this.options.parent instanceof Element) { - console.warn('Menu.init: Не установлен parent'); - } - this.setParent(this.options.parent); - - this.render(); - this.options.parent.append(this.getNode()); - - this.addParentEventListener(); - this.addNodeEventListener(); - - //document.addEventListener('click', this.documentListenerHandler, false); - - this.node.setAttribute('data-kit-menu-init', 1); - this.bInit = true; - - }; - Menu.prototype.reInit = function (recursiveCalcStyle = false) { - console.warn('Menu: reInit ' + this.id); - if(this.bInit === false) { - return; - } - - this.removeNodeEventListener(); - this.removeParentEventListener(); - //this.removeDocumentEventListener(); - - //this.removeAnimation(); - - if(this.node.parentElement !== this.options.parent) { - this.removeAnimation(); - this.node.remove(); - this.options.parent.prepend(this.node); - } - - this.render(); - - if(this.bActive) { - if(recursiveCalcStyle) { - this.calcStyleChain(); - } else { - this.calcStyle(); - } - this.showNode(); - } else { - this.hideNode(); - } - - this.addNodeEventListener(); - this.addParentEventListener(); - //this.addDocumentEventListener(); - }; - - - Menu.prototype.toggle = function() { - if(this.node.classList.toggle('active')) { - this.showNode(); - } else { - this.hide(); - } - }; - Menu.prototype.parentAction = function (event) { - event.stopPropagation(); - // event.stopImmediatePropagation(); - switch (event.type) { - case 'mouseout': - if (this.needHideByParent(event.relatedTarget)) { - this.hideNodeDeferred(); - } - break; - case 'mouseover': - this.showNode(); - break; - case 'click': - this.toggle(); - break; - } - }; - Menu.prototype.nodeAction = function (event) { - event.stopPropagation(); - // event.stopImmediatePropagation(); - switch (event.type) { - case 'mouseout': - break; - case 'mouseover': - break; - case 'mouseleave': - if(this.options.eventType === 'hover') { - this.hideNodeDeferred(); - } - break; - case 'mouseenter': - this.deferredHideCancel(); - break; - } - }; - Menu.prototype.needHideByParent = function(target) { - var its_menu = target === this.node || this.node.contains(target); - var its_parent = target === this.options.parent; - var is_active_parent = this.node.classList.contains('active'); - return !its_menu && !its_parent && is_active_parent; - }; - Menu.prototype.documentListener = function(event) { - // console.log('documentListener'); - // console.log(event); - - if(this.options.eventType === 'click') { - if (this.needHideByParent(event.target)) { - this.toggle(); - } - } - }; /** - * @param options {kitMenuClassDefaultOptions} - * @return {Menu} + * @param content HTMLElement | string + * @returns {MenuItem} */ - Menu.prototype.setOptions = function (options = {}) { - this.options = Object.assign({}, this.options, options); - this.setParent(this.options.parent); + MenuItem.prototype.setIcon = function (content = '') { + this.options.icon = content; + var wrap = this.getNodeScopeElementByClassName('kit-menu-item__icon'); + this.setContent(wrap, content); return this; }; - var MenuItemClass = function () { + /** + * @param sort int + * @returns {MenuItem} + */ + MenuItem.prototype.setSort = function (sort = 500) { + this.options.sort = Number(sort); + return this; + }; - function MenuItem(parentId) { - var _thisMenuItem = this; - this.parentId = Number(parentId); - this.node = Element; - this.bInit = false; - this.bActive = false; - this.child = null; - - /** - * @class kitMenuItemOptions - */ - this.options = { - id: '', - icon: libModule.svg.options, - arrow: libModule.svg.arrowMenu, - label: 'menu', - href: 'javascript:void(0);', - class: 'kit-menu-item', - sort: 500, - visible: true, - /** @type {kitMenuItemHandler} */ - hover: this.defaultHoverHandler, - /** @type {kitMenuItemHandler} */ - click: this.defaultClickHandler, - dblclick: this.defaultDblClickHandler, - }; - - this.handleEvent = function(event) { - event.stopPropagation(); - switch(event.type) { - case 'mouseover': - this.options.hover(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); - break; - case 'click': - this.options.click(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); - break; - case 'dblclick': - this.options.dblclick(event, _thisMenuItem, MenuList[_thisMenuItem.parentId]); - break; - } - }; - this.createNode(); + /** + * @param content HTMLElement | string + * @returns {MenuItem} + */ + MenuItem.prototype.setArrow = function (content = '') { + this.options.arrow = content; + var wrap = this.getNodeScopeElementByClassName('kit-menu-item__arrow'); + this.setContent(wrap, content); + return this; + }; + MenuItem.prototype.setId = function (id = '') { + if(id) { + this.options.id = id; } + this.node.id = this.options.id; + return this; + }; + MenuItem.prototype.setVisible = function (visible = true) { + this.options.visible = visible; + this.node.style.display = this.options.visible?'':'none'; + return this; + }; - /** - * @param event {MouseEvent} - * @param menuItem {MenuItem} - * @param menu {Menu} - */ - MenuItem.prototype.defaultHoverHandler = function (event, menuItem, menu) { - console.log('hover: ' + menuItem.options.label); - }; - /** - * @param event {MouseEvent} - * @param menuItem {MenuItem} - * @param menu {Menu} - */ - MenuItem.prototype.defaultClickHandler = function (event, menuItem, menu) { - console.log('click: ' + menuItem.options.label); - menu.hide(); - }; - /** - * @param event {MouseEvent} - * @param menuItem {MenuItem} - * @param menu {Menu} - */ - MenuItem.prototype.defaultDblClickHandler = function (event, menuItem, menu) { - console.log('dblclick: ' + menuItem.options.label); - }; - - MenuItem.prototype.getMenu = function () { - return MenuList[this.parentId]; - }; - - MenuItem.prototype.getParent = function () { - if(MenuList[this.parentId] instanceof Menu) { - return MenuList[this.parentId].getNode(); - } - return null; - }; - - MenuItem.prototype.getId = function () { - return this.options.id; - }; - - /** - * @returns HTMLElement - */ - MenuItem.prototype.getNode = function () { - return this.node; - }; - - MenuItem.prototype.createNode = function () { - this.node = document.createElement('a'); - this.node.style.position = 'relative'; - this.node.dataset.parentId = this.parentId; - this.node.kit = this.node.kit || {}; - this.node.kit.menuItem = this; - }; - - /** - * @param content HTMLElement | string - * @returns {MenuItem} - */ - MenuItem.prototype.setLabel = function (content = '') { - this.options.label = content; - var wrap = this.getNodeScopeElementByClassName('kit-menu-item__label'); - this.setContent(wrap, content); - return this; - }; - - /** - * @param href - * @returns {MenuItem} - */ - MenuItem.prototype.setHref = function (href = 'javascript:void(0);') { - this.options.href = href; - this.getNode().setAttribute('href', href); - return this; - }; - - /** - * @param content HTMLElement | string - * @returns {MenuItem} - */ - MenuItem.prototype.setIcon = function (content = '') { - this.options.icon = content; - var wrap = this.getNodeScopeElementByClassName('kit-menu-item__icon'); - this.setContent(wrap, content); - return this; - }; - - /** - * @param sort int - * @returns {MenuItem} - */ - MenuItem.prototype.setSort = function (sort = 500) { - this.options.sort = Number(sort); - return this; - }; - - /** - * @param content HTMLElement | string - * @returns {MenuItem} - */ - MenuItem.prototype.setArrow = function (content = '') { - this.options.arrow = content; - var wrap = this.getNodeScopeElementByClassName('kit-menu-item__arrow'); - this.setContent(wrap, content); - return this; - }; - MenuItem.prototype.setId = function (id = '') { - if(id) { - this.options.id = id; - } - this.node.id = this.options.id; - return this; - }; - MenuItem.prototype.setVisible = function (visible = true) { - this.options.visible = visible; - this.node.style.display = this.options.visible?'':'none'; - return this; - }; - - /** - * @param {Menu} menu - * @return {MenuItem} - */ - MenuItem.prototype.setChild = function (menu) { - if(menu instanceof Menu) { - menu.setParent(this.node); - menu.init(); - } - else if( Array.isArray(menu) ) { - var menuClass; - menuClass = new Menu(); - menu.forEach(function (item, i) { - if(typeof item === 'object') { - menuClass.addItem(item); - } - }); - menuClass.setParent(this.node); - menuClass.init(); - } - return this; - }; - MenuItem.prototype.addClass = function (addClass = '') { + /** + * @param {Menu} menu + * @return {MenuItem} + */ + MenuItem.prototype.setChild = function (menu) { + if(menu instanceof Menu) { + menu.setParent(this.node); + menu.init(); + } + else if( Array.isArray(menu) ) { + var menuClass; + menuClass = new Menu(); + menu.forEach(function (item, i) { + if(typeof item === 'object') { + menuClass.addItem(item); + } + }); + menuClass.setParent(this.node); + menuClass.init(); + } + return this; + }; + MenuItem.prototype.addClass = function (addClass = '') { + if(addClass) { this.node.classList.add(addClass); + } + return this; + }; + + /** + * @param options Object + * @return {MenuItem} + */ + MenuItem.prototype.setOptions = function (options = {}) { + + this.options = Object.assign({}, this.options, options); + + return this; + }; + + /** + * @return {MenuItem} + */ + MenuItem.prototype.render = function () { + + this.setLabel(this.options.label); + this.setHref(this.options.href); + this.setId(this.options.id); + this.addClass(MENU_ITEM_CLASS); + this.addClass(this.options.class); + this.setChild(this.options.child); + this.setIcon(this.options.icon); + this.setArrow(this.options.arrow); + this.setVisible(this.options.visible); + this.setSort(this.options.sort); + + return this; + }; + + MenuItem.prototype.init = function () { + + if(this.bInit) { return this; - }; + } + this.render(); - /** - * @param options Object - * @return {MenuItem} - */ - MenuItem.prototype.setOptions = function (options = {}) { + this.node.removeEventListener('click', this, false); + this.node.removeEventListener('dblclick', this, false); + this.node.addEventListener('click', this, false); + this.node.addEventListener('dblclick', this, false); - this.options = Object.assign({}, this.options, options); + this.bInit = true; + return this; + }; - return this; - }; + MenuItem.prototype.reInit = function () { - /** - * @return {MenuItem} - */ - MenuItem.prototype.render = function () { + this.render(); - this.setLabel(this.options.label); - this.setHref(this.options.href); - this.setId(this.options.id); - this.addClass(this.options.class); - this.setChild(this.options.child); - this.setIcon(this.options.icon); - this.setArrow(this.options.arrow); - this.setVisible(this.options.visible); - this.setSort(this.options.sort); + this.node.removeEventListener('click', this, false); + this.node.removeEventListener('dblclick', this, false); + this.node.addEventListener('click', this, false); + this.node.addEventListener('dblclick', this, false); - return this; - }; + return this; + }; - MenuItem.prototype.init = function () { + MenuItem.prototype.remove = function () { + this.node.removeEventListener('click', this, false); + this.node.removeEventListener('dblclick', this, false); + var id = this.options.id; + //console.log('remove item' + id); + setTimeout((function(parentId, id){ + return function() { + if(MenuList.hasOwnProperty(parentId) && MenuList[parentId].itemList.hasOwnProperty(id)) { + delete MenuList[parentId].itemList[id]; + MenuList[parentId].init(); + } + }; + })(this.parentId, this.options.id),0); + }; - if(this.bInit) { - return this; - } - this.render(); + /** + * @param className + * @returns HTMLElement + */ + MenuItem.prototype.getNodeScopeElementByClassName = function(className = ''){ + var wrap; + this.node && (wrap = this.node.querySelector(':scope > .' + className)); - this.node.removeEventListener('click', this, false); - this.node.removeEventListener('dblclick', this, false); - this.node.addEventListener('click', this, false); - this.node.addEventListener('dblclick', this, false); + if(!wrap) { + wrap = document.createElement('div'); + wrap.classList.add(className); + this.node.append(wrap); + } + return wrap; + }; - this.bInit = true; - return this; - }; - - MenuItem.prototype.reInit = function () { - - this.render(); - - this.node.removeEventListener('click', this, false); - this.node.removeEventListener('dblclick', this, false); - this.node.addEventListener('click', this, false); - this.node.addEventListener('dblclick', this, false); - - return this; - }; - - MenuItem.prototype.remove = function () { - this.node.removeEventListener('click', this, false); - this.node.removeEventListener('dblclick', this, false); - var id = this.options.id; - //console.log('remove item' + id); - setTimeout((function(parentId, id){ - return function() { - if(MenuList.hasOwnProperty(parentId) && MenuList[parentId].itemList.hasOwnProperty(id)) { - delete MenuList[parentId].itemList[id]; - MenuList[parentId].reInit(); - } - }; - })(this.parentId, this.options.id),0); - }; - - /** - * @param className - * @returns HTMLElement - */ - MenuItem.prototype.getNodeScopeElementByClassName = function(className = ''){ - var wrap; - this.node && (wrap = this.node.querySelector(':scope > .' + className)); - - if(!wrap) { - wrap = document.createElement('div'); - wrap.classList.add(className); - this.node.append(wrap); - } - return wrap; - }; - - /** - * @param node HTMLElement - * @param content HTMLElement | string - * @param isText boolean - * @return boolean - */ - MenuItem.prototype.setContent = function(node, content, isText = false){ - if(!(node instanceof Element)) { - return false; - } - while (node.firstChild) { - node.removeChild(node.firstChild); - } - if((content instanceof Element) || isText) { - node.append(content); - } else { - node.innerHTML = content; - } - return true; - }; + /** + * @param node HTMLElement + * @param content HTMLElement | string + * @param isText boolean + * @return boolean + */ + MenuItem.prototype.setContent = function(node, content, isText = false){ + if(!(node instanceof Element)) { + return false; + } + while (node.firstChild) { + node.removeChild(node.firstChild); + } + if((content instanceof Element) || isText) { + node.append(content); + } else { + node.innerHTML = content; + } + return true; + }; - return MenuItem; - }(); - Menu.prototype.MenuItem = MenuItemClass; + return MenuItem; + }(); + Menu.prototype.MenuItem = MenuItemClass; + - return Menu; - })(); var getInstance = function(options = {}, items = []) { - if(options instanceof MenuClass) { + if(options instanceof Menu) { return options; } if(typeof options === 'string') { @@ -806,15 +641,9 @@ __PluginManager__.register('menu',function(module, exports, require) { if((options instanceof HTMLElement) && options.kit && options.kit.menu) { return options.kit.menu; } - return new MenuClass(options, items); + return new Menu(options, items); }; var getActiveMenuDataList = function(){ - function valueEx(value) { - if(typeof value === 'function') { - return value(); - } - return value; - } var idList = []; var dataList = []; var refList = []; @@ -823,20 +652,20 @@ __PluginManager__.register('menu',function(module, exports, require) { element = MenuList[id]; } var parentId = false, parentMenu; - if(!(refList.hasOwnProperty(id) && refList[id].parentMenu)) { - if(element) { - refList[id] = refList[id] || {}; - parentMenu = refList[id].parentMenu = element.getParentMenu(); - } - parentMenu && (parentId = parentMenu.id); - return parentId; + if(refList.hasOwnProperty(id) && refList[id].parentMenu) { + return refList[id].parentMenu.id; } - return refList[id].parentMenu.id; + if(element) { + refList[id] = refList[id] || {}; + parentMenu = refList[id].parentMenu = element.getParentMenu(); + } + parentMenu && (parentId = parentMenu.id); + return parentId; } MenuList.forEach(function(element){ var pos, posId, id, parentId; - if(!((element instanceof MenuClass) && element.bInit && element.bActive)) { + if(!((element instanceof Menu) && element.bInit && element.bActive)) { return; } id = element.id; @@ -845,7 +674,8 @@ __PluginManager__.register('menu',function(module, exports, require) { parentId = getParentId(id, element); var depth = function (id){ return function() { - return 1 + valueEx(refList[refList[id].data.parentId].data.depth) + var pid = refList[id].data.parentId; + return 1 + (refList.hasOwnProperty(pid)?(support.valueEx(refList[pid].data.depth)):0); }; }; !( @@ -879,11 +709,15 @@ __PluginManager__.register('menu',function(module, exports, require) { ) &&(idList.indexOf(id)===-1)&&(idList.push(id), dataList.push(refList[id].data = {id:id, depth: 1, parentId: 0, type: 4})); }); + var result = []; dataList.forEach(function (data) { - data.depth = valueEx(data.depth); + data.depth = support.valueEx(data.depth); data.menu = refList[data.id].menu; + if(data.menu) { + result.push(data); + } }); - return dataList; + return result; }; var getChainActiveMenuDataList = function (id) { var dataList = getActiveMenuDataList(), result = [], depth = 0; @@ -903,14 +737,14 @@ __PluginManager__.register('menu',function(module, exports, require) { var reInitAllMenu = function(){ var dataList = getActiveMenuDataList(); dataList.forEach(function(data) { - data.menu.reInit(); + data.menu.init(); }); }; var reCalcAllMenu = function(){ console.log('reCalcAllMenu'); var dataList = getActiveMenuDataList(); dataList.forEach(function(data) { - data.menu.calcStyle(); + data.menu.setPosition(); }); }; var autoload = function(doc = document, selector = '.kit-menu'){ @@ -920,7 +754,7 @@ __PluginManager__.register('menu',function(module, exports, require) { var menuList = doc.querySelectorAll(selector); menuList.forEach( function(menuNode, currentIndex, listObj) { - if(!menuNode.kit || !menuNode.kit.hasOwnProperty(defaultMenuOptions.nodeProperty)) { + if(!menuNode.kit || !menuNode.kit.hasOwnProperty(MENU_PLUGIN_NAME)) { } } @@ -940,7 +774,7 @@ __PluginManager__.register('menu',function(module, exports, require) { * @memberOf kit */ var menu = { - Class: MenuClass, + Class: Menu, getInstance: getInstance, reInitAllMenu: reInitAllMenu, reCalcAllMenu: reCalcAllMenu, diff --git a/assets/support/support.js b/assets/support/support.js index 78f776b..dd0af10 100644 --- a/assets/support/support.js +++ b/assets/support/support.js @@ -86,18 +86,23 @@ __PluginManager__.register('support', function(module, exports, require, global) if(isNode(selector) || isElement(selector)) { return selector; } - return undefined; + return null; } - var nameFromToStringRegex = /^function\s?([^\s(]*)/; - function className(object, defaultName) { - var result = ""; - if (typeof object === 'function') { - result = object.name || object.toString().match(nameFromToStringRegex)[1]; - } else if (typeof object.constructor === 'function') { - result = className(object.constructor, defaultName); + + var extend = function(target) { + if(!arguments[1]) { + return; } - return result || defaultName; - } + for(i=1; i < arguments.length; i++) { + var source = arguments[i]; + + for(var prop in source) { + if(!target[prop] && source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + } + }; /** @@ -117,7 +122,9 @@ __PluginManager__.register('support', function(module, exports, require, global) isFloat, isString, isNode, + isElement, getNode, + extend, }; return module.exports = support; diff --git a/assets/userAction/userAction.js b/assets/userAction/userAction.js index ff7b00e..93b6d6f 100644 --- a/assets/userAction/userAction.js +++ b/assets/userAction/userAction.js @@ -7,7 +7,13 @@ kit.PluginManager.register('userAction', function(module, exports, require, glob var Viewer = require('Viewer'); - + /** + * + * @param masterNode + * @param slaveNode + * @return {Popover} + * @constructor + */ var Popover = function (masterNode, slaveNode) { this.__setMasterNode(masterNode); this.__setSlaveNode(slaveNode); @@ -54,8 +60,15 @@ kit.PluginManager.register('userAction', function(module, exports, require, glob this.__masterAction.stop(); }; })(); - - + + + /** + * + * @param masterNode + * @param slaveNode + * @return {Hint} + * @constructor + */ var Hint = function (masterNode, slaveNode) { this.__setMasterNode(masterNode); this.__setSlaveNode(slaveNode); diff --git a/tests/kit.Collection.php b/tests/kit.Collection.php index 2503cf2..65f46d1 100644 --- a/tests/kit.Collection.php +++ b/tests/kit.Collection.php @@ -31,7 +31,7 @@ print_r($x); console.log(true, msg); return; } - console.error(msg, value, need); + console.error(msg, '-', 'value:', value, 'need:', need); } @@ -213,7 +213,14 @@ kit.ready(['collection'], function () { assertSame(x3.last(), 111, 'only last+'); assertSame(x3.length, 1, 'only length'); -x. + + xOb = {a: 'a10', b: 'b11', 10: 101}; + x = new kit.Collection(xOb); + x.set(11, 111); + assertSame(x.indexKey(11), 3, 'indexKey (int)'); + assertSame(x.indexKey('11'), 3, 'indexKey (string)'); + assertSame(x.indexKey('111'), -1, 'indexKey (-1)'); + }); diff --git a/tests/menu.php b/tests/menu.php index 9cbb703..5145cdc 100644 --- a/tests/menu.php +++ b/tests/menu.php @@ -140,7 +140,7 @@ kit.ready(['menu', 'animations'], function () { var menu; menu = kit.menu.getInstance({ alignOffset: [0, 5], - eventType: 'click', + eventType: 'popover', }, [ { label: 'еще (' + window.i + ')', @@ -161,19 +161,20 @@ kit.ready(['menu', 'animations'], function () { window.menuBuilder = (function(){ console.log('menuBuilder'); - window.menuBase = null; var menuBase = new kit.menu.Class(); + window.menuBase = menuBase; + menuBase.setOptions({ animation: kit.animations.scaleIn, alignOffset: [5, 5], hideDelay: 1000, parent: '#chat-message-15 .chat-message--manager-item-menu', /** - * доступно 2 режима click / hover, + * доступно 2 режима popover / hint, * понимать так: данное меню появляется по Клику на родитя (по дефолту hover) */ - eventType: 'click', + eventType: 'popover', }); /** @@ -249,7 +250,7 @@ kit.ready(['menu', 'animations'], function () { menuItem.remove(); }, }); - menu.reInit(); + menu.init(); }, }); /** @@ -262,16 +263,23 @@ kit.ready(['menu', 'animations'], function () { var item1 = menuBase.addItem({ label: 'меняем предка на R', + /** + * + * @param e + * @param menuItem + * @param {kit.menu.Class} menu + */ click: function(e, menuItem, menu) { console.log('клик by ' + menuItem.options.label); menuItem.setVisible(false); var tMenu = menu.getItemById(item2.getId()); + if(tMenu) { tMenu.setVisible(true); } - menu.setParent(document.querySelector('#change-context-menu-r')); + menu.setParent('#change-context-menu-r'); }, - }, true); + }); var item2 = menuBase.addItem({ label: 'меняем предка на X', visible: false, @@ -282,9 +290,9 @@ kit.ready(['menu', 'animations'], function () { if(tMenu) { tMenu.setVisible(true); } - menu.setParent(document.querySelector('#change-context-menu-x')); + menu.setParent('#change-context-menu-x'); }, - }, true); + }); menuBase.init(); diff --git a/tests/userAction.php b/tests/userAction.php index 1ed3425..af11726 100644 --- a/tests/userAction.php +++ b/tests/userAction.php @@ -33,11 +33,24 @@ $APPLICATION->ShowHead(); m5.viewer.animShowClass = kit.animations.scaleIn; m5.viewer.animHideClass = kit.animations.scaleOut; m5.run(); + // var m6 = new kit.userAction.Hint(); var m6 = new kit.userAction.Hint('#object8', '#object9'); m6.run(); m6.viewer.animShowClass = kit.animations.scaleIn; m6.viewer.animHideClass = kit.animations.scaleOut; + m6.run(); + var m7 = new kit.userAction.Hint(); + try { + m7.run(); + } catch (e) { + console.log(e); + } + try { + m7.stop(); + } catch (e) { + console.log(e); + } });