diff --git a/src/octoprint/static/js/app/main.js b/src/octoprint/static/js/app/main.js index cbf69503..63b1779f 100644 --- a/src/octoprint/static/js/app/main.js +++ b/src/octoprint/static/js/app/main.js @@ -262,6 +262,19 @@ $(function() { } }; + ko.bindingHandlers.contextMenu = { + init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var val = ko.utils.unwrapObservable(valueAccessor()); + + $(element).contextMenu(val); + }, + update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { + var val = ko.utils.unwrapObservable(valueAccessor()); + + $(element).contextMenu(val); + } + } + //~~ some additional hooks and initializations // make sure modals max out at the window height @@ -290,6 +303,62 @@ $(function() { } }; + $.fn.isChildOf = function (element) { + return $(element).has(this).length > 0; + } + + // from http://jsfiddle.net/KyleMit/X9tgY/ + $.fn.contextMenu = function (settings) { + return this.each(function () { + // Open context menu + $(this).on("contextmenu", function (e) { + // return native menu if pressing control + if (e.ctrlKey) return; + + $(settings.menuSelector) + .data("invokedOn", $(e.target)) + .show() + .css({ + position: "absolute", + left: getMenuPosition(e.clientX, 'width', 'scrollLeft'), + top: getMenuPosition(e.clientY, 'height', 'scrollTop'), + "z-index": 9999 + }).off('click') + .on('click', function (e) { + if (e.target.tagName.toLowerCase() == "input") + return; + + $(this).hide(); + + var $invokedOn = $(this).data("invokedOn"); + var $selectedMenu = $(e.target); + + settings.menuSelected.call(this, $invokedOn, $selectedMenu); + }); + + return false; + }); + + //make sure menu closes on any click + $(document).click(function () { + $(settings.menuSelector).hide(); + }); + }); + + function getMenuPosition(mouse, direction, scrollDir) { + var win = $(window)[direction](), + scroll = $(window)[scrollDir](), + menu = $(settings.menuSelector)[direction](), + position = mouse + scroll; + + // opening menu would pass the side of the page + if (mouse + menu > win && menu < mouse) + position -= menu; + + return position; + } + }; + // Use bootstrap tabdrop for tabs and pills $('.nav-pills, .nav-tabs').tabdrop(); diff --git a/src/octoprint/static/js/app/viewmodels/control.js b/src/octoprint/static/js/app/viewmodels/control.js index 9943a0fb..bef08513 100644 --- a/src/octoprint/static/js/app/viewmodels/control.js +++ b/src/octoprint/static/js/app/viewmodels/control.js @@ -140,7 +140,7 @@ $(function() { } if (control.hasOwnProperty("children")) { - control.children = self._processControls(control.children); + control.children = ko.observableArray(self._processControls(control.children)); if (!control.hasOwnProperty("layout") || !(control.layout == "vertical" || control.layout == "horizontal")) { control.layout = "vertical"; }