Newer
Older
/**
* @module package/quiqqer/menu/bin/Controls/Independent/MenuPanel
* @author www.pcsg.de (Henning Leutz)
*/
define('package/quiqqer/menu/bin/Controls/Independent/MenuPanel', [
'qui/QUI',
'qui/controls/desktop/Panel',
'qui/controls/sitemap/Map',
'qui/controls/sitemap/Item',
'qui/controls/windows/Confirm',
'qui/controls/contextmenu/Menu',
'qui/controls/contextmenu/Item',
'package/quiqqer/menu/bin/classes/IndependentHandler',
'text!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.ItemCard.html',
'text!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.Settings.html',
'css!package/quiqqer/menu/bin/Controls/Independent/MenuPanel.css'
], function (QUI, QUIPanel, QUIMap, QUIMapItem, QUIConfirm,
QUIContextMenu, QUIContextMenuItem, QUIContextSeparator, InputMultiLang,
QUIAjax, QUILocale, IndependentHandler, Mustache, templateItemCard, templateSettings) {
"use strict";
const lg = 'quiqqer/menu';
return new Class({
Extends: QUIPanel,
Type : 'package/quiqqer/menu/bin/Controls/Independent/MenuPanel',
Binds: [
'$onShow',
'$onCreate',
'$onInject',
'$openItem',
'$onContextMenu',
'$startDeSelect',
'$openMenuSettings',
'addItem',
'save',
],
options: {
menuId: false
},
initialize: function (options) {
this.parent(options);
this.$ActiveItem = null;
this.$ActiveMapItem = null;
this.$title = null;
this.$workingTitle = null;
this.$data = null;
this.setAttribute('#id', this.getAttribute('menuId'));
this.addEvents({
onShow : this.$onShow,
onInject: this.$onInject,
onCreate: this.$onCreate
});
},
$onCreate: function () {
this.getContent().addClass('quiqqer-menu-menuPanel');
// buttons
this.addButton({
name : 'save',
text : QUILocale.get('quiqqer/core', 'save'),
events: {
click: this.save
}
});
text : QUILocale.get('quiqqer/core', 'add'),
this.addButton({
textimage: 'fa fa-paint-brush',
name : 'clearcache',
text : QUILocale.get(lg, 'cache.clear.button.title'),
styles : {
'float': 'right'
},
events : {
click: (Btn) => {
Btn.disable();
Btn.setAttribute('textimage', 'fa fa-spinner fa-spin');
QUIAjax.post('package_quiqqer_menu_ajax_backend_independent_clearCache', () => {
Btn.setAttribute('textimage', 'fa fa-bars');
Btn.enable();
QUI.getMessageHandler(function (QUI) {
QUI.addSuccess(
QUILocale.get('quiqqer/menu', 'message.menu.publish.successful')
);
});
}, {
'package': 'quiqqer/menu',
menuId : this.getAttribute('menuId')
});
}
}
});
text : QUILocale.get('quiqqer/core', 'remove'),
events : {
click: this.addItem
}
});
// content
this.$MapContainer = new Element('div', {
'class': 'quiqqer-menu-menuPanel-mapContainer'
}).inject(this.getContent());
this.$InnerContainer = new Element('div', {
'class': 'quiqqer-menu-menuPanel-innerContainer'
}).inject(this.getContent());
this.$Map = new QUIMap({}).inject(this.$MapContainer);
},
$onInject: function () {
this.Loader.show();
Promise.all([
IndependentHandler.getMenu(this.getAttribute('menuId')),
this.$getMenuData()
]).then((result) => {
const menuData = result[0];
const data = result[1];
this.$data = menuData;
this.$title = data.title;
this.$workingTitle = data.workingTitle;
this.setAttribute('title', menuData.title);
this.setAttribute('icon', 'fa fa-bars');
this.refresh();
icon : 'fa fa-home',
text : menuData.title,
events: {
click : this.$openMenuSettings,
deSelect: this.$startDeSelect,
contextMenu: (Item, event) => {
event.stop();
const pos = Item.getElm().getPosition();
const Menu = new QUIContextMenu({
events: {
onBlur: function (Instance) {
Instance.hide();
Instance.destroy();
}
}
});
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-level-down',
text : QUILocale.get(lg, 'context.menu.insertChild'),
events: {
click: () => {
this.addItem(Item);
}
}
}));
if (Item.getChildren().length > 1) {
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-sort',
text : QUILocale.get(lg, 'context.menu.sort'),
events: {
click: () => {
this.sortChildren(Item);
}
}
}));
}
Menu.inject(document.body);
Menu.setPosition(pos.x, pos.y + 30);
Menu.setTitle(Item.getAttribute('text'));
Menu.show();
Menu.focus();
}
}
}).inject(this.$Map);
// build sitemap
if (menuData.data !== null &&
typeof menuData.data.children !== 'undefined' &&
menuData.data.children.length
) {
const buildChildren = (Parent, children) => {
for (i = 0, len = children.length; i < len; i++) {
data = children[i];
text = data.titleFrontend;
if (text === '' || text === '###') {
text = '?';
}
itemTitle: data.title,
itemType : data.type,
itemIcon : data.icon,
itemData : data.data,
events : {
click : this.$openItem,
contextMenu: this.$onContextMenu
}
});
Parent.appendChild(Item);
if (typeof data.data.status !== 'undefined' && data.data.status === 0) {
Item.deactivate();
}
if (typeof data.children !== 'undefined' && data.children.length) {
buildChildren(Item, data.children);
}
}
};
buildChildren(Start, menuData.data.children);
this.Loader.hide();
});
},
$onShow: function () {
},
save: function () {
this.Loader.show();
// map to array
const toArray = function (Item) {
let items = Item.getChildren();
if (Item.getType() === 'qui/controls/sitemap/Map') {
items = Item.$items;
}
let children = [];
for (let i = 0, len = items.length; i < len; i++) {
children.push(toArray(items[i]));
}
if (Item.getType() === 'qui/controls/sitemap/Map') {
return {
children: children
};
}
return {
title : Item.getAttribute('itemTitle'),
type : Item.getAttribute('itemType'),
data : Item.getAttribute('itemData'),
children: children
};
};

Michael Danielczok
committed
this.setMenuTitle();
let result = toArray(this.$Map.firstChild());
return this.$refreshItemDisplay().then(() => {
JSON.encode(this.$title),
JSON.encode(this.$workingTitle),

Michael Danielczok
committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
/**
* Set the title of this.$Map, so the title changes in the left panel.
* Also set menu title and working title to the variables:
* this.$title
* this.$workingTitle
*
* This function is a small workaround for this user flow:
* "User change the menu title (and working title) and save directly the menu by clicking save-button".
*/
setMenuTitle: function() {
const selected = this.$Map.getSelectedChildren();
if (selected.length === 1 && selected[0].getAttribute('value') !== 'start') {
return;
}
const Title = this.$InnerContainer.getElement('[name="title"]');
const WorkingTitle = this.$InnerContainer.getElement('[name="workingTitle"]');
if (!Title) {
return;
}
selected[0].setAttribute('itemTitle', Title.value);
this.$title = JSON.decode(Title.value);
this.$workingTitle = JSON.decode(WorkingTitle.value);
let current = QUILocale.getCurrent();
if (current in this.$title) {
selected[0].setAttribute('text', this.$title[current]);
selected[0].setAttribute('title', this.$title[current]);
}
},
addItem: function (Parent, where) {
if (typeof where === 'undefined') {
where = 'bottom';
}
if (typeof Parent === 'undefined') {
const items = this.$Map.getSelectedChildren();
if (items.length) {
Parent = items[0];
icon : 'fa fa-plus',
title : QUILocale.get(lg, 'quiqqer.menu.independent.addItem.title'),
maxHeight: 550,
maxWidth : 700,
autoclose: false,
events : {
onOpen: (Win) => {
const Content = Win.getContent();
Win.Loader.show();
Content.set(
'html',
`<p>`+ QUILocale.get(lg, 'create.window.text') +
'</p>' +
'<form style="width: 100%;">' +
' <div class="qui-menuPanel-optionList"></div>' +
'</form>'
);
IndependentHandler.getItemTypes().then((list) => {
this.$createOptionList(list, Content);
return QUI.parse(Win.getContent());
}).then(function () {
Win.Loader.hide();
});
},
onSubmit: (Win) => {
const Content = Win.getContent();
const Form = Content.getElement('form');
let type = Form.elements.itemType.value;
const Option = Form.getElement(
'[value="' + CSS.escape(type) + '"]'
itemType : Form.elements.itemType.value,
itemIcon : '',
events : {
click : this.$openItem,
contextMenu: this.$onContextMenu
}
};
Child = new QUIMapItem(itemAttributes);
Parent.appendChild(Child);
if (typeof Parent === 'function') {
Parent.open();
}
Child = new QUIMapItem(itemAttributes);
Parent.appendChild(Child, where);
this.save().then(() => {
return this.$refreshItemDisplay();
/**
* opens the item type change confirm window
*
* @param Item
*/
changeItemType: function (Item) {
if (typeof Item === 'undefined') {
return;
}
const itemType = Item.getAttribute('itemType');
new QUIConfirm({
icon : 'fa fa-edit',
title : QUILocale.get(lg, 'quiqqer.menu.independent.changeItemType.title'),
maxHeight: 550,
maxWidth : 700,
autoclose: false,
events : {
onOpen: (Win) => {
const Content = Win.getContent();
Content.set(
'html',
`<p>`+ QUILocale.get(lg, 'quiqqer.menu.independent.changeItemType.message') +
'</p>' +
'<form style="width: 100%;">' +
' <div class="qui-menuPanel-optionList"></div>' +
'</form>'
);
Win.Loader.show();
IndependentHandler.getItemTypes().then((list) => {
this.$createOptionList(list, Content, itemType);
return QUI.parse(Win.getContent());
}).then(function () {
Win.Loader.hide();
});
},
onSubmit: (Win) => {
Win.Loader.show();
const Content = Win.getContent();
const Form = Content.getElement('form');
const type = Form.elements.itemType.value;
const Option = Form.getElement(
'[value="' + CSS.escape(type) + '"]'
);
Item.setAttribute('itemType', type);
Item.setAttribute('icon', Option.get('data-icon'));
if (this.$ActiveMapItem && this.$ActiveMapItem === Item) {
Item.click();
this.$unloadCurrentItem();
this.$refreshItemDisplay().catch(console.error);
Win.close();
}
}
}).open();
},
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/**
* Create custom option list based on passed list of menu types
*
* @param list
* @param Content
* @param selected
*/
$createOptionList: function(list, Content, selected = false) {
const OptionsList = Content.getElement('.qui-menuPanel-optionList'),
selectedItem = selected ? selected : 'QUI\\Menu\\Independent\\Items\\Site';
const toggleSelected = function(event) {
OptionsList.getElements('label').forEach(function(Label) {
Label.classList.remove('checked');
});
event.target.getParent('label').classList.add('checked');
};
for (let i = 0, len = list.length; i < len; i++) {
const Item = list[i];
const Label = new Element('label', {
'class': 'qui-menuPanel-optionList__option',
html: Mustache.render(templateItemCard, {
title: Item.title,
desc: Item.desc,
icon: Item.icon,
value: Item.class
})
});
if (Item.class === selectedItem) {
Label.querySelector('input').checked = true;
Label.classList.add('checked');
}
Label.inject(OptionsList);
Label.getElement('input').addEventListener('change', toggleSelected);
}
},
sortChildren: function (Item) {
if (typeof Item === 'undefined') {
return;
}
require([
'package/quiqqer/menu/bin/Controls/Independent/MenuItemsSorting'
], function (MenuItemSorting) {
new MenuItemSorting({
Item : Item,
events: {
onSubmit: function (Instance, list) {
Item.$items = list;
Item.refresh();
}
/**
* opens the item - display the item data
*
* @param Item
*/
$openItem: function (Item) {
this.Loader.show();
return this.$refreshItemDisplay().then(() => {
this.$InnerContainer.set('html', '');
this.$ActiveItem = null;
this.$ActiveMapItem = null;
let control = '';
let type = Item.getAttribute('itemType');
for (let i = 0, len = list.length; i < len; i++) {
if (list[i].class === type) {
control = list[i].jsControl;
break;
}
}
if (control === '') {
this.Loader.hide();
return;
}
require([control], (cls) => {
const SitemapItem = this.$getActiveSitemapItem();
this.$ActiveMapItem = this.$getActiveSitemapItem();
this.$ActiveItem = new cls({
title : SitemapItem.getAttribute('itemTitle'),
type : SitemapItem.getAttribute('itemType'),
icon : SitemapItem.getAttribute('itemIcon'),
data : SitemapItem.getAttribute('itemData'),
events: {
load: () => {
this.Loader.hide();
}
}
}).inject(this.$InnerContainer);
}, (err) => {
console.error(err);
this.Loader.hide();
});
});
},
$openMenuSettings: function () {
this.Loader.show();
this.$unloadCurrentItem();
return this.$refreshItemDisplay().then(() => {
this.$ActiveItem = null;
this.$ActiveMapItem = null;
this.$InnerContainer.set('html', Mustache.render(templateSettings, {

Michael Danielczok
committed
title : QUILocale.get('quiqqer/menu', 'menu.title'),
workingTitle: QUILocale.get('quiqqer/menu', 'menu.workingTitle')

Michael Danielczok
committed
const TitleNode = this.$InnerContainer.getElement('[name="title"]'),
WorkingTitleNode = this.$InnerContainer.getElement('[name="workingTitle"]');
TitleNode.set('value', JSON.stringify(this.$title));
WorkingTitleNode.set('value', JSON.stringify(this.$workingTitle));
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
}).then(() => {
return QUI.parse(this.$InnerContainer);
}).then(() => {
// set values
this.Loader.hide();
});
},
$startDeSelect: function () {
const Title = this.$InnerContainer.getElement('[name="title"]');
const WorkingTitle = this.$InnerContainer.getElement('[name="workingTitle"]');
if (!Title) {
return;
}
// save first item
const selected = this.$Map.getSelectedChildren();
if (selected.length === 1 && selected[0].getAttribute('value') === 'start' && Title) {
selected[0].setAttribute('itemTitle', Title.value);
this.$title = JSON.decode(Title.value);
this.$workingTitle = JSON.decode(WorkingTitle.value);
let current = QUILocale.getCurrent();
if (current in this.$title) {
selected[0].setAttribute('text', this.$title[current]);
selected[0].setAttribute('title', this.$title[current]);
}
}
},
/**
* Unloads the current sitemap item
* The save method of the current active control is executed
*/
$unloadCurrentItem: function () {
if (!this.$ActiveItem) {
return;
}
if (typeof this.$ActiveItem.save !== 'function') {
return;
}
const data = this.$ActiveItem.save();
if (!this.$ActiveMapItem) {
return;
}
const ActiveItem = this.$ActiveMapItem;
ActiveItem.setAttribute('itemTitle', data.title);
ActiveItem.setAttribute('itemIcon', data.icon);
ActiveItem.setAttribute('itemData', data.data);
},
/**
* Refresh the name of the active map item
*
* @returns {Promise}
*/
$refreshItemDisplay: function () {
const Item = this.$ActiveMapItem;
if (Item === null) {
return Promise.resolve();
}
// check status
const data = Item.getAttribute('itemData');
if (typeof data.status !== 'undefined' && data.status === 0) {
Item.deactivate();
} else {
Item.activate();
}
// check name
return new Promise(function (resolve, reject) {
QUIAjax.get('package_quiqqer_menu_ajax_backend_independent_getItemTitle', (name) => {
if (name === '') {
name = '?';
}
Item.setAttribute('text', name);
resolve();
}, {
'package': 'quiqqer/menu',
item : JSON.encode({
icon : Item.getAttribute('itemIcon'),
title: Item.getAttribute('itemTitle'),
type : Item.getAttribute('itemType'),
data : Item.getAttribute('itemData'),
}),
onError : reject
});
});
/**
* Return the active item of the sitemap
*
* @returns {null|*}
*/
$getActiveSitemapItem: function () {
const item = this.$Map.getSelectedChildren();
if (item.length) {
return item[0];
}
return null;
},
/**
* Context menu für a sitemap item
*
* @param Item
* @param event
*/
$onContextMenu: function (Item, event) {
event.stop();
const pos = Item.getElm().getPosition();
const Menu = new QUIContextMenu({
events: {
onBlur: function (Instance) {
Instance.hide();
Instance.destroy();
}
}
});
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-arrow-up',
text : QUILocale.get(lg, 'context.menu.insertBefore'),
events: {
click: () => {
this.addItem(Item, 'before');
}
}
}));
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-arrow-down',
text : QUILocale.get(lg, 'context.menu.insertAfter'),
events: {
click: () => {
this.addItem(Item, 'after');
}
}
}));
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-level-down',
text : QUILocale.get(lg, 'context.menu.insertChild'),
events: {
click: () => {
this.addItem(Item);
}
}
}));
Menu.appendChild(new QUIContextSeparator({}));
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-edit',
text : QUILocale.get(lg, 'context.menu.changeType'),
events: {
click: () => {
this.changeItemType(Item);
}
}
}));
if (Item.getChildren().length > 1) {
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-sort',
text : QUILocale.get(lg, 'context.menu.sort'),
events: {
click: () => {
this.sortChildren(Item);
}
}
}));
}
Menu.appendChild(new QUIContextSeparator({}));
Menu.appendChild(new QUIContextMenuItem({
icon : 'fa fa-trash',
text : QUILocale.get(lg, 'context.menu.deleteChild'),
new QUIConfirm({
icon : 'fa fa-trash',
texticon : 'fa fa-trash',
title : QUILocale.get(lg, 'window.deleteItem.title'),
information: QUILocale.get(lg, 'window.deleteItem.information', {
entry: Item.getAttribute('text')
}),
text : QUILocale.get(lg, 'window.deleteItem.text'),
maxHeight : 300,
maxWidth : 500,
events : {
}
}
}));
Menu.inject(document.body);
Menu.setPosition(pos.x, pos.y + 30);
Menu.setTitle(Item.getAttribute('text'));
Menu.show();
Menu.focus();
},
$getMenuData: function () {
return new Promise((resolve, reject) => {
QUIAjax.get('package_quiqqer_menu_ajax_backend_independent_getData', resolve, {
'package': 'quiqqer/menu',
id : this.getAttribute('menuId'),
onError : reject
});
});