diff --git a/Makefile b/Makefile index 33b5598..84a769a 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,7 @@ define Package/doodle3d-client/install $(CP) $(PKG_BUILD_DIR)/www/favicon* $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/index.html $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/settings.html $(1)/www/ + $(CP) $(PKG_BUILD_DIR)/www/helpcontent.html $(1)/www/ $(CP) $(PKG_BUILD_DIR)/www/css/debug.min.css $(1)/www/css/ $(CP) $(PKG_BUILD_DIR)/www/css/settings.min.css $(1)/www/css/ diff --git a/js_src/Help.js b/js_src/Help.js index bf46efa..371321a 100644 --- a/js_src/Help.js +++ b/js_src/Help.js @@ -4,6 +4,7 @@ function GrandTour(_name) { console.log("GrandTour"); this.tour = ""; this.name = _name; + this.active = false; var self = this; this.init = function() { @@ -20,17 +21,18 @@ function GrandTour(_name) { 'nubPosition': 'auto', // override on a per tooltip bases 'scrollSpeed': 300, // Page scrolling speed in ms // 'timer': 2000, // 0 = off, all other numbers = time(ms) - 'startTimerOnClick': true, // true/false to start timer on first click +// 'startTimerOnClick': true, // true/false to start timer on first click 'nextButton': true, // true/false for next button visibility 'tipAnimation': 'fade', // 'pop' or 'fade' in each tip - 'pauseAfter': [], // array of indexes where to pause the tour after - 'tipAnimationFadeSpeed': 250, // if 'fade'- speed in ms of transition +// 'pauseAfter': [], // array of indexes where to pause the tour after + 'tipAnimationFadeSpeed': 350, // if 'fade'- speed in ms of transition // 'cookieMonster': true, // true/false for whether cookies are used // 'cookieDomain': false, // set to false or yoursite.com // 'cookieName': 'Doodle3DFirstTime', // choose your own cookie name // 'localStorage': true, // // 'localStorageKey': 'Doodle3DFirstTime', // choose your own cookie name 'preRideCallback' : self.preRideCallback, + 'preStepCallback': self.preStepCallback, // A method to call before each step 'postStepCallback': self.postStepCallback, // A method to call after each step 'postRideCallback': self.postRideCallback // a method to call once the tour closes }); @@ -40,41 +42,126 @@ function GrandTour(_name) { this.preRideCallback = function(index, tip) { console.log("GrandTour >> f:preRideCallback() >> index: " + index); - if ($.cookie("Doodle3DFirstTime") == "ridden" && index == 0) { - console.log("we've been here before..."); - // $(this).joyride('set_li', false, 1); + if (index == 0 && $.cookie("Doodle3DFirstTime") == "ridden") { + console.log("GrandTour >> f:preRideCallback() >> we've been here before..."); + + if ($.cookie("grandTourFinished")) { + // grand tour was previously finished (eh.. is that useful?) + + // executing this 3 times because there doesn't seem to be a 'go to step X' method +// $(this).joyride('set_li', false); + $(this).joyride('set_li', false); + $(this).joyride('set_li', false); + } else { + $(this).joyride('set_li', false); + } } - if ($.cookie("Doodle3DFirstTime") == 'ridden') { - console.log("we've been here before..."); - $(this).joyride('set_li', false); - } + + // bring up all the elements + thermometer.show(); + progressbar.show(); +// if ($.cookie("Doodle3DFirstTime") == 'ridden') { +// console.log("we've been here before..."); +// $(this).joyride('set_li', false, 4); +// } // if (index == 0) { // console.log("...yeah"); // $(this).joyride('set_li', false, 1); // } }; + this.preStepCallback = function(index, tip) { + console.log("GrandTour >> f:preStepCallback() >> index: " + index); + + var dataset = $(this)[0].$li[0].dataset; + if (dataset.action != undefined) { + console.log(" THERE'S AN ACTION!"); + switch (dataset.action) { + case "sayHello": + console.log(" action: sayHello"); + break; + case "showMessage": + console.log(" action: showMessage"); + message.set("Just a notification...", Message.NOTICE); + message.show(); + break; + case "showProgressBar": + console.log(" action: showProgressBar"); + progressbar.show(); + break; + case "showThermometer": + console.log(" action: showThermometer"); + thermometer.show(); + break; + } + } + }; this.postStepCallback = function(index, tip) { console.log("GrandTour >> f:postStepCallback() >> index: " + index); + + var dataset = $(this)[0].$li[0].dataset; + if (dataset.action != undefined) { + console.log(" THERE *WAS* AN ACTION!"); + switch (dataset.action) { + case "sayHello": + console.log(" action: sayHello"); + break; + case "showMessage": + console.log(" action: showMessage"); +// message.hide(); + break; + case "showProgressBar": + console.log(" action: showProgressBar"); +// progressbar.hide(); + break; + case "showThermometer": + console.log(" action: showThermometer"); +// thermometer.hide(); + break; + } + } }; this.postRideCallback = function(index, tip) { - console.log("GrandTour >> f:postRideCallback() >> index: " + index); +// console.log("GrandTour >> f:postRideCallback() >> index: " + index + ", self.active: " + self.active); +// console.log("GrandTour >> f:postRideCallback() >> this: " , self); + + self.active = false; $(document).trigger(helpTours.TOURFINISHED, self.name); + // hide the elements which were summoned for the purposes of the tour + thermometer.hide(); + progressbar.hide(); + message.hide(); + + // after seeing the grand tour for the first time ever, set cookie 'Doodle3DFirstTime' to true + if (!$.cookie("Doodle3DFirstTime")) { + $.cookie("Doodle3DFirstTime", 'ridden', { expires: 365, domain: false, path: '/' }); + } + if (index < $(this)[0].$tip_content.length - 1) { - console.log("doPostRideCallback >> ENDED BEFORE END"); - helpTours.startTour(helpTours.INFOREMINDER); + console.log("GrandTour >> f:postRideCallback() >> tour terminated before its true end"); + // tour wasn't finished + + // tour was ended prematurely. For only the first few visits, nag the user about being able to revisit the tour.. + if (parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) { + helpTours.startTour(helpTours.INFOREMINDER, helpTours); + } // infoReminderTour.start(); } else { - console.log("doPostRideCallback >> this is the end my friend..."); + // tour was finished + console.log("GrandTour >> f:postRideCallback() >> tour ended at its true end"); // we should be at the end... - $.cookie("Doodle3DFirstTime", 'ridden', { expires: 365, domain: false, path: '/' }); + if (!$.cookie("grandTourFinished") && parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) { + helpTours.startTour(helpTours.INFOREMINDER, helpTours); + } + $.cookie("grandTourFinished", 'yes', { expires: 365, domain: false, path: '/' }); } }; this.start = function() { - console.log("GrandTour >> f:start()"); + console.log("GrandTour >> f:start() >> this: " , this); + this.active = true; $(window).joyride('restart'); // self.tour(); }; @@ -85,6 +172,7 @@ function InfoReminderTour(_name) { console.log("InfoReminderTour"); this.tour = ""; this.name = _name; + this.active = false; var self = this; this.init = function(callback) { @@ -97,12 +185,12 @@ function InfoReminderTour(_name) { expose: true, 'tipAdjustmentX': 15, 'tipAdjustmentY': 15, - 'tipLocation': 'left', // 'top' or 'bottom' in relation to parent + 'tipLocation': 'bottom', // 'top' or 'bottom' in relation to parent 'nubPosition': 'auto', // override on a per tooltip bases 'scrollSpeed': 300, // Page scrolling speed in ms 'nextButton': true, // true/false for next button visibility 'tipAnimation': 'fade', // 'pop' or 'fade' in each tip - 'tipAnimationFadeSpeed': 250, // if 'fade'- speed in ms of transition + 'tipAnimationFadeSpeed': 350, // if 'fade'- speed in ms of transition 'preRideCallback' : self.preRideCallback, 'postStepCallback': self.postStepCallback, // A method to call after each step 'postRideCallback': self.postRideCallback // a method to call once the tour closes @@ -120,11 +208,13 @@ function InfoReminderTour(_name) { }; this.postRideCallback = function(index, tip) { console.log("InfoReminderTour >> f:postRideCallback() >> index: " + index + ", tip: " , tip); + this.active = false; $(document).trigger(helpTours.TOURFINISHED, self.name); }; this.start = function() { console.log("InfoReminderTour >> f:start()"); + this.active = true; $(window).joyride('restart'); // self.tour(); }; @@ -133,26 +223,31 @@ function InfoReminderTour(_name) { function initHelp() { console.log("f:initHelp()"); + // track number of visits of this user + if ($.cookie("Doodle3DVisitCounter") == null) { + $.cookie("Doodle3DVisitCounter", '0'); + } else { + $.cookie("Doodle3DVisitCounter", parseInt($.cookie("Doodle3DVisitCounter")) + 1); + } - -// grandTour = new GrandTour(); -// infoReminderTour = new InfoReminderTour(); - - // first call inits the tour -// joyride2(); - + // load the html file which describes the tour contents $("#helpContainer").load("helpcontent.html", function() { console.log("helpContent loaded"); - helpTours = new HelpTours(); - helpTours.init(); -// grandTour.init(); -//// infoReminderTour.init(); -// -// if ($.cookie("Doodle3DFirstTime") != "ridden") { -// console.log("intro tour has not been given yet > let's go!"); -// setTimeout(grandTour.start, 1000); -// } + helpTours = new HelpTours(); + + helpTours.init( function () { + + // only trigger starttour if user is seeing Doodle3D for the first time + if ($.cookie("Doodle3DFirstTime") != "ridden") { + console.log("initHelp >> intro tour has not been given yet > let's go!"); + setTimeout(helpTours.startTour, 750, helpTours.tours.grandTour, helpTours); + } else if (parseInt($.cookie("Doodle3DVisitCounter")) < helpTours.numTimesToShowNagPopup) { + console.log("initHelp >> Doodle3DFirstTime cookie is set, Doodle3DVisitCounter is < 4"); + // remind user of our nifty tour + setTimeout(helpTours.startTour, 750, helpTours.tours.infoReminderTour, helpTours); + } + }); }); } @@ -161,64 +256,97 @@ var helpTours; function HelpTours() { console.log("HelpTours"); + this.numTimesToShowNagPopup = 4; + this.WELCOMETOUR = "welcometour"; this.INFOREMINDER = "inforeminder"; this.TOURFINISHED = "tourfinished"; + this.tours = { + 'grandTour' : this.WELCOMETOUR, + 'infoReminderTour' : this.INFOREMINDER + }; + this.currActiveTour = ""; this.tourActive = false; var self = this; - this.init = function() { - console.log("HelpTours >> f:init"); + this.init = function(callback) { + console.log("HelpTours >> f:init >> self: " + self); $(document).on(this.TOURFINISHED, this.tourEnded); grandTour = new GrandTour(this.WELCOMETOUR); infoReminderTour = new InfoReminderTour(this.INFOREMINDER); - if ($.cookie("Doodle3DFirstTime") != "ridden") { - console.log("HelpTours >> f:init >> intro tour has not been given yet > let's go! (this.WELCOMETOUR = " + this.WELCOMETOUR + ")"); - setTimeout(this.startTour, 1000, this.WELCOMETOUR); - } +// this.tours["grandTour"] = self.WELCOMETOUR; +// this.tours["infoReminderTour "]= self.INFOREMINDER; + console.log("HelpTours >> f:init >> this.tours: " , this.tours); + + if (callback != undefined) callback(); }; - this.startTour = function(which) { - console.log("HelpTours >> f:startTour >> target to start: '" + which); + this.startTour = function(which, scope) { + if (scope == undefined) scope = this; +// console.log("HelpTours >> f:startTour >> scope: " , scope); +// console.log("HelpTours >> f:startTour >> currActiveTour: " , scope.currActiveTour.name); +// console.log("HelpTours >> f:startTour >> currActiveTour.active: " , scope.currActiveTour.active); +// console.log("HelpTours >> f:startTour >> target to start: '" + which); + + switch (which) { - case self.WELCOMETOUR: + case scope.WELCOMETOUR: // do welcometour - console.log("HelpTours >> f:startTour >> case this.WELCOMETOUR >> self.tourActive = " + self.tourActive); - if (this.tourActive) { - $(window).joyride('end'); - this.tourActive = false; +// console.log("HelpTours >> f:startTour >> case this.WELCOMETOUR >> scope.tourActive = " + scope.tourActive); + console.log("HelpTours >> f:startTour >> case this.WELCOMETOUR"); + if (scope.tourActive) { + if (scope.currActiveTour.active == true) { + $(window).joyride('end'); + scope.currActiveTour = undefined; + } + scope.tourActive = false; } $(window).joyride('destroy'); - grandTour.init(); - grandTour.start(); - this.tourActive = true; +// var self = this; + grandTour.init(); + setTimeout(function(scp) { + grandTour.start(); + scp.currActiveTour = grandTour; + scp.tourActive = true; + }, 250, scope); // $(window).joyride('restart'); break; case self.INFOREMINDER: // do info reminder - console.log("HelpTours >> f:startTour >> case self.INFOREMINDER >> self.tourActive = " + self.tourActive); - if (this.tourActive) { - $(window).joyride('end'); - this.tourActive = false; +// console.log("HelpTours >> f:startTour >> case self.INFOREMINDER >> scope.tourActive = " + scope.tourActive); + console.log("HelpTours >> f:startTour >> case self.INFOREMINDER"); + if (scope.tourActive) { +// console.log(" killing previous joyride... "); + if (scope.currActiveTour.active == true) { + $(window).joyride('end'); + scope.currActiveTour = undefined; + } +// console.log(" setting tourActive to false...."); + scope.tourActive = false; +// console.log(" scope.tourActive: " + scope.tourActive); } $(window).joyride('destroy'); - infoReminderTour.init(); - infoReminderTour.start(); - this.tourActive = true; +// var self = this; + infoReminderTour.init(); + setTimeout(function(scp) { + infoReminderTour.start(); + scp.currActiveTour = infoReminderTour; + scp.tourActive = true; + }, 250, scope); break; } } this.tourEnded = function(e, n) { - console.log("HelpTours >> f:tourEnded >> name: " + n); + console.log("HelpTours >> f:tourEnded >> this.tourActive: " + self.tourActive + ", name: " + n); - this.tourActive = false; + self.tourActive = false; } } \ No newline at end of file diff --git a/js_src/Message.js b/js_src/Message.js index dc3cab3..54c347e 100644 --- a/js_src/Message.js +++ b/js_src/Message.js @@ -10,7 +10,7 @@ function Message() { this.$element; var self = this; - var autoHideDelay = 2000; + var autoHideDelay = 5000; var autohideTimeout; this.init = function($element) { diff --git a/js_src/Printer.js b/js_src/Printer.js index 5895831..bdbd89f 100644 --- a/js_src/Printer.js +++ b/js_src/Printer.js @@ -11,7 +11,7 @@ function setPrintprogress(val) { //*/ function Printer() { - + Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected"; Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected @@ -21,22 +21,22 @@ function Printer() { Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being send to the printer, leaving will result in a incomplete 3D print"; - + this.temperature = 0; this.targetTemperature = 0; this.currentLine = 0; this.totalLines = 0; this.bufferedLines = 0; this.state = Printer.UNKNOWN_STATE; - this.hasControl = true; // whether this client has control access - - this.wifiboxURL; - + this.hasControl = true; // whether this client has control access + + this.wifiboxURL; + this.checkStatusInterval = 3000; this.checkStatusDelay; this.timeoutTime = 3000; this.sendPrintPartTimeoutTime = 5000; - + this.gcode; // gcode to be printed this.sendLength = 1500; // max amount of gcode lines per post (limited because WiFi box can't handle to much) @@ -45,16 +45,16 @@ function Printer() { this.retryCheckStatusDelay; // retry setTimout instance this.retryStopDelay; // retry setTimout instance this.retryPreheatDelay; // retry setTimout instance - - this.maxGCodeSize = 10; // max size of gcode in MB's (estimation) - + + Printer.MAX_GCODE_SIZE = 10; // max size of gcode in MB's (estimation) + this.stateOverruled = false; - + // Events Printer.UPDATE = "update"; - + var self = this; - + this.init = function() { console.log("Printer:init"); //this.wifiboxURL = "http://" + window.location.host + "/cgi-bin/d3dapi"; @@ -62,21 +62,21 @@ function Printer() { this.wifiboxURL = wifiboxURL; //this.wifiboxURL = "proxy5.php"; console.log(" wifiboxURL: ",this.wifiboxURL); - + if(autoUpdate) { this.startStatusCheckInterval(); } } - + this.preheat = function() { console.log("Printer:preheat"); - + if( this.state == Printer.BUFFERING_STATE || this.state == Printer.PRINTING_STATE || this.state == Printer.STOPPING_STATE) { return; } - + var self = this; if (communicateWithWifibox) { $.ajax({ @@ -91,7 +91,7 @@ function Printer() { self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay } } - }).fail(function() { + }).fail(function() { console.log("Printer:preheat: failed"); clearTimeout(self.retryPreheatDelay); self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay @@ -100,34 +100,41 @@ function Printer() { console.log ("Printer >> f:preheat() >> communicateWithWifibox is false, so not executing this function"); } } - + this.print = function(gcode) { console.log("Printer:print"); console.log(" gcode total # of lines: " + gcode.length); - + message.set("Sending doodle to printer...",Message.NOTICE); self.addLeaveWarning(); - + /*for (i = 0; i < gcode.length; i++) { gcode[i] += " (" + i + ")"; }*/ - + this.sendIndex = 0; this.gcode = gcode; - + //console.log(" gcode[20]: ",gcode[20]); var gcodeLineSize = this.byteSize(gcode[20]); //console.log(" gcodeLineSize: ",gcodeLineSize); var gcodeSize = gcodeLineSize*gcode.length/1024/1024; // estimate gcode size in MB's console.log(" gcodeSize: ",gcodeSize); - - if(gcodeSize > this.maxGCodeSize) { - console.log("Error: Printer:print: gcode file is probably to big ("+gcodeSize+"MB) (max: "+this.maxGCodeSize+"MB)"); + + if(gcodeSize > Printer.MAX_GCODE_SIZE) { + alert("Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)"); + console.log("Error: Printer:print: gcode file is probably too big ("+gcodeSize+"MB) (max: "+Printer.MAX_GCODE_SIZE+"MB)"); + + this.overruleState(Printer.IDLE_STATE); + this.startStatusCheckInterval(); + message.hide(); + self.removeLeaveWarning(); + return; } - + //this.targetTemperature = settings["printer.temperature"]; // slight hack - + this.sendPrintPart(this.sendIndex, this.sendLength); } this.byteSize = function(s){ @@ -135,10 +142,10 @@ function Printer() { } this.sendPrintPart = function(sendIndex,sendLength) { console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength); - + var firstOne = (sendIndex == 0)? true : false; var start = firstOne; // start printing right away - + var completed = false; if (this.gcode.length < (sendIndex + sendLength)) { console.log(" sending less than max sendLength (and last)"); @@ -147,7 +154,7 @@ function Printer() { completed = true; } var gcodePart = this.gcode.slice(sendIndex, sendIndex+sendLength); - + var postData = { gcode: gcodePart.join("\n"), first: firstOne, start: start}; var self = this; if (communicateWithWifibox) { @@ -159,7 +166,7 @@ function Printer() { timeout: this.sendPrintPartTimeoutTime, success: function(data){ console.log("Printer:sendPrintPart response: ",data); - + if(data.status == "success") { if (completed) { console.log("Printer:sendPrintPart:gcode sending completed"); @@ -170,8 +177,8 @@ function Printer() { //self.targetTemperature = settings["printer.temperature"]; // slight hack } else { // only if the state hasn't bin changed (by for example pressing stop) we send more gcode - - console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")"); + + console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")"); if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) { console.log("Printer:sendPrintPart:sending next part"); self.sendPrintPart(sendIndex + sendLength, sendLength); @@ -179,22 +186,22 @@ function Printer() { } } // after we know the first gcode packed has bin received or failed - // (and the driver had time to update the printer.state) + // (and the driver had time to update the printer.state) // we start checking the status again if(sendIndex == 0) { self.startStatusCheckInterval(); } } - }).fail(function() { + }).fail(function() { console.log("Printer:sendPrintPart: failed"); clearTimeout(self.retrySendPrintPartDelay); self.retrySendPrintPartDelay = setTimeout(function() { console.log("request printer:sendPrintPart failed retry"); - self.sendPrintPart(sendIndex, sendLength) + self.sendPrintPart(sendIndex, sendLength) },self.retryDelay); // retry after delay - + // after we know the gcode packed has bin received or failed - // (and the driver had time to update the printer.state) + // (and the driver had time to update the printer.state) // we start checking the status again self.startStatusCheckInterval(); }); @@ -202,7 +209,7 @@ function Printer() { console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function"); } } - + this.stop = function() { console.log("Printer:stop"); var self = this; @@ -214,19 +221,19 @@ function Printer() { timeout: this.timeoutTime, success: function(data){ console.log("Printer:stop response: ", data); - + // after we know the stop has bin received or failed - // (and the driver had time to update the printer.state) + // (and the driver had time to update the printer.state) // we start checking the status again self.startStatusCheckInterval(); } - }).fail(function() { + }).fail(function() { console.log("Printer:stop: failed"); clearTimeout(self.retryStopDelay); self.retryStopDelay = setTimeout(function() { self.stop() },self.retryDelay); // retry after delay - + // after we know the stop has bin received or failed - // (and the driver had time to update the printer.state) + // (and the driver had time to update the printer.state) // we start checking the status again self.startStatusCheckInterval(); }); @@ -258,9 +265,9 @@ function Printer() { timeout: this.timeoutTime, success: function(response){ //console.log(" Printer:status: ",response.data.state); //," response: ",response); - + self.handleStatusUpdate(response); - + clearTimeout(self.checkStatusDelay); clearTimeout(self.retryCheckStatusDelay); self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval); @@ -289,11 +296,11 @@ function Printer() { self.state = data.state; //console.log(" state > ",self.state); } - + // temperature self.temperature = data.hotend; self.targetTemperature = data.hotend_target; - + // progress self.currentLine = data.current_line; self.totalLines = data.total_lines; @@ -301,7 +308,7 @@ function Printer() { // access self.hasControl = data.has_control; - + if(self.state == Printer.PRINTING_STATE || self.state == Printer.STOPPING_STATE) { console.log("progress: ",self.currentLine+"/"+self.totalLines+" ("+self.bufferedLines+") ("+self.state+")"); } @@ -311,20 +318,21 @@ function Printer() { this.overruleState = function(newState) { this.stateOverruled = true; console.log(" stateOverruled: ",this.stateOverruled); - + self.state = newState; - + $(document).trigger(Printer.UPDATE); - + this.stopStatusCheckInterval(); } - + this.removeLeaveWarning = function() { window.onbeforeunload = null; } this.addLeaveWarning = function() { window.onbeforeunload = function() { + console.log("WARNING:"+Printer.ON_BEFORE_UNLOAD_MESSAGE); return Printer.ON_BEFORE_UNLOAD_MESSAGE; }; } -} +} \ No newline at end of file diff --git a/js_src/Progressbar.js b/js_src/Progressbar.js index a148ea8..0a91a3e 100644 --- a/js_src/Progressbar.js +++ b/js_src/Progressbar.js @@ -12,6 +12,9 @@ function Progressbar() { this.quartPI = .5 * Math.PI; this.twoPI = 2 * Math.PI; + // To make the progressbar start with a minimal amount of 'progress' + // so that you can visually see that there is progress + this.progressPadding = Math.PI * .1; this.$canvas; this.canvas; @@ -73,7 +76,7 @@ function Progressbar() { this.context.beginPath(); this.context.moveTo(45, 45); this.context.lineTo(45, 0); - this.context.arc(45, 45, 45, -this.quartPI, -this.quartPI + (progress * (this.twoPI)), false); // circle bottom of thermometer + this.context.arc(45, 45, 45, -this.quartPI, -this.quartPI + this.progressPadding + (progress * (this.twoPI - this.progressPadding)), false); // circle bottom of thermometer this.context.lineTo(45, 45); this.context.clip(); diff --git a/js_src/SettingsWindow.js b/js_src/SettingsWindow.js index 9c56c0c..9170b8a 100644 --- a/js_src/SettingsWindow.js +++ b/js_src/SettingsWindow.js @@ -250,16 +250,13 @@ function SettingsWindow() { } this.displayValidationError = function(key,msg) { var formElement = self.form.find("[name|='"+key+"']"); - console.log("formElement: ",formElement); formElement.addClass("error"); var errorMsg = "

"+msg+"

" formElement.after(errorMsg); } this.clearValidationErrors = function() { - var formElements = self.form.find(".error"); - formElements.each( function(index,element) { - $(element).removeClass("error"); - }); + self.form.find(".errorMsg").remove(); + self.form.find(".error").removeClass("error"); } this.readForm = function() { diff --git a/js_src/buttonbehaviors.js b/js_src/buttonbehaviors.js index 7ce03c4..25cd55e 100644 --- a/js_src/buttonbehaviors.js +++ b/js_src/buttonbehaviors.js @@ -170,7 +170,7 @@ function initButtonBehavior() { btnInfo.mouseup(function(e) { e.preventDefault(); console.log("btnInfo mouse up"); - helpTours.startTour(helpTours.WELCOMETOUR); + if (!clientInfo.isSmartphone) helpTours.startTour(helpTours.WELCOMETOUR); }); // DEBUG diff --git a/js_src/gcodeGenerating.js b/js_src/gcodeGenerating.js index 8cd3a4c..d75bc23 100644 --- a/js_src/gcodeGenerating.js +++ b/js_src/gcodeGenerating.js @@ -25,7 +25,7 @@ gcodeEnd.push("G90"); // absolute positioning gcodeEnd.push("M117 Done "); // display message (20 characters to clear whole screen)*/ -var MAX_POINTS_TO_PRINT = 400000; //80000; //40000; +var MAX_POINTS_TO_PRINT = 200000; //400000; //80000; //40000; var gcode = []; function generate_gcode() { @@ -139,9 +139,11 @@ function generate_gcode() { //console.log(" pointsToPrint: ",pointsToPrint); //console.log(" MAX_POINTS_TO_PRINT: ",MAX_POINTS_TO_PRINT); + console.log("pointsToPrint: ",pointsToPrint); + if(pointsToPrint > MAX_POINTS_TO_PRINT) { - alert("Sorry, your doodle to to complex and / or to high"); - console.log("WARNING: to many points to convert to gcode"); + alert("Sorry, your doodle too complex and / or to high"); + console.log("ERROR: to many points too convert to gcode"); return []; } diff --git a/js_src/main.js b/js_src/main.js index adc2a89..0eb87d4 100644 --- a/js_src/main.js +++ b/js_src/main.js @@ -20,10 +20,11 @@ var $drawAreaContainer, $doodleCanvas, doodleCanvas, doodleCanvasContext, $previ var showhideInterval; var showOrHide = false; +var clientInfo = {}; + $(function() { console.log("ready"); - //TODO give this a more logical place in code if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1"); @@ -49,13 +50,17 @@ $(function() { console.log("wifiboxIsRemote: " + wifiboxIsRemote); console.log("wifibox URL: " + wifiboxURL); + // rudimentary client info + clientInfo.isMobileDevice = isMobileDevice(); + clientInfo.isSmartphone = isSmartphone(); + initDoodleDrawing(); initPreviewRendering(); initLayouting(); initSidebars(); initButtonBehavior(); initVerticalShapes(); - initHelp(); + if (!clientInfo.isSmartphone) initHelp(); thermometer.init($("#thermometerCanvas"), $("#thermometerContainer")); progressbar.init($("#progressbarCanvas"), $("#progressbarCanvasContainer")); diff --git a/js_src/utils.js b/js_src/utils.js index 5ab9f65..3a88529 100644 --- a/js_src/utils.js +++ b/js_src/utils.js @@ -5,3 +5,24 @@ function getURLParameter(name) { (new RegExp('[&?]'+name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1] ); } + +// returns true for all smartphones and tablets +function isMobileDevice() { + return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Windows Mobile/i.test(navigator.userAgent); +} + +// returns true for smartphones (Android will be a bit dodgy (tablet or phone, all depends on pixels vs devicePixelRatio...) +function isSmartphone() { + var returnBool = false; + if( /Android/i.test(navigator.userAgent) && window.devicePixelRatio > 1) { + var w = $(window).width() / window.devicePixelRatio; + console.log("Android device >> ratio'd width: " + w); + if (w < 480) { + returnBool = true; + } + } else { + returnBool = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini|Windows Mobile/i.test(navigator.userAgent) + } + + return returnBool; +} diff --git a/less/help_joyride-2.1.less b/less/help_joyride-2.1.less index 2ec4430..cfa7f99 100644 --- a/less/help_joyride-2.1.less +++ b/less/help_joyride-2.1.less @@ -1,11 +1,8 @@ -/* Artfully masterminded by ZURB */ -body { - /*position: relative;*/ -} - -//#joyRideTipContent { display: none; } -// -//.joyRideTipContent { display: none; } +//@helpBlue: #2470E2; +@darkBlue: #013; +@helpBlue: #1B76FF; +@helpFullBlue: rgb(0,85,214); +@helpDarkBlue: darken(desaturate(@helpBlue, 25%), 35%); /* Default styles for the container */ .joyride-tip-guide { @@ -13,7 +10,8 @@ body { // background: #000; background: rgba(255, 255, 255, 0.92); display: none; - color: #222; + color: @darkBlue; +// color: rgb(0,99,255); width: 300px; z-index: 101; top: 0; /* keeps the page from scrolling when calculating position */ @@ -21,7 +19,9 @@ body { // font-family: "HelveticaNeue", "Helvetica Neue", "Helvetica", Helvetica, Arial, Lucida, sans-serif; font-weight: normal; border-radius: 10px; - border: 3px solid #5FCE4F; +// border: 3px solid #5FCE4F; +// border: 3px solid #374952; + border: 3px solid @helpFullBlue; box-shadow: 0 0 15px rgba(0, 0, 0, 0.4); } @@ -64,7 +64,8 @@ body { and override the top,left,right colors below. */ // border-color: #000; - border-color: rgba(67, 216, 20, 1.0); +// border-color: rgba(67, 216, 20, 1.0) !important; + border-color: @helpFullBlue !important; // border-color: rgba(0,0,0,0.8); border-top-color: transparent !important; border-left-color: transparent !important; @@ -83,7 +84,8 @@ body { and override the bottom,left,right colors below. */ // border-color: #000; - border-color: rgba(67, 216, 20, 1.0) !important; +// border-color: rgba(67, 216, 20, 1.0) !important; + border-color: @helpFullBlue !important; // border-color: rgba(0,0,0,0.8) !important; border-bottom-color: transparent !important; border-left-color: transparent !important; @@ -95,7 +97,8 @@ body { .joyride-tip-guide span.joyride-nub.right { // border-color: #000; - border-color: rgba(67, 216, 20, 1.0) !important; +// border-color: rgba(67, 216, 20, 1.0) !important; + border-color: @helpFullBlue !important; // border-color: rgba(0,0,0,0.8) !important; border-top-color: transparent !important; border-right-color: transparent !important; @@ -109,7 +112,8 @@ body { .joyride-tip-guide span.joyride-nub.left { // border-color: #000; - border-color: rgba(67, 216, 20, 1.0) !important; +// border-color: rgba(67, 216, 20, 1.0) !important; + border-color: @helpFullBlue !important; // border-color: rgba(0,0,0,0.8) !important; border-top-color: transparent !important; border-left-color: transparent !important; @@ -122,8 +126,8 @@ body { } .joyride-tip-guide span.joyride-nub.top-right { - border-color: #000; - border-color: rgba(0,0,0,0.8); +// border-color: #000; + border-color: @helpFullBlue; border-top-color: transparent !important; border-left-color: transparent !important; border-right-color: transparent !important; @@ -143,7 +147,8 @@ body { line-height: 1.25; margin: 0; font-weight: bold; - color: #2DDF34; +// color: #2DDF34; + color: @helpFullBlue; // color: #fff; } } @@ -160,12 +165,15 @@ body { line-height: 18px; } .joyride-tip-guide a { - color: rgb(255,255,255); +// color: rgb(255,255,255); + color: @helpFullBlue; text-decoration: none; - border-bottom: dotted 1px rgba(255,255,255,0.6); +// border-bottom: dotted 1px rgba(255,255,255,0.6); + border-bottom: dotted 1px lighten(@helpFullBlue, 20%); } .joyride-tip-guide a:hover { - color: rgba(255,255,255,0.8); +// color: rgba(255,255,255,0.8); + color: lighten(@helpFullBlue, 20%); border-bottom: none; } diff --git a/www/helpcontent.html b/www/helpcontent.html index 950cec9..a9d75cb 100644 --- a/www/helpcontent.html +++ b/www/helpcontent.html @@ -16,30 +16,58 @@

You can control all the details for you tour stop. Any valid HTML will work inside of Joyride.

linkme beautiful.

+
  • +

    previous and next

    +

    Get the details right by styling Joyride with a custom stylesheet!

    +
  • Save

    Get the details right by styling Joyride with a custom stylesheet!

  • -
  • -

    Modal

    -

    It works as a modal too!

    -
  • Oops

    It works right aligned.

  • +
  • +

    Now for the right panel

    +

    It works as a modal too!

    +
  • -

    Print

    +

    Right Panel

    It works with classes, and only on the first visible element with that class.

  • Print

    It works with classes, and only on the first visible element with that class.

  • -
  • +
  • Stop

    It works with classes, and only on the first visible element with that class.

  • +
  • +

    progressguage

    +

    It works with classes, and only on the first visible element with that class.

    +
  • +
  • +

    Thermometer

    +

    It works with classes, and only on the first visible element with that class.

    +
  • +
  • +

    Status messages

    +

    Status messages can inform you about the connection between Doodle3D and your 3D printer

    +
  • +
  • +

    Status messages

    +

    Status messages can inform you about the connection between Doodle3D and your 3D printer

    +
  • +
  • +

    That was the tour

    +

    You're now ready to start using Doodle3d!

    +
  • + + + +
      @@ -49,6 +77,13 @@
    +
      +
    1. +

      Reminder

      +

      You can always find this tour in the info window.

      +
    2. +
    +