diff --git a/src/octoprint/static/js/app/helpers.js b/src/octoprint/static/js/app/helpers.js index 7f97ec46..7c133ecd 100644 --- a/src/octoprint/static/js/app/helpers.js +++ b/src/octoprint/static/js/app/helpers.js @@ -431,3 +431,17 @@ function showOfflineOverlay(title, message, reconnectCallback) { function hideOfflineOverlay() { $("#offline_overlay").hide(); } + +function showConfirmationDialog(message, onacknowledge) { + var confirmationDialog = $("#confirmation_dialog"); + var confirmationDialogAck = $(".confirmation_dialog_acknowledge", confirmationDialog); + + $(".confirmation_dialog_message", confirmationDialog).text(message); + confirmationDialogAck.unbind("click"); + confirmationDialogAck.bind("click", function (e) { + e.preventDefault(); + $("#confirmation_dialog").modal("hide"); + onacknowledge(e); + }); + confirmationDialog.modal("show"); +} \ No newline at end of file diff --git a/src/octoprint/static/js/app/viewmodels/control.js b/src/octoprint/static/js/app/viewmodels/control.js index bef08513..18bbe42c 100644 --- a/src/octoprint/static/js/app/viewmodels/control.js +++ b/src/octoprint/static/js/app/viewmodels/control.js @@ -1,518 +1,510 @@ -$(function() { - function ControlViewModel(parameters) { - var self = this; - - self.loginState = parameters[0]; - self.settings = parameters[1]; - - self._createToolEntry = function () { - return { - name: ko.observable(), - key: ko.observable() - } - }; - - self.isErrorOrClosed = ko.observable(undefined); - self.isOperational = ko.observable(undefined); - self.isPrinting = ko.observable(undefined); - self.isPaused = ko.observable(undefined); - self.isError = ko.observable(undefined); - self.isReady = ko.observable(undefined); - self.isLoading = ko.observable(undefined); - - self.extrusionAmount = ko.observable(undefined); - self.controls = ko.observableArray([]); - - self.tools = ko.observableArray([]); - - self.feedRate = ko.observable(100); - self.flowRate = ko.observable(100); - - self.feedbackControlLookup = {}; - - self.controlsFromServer = []; - self.additionalControls = []; - - self.webcamDisableTimeout = undefined; - - self.keycontrolActive = ko.observable(false); - self.keycontrolHelpActive = ko.observable(false); - self.keycontrolPossible = ko.computed(function () { - return self.isOperational() && !self.isPrinting() && self.loginState.isUser() && !$.browser.mobile; - }); - self.showKeycontrols = ko.computed(function () { - return self.keycontrolActive() && self.keycontrolPossible(); - }); - - self.settings.printerProfiles.currentProfileData.subscribe(function () { - self._updateExtruderCount(); - self.settings.printerProfiles.currentProfileData().extruder.count.subscribe(self._updateExtruderCount); - }); - self._updateExtruderCount = function () { - var tools = []; - - var numExtruders = self.settings.printerProfiles.currentProfileData().extruder.count(); - if (numExtruders > 1) { - // multiple extruders - for (var extruder = 0; extruder < numExtruders; extruder++) { - tools[extruder] = self._createToolEntry(); - tools[extruder]["name"](gettext("Tool") + " " + extruder); - tools[extruder]["key"]("tool" + extruder); - } - } else { - // only one extruder, no need to add numbers - tools[0] = self._createToolEntry(); - tools[0]["name"](gettext("Hotend")); - tools[0]["key"]("tool0"); - } - - self.tools(tools); - }; - - self.fromCurrentData = function (data) { - self._processStateData(data.state); - }; - - self.fromHistoryData = function (data) { - self._processStateData(data.state); - }; - - self._processStateData = function (data) { - self.isErrorOrClosed(data.flags.closedOrError); - self.isOperational(data.flags.operational); - self.isPaused(data.flags.paused); - self.isPrinting(data.flags.printing); - self.isError(data.flags.error); - self.isReady(data.flags.ready); - self.isLoading(data.flags.loading); - }; - - self.onEventRegisteredMessageReceived = function(payload) { - if (payload.key in self.feedbackControlLookup) { - var outputs = self.feedbackControlLookup[payload.key]; - _.each(payload.outputs, function(value, key) { - if (outputs.hasOwnProperty(key)) { - outputs[key](value); - } - }); - } - }; - - self.rerenderControls = function () { - var allControls = self.controlsFromServer.concat(self.additionalControls); - self.controls(self._processControls(allControls)) - }; - - self.requestData = function () { - $.ajax({ - url: API_BASEURL + "printer/command/custom", - method: "GET", - dataType: "json", - success: function (response) { - self._fromResponse(response); - } - }); - }; - - self._fromResponse = function (response) { - self.controlsFromServer = response.controls; - self.rerenderControls(); - }; - - self._processControls = function (controls) { - for (var i = 0; i < controls.length; i++) { - controls[i] = self._processControl(controls[i]); - } - return controls; - }; - - self._processControl = function (control) { - if (control.hasOwnProperty("processed") && control.processed) { - return control; - } - - if (control.hasOwnProperty("template") && control.hasOwnProperty("key") && control.hasOwnProperty("template_key") && !control.hasOwnProperty("output")) { - control.output = ko.observable(""); - if (!self.feedbackControlLookup.hasOwnProperty(control.key)) { - self.feedbackControlLookup[control.key] = {}; - } - self.feedbackControlLookup[control.key][control.template_key] = control.output; - } - - if (control.hasOwnProperty("children")) { - control.children = ko.observableArray(self._processControls(control.children)); - if (!control.hasOwnProperty("layout") || !(control.layout == "vertical" || control.layout == "horizontal")) { - control.layout = "vertical"; - } - } - - if (control.hasOwnProperty("input")) { - for (var i = 0; i < control.input.length; i++) { - control.input[i].value = ko.observable(control.input[i].default); - if (!control.input[i].hasOwnProperty("slider")) { - control.input[i].slider = false; - } - } - } - - var js; - if (control.hasOwnProperty("javascript")) { - js = control.javascript; - - // if js is a function everything's fine already, but if it's a string we need to eval that first - if (!_.isFunction(js)) { - control.javascript = function (data) { - eval(js); - }; - } - } - - if (control.hasOwnProperty("enabled")) { - js = control.enabled; - - // if js is a function everything's fine already, but if it's a string we need to eval that first - if (!_.isFunction(js)) { - control.enabled = function (data) { - return eval(js); - } - } - } - - control.processed = true; - return control; - }; - - self.isCustomEnabled = function (data) { - if (data.hasOwnProperty("enabled")) { - return data.enabled(data); - } else { - return self.isOperational() && self.loginState.isUser(); - } - }; - - self.clickCustom = function (data) { - var callback; - if (data.hasOwnProperty("javascript")) { - callback = data.javascript; - } else { - callback = self.sendCustomCommand; - } - - if (data.confirm) { - var confirmationDialog = $("#confirmation_dialog"); - var confirmationDialogAck = $(".confirmation_dialog_acknowledge", confirmationDialog); - - $(".confirmation_dialog_message", confirmationDialog).text(data.confirm); - confirmationDialogAck.unbind("click"); - confirmationDialogAck.bind("click", function (e) { - e.preventDefault(); - $("#confirmation_dialog").modal("hide"); - callback(data); - }); - confirmationDialog.modal("show"); - } else { - callback(data); - } - }; - - self.sendJogCommand = function (axis, multiplier, distance) { - if (typeof distance === "undefined") - distance = $('#jog_distance button.active').data('distance'); - if (self.settings.printerProfiles.currentProfileData() && self.settings.printerProfiles.currentProfileData()["axes"] && self.settings.printerProfiles.currentProfileData()["axes"][axis] && self.settings.printerProfiles.currentProfileData()["axes"][axis]["inverted"]()) { - multiplier *= -1; - } - - var data = { - "command": "jog" - }; - data[axis] = distance * multiplier; - - self.sendPrintHeadCommand(data); - }; - - self.sendHomeCommand = function (axis) { - self.sendPrintHeadCommand({ - "command": "home", - "axes": axis - }); - }; - - self.sendFeedRateCommand = function () { - self.sendPrintHeadCommand({ - "command": "feedrate", - "factor": self.feedRate() - }); - }; - - self.sendExtrudeCommand = function () { - self._sendECommand(1); - }; - - self.sendRetractCommand = function () { - self._sendECommand(-1); - }; - - self.sendFlowRateCommand = function () { - self.sendToolCommand({ - "command": "flowrate", - "factor": self.flowRate() - }); - }; - - self._sendECommand = function (dir) { - var length = self.extrusionAmount(); - if (!length) length = self.settings.printer_defaultExtrusionLength(); - - self.sendToolCommand({ - command: "extrude", - amount: length * dir - }); - }; - - self.sendSelectToolCommand = function (data) { - if (!data || !data.key()) return; - - self.sendToolCommand({ - command: "select", - tool: data.key() - }); - }; - - self.sendPrintHeadCommand = function (data) { - $.ajax({ - url: API_BASEURL + "printer/printhead", - type: "POST", - dataType: "json", - contentType: "application/json; charset=UTF-8", - data: JSON.stringify(data) - }); - }; - - self.sendToolCommand = function (data) { - $.ajax({ - url: API_BASEURL + "printer/tool", - type: "POST", - dataType: "json", - contentType: "application/json; charset=UTF-8", - data: JSON.stringify(data) - }); - }; - - self.sendCustomCommand = function (command) { - if (!command) - return; - - var data = undefined; - if (command.hasOwnProperty("command")) { - // single command - data = {"command": command.command}; - } else if (command.hasOwnProperty("commands")) { - // multi command - data = {"commands": command.commands}; - } else if (command.hasOwnProperty("script")) { - data = {"script": command.script}; - if (command.hasOwnProperty("context")) { - data["context"] = command.context; - } - } else { - return; - } - - if (command.hasOwnProperty("input")) { - // parametric command(s) - data["parameters"] = {}; - _.each(command.input, function(input) { - if (!input.hasOwnProperty("parameter") || !input.hasOwnProperty("value")) { - return; - } - - data["parameters"][input.parameter] = input.value(); - }); - } - - $.ajax({ - url: API_BASEURL + "printer/command", - type: "POST", - dataType: "json", - contentType: "application/json; charset=UTF-8", - data: JSON.stringify(data) - }) - }; - - self.displayMode = function (customControl) { - if (customControl.hasOwnProperty("children")) { - return "customControls_containerTemplate"; - } else { - return "customControls_controlTemplate"; - } - }; - - self.rowCss = function (customControl) { - var span = "span2"; - var offset = ""; - if (customControl.hasOwnProperty("width")) { - span = "span" + customControl.width; - } - if (customControl.hasOwnProperty("offset")) { - offset = "offset" + customControl.offset; - } - return span + " " + offset; - }; - - self.onStartup = function () { - self.requestData(); - }; - - self.onTabChange = function (current, previous) { - if (current == "#control") { - if (self.webcamDisableTimeout != undefined) { - clearTimeout(self.webcamDisableTimeout); - } - var webcamImage = $("#webcam_image"); - var currentSrc = webcamImage.attr("src"); - if (currentSrc === undefined || currentSrc.trim() == "") { - var newSrc = CONFIG_WEBCAM_STREAM; - if (CONFIG_WEBCAM_STREAM.lastIndexOf("?") > -1) { - newSrc += "&"; - } else { - newSrc += "?"; - } - newSrc += new Date().getTime(); - - webcamImage.attr("src", newSrc); - } - } else if (previous == "#control") { - // only disable webcam stream if tab is out of focus for more than 5s, otherwise we might cause - // more load by the constant connection creation than by the actual webcam stream - self.webcamDisableTimeout = setTimeout(function () { - $("#webcam_image").attr("src", ""); - }, 5000); - } - }; - - self.onAllBound = function (allViewModels) { - var additionalControls = []; - _.each(allViewModels, function (viewModel) { - if (viewModel.hasOwnProperty("getAdditionalControls")) { - additionalControls = additionalControls.concat(viewModel.getAdditionalControls()); - } - }); - if (additionalControls.length > 0) { - self.additionalControls = additionalControls; - self.rerenderControls(); - } - }; - - self.onFocus = function (data, event) { - if (!self.settings.feature_keyboardControl()) return; - self.keycontrolActive(true); - }; - - self.onMouseOver = function (data, event) { - if (!self.settings.feature_keyboardControl()) return; - $("#webcam_container").focus(); - self.keycontrolActive(true); - }; - - self.onMouseOut = function (data, event) { - if (!self.settings.feature_keyboardControl()) return; - $("#webcam_container").blur(); - self.keycontrolActive(false); - }; - - self.toggleKeycontrolHelp = function () { - self.keycontrolHelpActive(!self.keycontrolHelpActive()); - }; - - self.onKeyDown = function (data, event) { - if (!self.settings.feature_keyboardControl()) return; - - var button = undefined; - var visualizeClick = true; - - switch (event.which) { - case 37: // left arrow key - // X- - button = $("#control-xdec"); - break; - case 38: // up arrow key - // Y+ - button = $("#control-yinc"); - break; - case 39: // right arrow key - // X+ - button = $("#control-xinc"); - break; - case 40: // down arrow key - // Y- - button = $("#control-ydec"); - break; - case 49: // number 1 - case 97: // numpad 1 - // Distance 0.1 - button = $("#control-distance01"); - visualizeClick = false; - break; - case 50: // number 2 - case 98: // numpad 2 - // Distance 1 - button = $("#control-distance1"); - visualizeClick = false; - break; - case 51: // number 3 - case 99: // numpad 3 - // Distance 10 - button = $("#control-distance10"); - visualizeClick = false; - break; - case 52: // number 4 - case 100: // numpad 4 - // Distance 100 - button = $("#control-distance100"); - visualizeClick = false; - break; - case 33: // page up key - case 87: // w key - // z lift up - button = $("#control-zinc"); - break; - case 34: // page down key - case 83: // s key - // z lift down - button = $("#control-zdec"); - break; - case 36: // home key - // xy home - button = $("#control-xyhome"); - break; - case 35: // end key - // z home - button = $("#control-zhome"); - break; - default: - event.preventDefault(); - return false; - } - - if (button === undefined) { - return false; - } else { - event.preventDefault(); - if (visualizeClick) { - button.addClass("active"); - setTimeout(function () { - button.removeClass("active"); - }, 150); - } - button.click(); - } - }; - - } - - OCTOPRINT_VIEWMODELS.push([ - ControlViewModel, - ["loginStateViewModel", "settingsViewModel"], - "#control" - ]); -}); +$(function() { + function ControlViewModel(parameters) { + var self = this; + + self.loginState = parameters[0]; + self.settings = parameters[1]; + + self._createToolEntry = function () { + return { + name: ko.observable(), + key: ko.observable() + } + }; + + self.isErrorOrClosed = ko.observable(undefined); + self.isOperational = ko.observable(undefined); + self.isPrinting = ko.observable(undefined); + self.isPaused = ko.observable(undefined); + self.isError = ko.observable(undefined); + self.isReady = ko.observable(undefined); + self.isLoading = ko.observable(undefined); + + self.extrusionAmount = ko.observable(undefined); + self.controls = ko.observableArray([]); + + self.tools = ko.observableArray([]); + + self.feedRate = ko.observable(100); + self.flowRate = ko.observable(100); + + self.feedbackControlLookup = {}; + + self.controlsFromServer = []; + self.additionalControls = []; + + self.webcamDisableTimeout = undefined; + + self.keycontrolActive = ko.observable(false); + self.keycontrolHelpActive = ko.observable(false); + self.keycontrolPossible = ko.computed(function () { + return self.isOperational() && !self.isPrinting() && self.loginState.isUser() && !$.browser.mobile; + }); + self.showKeycontrols = ko.computed(function () { + return self.keycontrolActive() && self.keycontrolPossible(); + }); + + self.settings.printerProfiles.currentProfileData.subscribe(function () { + self._updateExtruderCount(); + self.settings.printerProfiles.currentProfileData().extruder.count.subscribe(self._updateExtruderCount); + }); + self._updateExtruderCount = function () { + var tools = []; + + var numExtruders = self.settings.printerProfiles.currentProfileData().extruder.count(); + if (numExtruders > 1) { + // multiple extruders + for (var extruder = 0; extruder < numExtruders; extruder++) { + tools[extruder] = self._createToolEntry(); + tools[extruder]["name"](gettext("Tool") + " " + extruder); + tools[extruder]["key"]("tool" + extruder); + } + } else { + // only one extruder, no need to add numbers + tools[0] = self._createToolEntry(); + tools[0]["name"](gettext("Hotend")); + tools[0]["key"]("tool0"); + } + + self.tools(tools); + }; + + self.fromCurrentData = function (data) { + self._processStateData(data.state); + }; + + self.fromHistoryData = function (data) { + self._processStateData(data.state); + }; + + self._processStateData = function (data) { + self.isErrorOrClosed(data.flags.closedOrError); + self.isOperational(data.flags.operational); + self.isPaused(data.flags.paused); + self.isPrinting(data.flags.printing); + self.isError(data.flags.error); + self.isReady(data.flags.ready); + self.isLoading(data.flags.loading); + }; + + self.onEventRegisteredMessageReceived = function(payload) { + if (payload.key in self.feedbackControlLookup) { + var outputs = self.feedbackControlLookup[payload.key]; + _.each(payload.outputs, function(value, key) { + if (outputs.hasOwnProperty(key)) { + outputs[key](value); + } + }); + } + }; + + self.rerenderControls = function () { + var allControls = self.controlsFromServer.concat(self.additionalControls); + self.controls(self._processControls(allControls)) + }; + + self.requestData = function () { + $.ajax({ + url: API_BASEURL + "printer/command/custom", + method: "GET", + dataType: "json", + success: function (response) { + self._fromResponse(response); + } + }); + }; + + self._fromResponse = function (response) { + self.controlsFromServer = response.controls; + self.rerenderControls(); + }; + + self._processControls = function (controls) { + for (var i = 0; i < controls.length; i++) { + controls[i] = self._processControl(controls[i]); + } + return controls; + }; + + self._processControl = function (control) { + if (control.hasOwnProperty("processed") && control.processed) { + return control; + } + + if (control.hasOwnProperty("template") && control.hasOwnProperty("key") && control.hasOwnProperty("template_key") && !control.hasOwnProperty("output")) { + control.output = ko.observable(""); + if (!self.feedbackControlLookup.hasOwnProperty(control.key)) { + self.feedbackControlLookup[control.key] = {}; + } + self.feedbackControlLookup[control.key][control.template_key] = control.output; + } + + if (control.hasOwnProperty("children")) { + control.children = ko.observableArray(self._processControls(control.children)); + if (!control.hasOwnProperty("layout") || !(control.layout == "vertical" || control.layout == "horizontal" || control.layout == "horizontal_grid")) { + control.layout = "vertical"; + } + } + + if (control.hasOwnProperty("input")) { + for (var i = 0; i < control.input.length; i++) { + control.input[i].value = ko.observable(control.input[i].default); + if (!control.input[i].hasOwnProperty("slider")) { + control.input[i].slider = false; + } + } + } + + var js; + if (control.hasOwnProperty("javascript")) { + js = control.javascript; + + // if js is a function everything's fine already, but if it's a string we need to eval that first + if (!_.isFunction(js)) { + control.javascript = function (data) { + eval(js); + }; + } + } + + if (control.hasOwnProperty("enabled")) { + js = control.enabled; + + // if js is a function everything's fine already, but if it's a string we need to eval that first + if (!_.isFunction(js)) { + control.enabled = function (data) { + return eval(js); + } + } + } + + control.processed = true; + return control; + }; + + self.isCustomEnabled = function (data) { + if (data.hasOwnProperty("enabled")) { + return data.enabled(data); + } else { + return self.isOperational() && self.loginState.isUser(); + } + }; + + self.clickCustom = function (data) { + var callback; + if (data.hasOwnProperty("javascript")) { + callback = data.javascript; + } else { + callback = self.sendCustomCommand; + } + + if (data.confirm) { + showConfirmationDialog(data.confirm, function (e) { + callback(data); + }); + } else { + callback(data); + } + }; + + self.sendJogCommand = function (axis, multiplier, distance) { + if (typeof distance === "undefined") + distance = $('#jog_distance button.active').data('distance'); + if (self.settings.printerProfiles.currentProfileData() && self.settings.printerProfiles.currentProfileData()["axes"] && self.settings.printerProfiles.currentProfileData()["axes"][axis] && self.settings.printerProfiles.currentProfileData()["axes"][axis]["inverted"]()) { + multiplier *= -1; + } + + var data = { + "command": "jog" + }; + data[axis] = distance * multiplier; + + self.sendPrintHeadCommand(data); + }; + + self.sendHomeCommand = function (axis) { + self.sendPrintHeadCommand({ + "command": "home", + "axes": axis + }); + }; + + self.sendFeedRateCommand = function () { + self.sendPrintHeadCommand({ + "command": "feedrate", + "factor": self.feedRate() + }); + }; + + self.sendExtrudeCommand = function () { + self._sendECommand(1); + }; + + self.sendRetractCommand = function () { + self._sendECommand(-1); + }; + + self.sendFlowRateCommand = function () { + self.sendToolCommand({ + "command": "flowrate", + "factor": self.flowRate() + }); + }; + + self._sendECommand = function (dir) { + var length = self.extrusionAmount(); + if (!length) length = self.settings.printer_defaultExtrusionLength(); + + self.sendToolCommand({ + command: "extrude", + amount: length * dir + }); + }; + + self.sendSelectToolCommand = function (data) { + if (!data || !data.key()) return; + + self.sendToolCommand({ + command: "select", + tool: data.key() + }); + }; + + self.sendPrintHeadCommand = function (data) { + $.ajax({ + url: API_BASEURL + "printer/printhead", + type: "POST", + dataType: "json", + contentType: "application/json; charset=UTF-8", + data: JSON.stringify(data) + }); + }; + + self.sendToolCommand = function (data) { + $.ajax({ + url: API_BASEURL + "printer/tool", + type: "POST", + dataType: "json", + contentType: "application/json; charset=UTF-8", + data: JSON.stringify(data) + }); + }; + + self.sendCustomCommand = function (command) { + if (!command) + return; + + var data = undefined; + if (command.hasOwnProperty("command")) { + // single command + data = {"command": command.command}; + } else if (command.hasOwnProperty("commands")) { + // multi command + data = {"commands": command.commands}; + } else if (command.hasOwnProperty("script")) { + data = {"script": command.script}; + if (command.hasOwnProperty("context")) { + data["context"] = command.context; + } + } else { + return; + } + + if (command.hasOwnProperty("input")) { + // parametric command(s) + data["parameters"] = {}; + _.each(command.input, function(input) { + if (!input.hasOwnProperty("parameter") || !input.hasOwnProperty("value")) { + return; + } + + data["parameters"][input.parameter] = input.value(); + }); + } + + $.ajax({ + url: API_BASEURL + "printer/command", + type: "POST", + dataType: "json", + contentType: "application/json; charset=UTF-8", + data: JSON.stringify(data) + }) + }; + + self.displayMode = function (customControl) { + if (customControl.hasOwnProperty("children")) { + return "customControls_containerTemplate"; + } else { + return "customControls_controlTemplate"; + } + }; + + self.rowCss = function (customControl) { + var span = "span2"; + var offset = ""; + if (customControl.hasOwnProperty("width")) { + span = "span" + customControl.width; + } + if (customControl.hasOwnProperty("offset")) { + offset = "offset" + customControl.offset; + } + return span + " " + offset; + }; + + self.onStartup = function () { + self.requestData(); + }; + + self.onTabChange = function (current, previous) { + if (current == "#control") { + if (self.webcamDisableTimeout != undefined) { + clearTimeout(self.webcamDisableTimeout); + } + var webcamImage = $("#webcam_image"); + var currentSrc = webcamImage.attr("src"); + if (currentSrc === undefined || currentSrc.trim() == "") { + var newSrc = CONFIG_WEBCAM_STREAM; + if (CONFIG_WEBCAM_STREAM.lastIndexOf("?") > -1) { + newSrc += "&"; + } else { + newSrc += "?"; + } + newSrc += new Date().getTime(); + + webcamImage.attr("src", newSrc); + } + } else if (previous == "#control") { + // only disable webcam stream if tab is out of focus for more than 5s, otherwise we might cause + // more load by the constant connection creation than by the actual webcam stream + self.webcamDisableTimeout = setTimeout(function () { + $("#webcam_image").attr("src", ""); + }, 5000); + } + }; + + self.onAllBound = function (allViewModels) { + var additionalControls = []; + _.each(allViewModels, function (viewModel) { + if (viewModel.hasOwnProperty("getAdditionalControls")) { + additionalControls = additionalControls.concat(viewModel.getAdditionalControls()); + } + }); + if (additionalControls.length > 0) { + self.additionalControls = additionalControls; + self.rerenderControls(); + } + }; + + self.onFocus = function (data, event) { + if (!self.settings.feature_keyboardControl()) return; + self.keycontrolActive(true); + }; + + self.onMouseOver = function (data, event) { + if (!self.settings.feature_keyboardControl()) return; + $("#webcam_container").focus(); + self.keycontrolActive(true); + }; + + self.onMouseOut = function (data, event) { + if (!self.settings.feature_keyboardControl()) return; + $("#webcam_container").blur(); + self.keycontrolActive(false); + }; + + self.toggleKeycontrolHelp = function () { + self.keycontrolHelpActive(!self.keycontrolHelpActive()); + }; + + self.onKeyDown = function (data, event) { + if (!self.settings.feature_keyboardControl()) return; + + var button = undefined; + var visualizeClick = true; + + switch (event.which) { + case 37: // left arrow key + // X- + button = $("#control-xdec"); + break; + case 38: // up arrow key + // Y+ + button = $("#control-yinc"); + break; + case 39: // right arrow key + // X+ + button = $("#control-xinc"); + break; + case 40: // down arrow key + // Y- + button = $("#control-ydec"); + break; + case 49: // number 1 + case 97: // numpad 1 + // Distance 0.1 + button = $("#control-distance01"); + visualizeClick = false; + break; + case 50: // number 2 + case 98: // numpad 2 + // Distance 1 + button = $("#control-distance1"); + visualizeClick = false; + break; + case 51: // number 3 + case 99: // numpad 3 + // Distance 10 + button = $("#control-distance10"); + visualizeClick = false; + break; + case 52: // number 4 + case 100: // numpad 4 + // Distance 100 + button = $("#control-distance100"); + visualizeClick = false; + break; + case 33: // page up key + case 87: // w key + // z lift up + button = $("#control-zinc"); + break; + case 34: // page down key + case 83: // s key + // z lift down + button = $("#control-zdec"); + break; + case 36: // home key + // xy home + button = $("#control-xyhome"); + break; + case 35: // end key + // z home + button = $("#control-zhome"); + break; + default: + event.preventDefault(); + return false; + } + + if (button === undefined) { + return false; + } else { + event.preventDefault(); + if (visualizeClick) { + button.addClass("active"); + setTimeout(function () { + button.removeClass("active"); + }, 150); + } + button.click(); + } + }; + + } + + OCTOPRINT_VIEWMODELS.push([ + ControlViewModel, + ["loginStateViewModel", "settingsViewModel"], + "#control" + ]); +}); diff --git a/src/octoprint/static/js/app/viewmodels/navigation.js b/src/octoprint/static/js/app/viewmodels/navigation.js index dff18142..ee8a4065 100644 --- a/src/octoprint/static/js/app/viewmodels/navigation.js +++ b/src/octoprint/static/js/app/viewmodels/navigation.js @@ -35,17 +35,9 @@ $(function() { }) }; if (action.confirm) { - var confirmationDialog = $("#confirmation_dialog"); - var confirmationDialogAck = $(".confirmation_dialog_acknowledge", confirmationDialog); - - $(".confirmation_dialog_message", confirmationDialog).text(action.confirm); - confirmationDialogAck.unbind("click"); - confirmationDialogAck.bind("click", function(e) { - e.preventDefault(); - $("#confirmation_dialog").modal("hide"); - callback(); + showConfirmationDialog(action.confirm, function (e) { + callback(); }); - confirmationDialog.modal("show"); } else { callback(); }