@progress/kendo-ui
Version:
This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.
1,341 lines (1,340 loc) • 58.5 kB
JavaScript
//#region ../src/kendo.window.js
const __meta__ = {
id: "window",
name: "Window",
category: "web",
description: "The Window widget displays content in a modal or non-modal HTML window.",
depends: [
"draganddrop",
"popup",
"icons"
],
features: [{
id: "window-fx",
name: "Animation",
description: "Support for animation",
depends: ["fx"]
}]
};
(function($, undefined) {
var kendo = window.kendo, Widget = kendo.ui.Widget, TabKeyTrap = kendo.ui.Popup.TabKeyTrap, Draggable = kendo.ui.Draggable, isPlainObject = $.isPlainObject, activeElement = kendo._activeElement, outerWidth = kendo._outerWidth, outerHeight = kendo._outerHeight, extend = $.extend, each = $.each, template = kendo.template, BODY = "body", templates, NS = ".kendoWindow", MODAL_NS = ".kendoWindowModal", KWINDOW = ".k-window", KWINDOWTITLE = ".k-window-title", KWINDOWTITLEBAR = KWINDOWTITLE + "bar", KWINDOWCONTENT = ".k-window-content", KDIALOGCONTENT = ".k-dialog-content", KWINDOWRESIZEHANDLES = ".k-resize-handle", KOVERLAY = ".k-overlay", KWINDOWMINIMIZED = "k-window-minimized", KCONTENTFRAME = "k-content-frame", LOADINGICONCLASS = "k-i-loading", KHOVERSTATE = "k-hover", KFOCUSEDSTATE = "k-focus", MAXIMIZEDSTATE = "k-window-maximized", INLINE_FLEX = "k-display-inline-flex", VISIBLE = ":visible", KHIDDEN = "k-hidden", HIDDEN = "hidden", CURSOR = "cursor", OPEN = "open", ACTIVATE = "activate", DEACTIVATE = "deactivate", CLOSE = "close", REFRESH = "refresh", MINIMIZE = "minimize", MAXIMIZE = "maximize", RESIZESTART = "resizeStart", RESIZE = "resize", RESIZEEND = "resizeEnd", DRAGSTART = "dragstart", DRAGEND = "dragend", RESTORE = "restore", KENDOKEYDOWN = "kendoKeydown", ERROR = "error", OVERFLOW = "overflow", DATADOCOVERFLOWRULE = "original-overflow-rule", ZINDEX = "zIndex", MINIMIZE_MAXIMIZEICONSELECTORS = ".k-window-titlebar-actions .k-i-window-minimize,.k-window-titlebar-actions .k-i-window,.k-window-titlebar-actions .k-svg-i-window-minimize,.k-window-titlebar-actions .k-svg-i-window", KPINICONCLASSSELECTOR = ".k-i-pin,.k-svg-i-pin", KUNPINICONCLASSSELECTOR = ".k-i-unpin,.k-svg-i-unpin", PIN_UNPINICONCLASSSELECTOR = KPINICONCLASSSELECTOR + "," + KUNPINICONCLASSSELECTOR, TITLEBAR_BUTTONSSELECTOR = ".k-window-titlebar .k-window-titlebar-action", REFRESHICONSELECTOR = ".k-window-titlebar .k-i-arrow-rotate-cw,.k-window-titlebar .k-svg-i-arrow-rotate-cw", WINDOWEVENTSHANDLED = "WindowEventsHandled", zero = /^0[a-z]*$/i, isLocalUrl = kendo.isLocalUrl, SIZE = {
small: "k-window-sm",
medium: "k-window-md",
large: "k-window-lg"
};
function defined(x) {
return typeof x != "undefined";
}
function toInt(element, property) {
return parseInt(element.css(property), 10) || 0;
}
function constrain(value, low, high) {
var normalizedValue;
if (value && isNaN(value) && value.toString().indexOf("px") < 0) {
normalizedValue = value;
} else {
normalizedValue = Math.max(Math.min(parseInt(value, 10), high === Infinity ? high : parseInt(high, 10)), low === -Infinity ? low : parseInt(low, 10));
}
return normalizedValue;
}
function executableScript() {
return !this.type || this.type.toLowerCase().indexOf("script") >= 0;
}
function getPosition(elem) {
var result = {
top: elem.offsetTop,
left: elem.offsetLeft
}, parent = elem.offsetParent;
while (parent) {
result.top += parent.offsetTop;
result.left += parent.offsetLeft;
var parentOverflowX = $(parent).css("overflowX");
var parentOverflowY = $(parent).css("overflowY");
if (parentOverflowY === "auto" || parentOverflowY === "scroll") {
result.top -= parent.scrollTop;
}
if (parentOverflowX === "auto" || parentOverflowX === "scroll") {
result.left -= parent.scrollLeft;
}
parent = parent.offsetParent;
}
return result;
}
var Window = Widget.extend({
init: function(element, options) {
var that = this, wrapper, offset = {}, visibility, display, position, isVisible = false, content, windowContent, windowFrame, globalWindow, suppressActions = options && options.actions && !options.actions.length, id;
Widget.fn.init.call(that, element, options);
options = that.options;
position = options.position;
element = that.element;
content = options.content;
globalWindow = $(window);
if (suppressActions) {
options.actions = [];
}
that.appendTo = $(options.appendTo);
that.containment = options.draggable.containment ? $(options.draggable.containment).first() : null;
if (content && !isPlainObject(content)) {
content = options.content = { url: content };
}
element.find("script").filter(executableScript).remove();
if (!element.parent().is(that.appendTo) && !that.containment && (position.top === undefined || position.left === undefined)) {
if (element.is(VISIBLE)) {
offset = element.offset();
isVisible = true;
} else {
visibility = element.css("visibility");
display = element.css("display");
element.css({
visibility: HIDDEN,
display: ""
});
if (document.body.contains(element[0])) {
offset = element.offset();
} else {
offset = {
top: 0,
left: 0
};
}
element.css({
visibility,
display
});
}
if (position.top === undefined) {
position.top = offset.top;
}
if (position.left === undefined) {
position.left = offset.left;
}
}
if (!defined(options.visible) || options.visible === null) {
options.visible = element.is(VISIBLE);
}
wrapper = that.wrapper = element.closest(KWINDOW);
if (!element.is(".k-window-content") || !wrapper[0]) {
element.addClass("k-window-content");
element.attr("tabindex", 0);
that._createWindow(element, options);
wrapper = that.wrapper = element.closest(KWINDOW);
that.title(that.options.title);
that._dimensions();
if (options._footerTemplate) {
that.wrapper.append(kendo.template(options._footerTemplate)(options._footerMessages));
}
}
if (options.themeColor && options.themeColor !== "none") {
wrapper.addClass(kendo.getValidCssClass("k-window-", "themeColor", options.themeColor));
}
that.minTop = that.minLeft = -Infinity;
that.maxTop = that.maxLeft = Infinity;
that._position();
if (content) {
that.refresh(content);
}
if (options.visible) {
that.toFront(null, !options.modal);
}
windowContent = wrapper.children(KWINDOWCONTENT);
if (options.visible && options.modal) {
that._overlay(wrapper.is(VISIBLE)).css({ opacity: .5 });
}
wrapper.on("mouseenter" + NS, TITLEBAR_BUTTONSSELECTOR, that._buttonEnter.bind(that)).on("mouseleave" + NS, TITLEBAR_BUTTONSSELECTOR, that._buttonLeave.bind(that)).on("click" + NS, "> " + TITLEBAR_BUTTONSSELECTOR, that._windowActionHandler.bind(that)).on("keydown" + NS, that, that._keydown.bind(that)).on("focus" + NS, that._focus.bind(that)).on("blur" + NS, that._blur.bind(that));
windowContent.on("keydown" + NS, that, that._keydownContent.bind(that));
windowFrame = windowContent.find("." + KCONTENTFRAME)[0];
if (windowFrame && !globalWindow.data(WINDOWEVENTSHANDLED)) {
globalWindow.on("blur" + NS, function() {
var element = $(document.activeElement).parent(KWINDOWCONTENT);
if (element.length) {
var windowInstance = kendo.widgetInstance(element);
windowInstance._focus();
}
});
globalWindow.on("focus" + NS, function() {
$(KWINDOWCONTENT).not(KDIALOGCONTENT).each(function(i, element) {
kendo.widgetInstance($(element))._blur();
});
});
globalWindow.data(WINDOWEVENTSHANDLED, true);
}
this._resizable();
this._draggable();
if (options.pinned && this.wrapper.is(":visible")) {
that.pin();
}
id = element.attr("id");
if (id) {
id = id + "_wnd_title";
wrapper.attr({
"role": "dialog",
"aria-labelledby": id
}).children(KWINDOWTITLEBAR).children(KWINDOWTITLE).attr("id", id);
}
wrapper.add(wrapper.children(".k-resize-handle," + KWINDOWTITLEBAR)).on(kendo.support.mousedown + NS, that.toFront.bind(that));
that.touchScroller = kendo.touchScroller(element);
that._resizeHandler = that._onDocumentResize.bind(that);
that._marker = kendo.guid().substring(0, 8);
$(window).on("resize" + NS + that._marker, that._resizeHandler);
if (options.visible) {
that.trigger(OPEN);
that.trigger(ACTIVATE);
}
kendo.notify(that);
if (this.options.modal) {
this._tabKeyTrap = new TabKeyTrap(wrapper);
this._tabKeyTrap.trap();
this._tabKeyTrap.shouldTrap = function() {
return wrapper.data("isFront");
};
}
if (that._showWatermarkOverlay) {
that._showWatermarkOverlay(that.wrapper[0]);
}
},
_buttonEnter: function(e) {
$(e.currentTarget).addClass(KHOVERSTATE);
},
_buttonLeave: function(e) {
$(e.currentTarget).removeClass(KHOVERSTATE);
},
_focus: function() {
this.wrapper.addClass(KFOCUSEDSTATE);
},
_blur: function() {
this.wrapper.removeClass(KFOCUSEDSTATE);
},
_dimensions: function() {
var wrapper = this.wrapper;
var options = this.options;
var width = options.width;
var height = options.height;
var maxHeight = options.maxHeight;
var sizeClass = options.size;
var dimensions = [
"minWidth",
"minHeight",
"maxWidth",
"maxHeight"
];
var contentBoxSizing = wrapper.css("box-sizing") == "content-box";
var lrBorderWidth = contentBoxSizing ? toInt(wrapper, "border-left-width") + toInt(wrapper, "border-right-width") : 0;
var tbBorderWidth = contentBoxSizing ? toInt(wrapper, "border-top-width") + toInt(wrapper, "border-bottom-width") : 0;
var paddingTop = contentBoxSizing ? toInt(wrapper, "padding-top") : 0;
if (this.containment && !this._isPinned) {
this._updateBoundaries();
options.maxHeight = Math.min(this.containment.height - (tbBorderWidth + paddingTop), maxHeight);
options.maxWidth = Math.min(this.containment.width - lrBorderWidth, options.maxWidth);
}
for (var i = 0; i < dimensions.length; i++) {
var value = options[dimensions[i]] || "";
if (value != Infinity) {
wrapper.css(dimensions[i], value);
}
}
if (maxHeight != Infinity) {
this.element.css("maxHeight", maxHeight);
}
if (width) {
wrapper.outerWidth(constrain(width, options.minWidth, options.maxWidth));
} else {
wrapper.outerWidth("");
}
if (height) {
wrapper.outerHeight(constrain(height, options.minHeight, options.maxHeight));
} else {
wrapper.outerHeight("");
}
if (!options.visible) {
wrapper.removeClass(INLINE_FLEX).hide();
}
if (sizeClass && SIZE[sizeClass]) {
wrapper.addClass(SIZE[sizeClass]);
}
},
_position: function() {
var wrapper = this.wrapper, position = this.options.position, containmentTop, containmentLeft;
this._updateBoundaries();
if (this.containment) {
position.top = position.top || 0;
position.left = position.left || 0;
containmentTop = position.top.toString().indexOf("%") > 0 ? parseInt(this.containment.height * (parseFloat(position.top) / 100), 10) : position.top;
containmentLeft = position.left.toString().indexOf("%") > 0 ? parseInt(this.containment.width * (parseFloat(position.left) / 100), 10) : position.left;
position.top = constrain(containmentTop, this.minTop, this.maxTop);
position.left = constrain(containmentLeft, this.minLeft, this.maxLeft);
}
if (position.top && position.top.toString().indexOf("px") > 0) {
position.top = Number(position.top.replace("px", ""));
}
if (position.left && position.left.toString().indexOf("px") > 0) {
position.left = Number(position.left.replace("px", ""));
}
if (position.top === 0) {
position.top = position.top.toString();
}
if (position.left === 0) {
position.left = position.left.toString();
}
wrapper.css({
top: position.top || "",
left: position.left || ""
});
},
_updateBoundaries: function() {
var containment = this.containment;
if (!containment) {
return null;
}
containment.width = containment.innerWidth();
containment.height = containment.innerHeight();
if (parseInt(containment.width, 10) > containment[0].clientWidth) {
containment.width -= kendo.support.scrollbar();
}
if (parseInt(containment.height, 10) > containment[0].clientHeight) {
containment.height -= kendo.support.scrollbar();
}
containment.position = getPosition(containment[0]);
if (this._isPinned) {
this.minTop = this.minLeft = -Infinity;
this.maxTop = this.maxLeft = Infinity;
} else {
this.minTop = containment.scrollTop();
this.minLeft = containment.scrollLeft();
this.maxLeft = this.minLeft + containment.width - outerWidth(this.wrapper, true);
this.maxTop = this.minTop + containment.height - outerHeight(this.wrapper, true);
}
},
_animationOptions: function(id) {
var animation = this.options.animation;
var basicAnimation = {
open: { effects: {} },
close: {
hide: true,
effects: {}
}
};
return animation && animation[id] || basicAnimation[id];
},
_resize: function() {
kendo.resize(this.element.children());
},
_resizable: function() {
var resizable = this.options.resizable;
var wrapper = this.wrapper;
if (this.resizing) {
wrapper.off("dblclick" + NS).children(KWINDOWRESIZEHANDLES).remove();
this.resizing.destroy();
this.resizing = null;
}
if (resizable) {
wrapper.on("dblclick" + NS, KWINDOWTITLEBAR, (function(e) {
if (!$(e.target).closest(".k-window-titlebar-action").length) {
this.toggleMaximization();
}
}).bind(this));
each("n e s w se sw ne nw".split(" "), function(index, handler) {
wrapper.append(templates.resizeHandle(handler));
});
this.resizing = new WindowResizing(this);
}
wrapper = null;
},
_draggable: function() {
var draggable = this.options.draggable;
if (this.dragging) {
this.dragging.destroy();
this.dragging = null;
}
if (draggable) {
this.dragging = new WindowDragging(this, draggable.dragHandle || KWINDOWTITLEBAR, draggable.clickMoveClick);
}
},
_actions: function() {
var options = this.options;
var actions = options.actions;
var pinned = options.pinned;
var titlebar = this.wrapper.children(KWINDOWTITLEBAR);
var container = titlebar.find(".k-window-titlebar-actions");
var windowSpecificCommands = ["minimize", "maximize"];
var icons = {
"maximize": "window",
"refresh": "arrow-rotate-cw",
"custom": "gear"
};
var icon;
actions = $.map(actions, function(action) {
action = pinned && action.toLowerCase() === "pin" ? "unpin" : action;
icon = icons[action.toLowerCase()] || "";
return {
name: windowSpecificCommands.indexOf(action.toLowerCase()) > -1 ? "window-" + action : action,
icon: action.toLowerCase() == "close" ? "x" : icon
};
});
container.html(kendo.render(templates.action, actions));
},
setOptions: function(options) {
var that = this;
var sizeClass = that.options.size;
var doc = this.containment && !that._isPinned ? this.containment : $(document);
var cachedOptions = JSON.parse(JSON.stringify(options));
that.wrapper.removeClass(kendo.getValidCssClass("k-window-", "themeColor", that.options.themeColor));
extend(options.position, that.options.position);
extend(options.position, cachedOptions.position);
that._containerScrollTop = doc.scrollTop();
that._containerScrollLeft = doc.scrollLeft();
Widget.fn.setOptions.call(that, options);
var scrollable = that.options.scrollable !== false;
that.restore();
if (typeof options.title !== "undefined") {
that.title(options.title);
}
that.wrapper.removeClass(SIZE[sizeClass]);
that._dimensions();
that._position();
that._resizable();
that._draggable();
that._actions();
if (that.options.themeColor && that.options.themeColor !== "none") {
that.wrapper.addClass(kendo.getValidCssClass("k-window-", "themeColor", that.options.themeColor));
}
if (typeof options.modal !== "undefined") {
var visible = that.options.visible !== false;
that._enableDocumentScrolling();
that._overlay(options.modal && visible);
}
that.element.css(OVERFLOW, scrollable ? "" : "hidden");
},
events: [
OPEN,
ACTIVATE,
DEACTIVATE,
CLOSE,
MINIMIZE,
MAXIMIZE,
REFRESH,
RESTORE,
RESIZESTART,
RESIZE,
RESIZEEND,
DRAGSTART,
DRAGEND,
KENDOKEYDOWN,
ERROR
],
options: {
name: "Window",
animation: {
open: {
effects: {
zoom: { direction: "in" },
fade: { direction: "in" }
},
duration: 350
},
close: {
effects: {
zoom: {
direction: "out",
properties: { scale: .7 }
},
fade: { direction: "out" }
},
duration: 350,
hide: true
}
},
title: "",
themeColor: "",
actions: ["Close"],
autoFocus: true,
modal: false,
size: "auto",
resizable: true,
draggable: true,
minWidth: 90,
minHeight: 50,
maxWidth: Infinity,
maxHeight: Infinity,
pinned: false,
scrollable: true,
position: {},
content: null,
visible: null,
height: null,
width: null,
appendTo: "body",
isMaximized: false,
isMinimized: false
},
_closable: function() {
return $.inArray("close", $.map(this.options.actions, function(x) {
return x.toLowerCase();
})) > -1;
},
_keydownContent: function(e) {
var that = this, keys = kendo.keys, keyCode = e.keyCode;
if (keyCode == keys.ESC && that._closable()) {
e.stopPropagation();
that._close(false);
}
},
_keydown: function(e) {
var that = this, options = that.options, keys = kendo.keys, keyCode = e.keyCode, wrapper = that.wrapper, offset, handled, distance = 10, isMaximized = options.isMaximized, isMinimized = options.isMinimized, newWidth, newHeight, w, h;
if (keyCode == keys.ESC && that._closable()) {
e.stopPropagation();
that._close(false);
}
if (e.target != e.currentTarget || that._closing) {
return;
}
if (e.altKey && keyCode == 82) {
that.refresh();
}
if (e.altKey && keyCode == 80) {
if (that.options.pinned) {
that.unpin();
} else {
that.pin();
}
}
if (e.altKey && keyCode == keys.UP) {
if (isMinimized) {
that.restore();
that.wrapper.trigger("focus");
} else if (!isMaximized) {
that.maximize();
that.wrapper.trigger("focus");
}
} else if (e.altKey && keyCode == keys.DOWN) {
if (!isMinimized && !isMaximized) {
that.minimize();
that.wrapper.trigger("focus");
} else if (isMaximized) {
that.restore();
that.wrapper.trigger("focus");
}
}
offset = kendo.getOffset(wrapper);
if (that.containment && !that._isPinned) {
offset = that.options.position;
}
if (options.draggable && !e.ctrlKey && !e.altKey && !isMaximized) {
that._updateBoundaries();
if (keyCode == keys.UP) {
offset.top = constrain(offset.top - distance, that.minTop, that.maxTop);
handled = wrapper.css("top", offset.top);
} else if (keyCode == keys.DOWN) {
offset.top = constrain(offset.top + distance, that.minTop, that.maxTop);
handled = wrapper.css("top", offset.top);
} else if (keyCode == keys.LEFT) {
offset.left = constrain(offset.left - distance, that.minLeft, that.maxLeft);
handled = wrapper.css("left", offset.left);
} else if (keyCode == keys.RIGHT) {
offset.left = constrain(offset.left + distance, that.minLeft, that.maxLeft);
handled = wrapper.css("left", offset.left);
}
}
if (options.resizable && e.ctrlKey && !isMaximized && !isMinimized) {
if (keyCode == keys.UP) {
handled = true;
newHeight = wrapper.outerHeight() - distance;
} else if (keyCode == keys.DOWN) {
handled = true;
if (that.containment && !that._isPinned) {
newHeight = Math.min(wrapper.outerHeight() + distance, that.containment.height - offset.top - toInt(wrapper, "padding-top") - toInt(wrapper, "borderBottomWidth") - toInt(wrapper, "borderTopWidth"));
} else {
newHeight = wrapper.outerHeight() + distance;
}
} else if (keyCode == keys.LEFT) {
handled = true;
newWidth = wrapper.outerWidth() - distance;
} else if (keyCode == keys.RIGHT) {
handled = true;
if (that.containment && !that._isPinned) {
newWidth = Math.min(wrapper.outerWidth() + distance, that.containment.width - offset.left - toInt(wrapper, "borderLeftWidth") - toInt(wrapper, "borderRightWidth"));
} else {
newWidth = wrapper.outerWidth() + distance;
}
}
if (handled) {
w = constrain(newWidth, options.minWidth, options.maxWidth);
h = constrain(newHeight, options.minHeight, options.maxHeight);
if (!isNaN(w)) {
wrapper.outerWidth(w);
that.options.width = w + "px";
}
if (!isNaN(h)) {
wrapper.outerHeight(h);
that.options.height = h + "px";
}
that.resize();
}
}
if (handled) {
e.preventDefault();
}
},
_overlay: function(visible) {
var overlay = this.containment ? this.containment.children(KOVERLAY) : this.appendTo.children(KOVERLAY), wrapper = this.wrapper, display = visible ? "inline-flex" : "none", zIndex = parseInt(wrapper.css(ZINDEX), 10) - 1;
if (!overlay.length) {
overlay = $("<div class='k-overlay' />");
}
overlay.insertBefore(wrapper[0]).css({
zIndex,
display
});
if (this.options.modal.preventScroll && !this.containment) {
this._stopDocumentScrolling();
}
return overlay;
},
_actionForIcon: function(icon) {
var iconClass = /\bk(-svg)?-i(-\w+)+\b/.exec(icon[0].className)[0];
return {
"x": "_close",
"window": "maximize",
"window-minimize": "minimize",
"window-restore": "restore",
"arrow-rotate-cw": "refresh",
"pin": "pin",
"unpin": "unpin"
}[iconClass.replace(/(k-i-|k-svg-i-)/, "")];
},
_windowActionHandler: function(e) {
if (this._closing) {
return;
}
var icon = $(e.target).closest(".k-window-titlebar-action").find(".k-icon,.k-svg-icon");
var action = this._actionForIcon(icon);
if (action) {
e.preventDefault();
this[action]();
return false;
}
},
_modals: function() {
var that = this, windowElements = $(KWINDOW + VISIBLE), windowInstance, modals = [];
for (var i = 0; i < windowElements.length; i += 1) {
windowInstance = that._object($(windowElements[i]));
if (windowInstance && windowInstance.options && windowInstance.options.modal && windowInstance.options.visible && windowInstance.options.appendTo === that.options.appendTo && (!windowInstance.containment || that.containment && windowInstance.containment[0] === that.containment[0])) {
modals.push(windowInstance.wrapper[0]);
}
}
modals.sort(function(a, b) {
return a.style.zIndex - b.style.zIndex;
});
that = null;
return $(modals);
},
_object: function(element) {
var content = element.children(KWINDOWCONTENT);
var widget = content.getKendoWindow();
if (widget) {
return widget;
}
return undefined;
},
center: function() {
var that = this, position = that.options.position, wrapper = that.wrapper, documentWindow = $(window), scrollTop = 0, scrollLeft = 0, newTop, newLeft;
if (that.options.isMaximized) {
return that;
}
if (that.options.pinned && !that._isPinned) {
that.pin();
}
if (!that.options.pinned) {
scrollTop = documentWindow.scrollTop();
scrollLeft = documentWindow.scrollLeft();
}
if (this.containment && !that.options.pinned) {
newTop = this.minTop + (this.maxTop - this.minTop) / 2;
newLeft = this.minLeft + (this.maxLeft - this.minLeft) / 2;
} else {
that._scrollIsAppended = true;
newLeft = scrollLeft + Math.max(0, (documentWindow.width() - wrapper.outerWidth()) / 2);
newTop = scrollTop + Math.max(0, (documentWindow.height() - wrapper.outerHeight() - toInt(wrapper, "paddingTop")) / 2);
}
wrapper.css({
left: newLeft,
top: newTop
});
position.top = newTop;
position.left = newLeft;
return that;
},
title: function(title) {
var that = this, value, encoded = true, wrapper = that.wrapper, titleBar = wrapper.children(KWINDOWTITLEBAR), titleElement = titleBar.children(KWINDOWTITLE);
if (!arguments.length) {
return titleElement.html();
}
if ($.isPlainObject(title)) {
value = typeof title.text !== "undefined" ? title.text : "";
encoded = title.encoded !== false;
} else {
value = title;
}
if (value === false) {
wrapper.addClass("k-window-titleless");
wrapper.css("padding-top", 0);
titleBar.remove();
} else {
if (!titleBar.length) {
wrapper.prepend(templates.titlebar({ title: encoded ? kendo.htmlEncode(value) : value }));
that._actions();
titleBar = wrapper.children(KWINDOWTITLEBAR);
} else {
titleElement.html(encoded ? kendo.htmlEncode(value) : value);
}
}
that.options.title = value;
return that;
},
content: function(html, data) {
var content = this.wrapper.children(KWINDOWCONTENT), scrollContainer = content.children(".km-scroll-container");
content = scrollContainer[0] ? scrollContainer : content;
if (!defined(html)) {
return content.html();
}
kendo.destroy(this.element.children());
content.empty().html(html);
return this;
},
open: function() {
var that = this, wrapper = that.wrapper, options = that.options, showOptions = this._animationOptions("open"), contentElement = wrapper.children(KWINDOWCONTENT), overlay, otherModalsVisible, containmentContext = this.containment && !that._isPinned, doc = containmentContext ? this.containment : $(document);
if (!that.trigger(OPEN)) {
if (that._closing) {
wrapper.kendoStop(true, true);
}
that._closing = false;
that.toFront();
if (options.autoFocus) {
that.wrapper.trigger("focus");
}
options.visible = true;
if (options.modal) {
otherModalsVisible = !!that._modals().length;
overlay = that._overlay(otherModalsVisible);
overlay.kendoStop(true, true);
if (showOptions.duration && kendo.effects.Fade && !otherModalsVisible) {
var overlayFx = kendo.fx(overlay).fadeIn();
overlayFx.duration(showOptions.duration || 0);
overlayFx.endValue(.5);
overlayFx.play();
} else {
overlay.css("opacity", .5);
}
overlay.show();
$(window).on("focus" + MODAL_NS, function() {
if (wrapper.data("isFront") && !$(document.activeElement).closest(wrapper).length) {
that.wrapper.trigger("focus");
}
});
}
if (!wrapper.is(VISIBLE)) {
contentElement.css(OVERFLOW, HIDDEN);
wrapper.css({ display: "inline-flex" });
wrapper.kendoStop().kendoAnimate({
effects: showOptions.effects,
duration: showOptions.duration,
complete: this._activate.bind(this)
});
}
}
if (options.isMaximized) {
that._containerScrollTop = doc.scrollTop();
that._containerScrollLeft = doc.scrollLeft();
that._stopDocumentScrolling();
}
if (this.options.pinned && !this._isPinned) {
this.pin();
}
return that;
},
_activate: function() {
var scrollable = this.options.scrollable !== false;
if (this.options.autoFocus) {
this.wrapper.trigger("focus");
}
this.element.css(OVERFLOW, scrollable ? "" : "hidden");
kendo.resize(this.element.children());
this.trigger(ACTIVATE);
},
_removeOverlay: function(suppressAnimation) {
var modals = this._modals();
var options = this.options;
var hideOverlay = options.modal && !modals.length;
var hideOptions = this._animationOptions("close");
if (hideOverlay) {
if (!suppressAnimation && hideOptions.duration && kendo.effects.Fade) {
var overlayFx = kendo.fx(options.modal ? this._overlay(true) : $(undefined)).fadeOut();
overlayFx.duration(hideOptions.duration || 0);
overlayFx.startValue(.5);
overlayFx.play();
} else {
this._overlay(false).remove();
}
if (options.modal.preventScroll) {
this._enableDocumentScrolling();
}
} else if (modals.length) {
this._object(modals.last())._overlay(true);
if (options.modal.preventScroll) {
this._stopDocumentScrolling();
}
}
},
_close: function(systemTriggered) {
var that = this, wrapper = that.wrapper, options = that.options, showOptions = this._animationOptions("open"), hideOptions = this._animationOptions("close"), containmentContext = this.containment && !that._isPinned, doc = containmentContext ? this.containment : $(document), defaultPrevented;
if (that._closing) {
return;
}
defaultPrevented = that.trigger(CLOSE, { userTriggered: !systemTriggered });
that._closing = !defaultPrevented;
if (wrapper.is(VISIBLE) && !defaultPrevented) {
options.visible = false;
$(KWINDOW).each(function(i, element) {
var contentElement = $(element).children(KWINDOWCONTENT);
if (element != wrapper && contentElement.find("> ." + KCONTENTFRAME).length > 0) {
contentElement.children(KOVERLAY).remove();
}
});
this._removeOverlay();
const buttons = that.wrapper.find(TITLEBAR_BUTTONSSELECTOR);
buttons.css("transition", "none");
const stopButtonTransitionEndBubbling = function(e) {
e.stopPropagation();
};
buttons.on("transitionend", stopButtonTransitionEndBubbling);
wrapper.kendoStop().kendoAnimate({
effects: hideOptions.effects || showOptions.effects,
reverse: hideOptions.reverse === true,
duration: hideOptions.duration,
complete: function() {
buttons.off("transitionend", stopButtonTransitionEndBubbling);
buttons.css("transition", "");
that._deactivate();
}
});
$(window).off(MODAL_NS);
}
if (that.options.isMaximized) {
that._enableDocumentScrolling();
if (that._containerScrollTop && that._containerScrollTop > 0) {
doc.scrollTop(that._containerScrollTop);
}
if (that._containerScrollLeft && that._containerScrollLeft > 0) {
doc.scrollLeft(that._containerScrollLeft);
}
}
if (that.options.iframe) {
that.wrapper.trigger("blur");
}
},
_deactivate: function() {
var that = this;
that.wrapper.removeClass(INLINE_FLEX).hide().css("opacity", "");
that.trigger(DEACTIVATE);
if (that.options.modal) {
var lastModal = that._object(that._modals().last());
if (lastModal) {
lastModal.toFront();
}
}
},
close: function() {
this._close(true);
return this;
},
_actionable: function(element) {
return $(element).is(`${TITLEBAR_BUTTONSSELECTOR}, :input, a, .k-input, .k-icon, .k-svg-icon, .k-svg-icon>svg, .k-svg-icon>svg>path, .k-icon-button, [role='gridcell'], .k-input-inner, .k-input-value-text`);
},
_shouldFocus: function(target) {
var active = activeElement(), element = this.wrapper;
return this.options.autoFocus && !$(active).is(element) && !this._actionable(target) && (!element.find(active).length || !element.find(target).length);
},
toFront: function(e, avoidFocus) {
let that = this, wrapper = that.wrapper, currentWindow = wrapper[0], containmentContext = that.containment && !that._isPinned, openAnimation = this._animationOptions("open"), zIndex = +wrapper.css(ZINDEX), originalZIndex = zIndex, target = e && e.target || null, parentZIndex = 0;
$(KWINDOW).each(function(i, element) {
let windowObject = $(element), zIndexNew = windowObject.css(ZINDEX), contentElement = windowObject.children(KWINDOWCONTENT);
parentZIndex = Math.max(parentZIndex, +windowObject.parent().css(ZINDEX) || 0);
if (!isNaN(zIndexNew)) {
zIndex = Math.max(+zIndexNew, zIndex);
if (parentZIndex) {
zIndex = Math.max(parentZIndex, zIndex);
}
}
wrapper.data("isFront", element == currentWindow);
if (element != currentWindow && contentElement.find("." + KCONTENTFRAME).length && !contentElement.find(KOVERLAY).length) {
contentElement.append(templates.overlay);
}
});
if (!wrapper[0].style.zIndex || originalZIndex < zIndex) {
wrapper.css(ZINDEX, zIndex + 2);
}
that.element.find("> .k-overlay").remove();
if (that._shouldFocus(target)) {
if (!avoidFocus) {
setTimeout(function() {
that.wrapper.trigger("focus");
}, openAnimation ? openAnimation.duration : 0);
}
var scrollTop = containmentContext ? that.containment.scrollTop() : $(window).scrollTop(), windowTop = parseInt(wrapper.position().top, 10);
if (!that.options.pinned && windowTop > 0 && windowTop < scrollTop) {
if (scrollTop > 0) {
$(window).scrollTop(windowTop);
} else {
wrapper.css("top", scrollTop);
}
}
}
wrapper = null;
return that;
},
toggleMaximization: function() {
if (this._closing) {
return this;
}
return this[this.options.isMaximized ? "restore" : "maximize"]();
},
restore: function() {
var that = this;
var options = that.options;
var minHeight = options.minHeight;
var restoreOptions = that.restoreOptions;
var shouldRestrictTop;
var container = that.containment && !that._isPinned ? that.containment : $(document);
if (!options.isMaximized && !options.isMinimized) {
return that;
}
if (minHeight && minHeight != Infinity) {
that.wrapper.css("min-height", minHeight);
}
if (restoreOptions && !options.isMaximized) {
restoreOptions.height = constrain(restoreOptions.height, that.options.minHeight, that.options.maxHeight);
shouldRestrictTop = options.position.top + parseInt(restoreOptions.height, 10) > that.maxTop;
if (shouldRestrictTop) {
options.position.top = constrain(options.position.top, that.minTop, that.maxTop - parseInt(restoreOptions.height, 10));
extend(restoreOptions, {
left: options.position.left,
top: options.position.top
});
}
}
that.wrapper.css({
position: options.pinned ? "fixed" : "absolute",
left: restoreOptions.left,
top: restoreOptions.top,
width: restoreOptions.width,
height: restoreOptions.height
}).removeClass(MAXIMIZEDSTATE).removeClass(KWINDOWMINIMIZED).find(".k-window-content,.k-resize-handle").show().end().find(".k-window-titlebar .k-i-window-restore,.k-window-titlebar .k-svg-i-window-restore").parent().remove().end().end().find(MINIMIZE_MAXIMIZEICONSELECTORS).parent().show().end().end().find(PIN_UNPINICONCLASSSELECTOR).parent().show();
if (options.isMaximized) {
that.wrapper.find(".k-i-window,.k-svg-i-window").parent().trigger("focus");
} else if (options.isMinimized) {
that.wrapper.find(".k-i-window-minimize,.k-svg-i-window-minimize").parent().trigger("focus");
}
that.options.width = restoreOptions.width;
that.options.height = restoreOptions.height;
if (!that.options.modal.preventScroll) {
that._enableDocumentScrolling();
}
if (that._containerScrollTop && that._containerScrollTop > 0) {
container.scrollTop(that._containerScrollTop);
}
if (that._containerScrollLeft && that._containerScrollLeft > 0) {
container.scrollLeft(that._containerScrollLeft);
}
options.isMaximized = options.isMinimized = false;
that.wrapper.removeAttr("aria-labelled-by");
that.resize();
that.trigger(RESTORE);
return that;
},
_sizingAction: function(actionId, callback) {
var that = this, wrapper = that.wrapper, style = wrapper[0].style, options = that.options;
if (options.isMaximized || options.isMinimized) {
return that;
}
that.restoreOptions = {
width: style.width,
height: style.height
};
wrapper.children(KWINDOWRESIZEHANDLES).hide().end().children(KWINDOWTITLEBAR).find(MINIMIZE_MAXIMIZEICONSELECTORS).parent().hide().eq(0).before(templates.action({ name: "window-restore" }));
callback.call(that);
that.wrapper.children(KWINDOWTITLEBAR).find(PIN_UNPINICONCLASSSELECTOR).parent().toggle(actionId !== "maximize");
that.trigger(actionId);
wrapper.find(".k-i-window-restore,.k-svg-i-window-restore").parent().trigger("focus");
return that;
},
maximize: function() {
this._sizingAction("maximize", function() {
var that = this, wrapper = that.wrapper, containmentContext = this.containment && !that._isPinned, position = wrapper.position(), doc = $(document);
extend(that.restoreOptions, {
left: position.left + (containmentContext ? this.containment.scrollLeft() : 0),
top: position.top + (containmentContext ? this.containment.scrollTop() : 0)
});
this._containerScrollTop = containmentContext ? this.containment.scrollTop() : doc.scrollTop();
this._containerScrollLeft = containmentContext ? this.containment.scrollLeft() : doc.scrollLeft();
that._stopDocumentScrolling();
wrapper.css({
top: containmentContext ? this.containment.scrollTop() : 0,
left: containmentContext ? this.containment.scrollLeft() : 0,
position: containmentContext ? "absolute" : "fixed"
}).addClass(MAXIMIZEDSTATE);
that.options.isMaximized = true;
that._onDocumentResize();
});
return this;
},
_stopDocumentScrolling: function() {
var that = this;
var containment = that.containment;
if (containment && !that._isPinned) {
that._storeOverflowRule(containment);
containment.css(OVERFLOW, HIDDEN);
that.wrapper.css({
maxWidth: containment.innerWidth(),
maxHeight: containment.innerHeight()
});
return;
}
var $body = $("body");
that._storeOverflowRule($body);
$body.css(OVERFLOW, HIDDEN);
var $html = $("html");
that._storeOverflowRule($html);
$html.css(OVERFLOW, HIDDEN);
},
_enableDocumentScrolling: function() {
var that = this;
var containment = that.containment;
if (containment && !that._isPinned) {
that._restoreOverflowRule(containment);
that.wrapper.css({
maxWidth: containment.width,
maxHeight: containment.height
});
return;
}
that._restoreOverflowRule($(document.body));
that._restoreOverflowRule($("html"));
},
_storeOverflowRule: function($element) {
if (this._isOverflowStored($element)) {
return;
}
var overflowRule = $element.get(0).style.overflow;
if (typeof overflowRule === "string") {
$element.data(DATADOCOVERFLOWRULE, overflowRule);
}
},
_isOverflowStored: function($element) {
return typeof $element.data(DATADOCOVERFLOWRULE) === "string";
},
_restoreOverflowRule: function($element) {
var overflowRule = $element.data(DATADOCOVERFLOWRULE);
if (overflowRule !== null && overflowRule !== undefined) {
$element.css(OVERFLOW, overflowRule);
$element.removeData(DATADOCOVERFLOWRULE);
} else {
$element.css(OVERFLOW, "");
}
},
isMaximized: function() {
return this.options.isMaximized;
},
minimize: function() {
this._sizingAction("minimize", function() {
var that = this;
that.wrapper.css({
height: "",
minHeight: ""
});
that.element.hide();
that.options.isMinimized = true;
});
this.wrapper.attr("aria-labelled-by", this.element.attr("aria-labelled-by"));
this.wrapper.addClass(KWINDOWMINIMIZED);
this._updateBoundaries();
return this;
},
isMinimized: function() {
return this.options.isMinimized;
},
pin: function() {
var that = this, win = $(window), wrapper = that.wrapper, options = that.options, position = options.position, top = this.containment ? getPosition(wrapper[0]).top + toInt(this.containment, "borderTopWidth") : toInt(wrapper, "top"), left = this.containment ? getPosition(wrapper[0]).left + toInt(this.containment, "borderLeftWidth") : toInt(wrapper, "left");
if (!that.options.isMaximized) {
position.top = top;
position.left = left;
if (that._scrollIsAppended && (!this.containment || this.containment.css("position") !== "fixed")) {
position.top -= win.scrollTop();
position.left -= win.scrollLeft();
that._scrollIsAppended = false;
}
wrapper.css(extend(position, { position: "fixed" }));
var pinIcon = wrapper.children(KWINDOWTITLEBAR).find(KPINICONCLASSSELECTOR).eq(0);
if (pinIcon.length > 0) {
kendo.ui.icon(pinIcon, { icon: "unpin" });
}
that._isPinned = true;
that.options.pinned = true;
if (this.containment) {
options.maxWidth = options.maxHeight = Infinity;
wrapper.css({
maxWidth: "",
maxHeight: ""
});
}
}
},
unpin: function() {
var that = this, win = $(window), wrapper = that.wrapper, options = that.options, position = that.options.position, containment = that.containment, top = parseInt(wrapper.css("top"), 10) + win.scrollTop(), left = parseInt(wrapper.css("left"), 10) + win.scrollLeft();
if (!that.options.isMaximized) {
that._isPinned = false;
that._scrollIsAppended = true;
that.options.pinned = false;
if (containment) {
that._updateBoundaries();
options.maxWidth = Math.min(containment.width, options.maxWidth);
options.maxHeight = Math.min(containment.height - toInt(wrapper, "padding-top"), options.maxHeight);
wrapper.css({
maxWidth: options.maxWidth,
maxHeight: options.maxHeight
});
if (top < containment.position.top) {
top = that.minTop;
} else if (top > containment.position.top + containment.height) {
top = that.maxTop;
} else {
top = top + containment.scrollTop() - (containment.position.top + toInt(containment, "border-top-width"));
}
if (left < containment.position.left) {
left = that.minLeft;
} else if (left > containment.position.left + containment.width) {
left = that.maxLeft;
} else {
left = left + containment.scrollLeft() - (containment.position.left + toInt(containment, "border-left-width"));
}
}
position.top = constrain(top, that.minTop, that.maxTop);
position.left = constrain(left, that.minLeft, that.maxLeft);
wrapper.css(extend(position, { position: "" }));
var pinIcon = wrapper.children(KWINDOWTITLEBAR).find(KUNPINICONCLASSSELECTOR).eq(0);
if (pinIcon.length > 0) {
kendo.ui.icon(pinIcon, { icon: "pin" });
}
}
},
_onDocumentResize: function() {
var that = this, wrapper = that.wrapper, wnd = $(window), zoomLevel = kendo.support.zoomLevel(), contentBoxSizing = wrapper.css("box-sizing") == "content-box", w, h;
if (!that.options.isMaximized) {
return;
}
var lrBorderWidth = contentBoxSizing ? toInt(wrapper, "border-left-width") + toInt(wrapper, "border-right-width") : 0;
var tbBorderWidth = contentBoxSizing ? toInt(wrapper, "border-top-width") + toInt(wrapper, "border-bottom-width") : 0;
var paddingTop = contentBoxSizing ? toInt(wrapper, "padding-top") : 0;
if (that.containment && !that._isPinned) {
w = that.containment.innerWidth() - lrBorderWidth;
h = that.containment.innerHeight() - (tbBorderWidth + paddingTop);
} else {
w = wnd.width() / zoomLevel - lrBorderWidth;
h = wnd.height() / zoomLevel - (tbBorderWidth + paddingTop);
}
wrapper.css({
width: w,
height: h
});
that.options.width = w;
that.options.height = h;
that.resize();
},
refresh: function(options) {
var that = this, initOptions = that.options, element = $(that.element), iframe, showIframe, url;
if (!isPlainObject(options)) {
options = { url: options };
}
options = extend(initOptions.content, options);
showIframe = defined(initOptions.iframe) ? initOptions.iframe : options.iframe;
url = options.url;
if (url) {
if (!defined(showIframe)) {
showIframe = !isLocalUrl(url);
}
if (!showIframe) {
that._ajaxRequest(options);
} else {
iframe = element.find("." + KCONTENTFRAME)[0];
if (iframe) {
iframe.src = url || iframe.src;
} else {
element.html(templates.contentFrame(extend({}, initOptions, { content: options })));
}
element.find("." + KCONTENTFRAME).off("load" + NS).on("load" + NS, this._triggerRefresh.bind(this));
}
} else {
if (options.template) {
that.content(template(options.template)({}));
}
that.trigger(REFRESH);
}
element.toggleClass("k-window-iframecontent", !!showIframe);
return that;
},
_triggerRefresh: function() {
this.trigger(REFRESH);
},
_ajaxComplete: function() {
clearTimeout(this._loadingIconTimeout);
this.wrapper.find(REFRESHICONSELECTOR).removeClass(LOADINGICONCLASS);
},
_ajaxError: function(xhr, status) {
this.trigger(ERROR, {
status,
xhr
});
},
_ajaxSuccess: function(contentTemplate) {
return function(data) {
var html = data;
if (contentTemplate) {
html = template(contentTemplate)(data || {});
}
this.content(html, data);
this.element.prop("scrollTop", 0);
this.trigger(REFRESH);
};
},
_showLoading: function() {
this.wrapper.find(REFRESHICONSELECTOR).addClass(LOADINGICONCLASS);
},
_ajaxRequest: function(options) {
this._loadingIconTimeout = setTimeout(this._showLoading.bind(this), 100);
$.ajax(extend({
type: "GET",
dataType: "html",
cache: false,
error: this._ajaxError.bind(this),
complete: this._ajaxComplete.bind(this),
success: this._ajaxSuccess(options.template).bind(this)
}, options));
},
_destroy: function() {
if (this.resizing) {
this.resizing.destroy();
}
if (this.dragging) {
this.dragging.destroy();
}
this.wrapper.off(NS).children(KWINDOWCONTENT).off(NS).end().find(".k-resize-handle,.k-window-titlebar").off(NS);
$(window).off("resize" + NS + this._marker);
$(window).off(MODAL_NS);
$(window).off(NS);
clearTimeout(this._loadingIconTimeout);
Widget.fn.destroy.call(this);
this.unbind(undefined);
kendo.destroy(this.wrapper);
},
destroy: function() {
this._destroy();
if (this.options.modal) {
this._removeOverlay(true);
}
this.wrapper.empty().remove();
this.wrapper = this.appendTo = this.element = $();
},
_createWindow: function() {
var contentHtml = this.element, options = this.options, iframeSrcAttributes, wrapper, isRtl = kendo.support.isRtl(contentHtml);
if (options.scrollable === false) {
contentHtml.css("overflow", "hidden");
}
wrapper = $(templates.wrapper(options));
iframeSrcAttributes = contentHtml.find("iframe:not(.k-content-frame)").map(function() {
var src = this.getAttribute("src");
this.src = "";
return src;
});
wrapper.toggleClass("k-rtl", isRtl).attr("tabindex", 0).append(contentHtml).find("iframe:not(.k-content-frame)").each(function(index) {
this.src = iframeSrcAttributes[index];
});
if (this.containment) {
this.containment.prepend(wrapper);
} else if (this.appendTo) {
wrapper.appendTo(this.appendTo);
}
wrapper.find(".k-window-title").css(isRtl ? "left" : "right", outerWidth(wrapper.find(".k-window-titlebar-actions")) + 10);
contentHtml.css("visibility", "").show();
if ($(contentHtml).hasClass(KHIDDEN)) {
$(contentHtml).removeClass(KHIDDEN);
}
contentHtml.find("[data-role=editor]").each(function() {
var editor = $(this).data("kendoEditor");
if (editor) {
editor.refresh();
}
});
wrapper = contentHtml = null;
}
});
templates = {
wrapper: template(() => "<div class='k-window'></div>"),
action: template(({ name, icon }) => {
let iconName = (icon || "").toLowerCase() || name.toLowerCase();
if (iconName == "restore") {
iconName = "window-restore";
}
return kendo.html.renderButton(`<button role='button' class='k-window-titlebar-action' aria-label='${name}'></button>`, {
icon: iconName,
fillMode: "flat"
});
}),
titlebar: template(({ title }) => "<div class='k-window-titlebar'>" + `<span class='k-window-title'>${title}</span>` + "<div class='k-window-titlebar-actions'></div>" + "</div>"),
overlay: "<div class='k-overlay'></div>",
contentFrame: template(({ title, content }) => `<iframe frameborder='0' title='${title}' class='${KCONTENTFRAME}' ` + `src='${content.url}'>` + "This page requires frames in order to show content" + "</iframe>"),
resizeHandle: template((data) => `<div aria-hidden='true' class='k-resize-handle k-resize-${data}'></div>`)
};
function WindowResizing(wnd) {
var that = this;
that.owner = wnd;
that._preventDragging = false;
that._draggable = new Draggable(wnd.wrapper, {
filter: ">" + KWINDOWRESIZEHANDLES,
group: wnd.wrapper.id + "-resizing",
dragstart: that.dragstart.bind(that),
drag: that.drag.bind(that),
dragend: that.dragend.bind(that)
});
that._draggable.userEvents.bind("press", that.addOverlay.bind(that));
that._draggable.userEvents.bind("release", that.removeOverlay.bind(that));
}
WindowResizing.prototype = {
addOverlay: function() {
this.owner.wrapper.append(templates.overlay);
},
removeOverlay: function() {
this.owner.wrapper.find(KOVERLAY).remove();
},
dragstart: function(e) {
var that = this;
var wnd = that.owner;
var wrapper = wnd.wrapper;
that._preventDragging = wnd.trigger(RESIZESTART);
if (that._preventDragging) {
return;
}
that.elementPadding = parseInt(wrapper.css("padding-top"), 10);
that.initialPosition = kendo.getOffset(wrapper, "position");
that.resizeDirection = e.currentTarget.prop("className").replace("k-resize-handle k-resize-", "");
that.initialSize = {
width: wrapper.outerWidth(),
height: wrapper.outerHeight()
};
wnd._updateBoundaries();
that.containerOffset = wnd.containment ? wnd.containment.position : kendo.getOffset(wnd.appendTo);
var offsetParent = wrapper.offsetParent();
if (offsetParent.is("html")) {
that.containerOffset.top = that.containerOffset.left = 0;
} else {
var marginTop = offsetParent.css("margin-top");
var marginLeft = offsetParent.css("margin-left");
var hasMargin = !zero.test(marginTop) || !zero.test(marginLeft);
if (hasMargin) {
var wrapperPosition = getPositio