0

what i am doing is to generate a post navigation using pure javascript. But it shows beforeClosingTag is not a function

in the tools fuctions below , it shoud be a function because i did code beforeClosingTag as a function. in the snippet, it can generate the ul list but if you see through the web inspector, you can still find :

**Uncaught TypeError: greatApp.tools.insertHTMLString.beforeClosingTag is not a function**

And besides that, in my local environment, the same code but it cannot even show the ul list, i do not know why. Thanks

//global tools function(insertHTMLString.beforeClosingTag)

    var greatApp = greatApp || {};
    
    (function(){
      greatApp.tools = {
    
       insertHTMLString:  function(){
        /*****
            if elements have a native insertAdjacentHTML : use it in four html insertion functions with more sensible names
        *****/
    
            if(document.createElement('div').insertAdjacentHTML){
              return {
                  beforeOpeningTag: function(element,htmlString){
                    element.insertAdjacentHTML('beforebegin',htmlString);
                  },
                  afterOpeningTag:  function(element,htmlString){
                    element.insertAdjacentHTML('afterbegin',htmlString);
                  },
                  beforeClosingTag:  function(element,htmlString){
                    element.insertAdjacentHTML('beforeend',htmlString);
                  },
                  afterClosingTag:  function(element,htmlString){
                    element.insertAdjacentHTML('afterend',htmlString);
                  }
              }
            }//end if 
    
    
        /********
            otherwise, we have no native insertAdjacentHTML : implement the same four insertion functions and then use them to define insertAdjacentHTML
        ******/
    
               function fragment(htmlString){
                    var ele = document.createElement('div');
                    var frag = document.createDocumentFragment();
                    ele.innerHTML = htmlString;
    
                    //move all nodes from ele to frag
                    while(ele.firstChild)
                       frag.appendChild(ele.firstChild);
    
                    return frag;
               }        
               var insertHTMLString = {
                  beforeOpeningTag: function(element,htmlString){
                    element.parentNode.insertBefore(fragment(htmlString),element);
                  },
                  afterOpeningTag:  function(element,htmlString){
                    element.parentNode.insertBefore(fragment(htmlString),element.firstChild);
                  },
                  beforeClosingTag:  function(element,htmlString){
                    element.parentNode.appendChild(fragment(htmlString));
                  },
                  afterClosingTag:  function(element,htmlString){
                    element.parentNode.insertBefore(fragment(htmlString),element.nextSibling);
                  }                
               };
    
               /**
                  now implement insertAdjacentHMTL based on the functions above
              **/
    
              Element.prototype.insertAdjacentHMTL = function(pos, htmlString){
                switch(pos.toLowerCase()){
                  case "beforebegin": return insertHTMLString.beforeOpeningTag(this, htmlString);
                  case "afterbegin": return insertHTMLString.afterOpeningTag(this, htmlString);
                  case "beforeend": return insertHTMLString.beforeClosingTag(this, htmlString);
                  case "afterend": return insertHTMLString.beforeClosingTag(this, htmlString);
    
                }
              };
              return insertHTMLString;
        },
    
    }}());





//post js

(function(){
             var titles = document.querySelectorAll('.sideNav h3');
             var sideList = document.getElementsByClassName('sideList')[0];
             var ul = document.querySelectorAll('.sideList ul')[0];
   
               for(var i = 0; i< titles.length; i++){

                     var aWithhref = '<a href = ' + '#' + titles[i].getAttribute('id') + '>';
                     var titleText = titles[i].textContent || titles[i].innerText;
                     var li = '<li>'+ aWithhref + titleText +'</a>'+ '</li>';
                      
                    (Element.prototype.insertAjacentHTML)? ul.insertAdjacentHTML('beforeend',li) : greatApp.tools.insertHTMLString.beforeClosingTag(ul, li);
                 }   

         }());
<div class="row expanded docHomeDetails sideNav">
 <h3 id="homeCollectionUpdate"># Update</h3>
  <h3 id="homee"># home</h3>
  <h3 id="Update"># forum</h3>
</div>             
<div class="small-12 medium-4 columns sideList" data-sticky-container >
           
                   <div class="sticky" data-sticky data-top-anchor="homeCollectionUpdate" data-btm-anchor="homeCollectionMentorWrapper:bottom">
                      <ul>
                       <p>页面导航</p>
                      </ul>
                   </div>

                    
         </div>

     </div>

