• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
MagicMirror Forum
  • Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.

Nunjucks and Chartjs / Javascript

Scheduled Pinned Locked Moved Development
15 Posts 2 Posters 3.9k Views 2 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    sdetweil @lavolp3
    last edited by sdetweil Sep 27, 2019, 2:25 PM Sep 27, 2019, 2:19 PM

    @lavolp3 according to the code in app/js/module.js

    its either template OR dom, not both.

    	/* getDom()
    	 * This method generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
    	 * This method can to be subclassed if the module wants to display info on the mirror.
    	 * Alternatively, the getTemplate method could be subclassed.
    

    using Chart.js in my module I do

       				position: 'top_right',
    

    in config, so that is the base location
    then

    create the canvas div, and then the chart in the canvas (I could have multiple charts to draw, from an array of data)

    					var this_pin = wself.config.Pins[pin_index];
    					// clear the work variable
    					var canvas = null;
    					// try to locate the existing chart
    					if ((canvas = document.getElementById("myChart" + this_pin)) == null) {
    						var c = document.createElement("div");
    						c.style.width = wself.config.width + "px";
    						c.style.height = wself.config.height + "px";
    						if (!wself.config.stacked)
    						{c.style.display = "inline-block";}
    						wself.wrapper.appendChild(c);
    
    						canvas = document.createElement("canvas");
    						canvas.id = "myChart" + this_pin;
    						c.appendChild(canvas);
    					}
    					// if the chart has been created
    					if (wself.charts[pin_index] != null) {
    						// destroy it, update doesn't work reliably
    						wself.charts[pin_index].destroy();
    						// make it unreferenced
    						wself.charts[pin_index] = 0;
    					}
    					// create it now
    					wself.charts[pin_index] = new Chart(canvas, {
    						type: "line",
    						showLine: true,
    						data: {
    ...
                // then return the outer container div 
    		return wself.wrapper;
    

    U could download my module and look at it
    https://github.com/sdetweil/WaterLevels

    so, in the end I have

    wrapper  (div)
         div (chart 1)
           chart canvas
         div (chart 2)
           chart canvas
         ...
         div (chart n)
           chart canvas
    

    I have never used templates for anything… (I have enough trouble with normal code)

    Sam

    How to add modules

    learning how to use browser developers window for css changes

    L 2 Replies Last reply Sep 27, 2019, 2:26 PM Reply Quote 1
    • L Offline
      lavolp3 Module Developer @sdetweil
      last edited by Sep 27, 2019, 2:26 PM

      @sdetweil

      Thanks Sam.
      I have built a module with chart.js as well, no problme with that, however this time I am kind of dependant on nunjucks because I had forked a project and do not want to rebuild everything.

      But thanks for pointing me to the core code. I always forget to have a look into that.

      How to troubleshoot modules
      MMM-soccer v2, MMM-AVStock

      1 Reply Last reply Reply Quote 0
      • L Offline
        lavolp3 Module Developer @sdetweil
        last edited by Sep 27, 2019, 2:37 PM

        @sdetweil said in Nunjucks and Chartjs / Javascript:

        its either template OR dom, not both.
        /* getDom()

        • This method generates the dom which needs to be displayed. This method is called by the Magic Mirror core.
        • This method can to be subclassed if the module wants to display info on the mirror.
        • Alternatively, the getTemplate method could be subclassed.

        I understand this differently from the core code.
        From what I see getDom is the parent function and getTemplate fills this with html code from a template. So in a module using nunjucks you could call getDom AND getTemplate separately.
        And manipulate the dom after the template is loaded.
        But that is something I fail to do…

        How to troubleshoot modules
        MMM-soccer v2, MMM-AVStock

        S 1 Reply Last reply Sep 27, 2019, 2:40 PM Reply Quote 0
        • S Offline
          sdetweil @lavolp3
          last edited by sdetweil Sep 27, 2019, 2:55 PM Sep 27, 2019, 2:40 PM

          @lavolp3 note… if you have the functions getDom, and getTemplate and getTemplateData
          then the core methods will NOT be called.

          i think IF you have getDom , then unless YOU call them , getTemplate and getTemplateData will NOT be called. (because u replaced the built in getDom() with your own version)

          getTemplate and getTemplateData are ONLY called from the default getDom

          I confirmed this in one of my modules that uses getDom()… I added the template methods, and logged when they were called…

          getTemplate: function() {
          	Log.log("in getTemplate");
          	return "";
          },
          getTemplateData: function (){
          	Log.log("in getTemplateData");
          	return "";
          }
          

          they were not called

          Sam

          How to add modules

          learning how to use browser developers window for css changes

          L 1 Reply Last reply Sep 27, 2019, 3:08 PM Reply Quote 0
          • L Offline
            lavolp3 Module Developer @sdetweil
            last edited by Sep 27, 2019, 3:08 PM

            @sdetweil fully understood and agree.
            Thinking about replacing getdom with the native one and somehow implementing my chart function but there has to be a simpler way.

            After all getdom is the only function replacing the dom, in my case loading the template, isn’t it?. So there must be a way to manipulate the dom directly after it has been created.

            How to troubleshoot modules
            MMM-soccer v2, MMM-AVStock

            L 1 Reply Last reply Sep 27, 2019, 3:17 PM Reply Quote 0
            • L Offline
              lavolp3 Module Developer @lavolp3
              last edited by Sep 27, 2019, 3:17 PM

              Wait. There is an asynch function in the getdom function, isn’t there? So calling my function directly afterwards may lead to a state where the dom is not yet created. Hmm…

              How to troubleshoot modules
              MMM-soccer v2, MMM-AVStock

              S 1 Reply Last reply Sep 27, 2019, 5:11 PM Reply Quote 0
              • S Offline
                sdetweil @lavolp3
                last edited by Sep 27, 2019, 5:11 PM

                @lavolp3 the dom is created way back at the beginning when u receved the DOM_OBJECTS_CREATED notification… so, when your module is called later, the DOM exists… document. exists

                YOUR contribution to the dom may not be there for some time after your getDom() routine returns. MM does not specify how long…

                if I need to fiddle with the dom directly, I usually do that thru a time routine, set for 1-2 seconds after getdom returns.

                Sam

                How to add modules

                learning how to use browser developers window for css changes

                L 1 Reply Last reply Sep 30, 2019, 3:29 PM Reply Quote 0
                • L Offline
                  lavolp3 Module Developer @sdetweil
                  last edited by Sep 30, 2019, 3:29 PM

                  @sdetweil
                  Sam, thanks again for your valuable contribution.
                  I tried to meddle with the getdom function, which does not work because the returned module div is appended to a parent node somewhere else in the MM code hierarchy. And only then I can refer to the DOM elements. (I guess that’s what you meant and I haven’t understood).

                  So, although I didn’t like it, I kind of did it your way and included a 3-second setTimeout() call directly after the updateDom() call, in which I called my chart function.

                                      self.updateDom(self.config.animationSpeed);
                                      setTimeout (function() {
                                        self.createBarChart(...);
                                      }, 3000);
                  
                  

                  It works now.
                  I still don’t like it. :-)
                  But I want to move on.

                  How to troubleshoot modules
                  MMM-soccer v2, MMM-AVStock

                  S 1 Reply Last reply Sep 30, 2019, 3:46 PM Reply Quote 0
                  • S Offline
                    sdetweil @lavolp3
                    last edited by Sep 30, 2019, 3:46 PM

                    @lavolp3 said in Nunjucks and Chartjs / Javascript:

                    I tried to meddle with the getdom function, which does not work because the returned module div is appended to a parent node somewhere else in the MM code hierarchy. And only then I can refer to the DOM elements. (I guess that’s what you meant and I haven’t understood).

                    main.js

                    	var updateModuleContent = function(module, newHeader, newContent) {
                    		var moduleWrapper = document.getElementById(module.identifier);
                            if (moduleWrapper === null) return;
                    		var headerWrapper = moduleWrapper.getElementsByClassName("module-header");
                    		var contentWrapper = moduleWrapper.getElementsByClassName("module-content");
                    
                    		contentWrapper[0].innerHTML = "";
                    		contentWrapper[0].appendChild(newContent);
                    
                    		if( headerWrapper.length > 0 && newHeader) {
                    			headerWrapper[0].innerHTML = newHeader;
                    		}
                    	};
                    

                    takes the content returned from getDom() and inserts it into the div created by module_id in the dom tree in the ‘position’ specified.

                    in my code that is why i create the div ‘canvas’. I have the div object, in getDom, and can generate the content immediately… no timer waiting to look it up later

                                canvas = document.createElement("canvas");    // < ---
                                canvas.id = "myChart" + this_pin;
                                c.appendChild(canvas);                                           // < ---
                              }
                              // if the chart has been created
                              if (wLself.charts[pin_index] != null) {
                                  // destroy it, update doesn't work reliably
                                  wLself.charts[pin_index].destroy();
                                  // make it unreferenced
                                  wLself.charts[pin_index] = 0;
                              }
                    					try { 
                    						// create it now
                    						wLself.charts[pin_index] = new Chart(canvas, {   // < ---
                    

                    then getDom() returns the completed chart… no need for build later

                    Sam

                    How to add modules

                    learning how to use browser developers window for css changes

                    L 1 Reply Last reply Sep 30, 2019, 10:11 PM Reply Quote 0
                    • S Offline
                      sdetweil
                      last edited by sdetweil Sep 30, 2019, 4:52 PM Sep 30, 2019, 4:04 PM

                      the dom looks like this before any content is output (no < > to save errors)
                      matching index.html, with a div for each module, in its position div section
                      in fifo order

                      head
                      body
                          div class=fullscreen below"
                              div id="module_id_1" 
                                  div class="module-header"
                                  end-div
                                  div class="module-content"
                                  end div
                              end-div
                              div id="module_id_2"
                              end-div
                         div class="region top bar"
                            div class="container",
                                end-div
                            		div class="region top left" 
                                          div class="container"
                                          end-div
                                      end-div
                                         etc
                            	</div>
                      

                      then getDom() in each module is called, and its little html contribution is placed in its div id=“module-content” (by module_id)

                      but, until the dom.div.addChild(content) is done, the content is just in memory, NOT IN the dom…

                      then later the module signals the mirror runtime via updateDom()… ‘I have new content’,
                      and MM runtime calls the module’s getDom() and we repeat the process… note in the updateModule content
                      it REMOVES the prior content and injects the new…

                                      contentWrapper[0].innerHTML = "";  // < --- clear all content, the rough way
                      		contentWrapper[0].appendChild(newContent);  // < --- append the new module content tree
                      

                      SO, BIG dom object tree cleanup and rebuild…

                      i keep the module contribution, and modify it where appropriate, to reduce the change impact.

                      I always think the getDom() should be named getDomContribution()

                      Sam

                      How to add modules

                      learning how to use browser developers window for css changes

                      1 Reply Last reply Reply Quote 1
                      • 1
                      • 2
                      • 2 / 2
                      2 / 2
                      • First post
                        6/15
                        Last post
                      Enjoying MagicMirror? Please consider a donation!
                      MagicMirror created by Michael Teeuw.
                      Forum managed by Sam, technical setup by Karsten.
                      This forum is using NodeBB as its core | Contributors
                      Contact | Privacy Policy