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;
    },

}}());
0

1 Answer 1

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>

Sign up to request clarification or add additional context in comments.

6 Comments

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,^_^ .
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?
For "function is an object too" you can refer to following post. 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.
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
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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.