Thanks for help.

My code as follows:

//html

        <div class="small-12 medium-4 columns sideList" data-sticky-container >

           <div class="sticky" data-sticky data-top-anchor="homeCollectionUpdate" data-btm-anchor="homeCollectionMentorWrapper:bottom">
              <ul>
                <p>页面导航</p>
              </ul>
           </div>
        </div>

//javascript

     (function(){
         var titles = document.querySelectorAll('.sideNav h3');
         var sideList = document.getElementsByClassName('sideList')[0];
         var ul = document.querySelectorAll('.sideList ul')[0];

           for(var i = 0; i< titles.length; i++){

                 var aWithhref = '<a href = ' + '#' + titles[i].getAttribute('id') + '>';
                 var titleText = titles[i].textContent || titles[i].innerText;
                 var li = '<li>'+ aWithhref + titleText +'</a>'+ '</li>';

                (Element.prototype.insertAjacentHTML)? ul.insertAdjacentHTML('beforeend',li) : greatApp.tools.insertHTMLString.beforeClosingTag(ul, li);
             }   

     }());

//global tools function(insertHTMLString.beforeClosingTag)

var greatApp = greatApp || {};

(function(){
  greatApp.tools = {

   insertHTMLString:  function(){
    /*****
        if elements have a native insertAdjacentHTML : use it in four html insertion functions with more sensible names
    *****/

        if(document.createElement('div').insertAdjacentHTML){
          return {
              beforeOpeningTag: function(element,htmlString){
                element.insertAdjacentHTML('beforebegin',htmlString);
              },
              afterOpeningTag:  function(element,htmlString){
                element.insertAdjacentHTML('afterbegin',htmlString);
              },
              beforeClosingTag:  function(element,htmlString){
                element.insertAdjacentHTML('beforeend',htmlString);
              },
              afterClosingTag:  function(element,htmlString){
                element.insertAdjacentHTML('afterend',htmlString);
              }
          }
        }//end if 


    /********
        otherwise, we have no native insertAdjacentHTML : implement the same four insertion functions and then use them to define insertAdjacentHTML
    ******/

           function fragment(htmlString){
                var ele = document.createElement('div');
                var frag = document.createDocumentFragment();
                ele.innerHTML = htmlString;

                //move all nodes from ele to frag
                while(ele.firstChild)
                   frag.appendChild(ele.firstChild);

                return frag;
           }        
           var insertHTMLString = {
              beforeOpeningTag: function(element,htmlString){
                element.parentNode.insertBefore(fragment(htmlString),element);
              },
              afterOpeningTag:  function(element,htmlString){
                element.parentNode.insertBefore(fragment(htmlString),element.firstChild);
              },
              beforeClosingTag:  function(element,htmlString){
                element.parentNode.appendChild(fragment(htmlString));
              },
              afterClosingTag:  function(element,htmlString){
                element.parentNode.insertBefore(fragment(htmlString),element.nextSibling);
              }                
           };

           /**
              now implement insertAdjacentHMTL based on the functions above
          **/

          Element.prototype.insertAdjacentHMTL = function(pos, htmlString){
            switch(pos.toLowerCase()){
              case "beforebegin": return insertHTMLString.beforeOpeningTag(this, htmlString);
              case "afterbegin": return insertHTMLString.afterOpeningTag(this, htmlString);
              case "beforeend": return insertHTMLString.beforeClosingTag(this, htmlString);
              case "afterend": return insertHTMLString.beforeClosingTag(this, htmlString);

            }
          };
          return insertHTMLString;
    },

}}());
franklee
  • 63
  • 11

1 Answers1

0

This is because, insertHTMLString is a function and not an object. You can create an object like:

var innerHTMLObj = new greatApp.tools.insertHTMLString();    
(Element.prototype.insertAjacentHTML) ?
  ul.insertAdjacentHTML('beforeend', li): 
  innerHTMLObj.beforeClosingTag(ul, li);

Of you can replace it by an IIFE.

Object Implementation

//global tools function(insertHTMLString.beforeClosingTag)

var greatApp = greatApp || {};

