");
$('.jsPanel-connector-bottomright', panel).css('border-bottom-color', bgColor || calcConnectorBgBottom('bottomright'));
panel.option.position.offsetY = panel.option.position.offsetY + 10 || 10;
}
},
// returns elmt reference to elmt triggering the tooltip
setTrigger(pos) {
// pos = jsP.option.position.of used as trigger of the tooltip
if (typeof pos.of === 'string') {
return document.querySelector(pos.of);
} else if (pos.of.jquery) {
return pos.of[0];
} else {
return pos.of;
}
},
closeTooltips() {
$('.jsPanel-tooltip').each( (index, elmt) => elmt.jspanel.close() );
},
// add class depending on position
setTooltipClass(panel) {
let pos = panel.option.position;
if (pos.my === 'center-bottom' && pos.at === 'center-top') {
panel.addClass('jsPanel-tooltip-top');
} else if (pos.my === 'left-bottom' && pos.at === 'right-top') {
panel.addClass('jsPanel-tooltip-righttopcorner');
} else if (pos.my === 'left-center' && pos.at === 'right-center') {
panel.addClass('jsPanel-tooltip-right');
} else if (pos.my === 'left-top' && pos.at === 'right-bottom') {
panel.addClass('jsPanel-tooltip-rightbottomcorner');
} else if (pos.my === 'center-top' && pos.at === 'center-bottom') {
panel.addClass('jsPanel-tooltip-bottom');
} else if (pos.my === 'right-top' && pos.at === 'left-bottom') {
panel.addClass('jsPanel-tooltip-leftbottomcorner');
} else if (pos.my === 'right-center' && pos.at === 'left-center') {
panel.addClass('jsPanel-tooltip-left');
} else if (pos.my === 'right-bottom' && pos.at === 'left-top') {
panel.addClass('jsPanel-tooltip-lefttopcorner');
} else if (pos.my === 'center' && pos.at === 'center') {
panel.addClass('jsPanel-tooltip-center');
} else if (pos.my === 'right-top' && pos.at === 'left-top') {
panel.addClass('jsPanel-tooltip-lefttop');
} else if (pos.my === 'right-bottom' && pos.at === 'left-bottom') {
panel.addClass('jsPanel-tooltip-leftbottom');
} else if (pos.my === 'left-bottom' && pos.at === 'left-top') {
panel.addClass('jsPanel-tooltip-topleft');
} else if (pos.my === 'right-bottom' && pos.at === 'right-top') {
panel.addClass('jsPanel-tooltip-topright');
} else if (pos.my === 'left-top' && pos.at === 'right-top') {
panel.addClass('jsPanel-tooltip-righttop');
} else if (pos.my === 'left-bottom' && pos.at === 'right-bottom') {
panel.addClass('jsPanel-tooltip-rightbottom');
} else if (pos.my === 'left-top' && pos.at === 'left-bottom') {
panel.addClass('jsPanel-tooltip-bottomleft');
} else if (pos.my === 'right-top' && pos.at === 'right-bottom') {
panel.addClass('jsPanel-tooltip-bottomright');
}
},
setTooltipMode(panel, trigger) {
if (panel.option.paneltype.mode === 'semisticky') {
panel.hover(
() => $.noop(),
() => {
panel.close();
$(trigger).removeClass('hasTooltip');
}
);
} else if (panel.option.paneltype.mode === 'sticky') {
// tooltip remains in the DOM until closed manually
$.noop();
} else {
// tooltip will be removed whenever mouse leaves trigger
$(trigger).mouseout( () => {
panel.close();
$(trigger).removeClass('hasTooltip');
});
}
},
/* ----------------------------------------------------------------------------------------------- */
/* content specific functions -------------------------------------------------------------------- */
// loads content using jQuery.ajax();
ajax(panel) {
let oAjax = panel.option.contentAjax;
$.ajax(oAjax)
.done( (data, textStatus, jqXHR) => {
if (oAjax.autoload) {panel.content.append(data);}
if ($.isFunction(oAjax.done)) {oAjax.done.call(panel, data, textStatus, jqXHR, panel);}
})
.fail( (jqXHR, textStatus, errorThrown) => {
if ($.isFunction(oAjax.fail)) {oAjax.fail.call(panel, jqXHR, textStatus, errorThrown, panel);}
})
.always( (arg1, textStatus, arg3) => {
if ($.isFunction(oAjax.always)) {oAjax.always.call(panel, arg1, textStatus, arg3, panel);}
})
.then( (data, textStatus, jqXHR) => {
if (oAjax.then && $.isArray(oAjax.then)) {
if ($.isFunction(oAjax.then[0])) {oAjax.then[0].call(panel, data, textStatus, jqXHR, panel);}
}
}, (jqXHR, textStatus, errorThrown) => {
if ($.isArray(oAjax.then)) {
if ($.isFunction(oAjax.then[1])) {oAjax.then[1].call(panel, jqXHR, textStatus, errorThrown, panel);}
}
}
);
panel.data("ajaxURL", oAjax.url); // needed for exportPanels()
},
// loads content in an iFrame
iframe(panel) {
let iFrame = $("
"),
poi = panel.option.contentIframe;
// iframe content
if (poi.srcdoc) {
iFrame.prop("srcdoc", poi.srcdoc);
panel.data("iframeDOC", poi.srcdoc); // needed for exportPanels()
}
if (poi.src) {
iFrame.prop("src", poi.src);
panel.data("iframeSRC", poi.src); // needed for exportPanels()
}
//iframe size
(panel.option.contentSize.width !== "auto" && !poi.width) ? iFrame.css("width", "100%") : iFrame.prop("width", poi.width);
(panel.option.contentSize.height !== "auto" && !poi.height) ? iFrame.css("height", "100%") : iFrame.prop("height", poi.height);
//iframe name
if (poi.name) {iFrame.prop("name", poi.name);}
//iframe sandbox
if (poi.sandbox) {iFrame.prop("sandox", poi.sandbox);}
//iframe id
if (poi.id) {iFrame.prop("id", poi.id);}
//iframe style
if ($.isPlainObject(poi.style)) {iFrame.css(poi.style);}
//iframe css classes
if (typeof poi.classname === 'string') {
iFrame.addClass(poi.classname);
} else if ($.isFunction(poi.classname)) {
iFrame.addClass(poi.classname());
}
panel.content.append(iFrame);
},
contentReload(panel) {
if (panel.option.content) {
panel.content.empty().append(panel.option.content);
} else if (panel.option.contentAjax) {
panel.content.empty();
this.ajax(panel);
} else if (panel.option.contentIframe) {
panel.content.empty();
this.iframe(panel);
}
return panel;
},
contentResize(panel) {
let hdrftr;
panel.footer.hasClass('active') ? hdrftr = panel.header.outerHeight() + panel.footer.outerHeight() : hdrftr = panel.header.outerHeight();
panel.content.css({ height: (panel.outerHeight() - hdrftr) });
return panel;
},
/* ----------------------------------------------------------------------------------------------- */
/* controls, iconfont and title specific functions ----------------------------------------------- */
configIconfont(panel) {
let controlsArray = ["close", "maximize", "normalize", "minimize", "smallify", "smallifyrev"],
bootstrapArray = ["remove", "fullscreen", "resize-full", "minus", "chevron-up", "chevron-down"],
fontawesomeArray = ["times", "arrows-alt", "expand", "minus", "chevron-up", "chevron-down"],
optIconfont = panel.option.headerControls.iconfont,
controls = panel.header.headerbar;
// set icons
if (optIconfont === 'bootstrap' || optIconfont === 'glyphicon') {
controlsArray.forEach((item, i) => {
$('.jsPanel-btn-' + item + ' span', controls).removeClass().addClass('glyphicon glyphicon-' + bootstrapArray[i]);
});
$('.jsPanel-headerbar .jsPanel-btn', panel).css('padding-top', '4px');
} else if (optIconfont === 'font-awesome') {
controlsArray.forEach((item, i) => {
$('.jsPanel-btn-' + item + ' span', controls).removeClass().addClass('fa fa-' + fontawesomeArray[i]);
});
}
},
// disable/enable individual controls
headerControl(panel, ctrl, action) {
// within the jsPanel method headerControl parameter action default is set to 'enable'
let controls = panel.header.headerbar,
p = panel[0];
if (action === 'disable') {
if (p.getAttribute('data-btn'+ctrl) !== 'removed') {
p.setAttribute('data-btn'+ctrl, 'disabled');
// unbind handler and set styles // pointer events not supported by IE10 !!
$('.jsPanel-btn-'+ctrl, controls).css({pointerEvents: 'none', opacity:0.4, cursor: 'default'});
}
} else if (action === 'enable') {
if (p.getAttribute('data-btn'+ctrl) !== 'removed') {
p.setAttribute('data-btn'+ctrl, 'enabled');
// enable control and reset styles // pointer events not supported by IE10 !!
$('.jsPanel-btn-'+ctrl, controls).css({pointerEvents: 'auto', opacity:1, cursor: 'pointer'});
}
} else if (action === 'remove') {
if (ctrl !== 'close') {
p.setAttribute('data-btn'+ctrl, 'removed');
// remove control
$('.jsPanel-btn-'+ctrl, controls).remove();
}
}
return panel;
},
hideControls(sel, panel) {
let controls = panel.header.headerbar;
$("div", controls).css('display', 'flex');
$(sel, controls).css('display', 'none');
},
headerTitle(panel, text) {
if (text) {
panel.header.title.empty().append(text);
return panel;
}
return panel.header.title.html();
},
/* ----------------------------------------------------------------------------------------------- */
/* toolbar specific functions -------------------------------------------------------------------- */
// builds toolbar
configToolbar(toolbaritems, toolbarplace, panel) {
let el, elEvent;
toolbaritems.forEach( item => {
if(typeof item === "object") {
el = $(item.item);
// add text to button
if (typeof item.btntext === 'string') {el.append(item.btntext);}
// add class to button
if (typeof item.btnclass === 'string') {el.addClass(item.btnclass);}
toolbarplace.append(el);
// bind handler to the item
if ($.isFunction(item.callback)) {
elEvent = item.event || 'click';
el.on(elEvent, panel, item.callback);
// jsP is accessible in the handler as "event.data"
}
}
});
},
// add a toolbar to either header or footer - used by option & method
toolbar(panel, place, items) {
if (place === 'header') {
panel.header.toolbar.addClass('active');
if ($.isArray(items)) {
this.configToolbar(items, panel.header.toolbar, panel);
} else if ($.isFunction(items)) {
panel.header.toolbar.append(items(panel.header));
} else {
panel.header.toolbar.append(items);
}
} else if (place === 'footer') {
panel.content.removeClass('jsPanel-content-nofooter');
panel.footer.addClass('active');
if ($.isArray(items)) {
this.configToolbar(items, panel.footer, panel);
} else if ($.isFunction(items)) {
panel.footer.append(items(panel.footer));
} else {
panel.footer.append(items);
}
}
this.contentResize(panel);
return panel;
},
/* ----------------------------------------------------------------------------------------------- */
closeChildpanels(panel) {
$('.jsPanel', panel).each( (index, elmt) => {
// jspanel is not the global object jsPanel but the extension for the individual panel elmt
elmt.jspanel.close();
} );
return panel;
},
// helper function for the doubleclick handlers (title, content, footer)
dblclickhelper(odcs, panel) {
if (typeof odcs === 'string') {
if (odcs === "maximize" || odcs === "normalize") {
panel.data('status') === "normalized" ? panel.maximize() : panel.normalize();
} else if (odcs === "minimize" || odcs === "smallify" || odcs === "close") {
panel[odcs]();
}
}
},
// export a panel layout to localStorage and returns array with an object for each panel
exportPanels() {
let elmtOffset, elmtPosition, elmtTop, elmtLeft, elmtWidth, elmtHeight, elmtStatus, panelParent,
panelArr = [], exportedPanel,
panels = $(".jsPanel").not(".jsPanel-tooltip, .jsPanel-hint, .jsPanel-modal");
// normalize minimized/maximized panels before export
// status to restore is saved in exportedPanel.status
panels.each( (index, elmt) => {
// in 2.6.1 this did not work in the following .each() loop
if ($(elmt).data("status") !== "normalized") {
$(".jsPanel-btn-normalize", elmt).trigger("click");
}
});
panels.each( (index, elmt) => {
// normalize minimized/maximized panels before export
// status to restore is saved in exportedPanel.status
//if ($(elmt).data("status") !== "normalized") {
// $(".jsPanel-btn-normalize", elmt).trigger("click");
//}
panelParent = $(elmt).data("container");
elmtOffset = $(elmt).offset();
elmtPosition = $(elmt).position();
if (elmtStatus === "minimized") {
if (panelParent.toLowerCase() === "body") {
elmtTop = $(elmt).data("paneltop") - $(window).scrollTop();
elmtLeft = $(elmt).data("panelleft") - $(window).scrollLeft();
} else {
elmtTop = $(elmt).data("paneltop");
elmtLeft = $(elmt).data("panelleft");
}
elmtWidth = $(elmt).data("panelwidth");
elmtHeight = $(elmt).data("panelheight");
} else {
if (panelParent.toLowerCase() === "body") {
elmtTop = Math.floor(elmtOffset.top - $(window).scrollTop());
elmtLeft = Math.floor(elmtOffset.left - $(window).scrollLeft());
} else {
elmtTop = Math.floor(elmtPosition.top);
elmtLeft = Math.floor(elmtPosition.left);
}
elmtWidth = $(elmt).css("width");
elmtHeight = $(".jsPanel-content", elmt).css("height");
}
exportedPanel = {
status: $(elmt).data("status"),
id: $(elmt).prop("id"),
headerTitle: $(".jsPanel-title", elmt).html(),
custom: $(elmt).data("custom"),
content: $(elmt).data("content"),
contentSize: { width: elmtWidth, height: elmtHeight },
position: { my: 'left-top', at: 'left-top', offsetX: elmtLeft, offsetY: elmtTop }
};
if ($(elmt).data("ajaxURL")) {
exportedPanel.contentAjax = {
url: $(elmt).data("ajaxURL"),
autoload: true
};
}
if ($(elmt).data("iframeDOC") || $(elmt).data("iframeSRC")) {
exportedPanel.contentIframe = {
src: $(elmt).data("iframeSRC") || '',
srcdoc: $(elmt).data("iframeDOC") || ''
};
}
panelArr.push(exportedPanel);
// restore status that is saved
switch (exportedPanel.status) {
case "minimized":
$(".jsPanel-btn-minimize", elmt).trigger("click");
break;
case "maximized":
$(".jsPanel-btn-maximize", elmt).trigger("click");
break;
case "smallified":
$(".jsPanel-btn-smallify", elmt).trigger("click");
break;
case "smallifiedMax":
$(".jsPanel-btn-smallify", elmt).trigger("click");
break;
}
});
window.localStorage.setItem("jspanels", JSON.stringify(panelArr));
return panelArr;
},
// imports panel layout from localStorage.jspanels and restores panels
importPanels(predefinedConfigs) {
/* panelConfig needs to be an object with predefined configs.
* A config named "default" will be applied to ALL panels
*
* panelConfig = { default: { } [, config1 [, config2 [, configN ]]] };
*/
let savedPanels = JSON.parse(localStorage.jspanels) || {},
defaultConfig = predefinedConfigs["default"] || {},
restoredConfig;
savedPanels.forEach( (savedconfig) => {
// savedconfig represents one item in savedPanels
if (typeof savedconfig.custom.config === "string") {
restoredConfig = $.extend(true, {}, defaultConfig, predefinedConfigs[savedconfig.custom.config], savedconfig);
} else {
restoredConfig = $.extend(true, {}, defaultConfig, savedconfig);
}
// restore panel
$.jsPanel(restoredConfig);
});
},
// resize existing jsPanel; resizes the full panel (not content section only)
resize(panel, width, height) {
if (panel.data('status') !== "minimized") {
// callback to execute before a panel is resized
if ($.isFunction(panel.option.onbeforeresize)) {
if (panel.option.onbeforeresize.call(panel, panel) === false) {return panel;}
}
if(width && width !== null) {
panel.css("width", width);
} else {
let newWidth = panel.content.css("width") + panel.content.css('border-left-width');
panel.css("width", newWidth);
}
if(height && height !== null) {panel.css("height", height);}
panel.contentResize();
//panel.trigger("resizestop");
// callback to execute after a panel was resized
if ($.isFunction(panel.option.onresized)) {
if (panel.option.onresized.call(panel, panel) === false) {return panel;}
}
}
return panel;
},
// returns a z-index value for a panel in order to have it on top
setZi(panel) {
if (!panel.hasClass('jsPanel-modal')) {
if ((this.zi += 1) > panel.css('z-index')) {
panel.css('z-index', this.zi);
}
}
},
// reset all z-index values for non-modal jsPanels
resetZis() {
let array = [],
panels = $('.jsPanel:not(.jsPanel-modal):not(.jsPanel-hint)');
panels.each(function(index,item){
array.push(item);
});
array.sort(function(a, b) {
return $(a).css('z-index') - $(b).css('z-index');
}).forEach(function(item, index) {
if ((jsPanel.zi += 1) > $(item).css('z-index')) {
$(item).css('z-index', 100 + index);
}
});
this.zi = 99 + array.length;
},
updateCachedData(panel) {
let styles = window.getComputedStyle(panel[0],null);
panel.cachedData.top = styles.getPropertyValue('top');
panel.cachedData.left = styles.getPropertyValue('left');
panel.cachedData.width = styles.getPropertyValue('width');
panel.cachedData.height = styles.getPropertyValue('height');
}
};
$(document.body).append("
");
(function($){
$.jsPanel = function (config) {
let id,
panelconfig = config || {},
optConfig = panelconfig.config || {},
passedconfig = $.extend(true, {}, optConfig, panelconfig),
template = panelconfig.template || jsPanel.template,
jsP = $(template),
trigger, // elmt triggering the tooltip
oH, oW;
// enable paneltype: 'tooltip' for default tooltips
if (passedconfig.paneltype === "tooltip") {passedconfig.paneltype = {tooltip: true};}
// Extend our default config with those provided. Note that the first arg to extend is an empty object - this is to keep from overriding our "defaults" object.
if (!passedconfig.paneltype) {
// if option.paneltype is not set in passed config simply merge passed config with defaults
jsP.option = $.extend(true, {}, $.jsPanel.defaults, passedconfig);
} else if (passedconfig.paneltype === 'modal') {
// if panel to create is a modal first merge passed config with modal defaults and then with defaults
jsP.option = $.extend(true, {}, $.jsPanel.defaults, $.jsPanel.modaldefaults, passedconfig);
} else if (passedconfig.paneltype.tooltip) {
// if panel to create is a tooltip first merge passed config with tooltip defaults and then with defaults
jsP.option = $.extend(true, {}, $.jsPanel.defaults, $.jsPanel.tooltipdefaults, passedconfig);
} else if (passedconfig.paneltype === 'hint') {
// if panel to create is a hint first merge passed config with hint defaults and then with defaults
jsP.option = $.extend(true, {}, $.jsPanel.defaults, $.jsPanel.hintdefaults, passedconfig);
}
// check whether panel to create is tooltip
if (jsP.option.paneltype.tooltip) {
// the elmt triggering the tooltip
trigger = jsPanel.setTrigger(jsP.option.position);
// if panel to create is a tooltip and the trigger already has a tooltip exit jsPanel()
if ($(trigger).hasClass('hasTooltip')) {return false;}
}
/* to ease migrating from version 2.5.x to version 3.x ------------------------------------------------------ */
let newOptions = ['container', 'contentAjax', 'contentIframe', 'contentOverflow', 'contentSize', 'footerToolbar', 'headerControls', 'headerRemove', 'headerTitle', 'headerToolbar'],
oldOptions = ['selector', 'ajax', 'iframe', 'overflow', 'size', 'toolbarFooter', 'controls', 'removeHeader', 'title', 'toolbarHeader'];
// map oldOptions to newOptions
oldOptions.forEach(function (value, index) {
if (jsP.option[value]) {
jsP.option[newOptions[index]] = jsP.option[value];
}
});
// map old themes to new ones
switch (jsP.option.theme) {
case "light":
jsP.option.theme = 'gainsboro';
break;
case "medium":
jsP.option.theme = 'silver';
break;
case "dark":
jsP.option.theme = 'gray';
break;
case "autumngreen":
jsP.option.theme = '#5A521B';
break;
case "autumnbrown":
jsP.option.theme = '#823E1D';
break;
case "autumnred":
jsP.option.theme = '#852228';
break;
}
// map old bootstrap themes to new ones
if (jsP.option.bootstrap) {
switch (jsP.option.bootstrap) {
case "default":
jsP.option.theme = "bootstrap-default";
break;
case "primary":
jsP.option.theme = "bootstrap-primary";
break;
case "info":
jsP.option.theme = "bootstrap-info";
break;
case "success":
jsP.option.theme = "bootstrap-success";
break;
case "warning":
jsP.option.theme = "bootstrap-warning";
break;
case "danger":
jsP.option.theme = "bootstrap-danger";
break;
}
}
// map old option load to current option contentAjax
if (jsP.option.load.url) {
jsP.option.contentAjax = {
url: jsP.option.load.url,
autoload: true,
data: jsP.option.load.data || undefined,
done: jsP.option.load.complete || undefined
};
}
// map old panelstatus values to new option.panelstatus
if (jsP.option.panelstatus) {
jsP.option.panelstatus === 'smallifiedMax' ? jsP.option.setstatus = 'maximize smallify' : jsP.option.setstatus = jsP.option.panelstatus;
}
if (jsP.option.headerControls.buttons) {
jsP.option.headerControls.controls = jsP.option.headerControls.buttons;
}
/* ---------------------------------------------------------------------------------------------------------- */
// option.id ---------------------------------------------------------------------------------------------------
if (typeof jsP.option.id === "string") {
id = jsP.option.id;
} else if ($.isFunction(jsP.option.id)) {
jsP.option.id = id = jsP.option.id();
}
// check whether id already exists in document
if ($("#" + id).length > 0) {
console.warn("jsPanel Error: No jsPanel created - id attribute passed with option.id already exists in document");
return false;
} else {
jsP.attr("id", id);
}
jsP.data("custom", jsP.option.custom);
// panel properties
jsP.header = $('.jsPanel-hdr', jsP);
jsP.header.headerbar = $('.jsPanel-headerbar', jsP.header);
jsP.header.title = $('.jsPanel-title', jsP.header.headerbar);
jsP.header.controls = $('.jsPanel-controlbar', jsP.header.headerbar);
jsP.header.toolbar = $('.jsPanel-hdr-toolbar', jsP.header);
jsP.content = $('.jsPanel-content', jsP);
jsP.footer = $('.jsPanel-ftr', jsP);
jsP.data('status', 'initialized');
jsP.cachedData = {};
// panel methods
jsP.toolbarAdd = (place = 'header', items = []) => jsPanel.toolbar(jsP, place, items);
jsP.close = () => {
$(document).trigger('jspanelbeforeclose', id);
if ($.isFunction(jsP.option.onbeforeclose)) {
// do not close panel if onbeforeclose callback returns false
if (jsP.option.onbeforeclose.call(jsP, jsP) === false) {return jsP;}
}
// this code block is only relevant if panel uses autoposition ------------------------------
let jsPop = jsP.option.position;
if (jsPop.autoposition || ( typeof jsPop === 'string' && jsPop.match(/DOWN|RIGHT|UP|LEFT/))) {
let regex = /left-top|center-top|right-top|left-center|center|right-center|left-bottom|center-bottom|right-bottom/,
parent = $('#' + id).parent(),
match = document.getElementById(id).className.match(regex);
if (match) {
jsPanel.lastbeforeclose = {
parent: parent,
class: match[0]
};
}
}
// ------------------------------------------------------------------------------------------
// close all childpanels and then the panel itself
jsP.closeChildpanels().remove();
// remove id from activePanels.list
let index = jsPanel.activePanels.list.findIndex(function(element) { return element === id; });
if (index > -1) { jsPanel.activePanels.list.splice(index, 1); }
// remove replacement if present
$('#'+id+'-min').remove();
// remove modal backdrop of corresponding modal jsPanel
if (jsP.option.paneltype === 'modal') {$('#jsPanel-modal-backdrop-' + jsP.attr('id')).remove();}
// remove class hasTooltip from tooltip trigger if panel to close is tooltip
if (jsP.option.paneltype.tooltip) {$(trigger).removeClass('hasTooltip');}
$(document).trigger('jspanelclosed', id);
$(document).trigger('jspanelstatuschange', id);
// this code block is only relevant if panel uses autoposition ------------------------------
let container, panels, pos;
if (jsPanel.lastbeforeclose) {
container = jsPanel.lastbeforeclose.parent;
panels = $('.' + jsPanel.lastbeforeclose.class, container);
pos = jsPanel.lastbeforeclose.class;
}
// than reposition all elmts
if (panels) {
// remove classname from all panels
panels.each(function(index, elmt) {
$(elmt).removeClass(pos);
});
// reposition remaining autopositioned panels
panels.each(function(index, elmt) {
var direction = elmt.getAttribute('data-autoposition'),
oX = elmt.getAttribute('data-offsetx'),
oY = elmt.getAttribute('data-offsety');
jsPanel.position(elmt, {
my: pos,
at: pos,
autoposition: direction,
offsetX: oX,
offsetY: oY
});
});
}
jsPanel.lastbeforeclose = false;
// -----------------------------------------------------------------------------------------------
// call onclosed callback of panel to close
if ($.isFunction(jsP.option.onclosed)) {jsP.option.onclosed.call(jsP, jsP);}
jsPanel.resetZis();
};
jsP.closeChildpanels = () => jsPanel.closeChildpanels(jsP);
jsP.contentReload = () => jsPanel.contentReload(jsP);
jsP.contentResize = () => jsPanel.contentResize(jsP);
jsP.headerControl = (ctrl, action = 'enable') => {
if (ctrl) {
jsPanel.headerControl(jsP, ctrl, action);
} else {
['close','maximize','minimize','normalize','smallify'].forEach(function(value) {
jsPanel.headerControl(jsP, value, action);
});
}
return jsP;
};
jsP.headerTitle = text => jsPanel.headerTitle(jsP, text);
jsP.front = () => {
jsP.css('z-index', jsPanel.setZi(jsP));
jsPanel.resetZis();
$(document).trigger('jspanelfronted', id);
if ($.isFunction(jsP.option.onfronted)) {
// do not close panel if onfronted callback returns false
if (jsP.option.onfronted.call(jsP, jsP) === false) {
return jsP;
} else {
jsP.option.onfronted.call(jsP, jsP);
}
}
return jsP;
};
jsP.normalize = () => {
if (jsP.data('status') === 'normalized') {return jsP;}
$(document).trigger('jspanelbeforenormalize', id);
if ($.isFunction(jsP.option.onbeforenormalize)) {
// do not normalize panel if onbeforenormalize callback returns false
if (jsP.option.onbeforenormalize.call(jsP, jsP) === false) {return jsP;}
}
jsP.css({
left: jsP.cachedData.left,
top: jsP.cachedData.top,
width: jsP.cachedData.width,
height: jsP.cachedData.height,
zIndex: function(){jsPanel.setZi(jsP);}
}).data('status', 'normalized')
.contentResize();
jsPanel.hideControls(".jsPanel-btn-normalize, .jsPanel-btn-smallifyrev", jsP);
// remove replacement
$('#' + jsP.prop('id') + '-min').remove();
$(document).trigger('jspanelnormalized', id);
$(document).trigger('jspanelstatuschange', id);
// call onnormalized callback
if ($.isFunction(jsP.option.onnormalized)) {jsP.option.onnormalized.call(jsP, jsP);}
return jsP;
};
jsP.maximize = () => {
let margins = jsP.option.maximizedMargin,
pnt = jsP[0].parentNode;
if (jsP.data('status') === 'maximized') {return jsP;}
// cache panel data like size and position etc. for later use
if (jsP.data('status') === 'normalized') {jsPanel.updateCachedData(jsP);}
$(document).trigger('jspanelbeforemaximize', id);
if ($.isFunction(jsP.option.onbeforemaximize)) {
// do not maximize panel if onbeforemaximize callback returns false
if (jsP.option.onbeforemaximize.call(jsP, jsP) === false) {return jsP;}
}
if (pnt === document.body) {
// maximize within window
jsP.css({
width: (document.documentElement.clientWidth - margins.left - margins.right) + 'px',
height: (document.documentElement.clientHeight - margins.top - margins.bottom) + 'px',
left: margins.left + 'px',
top: margins.top + 'px'
});
if (jsP.option.position.fixed === false) {
jsP.css({
left: (window.pageXOffset + margins.left) + 'px',
top: (window.pageYOffset + margins.top) + 'px'
});
}
} else {
// maximize within parentNode
jsP.css({
width: (pnt.clientWidth - margins.left - margins.right) + 'px',
height: (pnt.clientHeight - margins.top - margins.bottom) + 'px',
left: margins.left + 'px',
top: margins.top + 'px'
});
}
// update current panel data like size and position etc. for later use
jsP.contentResize()
.data('status', 'maximized')
.css('z-index', jsPanel.setZi(jsP));
jsPanel.hideControls(".jsPanel-btn-maximize, .jsPanel-btn-smallifyrev", jsP);
// remove replacement
$('#' + jsP.prop('id') + '-min').remove();
$(document).trigger('jspanelmaximized', id);
$(document).trigger('jspanelstatuschange', id);
// call onmximized callback
if ($.isFunction(jsP.option.onmaximized)) {jsP.option.onmaximized.call(jsP, jsP);}
return jsP;
};
jsP.minimize = () => {
if (jsP.data('status') === 'minimized') {return jsP;}
$(document).trigger('jspanelbeforeminimize', id);
if ($.isFunction(jsP.option.onbeforeminimize)) {
// do not minimize panel if onbeforeminimize callback returns false
if (jsP.option.onbeforeminimize.call(jsP, jsP) === false) {return jsP;}
}
let fontColor = jsP.header.headerbar.css('color'),
bgColor;
if (!jsP.hasClass('panel')) {
// if not a bootstrap theme
bgColor = jsP.css('background-color');
} else {
if (jsP.header.css('background-color') === 'transparent') {
bgColor = jsP.css('background-color');
} else {
bgColor = jsP.header.css('background-color');
}
}
// cache panel data like size and position etc. for later use
if (jsP.data('status') === 'normalized') {jsPanel.updateCachedData(jsP);}
// create the replacement elmt
let replacement = $(jsPanel.replacementTemplate);
// safe current css.left of jsPanel
replacement.left = jsP.css('left');
// move jsPanel off screen
jsP.css('left', '-9999px')
.data('status', 'minimized');
// set replacement colors
replacement.css({backgroundColor: bgColor})
.prop('id', jsP.prop('id') + '-min')
.find('h3').css({color: fontColor})
.html(jsP.headerTitle());
$('.jsPanel-btn', replacement).css({color: fontColor});
// append replacement
// cont has a positive length if option.container is .jsPanel-content or descendant of .jsPanel-content
// so childpanels are minimized to their parent panel
let cont = $(jsP.option.container).closest('.jsPanel-content');
if (!cont.length) {
$('#jsPanel-replacement-container').append(replacement);
} else {
if (!$('.jsPanel-minimized-box').length) {
$(cont[0]).append("
");
}
$('.jsPanel-minimized-box').append(replacement);
}
$(document).trigger('jspanelminimized', id);
$(document).trigger('jspanelstatuschange', id);
// call onminimized callback
if ($.isFunction(jsP.option.onminimized)) {jsP.option.onminimized.call(jsP, jsP);}
// set handlers for replacement controls and disable replacement control if needed
$('.jsPanel-btn-normalize', replacement).css('display', 'block').click(function(){
jsP.css('left', replacement.left);
replacement.remove();
$('.jsPanel-btn-normalize', jsP).trigger('click');
});
if(jsP[0].dataset.btnnormalize === 'disabled'){
$('.jsPanel-btn-normalize', replacement).css({pointerEvents: 'none', opacity: 0.5, cursor: 'default'});
} else if (jsP[0].dataset.btnnormalize === 'removed') {
$('.jsPanel-btn-normalize', replacement).remove();
}
$('.jsPanel-btn-maximize', replacement).click(function () {
jsP.css('left', replacement.left);
replacement.remove();
$('.jsPanel-btn-maximize', jsP).trigger('click');
});
if(jsP[0].dataset.btnmaximize === 'disabled'){
$('.jsPanel-btn-maximize', replacement).css({pointerEvents: 'none', opacity: 0.5, cursor: 'default'});
} else if (jsP[0].dataset.btnmaximize === 'removed') {
$('.jsPanel-btn-maximize', replacement).remove();
}
$('.jsPanel-btn-close', replacement).click(function(){
replacement.remove();
jsP.close();
});
if(jsP[0].dataset.btnclose === 'disabled'){
$('.jsPanel-btn-close', replacement).css({pointerEvents: 'none', opacity: 0.5, cursor: 'default'});
}
return jsP;
};
jsP.reposition = position => jsPanel.reposition(jsP, position);
jsP.resize = (width, height) => jsPanel.resize(jsP, width, height);
jsP.smallify = () => {
if (jsP.data('status') === "normalized" || jsP.data('status') === "maximized") {
if (jsP.data('status') !== "smallified" && jsP.data('status') !== "smallifiedMax") {
// store jsP height in function property
jsP.smallify.height = jsP.outerHeight();
jsP.animate({
height: jsP.header.headerbar.outerHeight() + 'px'
});
if (jsP.data('status') === 'maximized') {
jsPanel.hideControls(".jsPanel-btn-maximize, .jsPanel-btn-smallify", jsP);
jsP.data('status', 'smallifiedMax');
$(document).trigger('jspanelsmallifiedmax', id);
} else {
jsPanel.hideControls(".jsPanel-btn-normalize, .jsPanel-btn-smallify", jsP);
jsP.data('status', 'smallified');
$(document).trigger('jspanelsmallified', id);
}
$(document).trigger('jspanelstatuschange', id);
if ($.isFunction(jsP.option.onsmallified)) {
jsP.option.onsmallified.call(jsP, jsP);
}
}
} else if (jsP.data('status') !== "minimized") {
jsP.animate({ height: jsP.smallify.height });
if (jsP.data('status') === 'smallified') {
jsPanel.hideControls(".jsPanel-btn-normalize, .jsPanel-btn-smallifyrev", jsP);
jsP.data('status', 'normalized');
$(document).trigger('jspanelnormalized', id);
$(document).trigger('jspanelstatuschange', id);
} else {
jsPanel.hideControls(".jsPanel-btn-maximize, .jsPanel-btn-smallifyrev", jsP);
jsP.data('status', 'maximized');
$(document).trigger('jspanelmaximized', id);
$(document).trigger('jspanelstatuschange', id);
}
if ($.isFunction(jsP.option.onunsmallified)) {
jsP.option.onunsmallified.call(jsP, jsP);
}
}
jsP.css('z-index', jsPanel.setZi(jsP));
return jsP;
};
jsP.setTheme = (passedtheme = jsP.option.theme.toLowerCase().replace(/ /g, ""), callback) => {
// remove all whitespace from passedtheme
passedtheme = passedtheme.toLowerCase().replace(/ /g, "");
let theme = [], bs, bstheme;
// first remove all theme related syles
jsPanel.themes.forEach(function (value, index, array) {
jsP.removeClass('panel card card-inverse jsPanel-theme-' + value + ' panel-' + value + ' card-' + value);
});
jsP.header.removeClass('panel-heading').title.removeClass('panel-title');
jsP.content.removeClass('panel-body').css('border-top-color', '');
jsP.footer.removeClass('panel-footer card-footer');
jsP.css('background', '').content.css({borderTop:'', backgroundColor: '', color:''});
$('.jsPanel-hdr *', jsP).css({color: ''});
jsP.header.toolbar.css({boxShadow:'', width: '', marginLeft: ''});
if (passedtheme.endsWith('filled')) {
theme[1] = 'filled';
theme[0] = passedtheme.substr(0, passedtheme.length - 6);
} else if (passedtheme.endsWith('filledlight')) {
theme[1] = 'filledlight';
theme[0] = passedtheme.substr(0, passedtheme.length - 11);
} else {
theme[1] = "";
theme[0] = passedtheme; // theme[0] is the primary color
}
// if first part of theme includes a "-" it's assumed to be a bootstrap theme
if (theme[0].match('-')) {
bs = theme[0].split('-');
bstheme = true;
}
if (!bstheme) {
if (jsPanel.themes.includes(theme[0])) {
jsP.addClass('jsPanel-theme-' + theme[0]);
// optionally set theme style
if (theme[1] === 'filled') {
jsP.content.css('background', '').addClass('jsPanel-content-filled');
} else if (theme[1] === 'filledlight') {
jsP.content.css('background', '').addClass('jsPanel-content-filledlight');
}
if (!jsP.option.headerToolbar) {jsP.content.css({borderTop:'1px solid ' + jsP.header.title.css('color')});}
} else {
// arbitrary colors themes
let colors = jsPanel.calcColors(theme[0]); // colors: [primeColor, secondColor, fontColorForPrimary]
jsP.css('background-color', colors[0]);
$('.jsPanel-hdr *', jsP).css({color: colors[3]});
if (jsP.option.headerToolbar) {
jsP.header.toolbar.css({boxShadow:'0 0 1px ' + colors[3] + ' inset', width: 'calc(100% + 4px)', marginLeft: '-2px'});
} else {
jsP.content.css({borderTop:'1px solid ' + colors[3]});
}
if (theme[1] === 'filled') {
jsP.content.css({'background-color': colors[0], color: colors[3]});
} else if (theme[1] === 'filledlight') {
jsP.content.css({'background-color': colors[1]});
}
}
} else {
// bootstrap themes
let pColor, bsColors;
jsP.addClass('panel panel-' + bs[1])
.addClass('card card-inverse card-' + bs[1])
.header.addClass('panel-heading')
.title.addClass('panel-title');
jsP.content.addClass('panel-body')
// fix css problems for panels nested in other bootstrap panels
.css('border-top-color', () => { return jsP.header.css('border-top-color'); });
jsP.footer.addClass('panel-footer card-footer');
// optional
if ($('.panel-heading', jsP).css('background-color') === 'transparent') {
pColor = jsP.css('background-color').replace(/\s+/g, '');
} else {
pColor = $('.panel-heading', jsP).css('background-color').replace(/\s+/g, '');
}
bsColors = jsPanel.calcColors(pColor);
$('*', jsP.header).css('color', bsColors[3]);
if (jsP.option.headerToolbar) {
jsP.header.toolbar.css({boxShadow:'0 0 1px ' + bsColors[3] + ' inset', width: 'calc(100% + 4px)', marginLeft: '-2px'});
} else {
jsP.content.css({borderTop:'1px solid ' + bsColors[3]});
}
if (theme[1] === 'filled') {
jsP.content.css({backgroundColor: pColor, color: bsColors[3]});
} else if (theme[1] === 'filledlight') {
jsP.content.css({backgroundColor: bsColors[1], color: '#000000'});
}
}
if (jsP.option.border) {
jsP.css('border', jsP.option.border + ' ' + theme[0]);
} else {
jsP.css('border', 'none');
}
if (callback && $.isFunction(callback)) {
callback.call(jsP, jsP);
}
return jsP;
};
/* to ease migrating from version 2.5.x to version 3.x ------------------------------------------------------ */
jsP.addToolbar = jsP.toolbarAdd;
jsP.reloadContent = jsP.contentReload;
jsP.resizeContent = jsP.contentResize;
jsP.control = jsP.headerControl;
jsP.title = jsP.headerTitle;
/* ---------------------------------------------------------------------------------------------------------- */
// jsPanel close
$('.jsPanel-btn-close', jsP).on('click', e => {
e.preventDefault();
jsP.close();
});
// jsPanel minimize
$('.jsPanel-btn-minimize', jsP).on('click', e => {
e.preventDefault();
jsP.minimize();
});
// jsPanel maximize
$('.jsPanel-btn-maximize', jsP).on('click', e => {
e.preventDefault();
jsP.maximize();
});
// jsPanel normalize
$('.jsPanel-btn-normalize', jsP).on('click', e => {
e.preventDefault();
jsP.normalize();
});
// jsPanel smallify
$('.jsPanel-btn-smallify, .jsPanel-btn-smallifyrev', jsP).on('click', e => {
e.preventDefault();
jsP.smallify();
});
/* option.headerRemove,
option.headerControls (controls in header right) ------------------------------------- */
if (!jsP.option.headerRemove) {
if (jsP.option.headerControls.controls === 'closeonly') {
$(".jsPanel-btn:not(.jsPanel-btn-close)", jsP.header.headerbar).remove();
["maximize", "minimize", "normalize", "smallify"].forEach( ctrl => {
jsP[0].setAttribute('data-btn' + ctrl, 'removed');
});
jsP[0].setAttribute('data-btn-close', 'enabled');
} else if (jsP.option.headerControls.controls === 'none') {
$(jsP.header.controls).remove();
["close", "maximize", "minimize", "normalize", "smallify"].forEach( ctrl => {
jsP[0].setAttribute('data-btn' + ctrl, 'removed');
});
} else {
// disable controls individually
["close", "maximize", "minimize", "normalize", "smallify"].forEach( ctrl => {
if (jsP.option.headerControls[ctrl] === 'disable') {
// disable individual control btn and store btn status in data attr
jsP.headerControl(ctrl, 'disable');
} else if (jsP.option.headerControls[ctrl] === 'remove') {
jsP.headerControl(ctrl, 'remove');
} else {
jsP[0].setAttribute('data-btn' + ctrl, 'enabled');
}
});
}
} else {
jsP.header.remove();
jsP.content.addClass('jsPanel-content-noheader');
["close", "maximize", "minimize", "normalize", "smallify"].forEach( ctrl => {
jsP[0].setAttribute('data-btn' + ctrl, 'removed');
});
}
/* insert iconfonts if option.headerControls.iconfont set (default is "jsglyph") ---------------------------- */
jsPanel.configIconfont(jsP);
/* option.paneltype ----------------------------------------------------------------------------------------- */
if (jsP.option.paneltype === "modal") {
jsPanel.insertModalBackdrop(jsP);
jsP.addClass('jsPanel-modal').css('z-index', jsPanel.modalcount + 9999);
} else if (jsP.option.paneltype === 'hint') {
jsP.addClass('jsPanel-hint').css('z-index', 10000);
} else if (jsP.option.paneltype.tooltip) {
trigger = jsPanel.setTrigger(jsP.option.position); // elmt triggering the tooltip
jsP.addClass('jsPanel-tooltip');
jsPanel.setTooltipClass(jsP);
if (jsP.option.paneltype.solo) {jsPanel.closeTooltips();}
jsPanel.setTooltipMode(jsP, trigger);
}
/* option.container ----------------------------------------------------------------------------------------- */
jsP.appendTo(jsP.option.container);
jsPanel.activePanels.list.push(id);
if (jsP.option.paneltype.tooltip) {$(trigger).addClass('hasTooltip');}
$(document).trigger('jspanelloaded', id);
jsP.data('container', jsP.option.container);
/* option.theme now includes bootstrap ---------------------------------------------------------------------- */
jsP.setTheme();
/* corrections for a removed header */
if (jsP.option.headerRemove|| $('.jsPanel-hdr').length < 1 ) {jsP.content.css('border', 'none');}
/* option.headerToolbar | default: false -------------------------------------------------------------------- */
if (jsP.option.headerToolbar && !jsP.option.headerRemove) {jsPanel.toolbar(jsP, 'header', jsP.option.headerToolbar);}
/* option.footerToolbar | default: false -------------------------------------------------------------------- */
if (jsP.option.footerToolbar) {jsPanel.toolbar(jsP, 'footer', jsP.option.footerToolbar);}
/* option.content ------------------------------------------------------------------------------------------- */
if (jsP.option.content) {
jsP.content.append(jsP.option.content);
jsP.data("content", jsP.option.content);
}
/* option.contentAjax --------------------------------------------------------------------------------------- */
if (typeof jsP.option.contentAjax === 'string') {
jsP.option.contentAjax = {
url: jsP.option.contentAjax,
autoload: true
};
jsPanel.ajax(jsP);
} else if ($.isPlainObject(jsP.option.contentAjax)) {
jsPanel.ajax(jsP);
}
/* option.contentIframe ------------------------------------------------------------------------------------- */
if ($.isPlainObject(jsP.option.contentIframe) && (jsP.option.contentIframe.src || jsP.option.contentIframe.srcdoc)) {jsPanel.iframe(jsP);}
/* tooltips continued --------------------------------------------------------------------------------------- */
/* jquery.css() doesn't work properly if jsPanel isn't in the DOM yet, so the code for the tooltip connectors
is placed after the jsPanel is appended to the DOM !!! */
if (jsP.option.paneltype.connector) {jsPanel.addConnector(jsP);}
/* option.contentSize - needs to be set before option.position and should be after option.content ------------------ */
if (typeof jsP.option.contentSize === 'string') {
let sizes = jsP.option.contentSize.trim().split(' '),
sizesLength = sizes.length;
jsP.option.contentSize = {
width: sizes[0],
height: sizes[--sizesLength]
};
}
if (jsP.option.contentSize.height === 0) {jsP.option.contentSize.height = '0';}
jsP.content.css({
width: jsP.option.contentSize.width || $.jsPanel.defaults.contentSize.width,
height: jsP.option.contentSize.height || $.jsPanel.defaults.contentSize.height
});
jsP.css({
// necessary if title text exceeds content width & correction for panel padding
// or if content section is removed prior positioning
//width: jsP.content.outerWidth() + 'px',
width: function() {
if ($('.jsPanel-content', jsP).length > 0) {
return jsP.content.outerWidth() + 'px';
} else {
return jsP.option.contentSize.width || $.jsPanel.defaults.contentSize.width;
}
},
zIndex: function(){jsPanel.setZi(jsP);} // set z-index to get new panel to front;
});
// after content width is set and jsP width is set accordingly set content width to 100%
jsP.content.css('width', '100%');
/* option.position ------------------------------------------------------------------------------------------ */
jsPanel.position(jsP, jsP.option.position);
jsP.data('status', 'normalized');
$(document).trigger('jspanelstatuschange', id);
// handlers for doubleclicks -----------------------------------------------------------------------------------
// dblclicks disabled for normal modals, hints and tooltips
if (!jsP.option.paneltype) {
if (jsP.option.dblclicks) {
if (jsP.option.dblclicks.title) {
jsP.header.headerbar.on('dblclick', e => {
e.preventDefault();
jsPanel.dblclickhelper(jsP.option.dblclicks.title, jsP);
});
}
if (jsP.option.dblclicks.content) {
jsP.content.on('dblclick', e => {
e.preventDefault();
jsPanel.dblclickhelper(jsP.option.dblclicks.content, jsP);
});
}
if (jsP.option.dblclicks.footer) {
jsP.footer.on('dblclick', e => {
e.preventDefault();
jsPanel.dblclickhelper(jsP.option.dblclicks.footer, jsP);
});
}
}
}
/* option.contentOverflow | default: 'hidden' -------------------------------------------------------------- */
if (typeof jsP.option.contentOverflow === 'string') {
jsP.content.css('overflow', jsP.option.contentOverflow);
} else if ($.isPlainObject(jsP.option.contentOverflow)) {
jsP.content.css({
'overflow-y': jsP.option.contentOverflow.vertical || jsP.option.contentOverflow['overflow-y'],
'overflow-x': jsP.option.contentOverflow.horizontal || jsP.option.contentOverflow['overflow-x']
});
}
/* option.draggable ----------------------------------------------------------------------------------------- */
if ($.isPlainObject(jsP.option.draggable)) {
jsP.draggable(jsP.option.draggable);
} else if (jsP.option.draggable === 'disabled') {
// reset cursor, draggable deactivated
$('.jsPanel-hdr, .jsPanel-ftr', jsP).css('cursor', 'default');
// jquery ui draggable initialize disabled to allow to query status
jsP.draggable({disabled: true});
} else {
// draggable is not even initialised
$('.jsPanel-hdr, .jsPanel-ftr', jsP).css('cursor', 'default');
}
/* option.resizable ----------------------------------------------------------------------------------------- */
if ($.isPlainObject(jsP.option.resizable)) {
jsP.resizable(jsP.option.resizable);
} else if (jsP.option.resizable === 'disabled') {
// jquery ui resizable initialize disabled to allow to query status
jsP.resizable({ disabled: true });
$('.ui-icon-gripsmall-diagonal-se, .ui-resizable-handle.ui-resizable-sw', jsP).css({'background-image': 'none', 'text-indent': -9999});
$('.ui-resizable-handle', jsP).css({'cursor': 'inherit'});
}
jsP.on("resize", () => jsP.contentResize() );
/* option.rtl | default: false - needs to be after option.resizable ----------------------------------------- */
if (jsP.option.rtl.rtl === true) {
$('.jsPanel-hdr, .jsPanel-headerbar, .jsPanel-titlebar, .jsPanel-controlbar, .jsPanel-hdr-toolbar, .jsPanel-ftr', jsP).addClass('jsPanel-rtl');
[ jsP.header.title, jsP.content, $("*", jsP.header.toolbar), $("*", jsP.footer) ].forEach( item => {
item.prop('dir', 'rtl');
if (jsP.option.rtl.lang) {item.prop('lang', jsP.option.rtl.lang);}
});
$('.ui-icon-gripsmall-diagonal-se', jsP).css({backgroundImage: 'none', textIndent: -9999});
}
/* option.show ---------------------------------------------------------------------------------------------- */
if (typeof jsP.option.show === "string") {jsP.addClass(jsP.option.show).css('opacity', 1);} //extra call to jQuery.css() needed for EDGE
/* option.headerTitle | needs to be late in the file! ------------------------------------------------------- */
jsP.header.title.empty().prepend(jsP.option.headerTitle);
/* VARIOUS EVENT HANDLERS ----------------------------------------------------------------------------------- */
// handler to move panel to foreground
jsP[0].addEventListener('mousedown', (e) => {
let zi = $(e.target).closest('.jsPanel').css('z-index');
if (!jsP.hasClass("jsPanel-modal") && zi <= jsPanel.zi) { jsP.front(); }
}, false);
jsPanel.updateCachedData(jsP);
/* option.setstatus ----------------------------------------------------------------------------------------- */
if (typeof jsP.option.setstatus === 'string') {
(jsP.option.setstatus === 'maximize smallify') ? jsP.maximize().smallify() : jsP[jsP.option.setstatus]();
}
/* option.autoclose | default: false ------------------------------------------------------------------------ */
if (typeof jsP.option.autoclose === 'number' && jsP.option.autoclose > 0) {
window.setTimeout(() => {
if (jsP) {jsP.close();}
}, jsP.option.autoclose);
}
// hndlers to normalize a panel and reset controls when resizing a smallified panel with mouse
jsP.on("resizestart", function () {
oW = jsP.outerWidth();
oH = jsP.outerHeight();
});
// but only when panel height changed (it's possible to resize only width of smallified panel)
jsP.on("resizestop", function () {
if (jsP.outerWidth() !== oW && jsP.outerHeight() === oH) {
jsPanel.hideControls(".jsPanel-btn-maximize, .jsPanel-btn-smallify", jsP);
jsP.data('status', 'smallified');
$(document).trigger('jspanelsmallified', id);
$(document).trigger('jspanelstatuschange', id);
} else if (jsP.outerHeight() !== oH) {
jsPanel.hideControls(".jsPanel-btn-normalize, .jsPanel-btn-smallifyrev", jsP);
jsP.data('status', 'normalized');
$(document).trigger('jspanelnormalized', id);
$(document).trigger('jspanelstatuschange', id);
}
});
/* adding a few methods/props directly to the HTMLElement --------------------------------------------------- */
jsP[0].jspanel = {
options: jsP.option,
close() { jsP.close(); },
normalize() {
jsP.normalize();
return jsP;
},
maximize() {
jsP.maximize();
return jsP;
},
minimize() {
jsP.minimize();
return jsP;
},
smallify() {
jsP.smallify();
return jsP;
},
front() {jsP.front();
return jsP;
},
closeChildpanels() {
jsP.closeChildpanels();
return jsP;
},
reposition(pos) {
jsP.reposition(pos);
return jsP;
},
resize(w,h) {
jsP.resize(w,h);
return jsP;
},
contentResize() {jsP.contentResize();
return jsP;
},
contentReload() {
jsP.contentReload();
return jsP;
},
headerTitle(text) {
jsP.headerTitle(text);
return jsP;
},
headerControl(ctrl, action) {
jsP.headerControl(ctrl, action);
return jsP;
},
toolbarAdd(place, tb) {
jsP.toolbarAdd(place, tb);
return jsP;
},
setTheme(theme) {
jsP.setTheme(theme);
return jsP;
},
noop() {
return jsP; // used in jsPanel.activePanels.getPanel()
}
};
// sample: document.getElementById('jsPanel-1').jspanel.close();
// or: document.querySelector('#jsPanel-1').jspanel.close();
// or using jquery: $('#jsPanel-1')[0].jspanel.close();
/* jsP.option.callback -------------------------------------------------------------------------------------- */
if (jsP.option.callback && $.isFunction(jsP.option.callback)) {
jsP.option.callback.call(jsP, jsP);
} else if ($.isArray(jsP.option.callback)) {
jsP.option.callback.forEach(item => {
if ($.isFunction(item)) {item.call(jsP, jsP);}
});
}
return jsP;
};
$.jsPanel.defaults = {
"autoclose": false,
"border": false,
"callback": false,
"container": 'body',
"content": false,
"contentAjax": false,
"contentIframe": false,
"contentOverflow": 'hidden',
"contentSize": {
width: 400,
height: 200
},
"custom": false,
"dblclicks": false,
"draggable": {
handle: 'div.jsPanel-hdr, div.jsPanel-ftr',
opacity: 0.8
},
"footerToolbar": false,
"headerControls": {
close: false,
maximize: false,
minimize: false,
normalize: false,
smallify: false,
controls: 'all',
iconfont: 'jsglyph'
},
"headerRemove": false,
"headerTitle": 'jsPanel',
"headerToolbar": false,
"id": () => `jsPanel-${jsPanel.id += 1}`,
"load": false,
"maximizedMargin": {
top: 5,
right: 5,
bottom: 5,
left: 5
},
"onbeforeclose": false,
"onbeforemaximize": false,
"onbeforeminimize": false,
"onbeforenormalize": false,
"onclosed": false,
"onmaximized": false,
"onminimized": false,
"onnormalized": false,
"onbeforeresize": false,
"onresized": false,
"onsmallified": false,
"onunsmallified": false,
"onfronted": false,
"paneltype": false,
"position": {
my: 'center',
at: 'center'
// all other defaults are set in jsPanel.position()
},
"resizable": {
handles: 'n, e, s, w, ne, se, sw, nw',
autoHide: false,
minWidth: 40,
minHeight: 40
},
"rtl": false,
"setstatus": false,
"show": false,
"template": false,
"theme": 'default'
};
$.jsPanel.modaldefaults = {
"draggable": 'disabled',
"headerControls": {controls: "closeonly"},
"position": {
my: 'center',
at: 'center'
},
"resizable": 'disabled'
};
$.jsPanel.tooltipdefaults = {
"draggable": false,
"headerControls": {controls: "closeonly"},
"position": {fixed: false},
"resizable": false
};
$.jsPanel.hintdefaults = {
"autoclose": 8000,
"draggable": false,
"headerControls": {controls: "closeonly"},
"resizable": false
};
/* body click handler: remove all tooltips on click in body except click is inside a jsPanel or trigger of tooltip */
$(document).ready(function () {
document.body.addEventListener('click', e => {
let isTT = $(e.target).closest('.jsPanel').length;
if (isTT < 1 && !$(e.target).hasClass('hasTooltip')) {
jsPanel.closeTooltips();
$('.hasTooltip').removeClass('hasTooltip');
}
}, false);
});
}(jQuery));