diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/css/knockout.contextmenu.css b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/css/knockout.contextmenu.css new file mode 100644 index 0000000..bedb129 --- /dev/null +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/css/knockout.contextmenu.css @@ -0,0 +1,59 @@ +/* knockout.contextmenu v1.0.0 + Nicolás Escalante - nlante@gmail.com + Issues: https://github.com/nescalante/knockout.contextmenu/issues + License: MIT */ + +.context-menu { + position: absolute; + padding: 0; + margin: 0; + z-index: 1030; + background-color: #ffffff; +} +.context-menu ul { + line-height: 1.6; + padding: 0; + margin: 0; + border: 1px solid #dddddd; + box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.3); +} +.context-menu ul > li { + padding: 4px 20px; + margin: 0; + z-index: 1031; + list-style-type: none; + cursor: pointer; + white-space: nowrap; + color: #333333; +} +.context-menu ul > li:hover { + background-color: #eeeeee; +} +.context-menu ul > li.disabled, +.context-menu ul > li.disabled a { + color: #666666; + cursor: default; +} +.context-menu ul > li.checked:before { + position: absolute; + content: "\2713"; + left: 7px; +} +.context-menu ul > li.with-url { + padding: 0; +} +.context-menu ul > li.with-url a { + display: block; + padding: 4px 20px; + text-decoration: none; + color: #333333; +} +.context-menu ul > li.separator { + margin: 4px 0; + padding: 0; + border-bottom: 1px solid #cccccc; + cursor: default; +} +.context-menu ul > li.separator:hover { + background-color: #ffffff; +} \ No newline at end of file diff --git a/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/js/knockout.contextmenu.js b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/js/knockout.contextmenu.js new file mode 100644 index 0000000..ca91eff --- /dev/null +++ b/DataCenter_Windows/WindowsDataCenter/WindowsDataCenter/www/js/knockout.contextmenu.js @@ -0,0 +1,364 @@ +/* knockout.contextmenu v1.0.0 + Nicolás Escalante - nlante@gmail.com + Issues: https://github.com/nescalante/knockout.contextmenu/issues + License: MIT */ + +(function (undefined) { + 'use strict'; + + // client + if (typeof ko !== undefined + '') { + bindContextMenu(ko); + } + + // node + if (typeof module !== undefined + '' && module.exports && typeof require !== undefined + '') { + bindContextMenu(require('knockout')); + } + + function bindContextMenu(ko) { + var currentMenu; + var elementMapping = []; + var utils = ko.utils; + var registerEvent = utils.registerEventHandler; + var isObservable = ko.isObservable; + + registerEvent(document, 'click', function (event) { + var button = event.which || event.button; + if (!event.defaultPrevented && button < 2) { + hideCurrentMenu(); + } + }); + + utils.contextMenu = { + getMenuFor: function (element, event) { + var result = getMapping(element); + + if (result) { + return result.get(event); + } + }, + + openMenuFor: function (element, event) { + var result = getMapping(element); + + if (result) { + return result.open(event); + } + }, + + }; + + ko.bindingHandlers.contextMenu = { + init: function (element, valueAccessor, allBindingsAccessor, viewModel) { + var eventsToHandle = valueAccessor() || {}; + var allBindings = allBindingsAccessor(); + var defaultClass = allBindings.contextMenuClass || 'context-menu'; + var activeElement; + + // bind on click? bind on context click? + if (allBindings.bindMenuOnClick) { + registerEvent(element, 'click', openMenu); + } + + if (allBindings.bindMenuOnContextMenu === undefined || allBindings.bindMenuOnContextMenu) { + registerEvent(element, 'contextmenu', openMenu); + } + + elementMapping.push({ + element: element, + get: function () { + return activeElement; + }, + + open: openMenu, + hide: function () { + if (activeElement) { + activeElement.hide(); + } + }, + }); + + function mouseX(evt) { + if (evt.pageX) { + return evt.pageX; + } else if (evt.clientX) { + return evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft); + } else { + return null; + } + } + + function mouseY(evt) { + if (evt.pageY) { + return evt.pageY; + } else if (evt.clientY) { + return evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop); + } else { + return null; + } + } + + function openMenu(event) { + var menuElement; + + activeElement = getMenu(event); + menuElement = activeElement.element; + + hideCurrentMenu(); + + if (menuElement) { + // make visibility hidden, then add to DOM so that we can get the height/width of the menu + menuElement.style.visibility = 'hidden'; + (document.body || document).appendChild(menuElement); + + // set location + if (event) { + var bottomOfViewport = window.innerHeight + window.pageYOffset; + var rightOfViewport = window.innerWidth + window.pageXOffset; + + if (mouseY(event) + menuElement.offsetHeight > bottomOfViewport) { + menuElement.style.top = 1 * (bottomOfViewport - menuElement.offsetHeight - 10) + 'px'; + } else { + menuElement.style.top = mouseY(event) + 'px'; + } + + if (mouseX(event) + menuElement.offsetWidth > rightOfViewport) { + menuElement.style.left = 1 * (rightOfViewport - menuElement.offsetWidth - 10) + 'px'; + } else { + menuElement.style.left = mouseX(event) + 'px'; + } + + event.preventDefault(); + event.stopPropagation(); + } else { + menuElement.style.top = (element.offsetTop + element.offsetHeight) + 'px'; + menuElement.style.left = (element.offsetLeft + element.offsetWidth) + 'px'; + } + + // now set to visible + menuElement.style.visibility = ''; + } + + // replace current menu with the recently created + currentMenu = menuElement; + + return activeElement; + } + + function getMenu(event) { + var menu; + var hasChecks = false; + var elements = []; + var actions = []; + var items = []; + var props = Object.keys( + ko.isObservable(eventsToHandle) ? + eventsToHandle() : + eventsToHandle + ); + + props.forEach(function (eventNameOutsideClosure) { + pushItem(eventNameOutsideClosure); + }); + + if (elements.length) { + menu = document.createElement('div'); + menu.className = defaultClass; + + // you may need padding to menus that has checks + menu.innerHTML = '