(function() {
  greatApp.tools = {

    insertHTMLString: function() {
      /*****
          if elements have a native insertAdjacentHTML : use it in four html insertion functions with more sensible names
      *****/

      if (document.createElement('div').insertAdjacentHTML) {
        return {
          beforeOpeningTag: function(element, htmlString) {
            element.insertAdjacentHTML('beforebegin', htmlString);
          },
          afterOpeningTag: function(element, htmlString) {
            element.insertAdjacentHTML('afterbegin', htmlString);
          },
          beforeClosingTag: function(element, htmlString) {
            element.insertAdjacentHTML('beforeend', htmlString);
          },
          afterClosingTag: function(element, htmlString) {
            element.insertAdjacentHTML('afterend', htmlString);
          }
        }
      } //end if 


      /********
          otherwise, we have no native insertAdjacentHTML : implement the same four insertion functions and then use them to define insertAdjacentHTML
      ******/

      function fragment(htmlString) {
        var ele = document.createElement('div');
        var frag = document.createDocumentFragment();
        ele.innerHTML = htmlString;

        //move all nodes from ele to frag
        while (ele.firstChild)
          frag.appendChild(ele.firstChild);

        return frag;
      }
      var insertHTMLString = {
        beforeOpeningTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element);
        },
        afterOpeningTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element.firstChild);
        },
        beforeClosingTag: function(element, htmlString) {
          element.parentNode.appendChild(fragment(htmlString));
        },
        afterClosingTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element.nextSibling);
        }
      };

      /**
                  now implement insertAdjacentHMTL based on the functions above
              **/

      Element.prototype.insertAdjacentHMTL = function(pos, htmlString) {
        switch (pos.toLowerCase()) {
          case "beforebegin":
            return insertHTMLString.beforeOpeningTag(this, htmlString);
          case "afterbegin":
            return insertHTMLString.afterOpeningTag(this, htmlString);
          case "beforeend":
            return insertHTMLString.beforeClosingTag(this, htmlString);
          case "afterend":
            return insertHTMLString.beforeClosingTag(this, htmlString);

        }
      };
      return insertHTMLString;
    },

  }
}());





//post js

(function() {
  var titles = document.querySelectorAll('.sideNav h3');
  var sideList = document.getElementsByClassName('sideList')[0];
  var ul = document.querySelectorAll('.sideList ul')[0];

  for (var i = 0; i < titles.length; i++) {

    var aWithhref = '<a href = ' + '#' + titles[i].getAttribute('id') + '>';
    var titleText = titles[i].textContent || titles[i].innerText;
    var li = '<li>' + aWithhref + titleText + '</a>' + '</li>';

    
    var innerHTMLObj = new greatApp.tools.insertHTMLString();
    
    (Element.prototype.insertAjacentHTML) ? ul.insertAdjacentHTML('beforeend', li): innerHTMLObj.beforeClosingTag(ul, li);
  }

}());
<div class="row expanded docHomeDetails sideNav">
  <h3 id="homeCollectionUpdate"># Update</h3>
  <h3 id="homee"># home</h3>
  <h3 id="Update"># forum</h3>

  <div class="small-12 medium-4 columns sideList" data-sticky-container>

    <div class="sticky" data-sticky data-top-anchor="homeCollectionUpdate" data-btm-anchor="homeCollectionMentorWrapper:bottom">
      <ul>
        <p>页面导航</p>
      </ul>
    </div>


  </div>

</div>

IIFE Implementation

//global tools function(insertHTMLString.beforeClosingTag)

var greatApp = greatApp || {};

