3

I have a page with elements in one class of variable heights based on the size of the text content of them. On page load I need to add 20px to the height of all of them.

var visibleposts = document.getElementsByClassName("post-contain");
   for(var i =0; i <= visibleposts.length; i++){
     visibleposts[i].style.height = visibleposts[i].offsetHeight + 20 + "px";
   }

That's the code I used. I put that inside of an init() function that runs on page load. However, I'm not sure how well that's working since it's running on a meteor server. I have it onload of the body. Like so:

<head>
  <script src="jquery-2.1.4.min.js"></script>
  <script src="main.js"></script>
</head>
<body onload="init();">
</body>

<template name="FullFeed">
  {{#each posts}}
<!--    <a href="whenisay://{{adjective}}/{{noun}}/{{user}}/{{likes}}/{{date}}/{{_id}}">-->
    <a href="UnLiked.png">
      <div class="post-contain">
        <div class="chant">When I say <span class="varline">{{adjective}}</span> you say <span class="varline">{{noun}}</span></div>
<!--
        <div class="author-box">
          <p>By {{user}}<span class="spacer"> - </span>
            <img class="heart" src="UnLiked.png" onclick="console.log('hello');"/>
          </p>
        </div>
-->
      </div>
    </a>
    <div class="author-box">
      <p>By {{user}}<span class="spacer"> - </span>
        <img class="heart" src="UnLiked.png" onclick="console.log('hello');"/>
      </p>
    </div>
  {{/each}}
</template>

If you want to debug it, it's running at http://whensayfeed.meteor.com

Isaac Wasserman
  • 1,461
  • 4
  • 19
  • 39

1 Answers1

0

As humble.rumble mentioned in the comment, your code is not working, because at the time body is loaded, there are not yet any ".post-contain" divs generated by the template FullFeed.

You should not execute the code to modify the template-generated DOM immediately in main.js, but use the Template.myTemplate.onRendered callback registering function. Update: Template.myTemplate.onRendered from Meteor does not wait for individual data being loaded. There are many solutions how to attach a callback after all items have been loaded. See other StackOveflow questions:

However, none of those are seamless and reasonably simple. That is why you can use MutationObserver instead. In your case, you want to observe for added <a/> items into <body/>, then find .post-contain:

new MutationObserver(function (mutations){
    mutations.forEach(function (mutation){
        $(mutation.addedNodes).each(function (){
            if (this.localName == "a")
                var myNewDiv = $(".post-contain",this)[0]
        });
    });
}).observe($("body")[0], {childList: true});

As I'm not familiar with the Template API, it is possible that Template global variable is not available until the document has been loaded, in which case you'd use JQuery's .ready( handler )

Since you are including JQuery, you may then as well use it to set the height. Try .height( function ). In your case it would look like this:

$(".post-contain").height(function (index, height) {
    // Increase the height of all ".post-contain" divs
    return (height + 20);
});

All those combined together then yield the following:

$(function(){
    new MutationObserver(function (mutations){
        mutations.forEach(function (mutation){
            $(mutation.addedNodes).each(function (){
                if (this.localName == "a")
                    $(".post-contain",this).height(function (index, height){
                        return (height + 20);
                    });
            });
        });
    }).observe($("body")[0], {childList: true});
});

I have tested this on a local Meteor installation.


By the way, why do you need to add the height like this? You would then have to take of of other events, like .resize(). If you want the divs to have an extra height based on the content, why not to use CSS padding instead?

Community
  • 1
  • 1
Sha
  • 152
  • 3
  • 8
  • This seems like it should work, but it doesn't. There's no error either. The current version with your code is up if you want to check the changes I made. – Isaac Wasserman Jun 13 '15 at 12:30
  • I couldn't find any of the code from my proposed answer in the Meteor processed files at [http://whensayfeed.meteor.com](http://whensayfeed.meteor.com) . Maybe you could upload all the source codes from your meteor directory and link it here. It may be easier to find the problem that way. – Sha Jun 13 '15 at 13:18
  • Here's the complete source: https://dl.dropboxusercontent.com/u/58842756/WhenISayFeed.zip – Isaac Wasserman Jun 13 '15 at 14:26
  • So I tested it locally. The callback of Template.myTemplate.onRendered actually executed before all the data were loaded. So replacing it with MutationObserver seemed as the simplest solution. I also found other SO questions regarding this particular problem. – Sha Jun 14 '15 at 06:52