self._replaceHeadingElements = function () {
- try {
- // Gets me all the elements with the class name heading
- var elems = document.getElementsByClassName("heading");
- for(let i=0; i < elems.length ; i++){
- var type = elems.item(i);
- // The next line gives me the element tag name (a, div, etc..)
- var tag = $(type).prop("tagName");
- var classNames = $(type).attr("class");
- var elementText = $(type).text();
- if( (classNames == 'container-fluid heading') && (tag =="A")){
- var dataTargetNames = $(type).attr('data-target');
- var idName = $(type).attr('data-test-id');
- var childs = $(type).children();
- var parents = $(type).parent();
- var new_id = dataTargetNames.concat("_heading").replace("#","");
- $(type).replaceWith("
");
- var new_Elem = document.getElementById(new_id);
- $(new_Elem).text(elementText);
- $(new_Elem).prepend(childs[0]);
- }
- }
- } catch (e) {
- self.logToConsole(e);
- }
+ try {
+ // Gets me all the elements with the class name heading
+ var elems = document.getElementsByClassName("heading");
+ for (let i = 0; i < elems.length; i++) {
+ var type = elems.item(i);
+ // The next line gives me the element tag name (a, div, etc..)
+ var tag = $(type).prop("tagName");
+ var classNames = $(type).attr("class");
+ var elementText = $(type).text();
+ if (classNames == "container-fluid heading" && tag == "A") {
+ var dataTargetNames = $(type).attr("data-target");
+ var idName = $(type).attr("data-test-id");
+ var childs = $(type).children();
+ var parents = $(type).parent();
+ var new_id = dataTargetNames
+ .concat("_heading")
+ .replace("#", "");
+ $(type).replaceWith(
+ '
'
+ );
+ var new_Elem = document.getElementById(new_id);
+ $(new_Elem).text(elementText);
+ $(new_Elem).prepend(childs[0]);
+ }
+ }
+ } catch (e) {
+ self.logToConsole(e);
+ }
};
//---------------------------------------------------------------------------
// Fixes the footer to the bottom of the page
- self.set_fixedFooter = function(enable) {
- try {
- $('.footer').css("position", "fixed");
- $('.footer').css("display", "inline-flex");
- $('.footer').css("justify-content","space-between");
- $('.footer').css("background-color", "rgb(233,233,233)");
- $('.footer').css("left","0px");
- $('.footer').css("bottom","0px");
- $('.footer').css("right","0px");
- } catch (e) {
- self.logToConsole(e);
- }
- };
- //---------------------------------------------------------------------------
- self.set_blocksWrapper = function(settingsPlugin){
- try {
- // The idea of this wrapper is to have the button for the connection and all the printer notifications
- // on the same space. So i'll just append the wrappers to the correct place
- $('#blocksWrapper').appendTo($('#BTC1'));
- // I want the printer notifications and be able to connect to the printer in the same space
- $('#blocks_notifications_wrapper').appendTo('#blocksWrapper');
- $('#sidebar_plugin_action_command_notification').prepend('
Notifications
');
- } catch (e) {
- self.logToConsole(e);
- }
- };
- //---------------------------------------------------------------------------
- self._correctFilesWrapper = function(settingsPlugin){
- try {
- $('#files_wrapper > div.container-fluid.heading').attr('role','group');
- $('.btn-group').css({'font-size': ''});
- $('#files_wrapper > div.container-fluid.heading').children().removeClass('btn-group');
- //i'm going to wrap the three files triggers inside a container
- $('#files_wrapper > .container-fluid > div.accordion-heading-button').wrapAll('
');
- $('#files > .accordion-inner').addClass('container-fluid body').removeClass('accordion-inner');
- $('#files_triggers').appendTo($('#files_heading'));
- } catch (e) {
- self.logToConsole(e);
- }
- };
- //---------------------------------------------------------------------------
- self.new_tabs = function (){
- self.set_tabWebStream();
- self.set_ControlWrapper();
- self.set_TemperatureWrapper();
- self.set_tabbable();
- }
-
- self.set_ControlWrapper = function(){
- try {
- // Remove the tab-pane class because it's no longer a tab pane, it's a separate wrapper now
- $('#control').removeClass('tab-pane').addClass('body');
- // Fix the size of the control wrapper letters.
- $('h1').css("font-size","15px");
- $('h1').css("font-weight","bold");
- // Now that i have this fan slider i really don't need the general tab.
- $('#control-jog-general').remove(); // Remove the general pane from control.
- $('#control-jog-xy').appendTo($('#control_xy'));
- $('#jog_distance').appendTo($('#control_xy'));
- $('#control-jog-z').appendTo($('#control_z'));
- $('#control-jog-feedrate').appendTo($('#feed_rate_mod'));
- $('#control-jog-extrusion').appendTo($('#control_extrusion'));
- $('#control-jog-flowrate').appendTo($('#flow_rate_mod'));
- $('#control').remove(); // Remove the old control from the ui
- } catch (e) {
- self.logToConsole("Control wrapper set error" + e);
- }
- };
- //---------------------------------------------------------------------------
- self.set_tabWebStream = function (settingsPlugin){
- try {
- $('#webcam_hls_container').appendTo($('#tab_plugin_BLOCKS'));
- $('#webcam_container').addClass("container-fluid");
- $('#webcam_container').appendTo($('#tab_plugin_BLOCKS'));
- var element = $('#webcam_container')
- $('#fullscreenButton').appendTo($('#webcam_container'));
-
- } catch (e) {
- self.logToConsole("Error on relocating webcam" + e);
- }
- };
- //---------------------------------------------------------------------------
- self.set_tabbable = function(settingsPlugin){
- try {
- // Remove the container borders.
- $('#tabs_content').css("border-right", "unset");
- $('#tabs_content').css("border-left", "unset");
- $('#tabs_content').css("border-bottom", "unset");
- $('div.tabbable').removeClass('span8');
- $('#timelapse > h1').attr('class','dark');
- // Remove the Tabs i don't need
- $('div.tabbable > ul.nav.nav-tabs > #control_link').remove();
- $('div.tabbable > ul.nav.nav-tabs > #temp_link').remove();
- $('div.tabbable > tabs_content > #temp');
- } catch (e) {
- self.logToConsole("Remove tabs error" + e);
- }
- };
- //---------------------------------------------------------------------------
- self.set_TemperatureWrapper = function(settingsPlugin) {
- try {
- $('#temp').wrap('
');
- $('#temp').removeClass('tab-pane').addClass('body');
- $('
').insertBefore("#temp");
- $('#temp').wrapInner('
');
- $('#temp_wrapper > a').wrap('
');
- $('#temp_wrapper > div > a').append('
');
- $('#temp_wrapper > div > a').append(' Temperature ');
- //Place the wrapper in my grid
- $('#temp_wrapper').appendTo($('#BBC1'));
- $('#temperature-table').css("margin-top","0px").css("table-layout","unset");
- $('#temperature-table').removeClass('table-bordered').removeClass("table").addClass("table-sm");
- // Just a little hack so i can use the temperatureViewModel graph
- // Basically it presses the button on the tabs to create the grid
- // After the grid is created the tab is deleted from the tab container
- // because i don't need that tab there anymore
- $('.temperature_target').css('width','42%');
- $('.temperature_offset').css('width','42%');
- $('.temperature_tool').css('width','9%');
- $('#temp_link > a').trigger('click');
- } catch (e) {
- self.logToConsole("Temperature wrapper error" + e);
- }
+ self.set_fixedFooter = function (enable) {
+ try {
+ $(".footer").css("position", "fixed");
+ $(".footer").css("display", "inline-flex");
+ $(".footer").css("justify-content", "space-between");
+ $(".footer").css("background-color", "rgb(233,233,233)");
+ $(".footer").css("left", "0px");
+ $(".footer").css("bottom", "0px");
+ $(".footer").css("right", "0px");
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ self.set_blocksWrapper = function (settingsPlugin) {
+ try {
+ // The idea of this wrapper is to have the button for the connection and all the printer notifications
+ // on the same space. So i'll just append the wrappers to the correct place
+ $("#blocksWrapper").appendTo($("#BTC1"));
+ // I want the printer notifications and be able to connect to the printer in the same space
+ $("#blocks_notifications_wrapper").appendTo("#blocksWrapper");
+ $("#sidebar_plugin_action_command_notification").prepend(
+ '
Notifications
'
+ );
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ self._correctFilesWrapper = function (settingsPlugin) {
+ try {
+ $("#files_wrapper > div.container-fluid.heading").attr(
+ "role",
+ "group"
+ );
+ $(".btn-group").css({ "font-size": "" });
+ $("#files_wrapper > div.container-fluid.heading")
+ .children()
+ .removeClass("btn-group");
+ //i'm going to wrap the three files triggers inside a container
+ $(
+ "#files_wrapper > .container-fluid > div.accordion-heading-button"
+ ).wrapAll('
');
+ $("#files > .accordion-inner")
+ .addClass("container-fluid body")
+ .removeClass("accordion-inner");
+ $("#files_triggers").appendTo($("#files_heading"));
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ self.new_tabs = function () {
+ self.set_TemperatureWrapper();
+ self.set_ControlWrapper();
+ self.set_tabbable();
+ };
+ //---------------------------------------------------------------------------
+ self.set_ControlWrapper = function () {
+ try {
+ // Remove the tab-pane class because it's no longer a tab pane, it's a separate wrapper now
+ $("#control").removeClass("tab-pane").addClass("body");
+ // Fix the size of the control wrapper letters.
+ $("h1").css("font-size", "15px");
+ $("h1").css("font-weight", "bold");
+ // Now that i have this fan slider i really don't need the general tab.
+ $("#control-jog-general").remove(); // Remove the general pane from control.
+ $("#control-jog-xy").appendTo($("#control_xy"));
+ $("#jog_distance").appendTo($("#control_xy"));
+ $("#control-jog-z").appendTo($("#control_z"));
+ $("#control-jog-feedrate").appendTo($("#feed_rate_mod"));
+ $("#control-jog-extrusion").appendTo($("#control_extrusion"));
+ $("#control-jog-flowrate").appendTo($("#flow_rate_mod"));
+ // $("#control").remove(); // Remove the old control from the ui
+ } catch (e) {
+ self.logToConsole("Control wrapper set error" + e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ self.set_tabbable = function (settingsPlugin) {
+ try {
+ // Remove the container borders.
+ $("#tabs_content").css("border-right", "unset");
+ $("#tabs_content").css("border-left", "unset");
+ $("#tabs_content").css("border-bottom", "unset");
+ $("div.tabbable").removeClass("span8");
+ $("#timelapse > h1").attr("class", "dark");
+ // Remove the Tabs i don't need
+ $("div.tabbable > ul.nav.nav-tabs > #control_link").remove();
+ $("div.tabbable > ul.nav.nav-tabs > #temp_link").remove();
+ $("div.tabbable > tabs_content > #temp");
+ } catch (e) {
+ self.logToConsole("Remove tabs error" + e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ self.set_TemperatureWrapper = function (settingsPlugin) {
+ try {
+ $("#temp").wrap(
+ '
'
+ );
+ $("#temp").removeClass("tab-pane").addClass("body");
+ $(
+ '
'
+ ).insertBefore("#temp");
+ $("#temp").wrapInner(
+ '
'
+ );
+ $("#temp_wrapper > a").wrap(
+ '
'
+ );
+ $("#temp_wrapper > div > a").append(
+ '
'
+ );
+ $("#temp_wrapper > div > a").append(" Temperature ");
+ //Place the wrapper in my grid
+ $("#temp_wrapper").appendTo($("#BBC1"));
+ $("#temperature-table")
+ .css("margin-top", "0px")
+ .css("table-layout", "unset");
+ $("#temperature-table")
+ .removeClass("table-bordered")
+ .removeClass("table")
+ .addClass("table-sm");
+ // Just a little hack so i can use the temperatureViewModel graph
+ // Basically it presses the button on the tabs to create the grid
+ // After the grid is created the tab is deleted from the tab container
+ // because i don't need that tab there anymore
+ $(".temperature_target").css("width", "42%");
+ $(".temperature_offset").css("width", "42%");
+ $(".temperature_tool").css("width", "9%");
+ $("#temp_link > a").trigger("click");
+ } catch (e) {
+ self.logToConsole("Temperature wrapper error" + e);
+ }
};
//---------------------------------------------------------------------------
// I really don't want my elements to be collapsible
// I'll set my containers fluid here
- self._set_removeCollapsible = function(enable){
- try {
- $('#temp_wrapper > div ').each( function() {
- $(this).removeClass('accordion-group').removeClass('accordion-heading').addClass('container-fluid');
- });
- $('#state_wrapper > div ').each( function() {
- $(this).removeClass('accordion-group').removeClass('accordion-heading').addClass('container-fluid');
- });
- $('#sidebar_plugin_action_command_notification_wrapper > div ').each( function() {
- $(this).removeClass('accordion-group').removeClass('accordion-heading').addClass('container-fluid');
- });
- $('div.col-4-md > div').removeClass('accordion-group').addClass('container-fluid');
- $('div.col-4-md > div > div').removeClass('accordion-heading').removeClass('accordion-body');
- $('div.col-4-md > div > div > a').parent().addClass('container-fluid heading');
- $('div.col-4-md > div > div > a').removeClass('accordion-toggle').addClass('container-fluid heading');
- $('#state').removeClass('in').removeClass('collapse').addClass('container-fluid body');
- $('#state_wrapper > div.heading > a').removeAttr('data-toggle');
- $('#sidebar_plugin_action_command_notification').removeClass('in').removeClass('collapse').addClass('container-fluid body');
- $('#sidebar_plugin_action_command_notification_wrapper > div.heading > a ').removeAttr('data-toggle');
- $('#files').removeClass('in').removeClass('collapse').addClass('container-fluid body');
- $('#files_wrapper > div.heading > a').removeAttr('data-toggle');
- } catch (e) {
- self.logToConsole("Remove collapsible error" + e);
- }
+ self._set_removeCollapsible = function (enable) {
+ try {
+ $("#temp_wrapper > div ").each(function () {
+ $(this)
+ .removeClass("accordion-group")
+ .removeClass("accordion-heading")
+ .addClass("container-fluid");
+ });
+ $("#state_wrapper > div ").each(function () {
+ $(this)
+ .removeClass("accordion-group")
+ .removeClass("accordion-heading")
+ .addClass("container-fluid");
+ });
+ $(
+ "#sidebar_plugin_action_command_notification_wrapper > div "
+ ).each(function () {
+ $(this)
+ .removeClass("accordion-group")
+ .removeClass("accordion-heading")
+ .addClass("container-fluid");
+ });
+ $("div.col-4-md > div")
+ .removeClass("accordion-group")
+ .addClass("container-fluid");
+ $("div.col-4-md > div > div")
+ .removeClass("accordion-heading")
+ .removeClass("accordion-body");
+ $("div.col-4-md > div > div > a")
+ .parent()
+ .addClass("container-fluid heading");
+ $("div.col-4-md > div > div > a")
+ .removeClass("accordion-toggle")
+ .addClass("container-fluid heading");
+ $("#state")
+ .removeClass("in")
+ .removeClass("collapse")
+ .addClass("container-fluid body");
+ $("#state_wrapper > div.heading > a").removeAttr("data-toggle");
+ $("#sidebar_plugin_action_command_notification")
+ .removeClass("in")
+ .removeClass("collapse")
+ .addClass("container-fluid body");
+ $(
+ "#sidebar_plugin_action_command_notification_wrapper > div.heading > a "
+ ).removeAttr("data-toggle");
+ $("#files")
+ .removeClass("in")
+ .removeClass("collapse")
+ .addClass("container-fluid body");
+ $("#files_wrapper > div.heading > a").removeAttr("data-toggle");
+ } catch (e) {
+ self.logToConsole("Remove collapsible error" + e);
+ }
};
//---------------------------------------------------------------------------
// I delete the accordion-inner class here
- self.remove_accordion = function (settingsPlugin){
- try {
- var all_elements = document.getElementsByClassName('accordion-inner');
- for (let i=0 ; i < all_elements.length ; i++){
- var elem = all_elements.item(i);
- $(elem).addClass('container-fluid').removeClass('accordion-inner');
- }
- } catch (e) {
- self.logToConsole(e);
- }
- };
- //---------------------------------------------------------------------------
- //---------------------------------------------------------------------------
- // Connection switch trigger functionality, this set of instructions is what
- // make the switch work
- //---------------------------------------------------------------------------
- // ~~ My observable trigger, lets me know if the connection switch is
- // ~~ on or off
- self.connectIt = ko.observable(undefined);
- // ~~ subscribes my switch to a funcion, this function will always run when the
- // ~~ switch state changes (When it's pressed or not)
- self.connectIt.subscribe(function(newVal){
- try {
- if(newVal){
- OctoPrint.connection.connect();
- self.logToConsole("Printer Connecting....");
- }else{
- OctoPrint.connection.disconnect();
- self.logToConsole("Printer Disconnecting...");
- }
- } catch (e) {
- ko.onError(e);
- }
- });
- // ~~ Change the text on my connection trigger switch
- // ~~ Will display Connected/Disconnected
- // ~~ it also changes the color of the connection trigger
- // ~~ Connected =:= Green
- // ~~ Disconnected =:= Red
- self.connection_labelText = ko.pureComputed(function () {
- try {
- if (self.connection.isErrorOrClosed()){
- self.set_ConnectionSwitch(false);
- return gettext("Disconnected");
- }else{
- self.set_ConnectionSwitch(true);
- return gettext("Connected");
- }
- } catch (e) {
- ko.onError(e);
- }
- });
- // This function replaces the color of the button acording to the switch state
- // It also stores the switch state in the localStorage
- self.set_ConnectionSwitch = function(val){
- try {
- var elems = document.querySelectorAll("[switch-color]");
- var size = elems.length;
- if(val === 'true' || val == true){
- for(let i=0; i<= size; i++){
- var elem = elems.item(i);
- $(elem).attr("switch-color", "green");
- }
- $('#blocks_printer_connect').prop("checked", true);
- self.setStorage('ConnectionState', true);
- }else{
- for(let i=0; i <= size; i++){
- var elem = elems.item(i);
- $(elem).attr("switch-color", "red");
- }
- $('#blocks_printer_connect').prop("checked", false);
- self.setStorage('ConnectionState', false);
- }
- } catch (e) {
- self.logToConsole(e);
- }
- };
- //---------------------------------------------------------------------------
- // This is for my fan slider, i can increment the fan speed by ~~1%
- self.fanControl = ko.observable(0);
- // This function is triggered everytime the value of fanControl changes
- self.fanControl.subscribe(function(rangeVal){
- try {
- var fanSpeed = 2.6*rangeVal;
- var fanCommand = 'M106 S'+fanSpeed;
- self.control.sendCustomCommand({type:'command', command: fanCommand});
- } catch (e) {
- self.logToConsole(e);
- }
- });
- self.fanText = ko.pureComputed( function() {
- try {
- var fanSpeed = self.fanControl();
- return gettext(fanSpeed +'%');
- } catch (e) {
- self.logToConsole(e);
- }
- });
- //---------------------------------------------------------------------------
- // This is for my disable motors button, sends the M18 GCode to disable the steppers.
- self.motorDisable = ko.observable(undefined);
- self.motorDisable.subscribe(function(Val){
- try {
- if(Val){
- self.control.sendCustomCommand({type: 'command', command:'M18'});
- }
- } catch (e) {
- self.logToConsole("Disable steppers error" + e);
- }
- });
- //---------------------------------------------------------------------------
- // The following set of functions serves for the load/unload filament buttons
- // and all the buttons to select which type of filament we have
- self.loadFilament = ko.observable(undefined);
- self.filamentType = ko.observable(['180°', '200°', '210°']);
- // The default temperature is set to 180 Celsius
- self.newTarget = ko.observable(180);
- self.loadFilament.subscribe(function(Val){
- try {
- if(Val){
- var newCommand = 'M109 S' + self.newTarget();
- self.control.sendCustomCommand({type: 'command', command: newCommand});
- self.control.sendCustomCommand({type: 'command', command: 'M600'});
- // Coolsdown the hotend
- self.temperature.setTargetsToZero();
- }
- } catch (e) {
- ko.onError("Change filament error" + e);
- }
- });
- // Executed everytime the user selects one of the temperatures on the Change Filament Button
- self.filamentOper = function (data){
- try {
- if (data == '180°'){
- self.newTarget(180);
- }else if (data == '200°'){
- self.newTarget(200);
- }else if (data == '210°') {
- self.newTarget(210);
- }
- } catch (e) {
- self.logToConsole("Filament change temperature change error" + e);
- }
- };
- //---------------------------------------------------------------------------
- // This next set of functions are responsible for the Light/Dark switch
- self.selectThemeColors = ko.observable(false);
- self._theming = function(){
- try {
- // Get the settings
- var theme = self.getStorage('themeType');
- self.selectThemeColors(theme);
- self._set_theme(theme);
- self.selectThemeColors.subscribe( function(val){
- self._set_theme(val);
- });
- } catch (e) {
- self.logToConsole("Error on getting theme" + e);
- }
- };
- self.themeSwitchText = ko.pureComputed( function() {
- try {
- if(self.selectThemeColors() === 'true' || self.selectThemeColors() == true){
- $('#LightDarkSwitch').css("border")
- return gettext("Dark");
- }else{
- return gettext("Light");
- }
- } catch (e) {
- self.logToConsole("Theme switch error:" + e);
- }
- });
- self._set_theme = function(val){
- try {
- var elements = document.querySelectorAll("[data-theme]");
- var size = elements.length;
- if(val === 'true' || val == true){
- for(let i = 0; i <= size; i++){
- var elem = elements.item(i);
- $(elem).attr("data-theme","dark");
- }
- $('#LightDarkSwitch').prop("checked", true);
- self.setStorage('themeType', val);
- }else{
- for(let i = 0; i <= size; i++){
- var elem = elements.item(i);
- $(elem).attr("data-theme","light");
- }
- $('#LightDarkSwitch').prop("checked", false);
- self.setStorage('themeType', val);
- }
- } catch (e) {
- self.logToConsole("Set theme error" + e);
- }
- };
- // -----------------------------------------------------------------------
- // The Gcode viewer was a little wonky so i fixed it here
- self.fix_gcode_viewer = function() {
- try {
- $('#gcode_layer_slider').css('width','0%');
- $('#gcode_layer_slider').css('height','94%');
- $('#gcode_command_slider').css('width','100%');
- $('#gcode_canvas').css('width','100%');
- $('#gcode_canvas').css('height','100%');
- } catch (e) {
- self.logToConsole(e);
- }
- };
- // -----------------------------------------------------------------------
- // This is from Ui UICustumizer made by LazeMSS
- // https://github.com/LazeMSS/OctoPrint-UICustomizer
- self.setStorage = function(cname,cvalue){
- try {
- if (!Modernizr.localstorage) return;
- if (window.location.pathname != "/"){
- cname = window.location.pathname+cname;
- }
- localStorage['plugin.BLOCKS.'+cname] = cvalue;
- } catch (e) {
- self.logToConsole(e);
- }
- };
- self.getStorage = function(cname){
- try {
- if (!Modernizr.localstorage) return undefined;
- if (window.location.pathname != "/"){
- cname = window.location.pathname+cname;
- }
- return localStorage['plugin.BLOCKS.'+cname];
- } catch (e) {
- self.logToConsole(e);
- }
- };
- // -----------------------------------------------------------------------
- // This section is related to the wifi set up
-
- self.ssid = ko.observable("");
- self.password = ko.observable("");
- self.pskValid = ko.observable(false);
- self.attemptValue = ko.pureComputed ({
- read: self.password,
- write: function(value){
- if (value.length >= 8){
- self.pskValid(true);
- self.password(value);
- }else{
- self.pskValid(false);
- };
- },
- owner: self
- });
- self.setNewWifi = function(){
- try{
- if(self.ssid() != "" && self.password() != ""){
- var _dict = {
- "ssid": self.ssid(),
- "psk": self.password(),
- };
-
- $.ajax({
- url: API_BASEURL + "plugin/BLOCKS",
- type: "POST",
- dataType: "json",
- data: JSON.stringify({
- command:"wifi_SetUp",
- ip: _dict,
- }),
- contentType: "application/json; charset=utf-8"
- });
- self.logToConsole("Wifi info sent." )
- self.ssid("");
- self.password("");
- }
- }catch(e){
- self.logToConsole("Set wifi error" + e)
- }
- };
+ self.remove_accordion = function (settingsPlugin) {
+ try {
+ var all_elements =
+ document.getElementsByClassName("accordion-inner");
+ for (let i = 0; i < all_elements.length; i++) {
+ var elem = all_elements.item(i);
+ $(elem)
+ .addClass("container-fluid")
+ .removeClass("accordion-inner");
+ }
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ //---------------------------------------------------------------------------
+ // Connection switch trigger functionality, this set of instructions is what
+ // make the switch work
+ //---------------------------------------------------------------------------
+ // ~~ My observable trigger, lets me know if the connection switch is
+ // ~~ on or off
+ self.connectIt = ko.observable(undefined);
+ // ~~ subscribes my switch to a funcion, this function will always run when the
+ // ~~ switch state changes (When it's pressed or not)
+ self.connectIt.subscribe(function (newVal) {
+ try {
+ if (newVal) {
+ OctoPrint.connection.connect();
+ self.logToConsole("Printer Connecting....");
+ } else {
+ OctoPrint.connection.disconnect();
+ self.logToConsole("Printer Disconnecting...");
+ }
+ } catch (e) {
+ ko.onError(e);
+ }
+ });
+ // ~~ Change the text on my connection trigger switch
+ // ~~ Will display Connected/Disconnected
+ // ~~ it also changes the color of the connection trigger
+ // ~~ Connected =:= Green
+ // ~~ Disconnected =:= Red
+ self.connection_labelText = ko.pureComputed(function () {
+ try {
+ if (self.connection.isErrorOrClosed()) {
+ self.set_ConnectionSwitch(false);
+ return gettext("Disconnected");
+ } else {
+ self.set_ConnectionSwitch(true);
+ return gettext("Connected");
+ }
+ } catch (e) {
+ ko.onError(e);
+ }
+ });
+ // This function replaces the color of the button acording to the switch state
+ // It also stores the switch state in the localStorage
+ self.set_ConnectionSwitch = function (val) {
+ try {
+ var elems = document.querySelectorAll("[switch-color]");
+ var size = elems.length;
+ if (val === "true" || val == true) {
+ for (let i = 0; i <= size; i++) {
+ var elem = elems.item(i);
+ $(elem).attr("switch-color", "green");
+ }
+ $("#blocks_printer_connect").prop("checked", true);
+ self.setStorage("ConnectionState", true);
+ } else {
+ for (let i = 0; i <= size; i++) {
+ var elem = elems.item(i);
+ $(elem).attr("switch-color", "red");
+ }
+ $("#blocks_printer_connect").prop("checked", false);
+ self.setStorage("ConnectionState", false);
+ }
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ //---------------------------------------------------------------------------
+ // This is for my fan slider, i can increment the fan speed by ~~1%
+ self.fanControl = ko.observable(0);
+ // This function is triggered everytime the value of fanControl changes
+ self.fanControl.subscribe(function (rangeVal) {
+ try {
+ var fanSpeed = 2.6 * rangeVal;
+ var fanCommand = "M106 S" + fanSpeed;
+ self.control.sendCustomCommand({
+ type: "command",
+ command: fanCommand,
+ });
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ });
+ self.fanText = ko.pureComputed(function () {
+ try {
+ var fanSpeed = self.fanControl();
+ return gettext(fanSpeed + "%");
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ });
+ //---------------------------------------------------------------------------
+ // This is for my disable motors button, sends the M18 GCode to disable the steppers.
+ self.motorDisable = ko.observable(undefined);
+ self.motorDisable.subscribe(function (Val) {
+ try {
+ if (Val) {
+ self.control.sendCustomCommand({
+ type: "command",
+ command: "M18",
+ });
+ }
+ } catch (e) {
+ self.logToConsole("Disable steppers error" + e);
+ }
+ });
+ //---------------------------------------------------------------------------
+ // The following set of functions serves for the load/unload filament buttons
+ // and all the buttons to select which type of filament we have
+ self.loadFilament = ko.observable(undefined);
+ self.filamentType = ko.observable(["180°", "200°", "210°"]);
+ // The default temperature is set to 180 Celsius
+ self.newTarget = ko.observable(180);
+ self.loadFilament.subscribe(function (Val) {
+ try {
+ if (Val) {
+ var newCommand = "M109 S" + self.newTarget();
+ self.control.sendCustomCommand({
+ type: "command",
+ command: newCommand,
+ });
+ self.control.sendCustomCommand({
+ type: "command",
+ command: "M600",
+ });
+ // Coolsdown the hotend
+ self.temperature.setTargetsToZero();
+ }
+ } catch (e) {
+ ko.onError("Change filament error" + e);
+ }
+ });
+ // Executed everytime the user selects one of the temperatures on the Change Filament Button
+ self.filamentOper = function (data) {
+ try {
+ if (data == "180°") {
+ self.newTarget(180);
+ } else if (data == "200°") {
+ self.newTarget(200);
+ } else if (data == "210°") {
+ self.newTarget(210);
+ }
+ } catch (e) {
+ self.logToConsole(
+ "Filament change temperature change error" + e
+ );
+ }
+ };
+ //---------------------------------------------------------------------------
+ // This next set of functions are responsible for the Light/Dark switch
+ self.selectThemeColors = ko.observable(false);
+ self._theming = function () {
+ try {
+ // Get the settings
+ var theme = self.getStorage("themeType");
+ self.selectThemeColors(theme);
+ self._set_theme(theme);
+ self.selectThemeColors.subscribe(function (val) {
+ self._set_theme(val);
+ });
+ } catch (e) {
+ self.logToConsole("Error on getting theme" + e);
+ }
+ };
+ self.themeSwitchText = ko.pureComputed(function () {
+ try {
+ if (
+ self.selectThemeColors() === "true" ||
+ self.selectThemeColors() == true
+ ) {
+ $("#LightDarkSwitch").css("border");
+ return gettext("Dark");
+ } else {
+ return gettext("Light");
+ }
+ } catch (e) {
+ self.logToConsole("Theme switch error:" + e);
+ }
+ });
+ self._set_theme = function (val) {
+ try {
+ var elements = document.querySelectorAll("[data-theme]");
+ var size = elements.length;
+ if (val === "true" || val == true) {
+ for (let i = 0; i <= size; i++) {
+ var elem = elements.item(i);
+ $(elem).attr("data-theme", "dark");
+ }
+ $("#LightDarkSwitch").prop("checked", true);
+ self.setStorage("themeType", val);
+ } else {
+ for (let i = 0; i <= size; i++) {
+ var elem = elements.item(i);
+ $(elem).attr("data-theme", "light");
+ }
+ $("#LightDarkSwitch").prop("checked", false);
+ self.setStorage("themeType", val);
+ }
+ } catch (e) {
+ self.logToConsole("Set theme error" + e);
+ }
+ };
+ // -----------------------------------------------------------------------
+ // The Gcode viewer was a little wonky so i fixed it here
+ self.fix_gcode_viewer = function () {
+ try {
+ $("#gcode_layer_slider").css("width", "0%");
+ $("#gcode_layer_slider").css("height", "94%");
+ $("#gcode_command_slider").css("width", "100%");
+ $("#gcode_canvas").css("width", "100%");
+ $("#gcode_canvas").css("height", "100%");
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ // -----------------------------------------------------------------------
+ // This is from Ui UICustumizer made by LazeMSS
+ // https://github.com/LazeMSS/OctoPrint-UICustomizer
+ self.setStorage = function (cname, cvalue) {
+ try {
+ if (!Modernizr.localstorage) return;
+ if (window.location.pathname != "/") {
+ cname = window.location.pathname + cname;
+ }
+ localStorage["plugin.BLOCKS." + cname] = cvalue;
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ self.getStorage = function (cname) {
+ try {
+ if (!Modernizr.localstorage) return undefined;
+ if (window.location.pathname != "/") {
+ cname = window.location.pathname + cname;
+ }
+ return localStorage["plugin.BLOCKS." + cname];
+ } catch (e) {
+ self.logToConsole(e);
+ }
+ };
+ // -----------------------------------------------------------------------
+ // This section is related to the wifi set up
- self.network_list = ko.observableArray([]);
- self.get_network_list = function(data){
- try{
- if (data == null) return;
- self.network_list.removeAll();
- var aux = ""
- for (var i = 0; i < data.length; i++){
- if (aux === data[i])
- continue;
- else{
- aux = data[i]
- self.network_list.push(data[i]);
- }
- }
- }catch (e){
- ko.onError("Network list Getter error" + e);
- }
- };
+ self.ssid = ko.observable("");
+ self.password = ko.observable("");
+ self.pskValid = ko.observable(false);
+ self.attemptValue = ko.pureComputed({
+ read: self.password,
+ write: function (value) {
+ if (value.length >= 8) {
+ self.pskValid(true);
+ self.password(value);
+ } else {
+ self.pskValid(false);
+ }
+ },
+ owner: self,
+ });
+ self.setNewWifi = function () {
+ try {
+ if (self.ssid() != "" && self.password() != "") {
+ var _dict = {
+ ssid: self.ssid(),
+ psk: self.password(),
+ };
- self.offline = ko.observable(!ONLINE);
- };
+ $.ajax({
+ url: API_BASEURL + "plugin/BLOCKS",
+ type: "POST",
+ dataType: "json",
+ data: JSON.stringify({
+ command: "wifi_SetUp",
+ ip: _dict,
+ }),
+ contentType: "application/json; charset=utf-8",
+ });
+ self.logToConsole("Wifi info sent.");
+ self.ssid("");
+ self.password("");
+ }
+ } catch (e) {
+ self.logToConsole("Set wifi error" + e);
+ }
+ };
+ self.network_list = ko.observableArray([]);
+ self.get_network_list = function (data) {
+ try {
+ if (data == null) return;
+ self.network_list.removeAll();
+ var aux = "";
+ for (var i = 0; i < data.length; i++) {
+ if (aux === data[i]) continue;
+ else {
+ aux = data[i];
+ self.network_list.push(data[i]);
+ }
+ }
+ } catch (e) {
+ ko.onError("Network list Getter error" + e);
+ }
+ };
+ self.offline = ko.observable(!ONLINE);
+ }
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
@@ -798,20 +935,21 @@ $(function() {
OCTOPRINT_VIEWMODELS.push({
construct: BlocksViewModel,
dependencies: [
- "settingsViewModel",
- "connectionViewModel",
- "controlViewModel",
- "temperatureViewModel",
- "appearanceViewModel",
- "accessViewModel",
- "printerStateViewModel"],
+ "settingsViewModel",
+ "connectionViewModel",
+ "controlViewModel",
+ "temperatureViewModel",
+ "appearanceViewModel",
+ "accessViewModel",
+ "printerStateViewModel",
+ ],
elements: [
- "#blocksWrapper",
- "#fanSlider",
- "#control_filament",
- "#LightDarkSwitchWrapper",
- "#wifiSetUpWindow",
- "#navbar_show_wifi_setup",
- ]
+ "#blocksWrapper",
+ "#fanSlider",
+ "#control_filament",
+ "#LightDarkSwitchWrapper",
+ "#wifiSetUpWindow",
+ "#navbar_show_wifi_setup",
+ ],
});
});
diff --git a/octoprint_BLOCKS/static/js/BLOCKS_WebCam.js b/octoprint_BLOCKS/static/js/BLOCKS_WebCam.js
index 08d96e9..ddf7568 100644
--- a/octoprint_BLOCKS/static/js/BLOCKS_WebCam.js
+++ b/octoprint_BLOCKS/static/js/BLOCKS_WebCam.js
@@ -5,152 +5,183 @@
* License: APGLv3
*/
-$(function() {
-
- function BLOCKS_WebCamViewModel(parameters) {
- var self = this;
-
- self.settings = parameters[0];
- self.loginState = parameters[1];
- self.control = parameters[2];
- self.access = parameters[3];
-
-
-
- self.webcamStatus = ko.observable(false);
-
- self.onTabChange = function(current, previous){
- if(current == "#tab_plugin_BLOCKS"){
- clearTimeout(self.control.webcamDisableTimeout);
- self.webcamStatus(true);
- $('#tab_plugin_BLOCKS_link > a').attr('class','blink');
- $('#tab_plugin_BLOCKS_link > a').css("color","#f56161ed");
- // Determine stream type and switch to corresponding webcam.
- // Took from the controlViewModel.
- var streamType = determineWebcamStreamType(self.settings.webcam_streamUrl());
- if (streamType == "mjpg") {
- self.control._switchToMjpgWebcam();
- } else if (streamType == "hls") {
- self.control._switchToHlsWebcam();
- } else {
- throw "Unknown stream type " + streamType;
- }
- }else{
- self.webcamStatus(false);
- $('#tab_plugin_BLOCKS_link > a').attr('class','');
- $('#tab_plugin_BLOCKS_link > a').css("color","");
- }
- };
-
-
- self.onBrowserTabVisibilityChange = function (status) {
- if (status) {
- clearTimeout(self.control.webcamDisableTimeout);
- self.webcamStatus(true);
- var streamType = determineWebcamStreamType(self.settings.webcam_streamUrl());
- if (streamType == "mjpg") {
- self.control._switchToMjpgWebcam();
- } else if (streamType == "hls") {
- self.control._switchToHlsWebcam();
- } else {
- self.webcamStatus(false);
- throw "Unknown stream type " + streamType;
- }
- }
- };
-
-
- self.fullScreenStyles = {
- "ON":{
- "width": "100%",
- "height": "100%",
- "z-index": "1070",
- "position": "fixed",
- "display": "block",
- "top": "0px",
- "bottom": "0px",
- "right": "0px",
- "left": "0px",
- },
- "OFF":{
- "width": "100%",
- "height": "100%",
- "z-index": "unset",
- "position": "relative",
- "display": "",
- "top": "unset",
- "bottom": "unset",
- "right": "unset",
- "left": "unset",
- },
- "ROTATOR_ON":{
- "height": "calc(100% / 1.78)",
- "top": "206px",
- "position": "relative",
- },
- "ROTATOR_OFF":{
- "height": "",
- "top": "0px",
- "position": "absolute",
- },
- "ROTATOR_ON_PAD":{
- "padding-bottom":"0%",
- },
- "ROTATOR_OFF_PAD":{
- "padding-bottom":"100%",
- },
- };
-
- self.fullScreenState = ko.observable(false);
- self.fullScreenButton = ko.observable(undefined);
- self.fullScreenButton.subscribe(function(val){
- try {
- if(self.fullScreenState() === false){
- self.fullScreenOperations(true);
- self.fullScreenState(true);
-
- }else if (self.fullScreenState() === true ){
- self.fullScreenState(false);
- self.fullScreenOperations(false);
- }
- } catch (e) {
- console.log(e);
- }
- });
+/*TODO: No control view model ele não utiliza como dependencia o webcam view model do plugin.
+ *
+ * Utilizam o ko, nas templates para dar bind da template da webcam para o control viewmodel
+ * Desta forma não utilizam como dependencia, mas depois na funcão vão buscar a data correspondente a
+ * camera para poder utilizar as funcoes desta
+ */
- self.fullScreenOperations = function(state){
- if(state === true){
- $('#webcam_rotator.webcam_rotated').css(self.fullScreenStyles.ROTATOR_ON_PAD);
- $('#webcam_rotator.webcam_rotated > .webcam_fixed_ratio').css(self.fullScreenStyles.ROTATOR_ON);
- $('#webcam_container').css(self.fullScreenStyles.ON);
- }else{
- $('#webcam_rotator.webcam_rotated').css(self.fullScreenStyles.ROTATOR_OFF_PAD);
- $('#webcam_rotator.webcam_rotated > .webcam_fixed_ratio').css(self.fullScreenStyles.ROTATOR_OFF);
- $('#webcam_container').css(self.fullScreenStyles.OFF);
- }
- };
- // This event listener serves for the full screen video player
- // When the user presses Escape when the video is full screen
- var bod = document.querySelector('html');
- bod.addEventListener('keydown', (e) => {
- if((e.key ==="Escape" || e.key === 'Esc') && self.fullScreenState()===true ){
- console.log(e);
- self.fullScreenState(false);
- self.fullScreenOperations(false);
- }
+$(function () {
+ function BLOCKS_WebCamViewModel(parameters) {
+ var self = this;
+
+ self.settings = parameters[0];
+ self.loginState = parameters[1];
+ self.control = parameters[2];
+ self.access = parameters[3];
+ self.classicWebcam = parameters[4];
+ self.webcamStatus = ko.observable(false);
+
+ self.onStartupComplete = function () {
+ // Append the camera container from control in the new tab
+ $("#webcam_plugins_container ").appendTo(
+ $("#tab_plugin_octoprint_BLOCKS")
+ );
+
+ $("#fullscreenButton").appendTo($("#webcam_img_container"));
+ OctoPrint.coreui.viewmodels.controlViewModel.recreateIntersectionObservers();
+ // I can now safelly remove the old control element from the page
+ $("#control").remove();
+ };
+
+ self.onTabChange = function (current, previous) {
+ if (current == "#tab_plugin_octoprint_BLOCKS") {
+ self.onActivateWebcamTabBlink(true);
+ self.webcamStatus(true);
+ OctoPrint.coreui.viewmodels.controlViewModel.onBrowserTabVisibilityChange(
+ true
+ );
+ } else {
+ self.onActivateWebcamTabBlink(false);
+ self.webcamStatus(false);
+ OctoPrint.coreui.viewmodels.controlViewModel.onBrowserTabVisibilityChange(
+ false
+ );
+ }
+
+ if (self.classicWebcam.webcamError()) {
+ console.log("There was an error on the webcam");
+ OctoPrint.coreui.viewmodels.controlViewModel.onBrowserTabVisibilityChange(self.webcamStatus());
+ }
+ };
+
+ self.onActivateWebcamTabBlink = function (value) {
+ if (value) {
+ $("#tab_plugin_octoprint_BLOCKS_link > a").attr(
+ "class",
+ "blink"
+ );
+ $("#tab_plugin_octoprint_BLOCKS_link > a").css(
+ "color",
+ "#f56161ed"
+ );
+ } else {
+ $("#tab_plugin_octoprint_BLOCKS_link > a").attr("class", "");
+ $("#tab_plugin_octoprint_BLOCKS_link > a").css("color", "");
+ }
+ };
+
+ self.fullScreenStyles = {
+ ON: {
+ // width: "100%",
+ width: window.innerWidth,
+ // height: "100%",
+ height: window.innerHeight,
+ "z-index": "1070",
+ position: "fixed",
+ display: "block",
+ top: "0px",
+ bottom: "0px",
+ right: "0px",
+ left: "0px",
+ },
+ OFF: {
+ width: "100%",
+ height: "100%",
+ "z-index": "unset",
+ position: "relative",
+ display: "",
+ top: "unset",
+ bottom: "unset",
+ right: "unset",
+ left: "unset",
+ },
+ ROTATOR_ON: {
+ height: "calc(100% / 1.78)",
+ top: "206px",
+ position: "relative",
+ },
+ ROTATOR_OFF: {
+ height: "",
+ top: "0px",
+ position: "absolute",
+ },
+ ROTATOR_ON_PAD: {
+ "padding-bottom": "0%",
+ },
+ ROTATOR_OFF_PAD: {
+ "padding-bottom": "100%",
+ },
+ };
+
+ self.fullScreenState = ko.observable(false);
+ self.fullScreenButton = ko.observable(undefined);
+
+ self._webcamFixedRatio = document.querySelector(".webcam_fixed_ratio");
+ self._webcamFixedRatioStyle =
+ this._webcamFixedRatio.style.paddingBottom;
+
+ self.fullScreenButton.subscribe(function (val) {
+ try {
+ // var _webcamFixedRatio = document.querySelector(".webcam_fixed_ratio");
+ if (self.fullScreenState() === false) {
+ self.fullScreenOperations(true);
+ self.fullScreenState(true);
+ } else if (self.fullScreenState() === true) {
+ self.fullScreenState(false);
+ self.fullScreenOperations(false);
+ }
+ } catch (e) {
+ console.log(e);
+ }
+ });
+
+ self.fullScreenOperations = function (state) {
+ if (state === true) {
+ $("#webcam_rotator.webcam_rotated").css(
+ self.fullScreenStyles.ROTATOR_ON_PAD
+ );
+ $("#webcam_rotator.webcam_rotated > .webcam_fixed_ratio").css(
+ self.fullScreenStyles.ROTATOR_ON
+ );
+ $("#webcam_img_container").css(self.fullScreenStyles.ON);
+ self._webcamFixedRatio.style.cssText = "padding-bottom: 49.5%;";
+ } else {
+ $("#webcam_rotator.webcam_rotated").css(
+ self.fullScreenStyles.ROTATOR_OFF_PAD
+ );
+ $("#webcam_rotator.webcam_rotated > .webcam_fixed_ratio").css(
+ self.fullScreenStyles.ROTATOR_OFF
+ );
+ $("#webcam_img_container").css(self.fullScreenStyles.OFF);
+ self._webcamFixedRatio.style.paddingBottom =
+ self._webcamFixedRatioStyle;
+ }
+ };
+ // This event listener serves for the full screen video player
+ // When the user presses Escape when the video is full screen
+ var bod = document.querySelector("html");
+ bod.addEventListener("keydown", (e) => {
+ if (
+ (e.key === "Escape" || e.key === "Esc") &&
+ self.fullScreenState() === true
+ ) {
+ self.fullScreenState(false);
+ self.fullScreenOperations(false);
+ }
+ });
+ }
+ OCTOPRINT_VIEWMODELS.push({
+ construct: BLOCKS_WebCamViewModel,
+ dependencies: [
+ "settingsViewModel",
+ "loginStateViewModel",
+ "controlViewModel",
+ "accessViewModel",
+ "classicWebcamViewModel",
+ ],
+ elements: ["#fullscreenButton"],
+ // elements: ["#classicwebcam_plugin_container"],
});
-
-
- }
- OCTOPRINT_VIEWMODELS.push({
- construct: BLOCKS_WebCamViewModel,
- dependencies: [
- "settingsViewModel",
- "loginStateViewModel",
- "controlViewModel",
- "accessViewModel"],
- elements: [
- "#fullscreenButton"
- ]
- });
});
diff --git a/octoprint_BLOCKS/templates/webcam_tab.jinja2 b/octoprint_BLOCKS/templates/webcam_tab.jinja2
index e69de29..ed0837c 100644
--- a/octoprint_BLOCKS/templates/webcam_tab.jinja2
+++ b/octoprint_BLOCKS/templates/webcam_tab.jinja2
@@ -0,0 +1,9 @@
+
diff --git a/octoprint_BLOCKS/templates/webcambar.jinja2 b/octoprint_BLOCKS/templates/webcambar.jinja2
index b3d055e..619ef14 100644
--- a/octoprint_BLOCKS/templates/webcambar.jinja2
+++ b/octoprint_BLOCKS/templates/webcambar.jinja2
@@ -1,5 +1,5 @@
-