Davesaggio
7/30/2019 - 9:13 AM

JavaScript custom functions

JavaScript custom functions

const ReadMore = (() => {
  let s;

  return {

    settings() {
      return {
        content: document.querySelectorAll('.js-read-more'),
        originalContentArr: [],
        truncatedContentArr: [],
        moreLink: "Leggi di più",
        lessLink: "",
      }
    },

    init() {
      s = this.settings();
      this.bindEvents();
    },

    bindEvents() {
      ReadMore.truncateText();
    },

    /**
     * Count Words
     * Helper to handle word count.
     * @param {string} str - Target content string.
     */
    countWords(str) {
      return str.split(/\s+/).length;
    },

    /**
     * Ellpise Content
     * @param {string} str - content string.
     * @param {number} wordsNum - Number of words to show before truncation.
     */
    ellipseContent(str, wordsNum) {
      return str.split(/\s+/).slice(0, wordsNum).join(' ') + '...';
    },

    /**
     * Truncate Text
     * Truncate and ellipses contented content
     * based on specified word count.
     * Calls createLink() and handleClick() methods.
     */
    truncateText() {

      for (let i = 0; i < s.content.length; i++) {
        //console.log(s.content)
        const originalContent = s.content[i].innerHTML;
        const numberOfWords = s.content[i].dataset.rmWords;
        const truncateContent = ReadMore.ellipseContent(originalContent, numberOfWords);
        const originalContentWords = ReadMore.countWords(originalContent);

        s.originalContentArr.push(originalContent);
        s.truncatedContentArr.push(truncateContent);

        if (numberOfWords < originalContentWords) {
          s.content[i].innerHTML = s.truncatedContentArr[i];
          let self = i;
          ReadMore.createLink(self)
        }
      }
      ReadMore.handleClick(s.content);
    },

    /**
     * Create Link
     * Creates and Inserts Read More Link
     * @param {number} index - index reference of looped item
     */
    createLink(index) {
      const linkWrap = document.createElement('span');

      linkWrap.className = 'read-more__link-wrap';

      linkWrap.innerHTML = `<a id="read-more_${index}"
                               class="read-more__link"
                               style="cursor:pointer;">
                               ${s.moreLink}
                           </a>`;

      // Inset created link
      s.content[index].parentNode.insertBefore(linkWrap, s.content[index].nextSibling);

    },

    /**
     * Handle Click
     * Toggle Click eve
     */
    handleClick(el) {
      const readMoreLink = document.querySelectorAll('.read-more__link');

      for (let j = 0, l = readMoreLink.length; j < l; j++) {

        readMoreLink[j].addEventListener('click', function() {

          const moreLinkID = this.getAttribute('id');
          let index = moreLinkID.split('_')[1];

          el[index].classList.toggle('is-expanded');

          if (this.dataset.clicked !== 'true') {
             el[index].innerHTML = s.originalContentArr[index];
             this.innerHTML = s.lessLink;
             this.dataset.clicked = true;
          } else {
            el[index].innerHTML = s.truncatedContentArr[index];
            this.innerHTML = s.moreLink;
            this.dataset.clicked = false;
          }
        });
      }
    },

    /**
     * Open All
     * Method to expand all instances on the page.
     * Will probably be useful with a destroy method.
     */
    openAll() {
      const instances = document.querySelectorAll('.read-more__link');
        for (let i = 0; i < instances.length; i++) {
          content[i].innerHTML = s.truncatedContentArr[i];
          instances[i].innerHTML = s.moreLink;
        }
      }
    }
})();

ReadMore.init();

// html <div js-read-more" data-rm-words="30">Lorem ipsum</div>