mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-11-16 13:07:14 +01:00
1006 lines
34 KiB
JavaScript
1006 lines
34 KiB
JavaScript
|
/**
|
||
|
* ## Initialisierung
|
||
|
*
|
||
|
* ### Initialisierung über HTML
|
||
|
*
|
||
|
* ```html
|
||
|
* <span
|
||
|
* class="label-loader"
|
||
|
* data-label-reference-table="wiedervorlage"
|
||
|
* data-label-reference-id="123"
|
||
|
* ></span>
|
||
|
* ```
|
||
|
*
|
||
|
* ### Initialisierung über Javascript
|
||
|
*
|
||
|
* ```html
|
||
|
* <span id="element"></span>
|
||
|
* ```
|
||
|
*
|
||
|
* ```javascript
|
||
|
* $('#element').labels({
|
||
|
* referenceTable: 'wiedervorlage',
|
||
|
* referenceId: 123
|
||
|
* });
|
||
|
* ```
|
||
|
*
|
||
|
* ### Initialisierung gemischt
|
||
|
*
|
||
|
* ```html
|
||
|
* <span id="element" data-label-reference-table="wiedervorlage"></span>
|
||
|
* ```
|
||
|
*
|
||
|
* ```javascript
|
||
|
* $('#element').labels({
|
||
|
* referenceId: 123
|
||
|
* });
|
||
|
* ```
|
||
|
*
|
||
|
* ## Initialisierungsoptionen
|
||
|
*
|
||
|
* * referenceTable: (Pflichtangabe)
|
||
|
* * referenceId: (Pflichtangabe)
|
||
|
* * trigger: CSS-ID-Selektor zum Öffnen des LabelManager-Overlays (Optional; Default: `null`)
|
||
|
* * autoload: Labels bei Initialisierung direkt vom Server laden? (Optional; Default: `true`)
|
||
|
* * compact: Labels kompakt darstellen? (Optional; Default: `false`)
|
||
|
*
|
||
|
* ## API
|
||
|
*
|
||
|
* ### API-Objekt holen
|
||
|
*
|
||
|
* ```javascript
|
||
|
* var api = $('#element').labelsApi();
|
||
|
* ```
|
||
|
*
|
||
|
* ### API-Methoden
|
||
|
*
|
||
|
* * `api.showOverlay()` Label-Overlay einblenden
|
||
|
* * `api.hideOverlay()` Label-Overlay ausblenden
|
||
|
*/
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Modul zum Rendern von Labeln
|
||
|
*
|
||
|
* @type {{render: *}}
|
||
|
*/
|
||
|
var LabelRenderer = (function ($) {
|
||
|
'use strict';
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
/**
|
||
|
* @param {Object} collection
|
||
|
*/
|
||
|
render: function (collection) {
|
||
|
|
||
|
Object.keys(collection).forEach(function (key) {
|
||
|
var labels = collection[key];
|
||
|
if (!Array.isArray(labels)) {
|
||
|
console.error('Can not render label data. Wrong data type.', labels);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Alle Label-Container mit der gleichen Referenz finden
|
||
|
// Bsp. key = 'labels-wiedervorlage-123'
|
||
|
var targetSelector = '.label-container.' + key;
|
||
|
var $target = $(targetSelector);
|
||
|
|
||
|
// Container-Element für Labels vorhanden?
|
||
|
if ($target.length === 0) {
|
||
|
console.error('Can not find label target for "' + key + '".');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$target.html('');
|
||
|
|
||
|
// Label-Elemente erzeugen und in Label-Container stecken
|
||
|
labels.forEach(function (item) {
|
||
|
if (!me.hasTypeLabel($target, item.type)) {
|
||
|
var $label = me.createLabelElement(item.type, item.title, item.bgcolor);
|
||
|
$label.appendTo($target);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$target.addClass(key);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} baseColor Hex color value
|
||
|
*
|
||
|
* @return {object}
|
||
|
*/
|
||
|
calculateLabelColors: function (baseColor) {
|
||
|
var altColor, colors;
|
||
|
var brightness = me.calculateColorBrightness(baseColor);
|
||
|
if (brightness === 'dark') {
|
||
|
altColor = me.calculateColorVariant(baseColor, 35);
|
||
|
colors = {
|
||
|
'background-color': altColor,
|
||
|
'border-color': baseColor,
|
||
|
'color': baseColor
|
||
|
};
|
||
|
} else {
|
||
|
altColor = me.calculateColorVariant(baseColor, -35);
|
||
|
colors = {
|
||
|
'background-color': baseColor,
|
||
|
'border-color': altColor,
|
||
|
'color': altColor
|
||
|
};
|
||
|
}
|
||
|
|
||
|
return colors;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} type
|
||
|
* @param {string} title
|
||
|
* @param {string} color Hex-Color (Format: #336699)
|
||
|
*
|
||
|
* @return {jQuery}
|
||
|
*/
|
||
|
createLabelElement: function (type, title, color) {
|
||
|
var altColor, bgColor, borderColor, textColor;
|
||
|
var brightness = me.calculateColorBrightness(color);
|
||
|
if (brightness === 'dark') {
|
||
|
altColor = me.calculateColorVariant(color, 35);
|
||
|
bgColor = altColor;
|
||
|
textColor = color;
|
||
|
borderColor = color;
|
||
|
} else {
|
||
|
altColor = me.calculateColorVariant(color, -35);
|
||
|
bgColor = color;
|
||
|
textColor = altColor;
|
||
|
borderColor = altColor;
|
||
|
}
|
||
|
|
||
|
var $label = $('<span class="label"></span>');
|
||
|
$label.addClass('label-manager-type-' + type);
|
||
|
$label.css('background-color', bgColor);
|
||
|
$label.css('border-color', borderColor);
|
||
|
$label.css('color', textColor);
|
||
|
$label.data('labelType', type);
|
||
|
$label.attr('title', title);
|
||
|
|
||
|
var $labelTextNormal = $('<span>').addClass('label-text-normal');
|
||
|
$labelTextNormal.html(title).appendTo($label);
|
||
|
|
||
|
var $labelTextCompact = $('<span>').addClass('label-text-compact');
|
||
|
$labelTextCompact.html(' ').appendTo($label);
|
||
|
|
||
|
return $label;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $element
|
||
|
* @param {string} type
|
||
|
*
|
||
|
* @return {boolean}
|
||
|
*/
|
||
|
hasTypeLabel: function ($element, type) {
|
||
|
var $result = $element.find('.label-manager-type-' + type);
|
||
|
|
||
|
return $result.length > 0;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} hexColor
|
||
|
*
|
||
|
* @return {string} [light|dark]
|
||
|
*/
|
||
|
calculateColorBrightness: function(hexColor) {
|
||
|
var rgbArr = me.convertHexColorToRgb(hexColor);
|
||
|
var r = parseInt(rgbArr[0], 10);
|
||
|
var g = parseInt(rgbArr[1], 10);
|
||
|
var b = parseInt(rgbArr[2], 10);
|
||
|
var yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
||
|
|
||
|
return (yiq >= 128) ? 'light' : 'dark';
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} hexColor
|
||
|
* @param {number} percent
|
||
|
*
|
||
|
* @return {string}
|
||
|
*/
|
||
|
calculateColorVariant: function(hexColor, percent) {
|
||
|
var rgbArr = me.convertHexColorToRgb(hexColor);
|
||
|
var difference = parseInt(percent * 2.55, 10);
|
||
|
var r = parseInt(rgbArr[0] + difference, 10);
|
||
|
var g = parseInt(rgbArr[1] + difference, 10);
|
||
|
var b = parseInt(rgbArr[2] + difference, 10);
|
||
|
|
||
|
// Sicherstellen dass RGB-Werte zwischen 0 und 255 liegen
|
||
|
r = Math.min(Math.max(r, 0), 255);
|
||
|
g = Math.min(Math.max(g, 0), 255);
|
||
|
b = Math.min(Math.max(b, 0), 255);
|
||
|
|
||
|
var rHex = r.toString(16);
|
||
|
if (rHex.length === 1) {
|
||
|
rHex = '0' + rHex;
|
||
|
}
|
||
|
var gHex = g.toString(16);
|
||
|
if (gHex.length === 1) {
|
||
|
gHex = '0' + gHex;
|
||
|
}
|
||
|
var bHex = b.toString(16);
|
||
|
if (bHex.length === 1) {
|
||
|
bHex = '0' + bHex;
|
||
|
}
|
||
|
|
||
|
return '#' + rHex + gHex + bHex;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} hexColor
|
||
|
*
|
||
|
* @return {Array|null}
|
||
|
*/
|
||
|
convertHexColorToRgb: function(hexColor) {
|
||
|
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||
|
hexColor = hexColor.replace(shorthandRegex, function(m, r, g, b) {
|
||
|
return '#' + r + r + g + g + b + b;
|
||
|
});
|
||
|
|
||
|
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hexColor);
|
||
|
return result ? [
|
||
|
parseInt(result[1], 16),
|
||
|
parseInt(result[2], 16),
|
||
|
parseInt(result[3], 16)
|
||
|
] : null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
render: me.render,
|
||
|
calculateLabelColors: me.calculateLabelColors
|
||
|
};
|
||
|
|
||
|
})(jQuery);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* LabelManager-Modul
|
||
|
*
|
||
|
* Der LabelManager erzeugt das Overlay zum Hinzufügen/Löschen von Labels.
|
||
|
*
|
||
|
* @type {{init: *, showOverlay: *, hideOverlay: *, destroy: *}}
|
||
|
*/
|
||
|
var LabelManager = (function ($, LabelRendererModule) {
|
||
|
'use strict';
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
selector: {
|
||
|
overlay: '#label-manager-overlay'
|
||
|
},
|
||
|
|
||
|
storage: {
|
||
|
$overlay: null
|
||
|
},
|
||
|
|
||
|
init: function () {
|
||
|
me.registerEvents();
|
||
|
},
|
||
|
|
||
|
destroy: function () {
|
||
|
me.unregisterEvents();
|
||
|
},
|
||
|
|
||
|
registerEvents: function () {
|
||
|
|
||
|
$(document).off('click.labelManager', '.label-manager');
|
||
|
$(document).on('click.labelManager', '.label-manager', function (event) {
|
||
|
event.preventDefault();
|
||
|
var $trigger = $(this);
|
||
|
me.showOverlayForElement($trigger);
|
||
|
});
|
||
|
|
||
|
$(document).off('change.labelManager', 'input.label-manager-type-checkbox');
|
||
|
$(document).on('change.labelManager', 'input.label-manager-type-checkbox', function (event) {
|
||
|
event.preventDefault();
|
||
|
var $checkbox = $(this);
|
||
|
var referenceTable = $checkbox.data('labelReferenceTable');
|
||
|
var referenceId = $checkbox.data('labelReferenceId');
|
||
|
var labelType = $checkbox.data('labelType');
|
||
|
|
||
|
if ($checkbox.prop('checked')) {
|
||
|
me.assignLabel(labelType, referenceTable, referenceId)
|
||
|
} else {
|
||
|
me.unassignLabel(labelType, referenceTable, referenceId);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
unregisterEvents: function () {
|
||
|
$(document).off('click.labelManager', '.label-manager');
|
||
|
$(document).off('change.labelManager', 'input.label-manager-type-checkbox');
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} labelType
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
*/
|
||
|
assignLabel: function (labelType, referenceTable, referenceId) {
|
||
|
if (typeof labelType !== 'string' || labelType === '') {
|
||
|
throw 'LabelManager: InvalidArgument "labelType".';
|
||
|
}
|
||
|
if (typeof referenceTable !== 'string' || referenceTable === '') {
|
||
|
throw 'LabelManager: InvalidArgument "referenceTable".';
|
||
|
}
|
||
|
if (typeof referenceId !== 'number' || referenceId === '' || referenceId === 0) {
|
||
|
throw 'LabelManager: InvalidArgument "referenceId".';
|
||
|
}
|
||
|
|
||
|
$.ajax({
|
||
|
url: 'index.php?module=ajax&action=labels&cmd=assign',
|
||
|
method: 'post',
|
||
|
dataType: 'json',
|
||
|
data: {
|
||
|
type: labelType,
|
||
|
reference_id: referenceId,
|
||
|
reference_table: referenceTable
|
||
|
},
|
||
|
success: function (result) {
|
||
|
LabelRendererModule.render(result.data);
|
||
|
},
|
||
|
error: function (jqXhr) {
|
||
|
alert('Fehler: ' + jqXhr.responseJSON.error);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} labelType
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
*/
|
||
|
unassignLabel: function (labelType, referenceTable, referenceId) {
|
||
|
if (typeof labelType !== 'string' || labelType === '') {
|
||
|
throw 'LabelManager: InvalidArgument "labelType".';
|
||
|
}
|
||
|
if (typeof referenceTable !== 'string' || referenceTable === '') {
|
||
|
throw 'LabelManager: InvalidArgument "referenceTable".';
|
||
|
}
|
||
|
if (typeof referenceId !== 'number' || referenceId === '' || referenceId === 0) {
|
||
|
throw 'LabelManager: InvalidArgument "referenceId".';
|
||
|
}
|
||
|
|
||
|
$.ajax({
|
||
|
url: 'index.php?module=ajax&action=labels&cmd=unassign',
|
||
|
method: 'post',
|
||
|
dataType: 'json',
|
||
|
data: {
|
||
|
type: labelType,
|
||
|
reference_id: referenceId,
|
||
|
reference_table: referenceTable
|
||
|
},
|
||
|
success: function (result) {
|
||
|
LabelRendererModule.render(result.data);
|
||
|
},
|
||
|
error: function (jqXhr) {
|
||
|
alert('Fehler: ' + jqXhr.responseJSON.error);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @return {jQuery}
|
||
|
*/
|
||
|
getOverlay: function () {
|
||
|
if (typeof me.storage.$overlay === 'undefined' || me.storage.$overlay === null) {
|
||
|
me.storage.$overlay = me.createOverlay();
|
||
|
}
|
||
|
|
||
|
return me.storage.$overlay;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Label-Manager-Overlay einblenden
|
||
|
*
|
||
|
* @param {jQuery} $trigger
|
||
|
*/
|
||
|
showOverlayForElement: function ($trigger) {
|
||
|
if (!$trigger instanceof jQuery) {
|
||
|
throw 'LabelManager: InvalidArgument "$trigger".';
|
||
|
}
|
||
|
|
||
|
var $overlay = me.getOverlay();
|
||
|
var referenceTable = $trigger.data('labelReferenceTable');
|
||
|
var referenceId = parseInt($trigger.data('labelReferenceId'));
|
||
|
|
||
|
// Label-Typen laden und rendern
|
||
|
me.fetchLabelTypesList(referenceTable, referenceId).then(me.renderLabelTypesList);
|
||
|
|
||
|
// Position des Overlays setzen + Overlay einblenden
|
||
|
var offset = me.calculateOverlayPosition($trigger, $overlay);
|
||
|
$overlay.css({
|
||
|
position: 'fixed',
|
||
|
top: offset.top,
|
||
|
left: offset.left,
|
||
|
right: null,
|
||
|
bottom: null
|
||
|
});
|
||
|
$overlay.show();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
* @param {number} offsetTop
|
||
|
* @param {number} offsetLeft
|
||
|
*/
|
||
|
showOverlay: function (referenceTable, referenceId, offsetTop, offsetLeft) {
|
||
|
var $overlay = me.getOverlay();
|
||
|
offsetTop += 0;
|
||
|
offsetLeft += 0;
|
||
|
|
||
|
// Label-Typen laden und rendern
|
||
|
me.fetchLabelTypesList(referenceTable, referenceId).then(me.renderLabelTypesList);
|
||
|
|
||
|
// Position des Overlays setzen + Overlay einblenden
|
||
|
$overlay.css({
|
||
|
position: 'fixed',
|
||
|
top: offsetTop,
|
||
|
left: offsetLeft,
|
||
|
right: null,
|
||
|
bottom: null
|
||
|
});
|
||
|
$overlay.show();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Label-Manager-Overlay ausblenden
|
||
|
*/
|
||
|
hideOverlay: function () {
|
||
|
if (me.storage.$overlay === null) {
|
||
|
$(me.selector.overlay).hide();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
me.getOverlay().hide();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Label-Manager-Overlay erzeugen
|
||
|
*
|
||
|
* @return {jQuery}
|
||
|
*/
|
||
|
createOverlay: function () {
|
||
|
var overlaySelector = me.selector.overlay;
|
||
|
if ($(overlaySelector).length > 0) {
|
||
|
return $(overlaySelector);
|
||
|
}
|
||
|
|
||
|
var overlayTemplate =
|
||
|
'<header><h1>Labels<span id="label-manager-close-icon" class="icon icon-close"></span></h1></header>' +
|
||
|
'<section class="content-list"></section>' +
|
||
|
'<footer><a href="index.php?module=datatablelabels&action=list" ' +
|
||
|
'class="button button-neutral button-block" target="_blank">' +
|
||
|
'Labels erstellen/bearbeiten</a></footer>';
|
||
|
|
||
|
var overlayIdAttr = overlaySelector.substr(1);
|
||
|
var $overlay = $('<div>').attr('id', overlayIdAttr).html(overlayTemplate);
|
||
|
|
||
|
$overlay.off('click.labelManager', '#label-manager-close-icon');
|
||
|
$overlay.on('click.labelManager', '#label-manager-close-icon', function (event) {
|
||
|
event.preventDefault();
|
||
|
$overlay.hide();
|
||
|
});
|
||
|
|
||
|
$overlay.hide();
|
||
|
$overlay.appendTo('body');
|
||
|
$overlay.draggable({
|
||
|
handle: 'header'
|
||
|
});
|
||
|
|
||
|
return $overlay;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Position für Label-Manager-Overlay berechnen
|
||
|
*
|
||
|
* @param {jQuery} $trigger
|
||
|
* @param {jQuery} $overlay
|
||
|
*
|
||
|
* @return {{top: number, left: number}}
|
||
|
*/
|
||
|
calculateOverlayPosition: function ($trigger, $overlay) {
|
||
|
var triggerOffset = $trigger.offset();
|
||
|
var overlayWidth = $overlay.width();
|
||
|
var overlayHeight = $overlay.height();
|
||
|
var windowWidth = $(window).width();
|
||
|
var windowHeight = $(window).height();
|
||
|
var windowScrollLeft = window.pageXOffset || 0;
|
||
|
var windowScrollTop = window.pageYOffset || 0;
|
||
|
var triggerTop = triggerOffset.top - windowScrollTop;
|
||
|
var triggerLeft = triggerOffset.left - windowScrollLeft;
|
||
|
|
||
|
// Overlay relativ zum "Öffner"-Link platzieren
|
||
|
var overlayLeft = triggerLeft + 20;
|
||
|
var overlayTop = triggerTop;
|
||
|
|
||
|
// Korrektur, falls Overlay rechts abgeschnitten werden würde
|
||
|
var overlayRightBoundary = overlayLeft + overlayWidth + 20;
|
||
|
if (overlayRightBoundary > windowWidth) {
|
||
|
overlayLeft = windowWidth - (overlayWidth + 20);
|
||
|
overlayTop += 20;
|
||
|
}
|
||
|
|
||
|
// Korrektur, falls Overlay unten abgeschnitten werden würde
|
||
|
var overlayBottomBoundary = overlayTop + overlayHeight;
|
||
|
if (overlayBottomBoundary > windowHeight) {
|
||
|
overlayTop = windowHeight - (overlayHeight + 20);
|
||
|
}
|
||
|
|
||
|
return {top: overlayTop, left: overlayLeft};
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Liste mit Label-Typen abrufen
|
||
|
*
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
*
|
||
|
* @return {jqXHR}
|
||
|
*/
|
||
|
fetchLabelTypesList: function (referenceTable, referenceId) {
|
||
|
if (typeof referenceTable !== 'string' || referenceTable === '') {
|
||
|
throw 'LabelManager: InvalidArgument "referenceTable".';
|
||
|
}
|
||
|
if (typeof referenceId !== 'number' || referenceId === '' || referenceId === 0) {
|
||
|
throw 'LabelManager: InvalidArgument "referenceId".';
|
||
|
}
|
||
|
|
||
|
return $.ajax({
|
||
|
url: 'index.php?module=ajax&action=labels&cmd=list',
|
||
|
method: 'post',
|
||
|
dataType: 'json',
|
||
|
data: {
|
||
|
reference_id: referenceId,
|
||
|
reference_table: referenceTable
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {Array|object[]} labelList
|
||
|
*/
|
||
|
renderLabelTypesList: function (labelList) {
|
||
|
var $overlay = me.getOverlay();
|
||
|
var $contentList = $overlay.find('section.content-list').html('').show();
|
||
|
|
||
|
if (labelList.length === 0) {
|
||
|
$contentList.html('Keine Label gefunden');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var itemHtml = '';
|
||
|
var itemTemplate =
|
||
|
'<div class="line">' +
|
||
|
'<input type="checkbox" id="label-manager-type-{{type}}" class="label-manager-type-checkbox" {{checkedAttr}}> ' +
|
||
|
'<label for="label-manager-type-{{type}}"><span class="label-title">{{title}}</span></label>' +
|
||
|
'</div>';
|
||
|
|
||
|
labelList.forEach(function (labelItem) {
|
||
|
var checkedAttr = labelItem.selected === true ? 'checked="checked"' : '';
|
||
|
itemHtml = itemTemplate;
|
||
|
itemHtml = itemHtml.replace('{{checkedAttr}}', checkedAttr);
|
||
|
itemHtml = itemHtml.replace('{{type}}', labelItem.type);
|
||
|
itemHtml = itemHtml.replace('{{type}}', labelItem.type);
|
||
|
itemHtml = itemHtml.replace('{{title}}', labelItem.title);
|
||
|
|
||
|
var $line = $(itemHtml);
|
||
|
var labelColors = LabelRendererModule.calculateLabelColors(labelItem.bgcolor);
|
||
|
$line.find('.label-title').css(labelColors);
|
||
|
|
||
|
var $checkbox = $line.find('.label-manager-type-checkbox');
|
||
|
$checkbox.data('labelType', labelItem.type);
|
||
|
$checkbox.data('labelTitle', labelItem.title);
|
||
|
$checkbox.data('labelColor', labelItem.bgcolor);
|
||
|
$checkbox.data('labelReferenceTable', labelItem.referenceTable);
|
||
|
$checkbox.data('labelReferenceId', labelItem.referenceId);
|
||
|
|
||
|
$contentList.append($line);
|
||
|
});
|
||
|
|
||
|
// Höhe zurücksetzen (wird durch Draggable gesetzt)
|
||
|
$overlay.css('height', 'auto');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
init: me.init,
|
||
|
destroy: me.destroy,
|
||
|
showOverlay: me.showOverlay,
|
||
|
hideOverlay: me.hideOverlay
|
||
|
};
|
||
|
|
||
|
})(jQuery, LabelRenderer);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Modul zum Laden von Labels
|
||
|
*
|
||
|
* @type {{loadElement: *, loadAll: *}}
|
||
|
*/
|
||
|
var LabelLoader = (function ($, LabelRendererModule) {
|
||
|
'use strict';
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
/**
|
||
|
* Lädt alle (noch) nicht geladenenen Labels
|
||
|
*/
|
||
|
loadAll: function () {
|
||
|
|
||
|
// Referenzen für benötigte Labels sammeln
|
||
|
var collection = me.collectLabels();
|
||
|
var collectionKeys = Object.keys(collection);
|
||
|
if (collectionKeys.length === 0) {
|
||
|
return; // Keine Daten vorhanden
|
||
|
}
|
||
|
|
||
|
// Label-Daten für gesammelte Labels abrufen und rendern
|
||
|
me.fetchCollection(collection).then(me.renderCollection, function (jqXhr) {
|
||
|
alert('LabelLoader-Fehler: ' + jqXhr.responseJSON.error);
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Lädt die Labels für ein einzelnes Element
|
||
|
*
|
||
|
* autoload-Einstellung wird ignoriert
|
||
|
*
|
||
|
* @param {jQuery} $element
|
||
|
*/
|
||
|
loadElement: function ($element) {
|
||
|
if (!$element instanceof jQuery) {
|
||
|
return;
|
||
|
}
|
||
|
if ($element.length !== 1) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var referenceTable = $element.data('labelReferenceTable');
|
||
|
var referenceId = $element.data('labelReferenceId');
|
||
|
var compactData = $element.data('labelCompact');
|
||
|
|
||
|
var compact = typeof compactData !== 'undefined' && typeof compactData === 'boolean' ? compactData : false;
|
||
|
|
||
|
// Pflicht-Optionen vorhanden
|
||
|
if (typeof referenceTable === 'undefined' || typeof referenceId === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
referenceId = parseInt(referenceId);
|
||
|
if (isNaN(referenceId)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$element.addClass('labels-' + referenceTable + '-' + referenceId);
|
||
|
$element.addClass('label-container');
|
||
|
$element.removeClass('label-loader');
|
||
|
|
||
|
if (compact) {
|
||
|
$element.addClass('label-compact');
|
||
|
}
|
||
|
|
||
|
me.fetchLabels(referenceTable, referenceId);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
*/
|
||
|
fetchLabels: function (referenceTable, referenceId) {
|
||
|
if (typeof referenceTable !== 'string' || referenceTable === '') {
|
||
|
throw 'LabelManager: InvalidArgument "referenceTable".';
|
||
|
}
|
||
|
if (typeof referenceId !== 'number' || referenceId === '' || referenceId === 0) {
|
||
|
throw 'LabelManager: InvalidArgument "referenceId".';
|
||
|
}
|
||
|
|
||
|
var collection = {};
|
||
|
collection[referenceTable] = [referenceId];
|
||
|
|
||
|
$.ajax({
|
||
|
url: 'index.php?module=ajax&action=labels&cmd=collect',
|
||
|
method: 'post',
|
||
|
dataType: 'json',
|
||
|
data: {
|
||
|
collection: collection
|
||
|
},
|
||
|
success: function (result) {
|
||
|
LabelRendererModule.render(result.data);
|
||
|
},
|
||
|
error: function (jqXhr) {
|
||
|
alert('Fehler: ' + jqXhr.responseJSON.error);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Sammelt alle Labels die noch nicht geladen wurden
|
||
|
*
|
||
|
* @return {Object} Collection von Labels die geladen werden müssen
|
||
|
*/
|
||
|
collectLabels: function () {
|
||
|
var result = {};
|
||
|
var $loaders = $('.label-loader');
|
||
|
|
||
|
$loaders.each(function () {
|
||
|
var $elem = $(this);
|
||
|
var referenceTable = $elem.data('labelReferenceTable');
|
||
|
var referenceId = $elem.data('labelReferenceId');
|
||
|
|
||
|
if (typeof referenceTable === 'undefined' || typeof referenceId === 'undefined') {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var autoloadData = $elem.data('labelAutoload');
|
||
|
var autoload = typeof autoloadData !== 'undefined' && typeof autoloadData === 'boolean' ? autoloadData : true;
|
||
|
if (!autoload) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Label-Container erstellen mit eindeutiger CSS-Klasse (aber nicht Unique)
|
||
|
// CSS-Klasse kann mehrmals vorkommen, in unterschiedlichen DataTables
|
||
|
// mit identischen Referenz-ID und -Tabelle.
|
||
|
$elem.addClass('labels-' + referenceTable + '-' + referenceId);
|
||
|
$elem.addClass('label-container');
|
||
|
$elem.removeClass('label-loader');
|
||
|
|
||
|
var compactData = $elem.data('labelCompact');
|
||
|
var compactStyle = typeof compactData !== 'undefined' && typeof compactData === 'boolean' ? compactData : false;
|
||
|
if (compactStyle) {
|
||
|
$elem.addClass('label-compact');
|
||
|
}
|
||
|
|
||
|
// References sammeln
|
||
|
if (!result.hasOwnProperty(referenceTable)) {
|
||
|
result[referenceTable] = [];
|
||
|
}
|
||
|
if (!me.inArray(referenceId, result[referenceTable])) {
|
||
|
result[referenceTable].push(referenceId);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return result;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} collection
|
||
|
*
|
||
|
* @return {jqXHR|null}
|
||
|
*/
|
||
|
fetchCollection: function (collection) {
|
||
|
return $.ajax({
|
||
|
url: 'index.php?module=ajax&action=labels&cmd=collect',
|
||
|
method: 'post',
|
||
|
dataType: 'json',
|
||
|
data: {collection: collection}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} collectionResult Das Ergebnis von me.fetchCollection()
|
||
|
*/
|
||
|
renderCollection: function (collectionResult) {
|
||
|
if (!collectionResult.hasOwnProperty('data')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LabelRendererModule.render(collectionResult.data);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Prüfen ob Wert in einem Array vorkommt
|
||
|
*
|
||
|
* @param {number|string} value
|
||
|
* @param {Array} array
|
||
|
*
|
||
|
* @return {boolean}
|
||
|
*/
|
||
|
inArray: function (value, array) {
|
||
|
return array.indexOf(value) > -1;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return {
|
||
|
loadAll: me.loadAll,
|
||
|
loadElement: me.loadElement
|
||
|
};
|
||
|
|
||
|
})(jQuery, LabelRenderer);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Labels jQuery-Plugin + LabelsApi
|
||
|
*
|
||
|
* Dokumentation: Siehe Dateianfang
|
||
|
*/
|
||
|
(function ($, LabelLoaderModule, LabelManagerModule) {
|
||
|
'use strict';
|
||
|
|
||
|
var LabelsApi = function ($element, options) {
|
||
|
|
||
|
var me = {
|
||
|
|
||
|
/** @property {Object} me.defaults Default configuration */
|
||
|
defaults: {
|
||
|
referenceTable: null, // Pflicht-Option
|
||
|
referenceId: null, // Pflicht-Option
|
||
|
autoload: true,
|
||
|
compact: false,
|
||
|
trigger: null
|
||
|
},
|
||
|
|
||
|
storage: {
|
||
|
$trigger: null,
|
||
|
$element: null,
|
||
|
options: {}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {jQuery} $element
|
||
|
* @param {Object} options
|
||
|
*/
|
||
|
init: function ($element, options) {
|
||
|
if (typeof $element === 'undefined') {
|
||
|
throw 'LabelsApi konnte nicht initialisiert werden. Element wurde nicht übergeben.';
|
||
|
}
|
||
|
|
||
|
if ($element.length !== 1) {
|
||
|
throw 'LabelsApi konnte nicht initialisiert werden. Trigger-Element wurde nicht gefunden.';
|
||
|
}
|
||
|
|
||
|
// Optionen mit Defaults mergen
|
||
|
// Reihenfolge: Javascript-Optionen überschreiben Data-Attribute
|
||
|
var dataAttributesAll = $element.data();
|
||
|
var dataAttributesLabel = me.filterDataAttributesByPrefix(dataAttributesAll, 'label');
|
||
|
var mergedOptions = $.extend({}, me.defaults, dataAttributesLabel, options);
|
||
|
|
||
|
// Benötigte Optionen prüfen
|
||
|
if (mergedOptions.referenceTable === null) {
|
||
|
throw 'LabelsApi konnte nicht initialisiert werden. Benötigte Option \'referenceTable\' fehlt.';
|
||
|
}
|
||
|
if (mergedOptions.referenceId === null) {
|
||
|
throw 'LabelsApi konnte nicht initialisiert werden. Benötigte Option \'referenceId\' fehlt.';
|
||
|
}
|
||
|
mergedOptions.referenceId = parseInt(mergedOptions.referenceId);
|
||
|
if (isNaN(mergedOptions.referenceId)) {
|
||
|
throw 'LabelsApi konnte nicht initialisiert werden. Benötigte Option \'referenceId\' ist ungültig.';
|
||
|
}
|
||
|
|
||
|
// Sicherstellen dass alle Data-Attribute gesetzt sind;
|
||
|
// bei Initialisierung über jQuery-Plugin mit Options-Array.
|
||
|
if (mergedOptions.hasOwnProperty('referenceTable')) {
|
||
|
$element.data('labelReferenceTable', mergedOptions.referenceTable);
|
||
|
}
|
||
|
if (mergedOptions.hasOwnProperty('referenceId')) {
|
||
|
$element.data('labelReferenceId', mergedOptions.referenceId);
|
||
|
}
|
||
|
if (mergedOptions.hasOwnProperty('autoload')) {
|
||
|
$element.data('labelAutoload', mergedOptions.autoload);
|
||
|
}
|
||
|
if (mergedOptions.hasOwnProperty('compact')) {
|
||
|
$element.data('labelCompact', mergedOptions.compact);
|
||
|
}
|
||
|
if (mergedOptions.hasOwnProperty('trigger')) {
|
||
|
$element.data('labelTrigger', mergedOptions.trigger);
|
||
|
}
|
||
|
|
||
|
LabelLoaderModule.loadElement($element);
|
||
|
|
||
|
if (typeof mergedOptions.trigger !== 'undefined' && mergedOptions.trigger !== null) {
|
||
|
me.initTriggerElement(mergedOptions.trigger, mergedOptions.referenceTable, mergedOptions.referenceId);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {string} triggerSelector
|
||
|
* @param {string} referenceTable
|
||
|
* @param {number} referenceId
|
||
|
*/
|
||
|
initTriggerElement: function (triggerSelector, referenceTable, referenceId) {
|
||
|
var $trigger = $(triggerSelector);
|
||
|
if ($trigger.length !== 1) {
|
||
|
console.warn('LabelsApi: Trigger-Element "' + triggerSelector + '" wurde nicht gefunden');
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$trigger
|
||
|
.addClass('label-manager')
|
||
|
.data('labelReferenceTable', referenceTable)
|
||
|
.data('labelReferenceId', referenceId);
|
||
|
|
||
|
me.storage.$trigger = $trigger;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Label-Manager-Overlay einblenden
|
||
|
*/
|
||
|
showOverlay: function () {
|
||
|
if (me.storage.$trigger === null) {
|
||
|
console.warn('LabelsApi: Kein Trigger definiert');
|
||
|
}
|
||
|
|
||
|
me.storage.$trigger.trigger('click.labelManager');
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Label-Manager-Overlay ausblenden
|
||
|
*/
|
||
|
hideOverlay: function () {
|
||
|
LabelManagerModule.hideOverlay();
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @param {object} attributes
|
||
|
* @param {string} prefix
|
||
|
*
|
||
|
* @return {object}
|
||
|
*/
|
||
|
filterDataAttributesByPrefix: function (attributes, prefix) {
|
||
|
if (typeof attributes !== 'object') {
|
||
|
throw 'LabelManagerApi: InvalidArgument "attributes".';
|
||
|
}
|
||
|
if (typeof prefix !== 'string' || prefix === '') {
|
||
|
throw 'LabelManagerApi: InvalidArgument "prefix".';
|
||
|
}
|
||
|
|
||
|
var filteredAttributes = {};
|
||
|
Object.keys(attributes).forEach(function (key) {
|
||
|
if (key.indexOf(prefix) === 0) {
|
||
|
var value = attributes[key];
|
||
|
var keyWithoutPrefix = key.substr(prefix.length);
|
||
|
var keyFirstCharLowered = keyWithoutPrefix.charAt(0).toLowerCase() + keyWithoutPrefix.slice(1);
|
||
|
filteredAttributes[keyFirstCharLowered] = value;
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return filteredAttributes;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
me.init($element, options);
|
||
|
|
||
|
return {
|
||
|
showOverlay: me.showOverlay,
|
||
|
hideOverlay: me.hideOverlay
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// jQuery-Plugin registrieren
|
||
|
$.fn.labels = function (options) {
|
||
|
return this.each(function () {
|
||
|
var $elem = $(this);
|
||
|
|
||
|
// Neue API-Instanz erzeugen
|
||
|
// Dokumentation: Siehe Dateianfang
|
||
|
var api = new LabelsApi($elem, options);
|
||
|
/**@return {{showOverlay: *, hideOverlay: *}} */
|
||
|
$elem.init.prototype.labelsApi = function () {
|
||
|
return api;
|
||
|
};
|
||
|
$elem.data('labelsApi', api);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
}(jQuery, LabelLoader, LabelManager));
|
||
|
|
||
|
|
||
|
$(function () {
|
||
|
|
||
|
LabelManager.init();
|
||
|
LabelLoader.loadAll();
|
||
|
|
||
|
// LabelManager-Overlay ausblenden beim Wechseln von Tabs
|
||
|
$('#tabs').on('tabsactivate', function() {
|
||
|
LabelManager.hideOverlay();
|
||
|
});
|
||
|
});
|