(function() {
  greatApp.tools = {

    insertHTMLString: (function() {
      /*****
          if elements have a native insertAdjacentHTML : use it in four html insertion functions with more sensible names
      *****/

      if (document.createElement('div').insertAdjacentHTML) {
        return {
          beforeOpeningTag: function(element, htmlString) {
            element.insertAdjacentHTML('beforebegin', htmlString);
          },
          afterOpeningTag: function(element, htmlString) {
            element.insertAdjacentHTML('afterbegin', htmlString);
          },
          beforeClosingTag: function(element, htmlString) {
            element.insertAdjacentHTML('beforeend', htmlString);
          },
          afterClosingTag: function(element, htmlString) {
            element.insertAdjacentHTML('afterend', htmlString);
          }
        }
      } //end if 


      /********
          otherwise, we have no native insertAdjacentHTML : implement the same four insertion functions and then use them to define insertAdjacentHTML
      ******/

      function fragment(htmlString) {
        var ele = document.createElement('div');
        var frag = document.createDocumentFragment();
        ele.innerHTML = htmlString;

        //move all nodes from ele to frag
        while (ele.firstChild)
          frag.appendChild(ele.firstChild);

        return frag;
      }
      var insertHTMLString = {
        beforeOpeningTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element);
        },
        afterOpeningTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element.firstChild);
        },
        beforeClosingTag: function(element, htmlString) {
          element.parentNode.appendChild(fragment(htmlString));
        },
        afterClosingTag: function(element, htmlString) {
          element.parentNode.insertBefore(fragment(htmlString), element.nextSibling);
        }
      };

      /**
                  now implement insertAdjacentHMTL based on the functions above
              **/

      Element.prototype.insertAdjacentHMTL = function(pos, htmlString) {
        switch (pos.toLowerCase()) {
          case "beforebegin":
            return insertHTMLString.beforeOpeningTag(this, htmlString);
          case "afterbegin":
            return insertHTMLString.afterOpeningTag(this, htmlString);
          case "beforeend":
            return insertHTMLString.beforeClosingTag(this, htmlString);
          case "afterend":
            return insertHTMLString.beforeClosingTag(this, htmlString);

        }
      };
      return insertHTMLString;
    })(),

  }
}());





//post js

(function() {
  var titles = document.querySelectorAll('.sideNav h3');
  var sideList = document.getElementsByClassName('sideList')[0];
  var ul = document.querySelectorAll('.sideList ul')[0];

  for (var i = 0; i < titles.length; i++) {

    var aWithhref = '<a href = ' + '#' + titles[i].getAttribute('id') + '>';
    var titleText = titles[i].textContent || titles[i].innerText;
    var li = '<li>' + aWithhref + titleText + '</a>' + '</li>';
    
    (Element.prototype.insertAjacentHTML) ? ul.insertAdjacentHTML('beforeend', li): greatApp.tools.insertHTMLString.beforeClosingTag(ul, li);
  }

}());
<div class="row expanded docHomeDetails sideNav">
  <h3 id="homeCollectionUpdate"># Update</h3>
  <h3 id="homee"># home</h3>
  <h3 id="Update"># forum</h3>

  <div class="small-12 medium-4 columns sideList" data-sticky-container>

    <div class="sticky" data-sticky data-top-anchor="homeCollectionUpdate" data-btm-anchor="homeCollectionMentorWrapper:bottom">
      <ul>
        <p>页面导航</p>
      </ul>
    </div>


  </div>

</div>
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • insertHTMLString is a function and not an object. ? I thought i return the functions like beforeClosingTag under insertHTMLString, so i can get it by insertHTMLString.beforeClosingTag. By the way, function is an object too. Can you explain this point more details, many thanks. I have learned js for only months. Just treat me as a new learner,^_^ . – franklee Jan 06 '16 at 08:08
  • In addition, by your way,( i have a tools.js global file), do i need to initialize all the method before i can get the function returned by the method? – franklee Jan 06 '16 at 08:12
  • For "function is an object too" you can refer to following [post](http://stackoverflow.com/questions/5158378/javascript-functions-are-objects). Point is when you write a function, until you call it nothing is returned. So if you want to access `a.b.c`, here `a` and `b` needs to be object. – Rajesh Jan 06 '16 at 08:17
  • Inspired by your comment above, i have found : greatApp.tools.insertHTMLString().beforeClosingTag(ul, li); can work for me . so that means without intializing the function, i can also get the value i want??Thanks – franklee Jan 06 '16 at 08:42
  • `greatApp.tools.insertHTMLString().beforeClosingTag` This is bad practice. You should assign it to a variable and use it. That way you will only need to call function `insertHTMLString()` once. – Rajesh Jan 06 '16 at 09:11
  • Thanks for your advice.greatApp.tools.insertHTMLString().beforeClosingTag and initializing an object, which do you suggest? – franklee Jan 06 '16 at 09:41