skip to Main Content

I need to get the most used content text of elements within a certain class. In my case the most recurrent phrase of elements: Service number 1

<div class="service_list">
 <span>Service number 1</span>
 <span>Service number 2</span>
</div>

<div class="service_list">
 <span>Service number 1</span>
 <span> Service number 3</span>
</div>

<div class="service_list">
 <span>Service number 1</span>
 <span> Service number 4</span>
</div>

2

Answers


  1. $.each($('div.service_list  span'), function(index, value) {
         $(this).html();
    }) 
    

    Hope it works for you.

    Login or Signup to reply.
  2. One approach is below, with explanatory comments in the JavaScript:

    // a collection of functions for use:
    // create() takes and element-type ('div', 'span'...) along with an Object
    // of properties ('className','textContent'...) and then returns the
    // created Element with those properties:
    let create = (tag, props) => Object.assign(
        // creating the element:
        document.createElement(tag),
        // the Object-literal containing the element's properties:
        props),
      // a simple function to remove existing content from a node,
      // taking a reference to a specific node:
      empty = (node) => {
        // while the node exists and that node has a firstChild:
        while (node && node.firstChild) {
          // we use parentNode.removeChild() to remove the
          // firstChild node; we use this rather than
          // Element.remove() because we wish to remove all
          // nodes, rather than allow inadvertent white-
          // space text-nodes to accumulate:
          node.removeChild(node.firstChild);
        }
      },
      // using an object of functions in order to allow related
      // functions to be grouped/exported as one:
      listServicePopularity = {
        // ascending implies - but I have not written - a corresponding
        // function of descending(); I leave this as an exercise for
        // reader:
        ascending: function() {
            // mentions is the element to which the results will
          // appended, and shown; here we use the get()
          // method to retrieve the first/only element
          // matching the selector:
          let mentions = this.get('.mentions'),
            // services consists of the elements the frequency
            // of which we're going to display in ordered form:
            services = this.getAll('.service_list > span'),
            // usage is ordered frequency of mentions; the
            // function this.getAll() returns an Array of
            // elements, so here we can use Array methods:
            usage = services
            // such as Array.prototype.map():
            .map(
                // using Arrow functions, we're not using 'this'
              // within the function, here we pass a reference
              // to the current Array-element, which is an
              // HTMLElement, and we create a new Array comprised
              // of the text-content of the elements, after we
              // remove leading/trailing white-space with
              // String.prototype.trim():
                (service) => service.textContent.trim()
            )
            // we then use Array.prototype.reduce to convert
            // the Array of Strings into an Object of
            // properties equal to the 
            // Array of [String, Count] pairs:
            .reduce(
                // passing in a reference to the accumulator
              // variable (the empty Object-literal that
              // follows the function declaration, which
              // is modified as the function iterates),
              // and the current Array-value (a string
              // comprised of the text-content of the
              // original element):
              (acc, curr) => {
                // if the accumulator has a property equal to the
                // text of the current Array-element:
                if (acc[curr]) {
                    // we increment the property-value of that
                  // property:
                  acc[curr] = acc[curr] + 1;
                // otherwise:
                } else {
                    // we define that property, and initialise its
                  // value to 1:
                  acc[curr] = 1;
                }
                // and we then return the accumulator for the
                // next iteration:
                return acc;
              // the Object literal - as mentioned - is the
              // initial state of the accumulator:
              }, {});
          // we call the empty() function to remove the existing
          // contents of the mentions element:
          empty(mentions);
          
          // and then call the this.output() function, passing
          // in what should be output, and to where it should
          // be inserted:
          this.output(usage, mentions)
        },
        // creating a document fragment to append multiple elements
        // to one parent-node at once, to minimise redrawing/repainting
        // events:
        fragment: document.createDocumentFragment(),
        // a function which takes a CSS selector and an element Node
        // (which defaults to document if no node is provided), and
        // returns the result of either Element.querySelector() or
        // document.querySelector() with the supplied CSS selector:
        get: (selector, context = document) => context.querySelector(selector),
        // much the same as above, except here we use document.querySelectorAll()
        // (or Element.querySelectorAll(), depending on the context
        // provided), and convert the result of that iterable NodeList
        // as an Array, using an Array-literal and the spread syntax:
        getAll: (selector, context = document) => [...context.querySelectorAll(selector)],
        // the output function; which takes two arguments, an Object
        // of what should be output (key-value pairs), and a reference
        // to the node to which it should be inserted:
        output: function(what, where) {
            // using Object.entries() to obtain a two-dimensional Array
          // of key-value pairs of the Object, and then calling
          // Array.prototype.sort() on the result:
          Object.entries(what).sort(
            // here we use destructuring assignment to map the
            // first array-element (the text of the original
            // element) as aText or bText, and the second element
            // (the frequency with which that text was mentioned)
            // as aCount or bCount.
            // in the function body we simply compare to see if aCount
            // is greater than bCount, and if so we return -1 (so
            // the first element (whose properties are aText, and cCount)
            // precedes the second; otherwise we return 1 which moves
            // after the second element (bText, bCount):
            ([aText, aCount], [bText, bCount]) => aCount > bCount ? -1 : 1
          // we then use Array.prototype.forEach():
          ).forEach(
            // here we again use destructuring to assign the Array-element
            // of the sorted Array into two variables, 'key' and 'value':
            ([key, value]) => {
                // we access the document-fragment, and append a newly-created
              // 'li' element:
              this.fragment.append(create('li', {
                // and assign its text-content to be equal to the interpolated
                // String - using a template-literal - of the 'key' and
                // the 'value':
                textContent: `${key} (${value})`
              }));
            });
          // after the forEach(), once all elements have been appended
          // to the document fragment, we then append that fragment
          // to the 'where' node passed to the function:
          where.append(this.fragment);
        }
      },
      // in order to test the function, we have a randomize function:
      randomize = () => {
        // an Array of service numbers:
        let services = [1, 2, 3, 4];
        // arguably the 'getAll()' function may be better defined
        // outside the listServicePopularity Object, but here we
        // use that function to get an Array of elements, and then
        // iterate over that Array with Array.prototype.forEach():
        listServicePopularity.getAll('.service_list > span').forEach(
            // passing in a reference to the current Array element of the Array
          // of Elements over which we're iterating.
          // in the function body we're setting the text-content of the
          // current Array-element using a Template-literal, which
          // outputs 'Service number <1-4>', using a naive call to
          // Math.random() to generate a number between 1 and 4,
          // this gives a pseudo-random Array-index which we
          // retrieve and add to the String:
          (el) => el.textContent = `Service number ${services[Math.floor( Math.random() * services.length )]}`
        );
        
        // we then call the function to generate, and ultimately output,
        // the service frequency, to have the frequency of the new set
        // of elements generated:
        listServicePopularity.ascending();
      };
      
    // binding the randomize() function to the 'click' event on the 
    // <button> element:
    document.querySelector('button').addEventListener('click', randomize);
    
    // using EventTarget.addEventListener() to bind the anonymous function
    // as the event-handler for the 'DOMContentLoaded' event on the
    // Window Object:
    window.addEventListener('DOMContentLoaded', (e) => {
        // calling the function once the DOM has loaded, to show the
      // frequency of services on page-load:
      listServicePopularity.ascending();
    });
    *,::before,::after {
      box-sizing: border-box;
      font-family: system-ui;
      font-size: 16px;
      margin: 0;
      padding: 0;
    }
    
    main {
      border: 2px solid hsl(120deg 30% 70%);
      display: grid;
      gap: 1em;
      inline-size: clamp(15rem, 50vw, 800px);
      margin-block: 1em;
      margin-inline: auto;
      padding: 0.25em;
    }
    
    .service_list {
      display: grid;
      gap: inherit;
      grid-template-columns: repeat(2, 1fr);
    }
    
    .service_list > span:first-child {
      text-align: end;
    }
    
    .mentions {
      padding-block: 0.5em;
      padding-inline: 1em;
    }
    
    .mentions::before {
      content: "Frequency of mentions:";
    }
    
    .mentions ::marker {
      color: hsl(120deg 70% 50%);
      font-weight: 600;
      font-style: italic;
    }
    
    .mentions li {
      margin-inline-start: 10%;
      margin-block-start: 0.5em;
      padding-inline-start: 0.4em;
      padding-block: 0.4em;
      position: relative;
    }
    
    .mentions li::after {
      content: '';
      background: linear-gradient(to right, hsl(120deg 70% 50% / 1), transparent);
      position: absolute;
      block-size: 3px;
      inline-size: 100%;
      bottom: 0;
      left: 0;
    }
    <main>
      <button type="button">Randomize Services</button>
      <div class="service_list">
        <span>Service number 1</span>
        <span>Service number 2</span>
      </div>
    
      <div class="service_list">
        <span>Service number 1</span>
        <span> Service number 3</span>
      </div>
    
      <div class="service_list">
        <span>Service number 1</span>
        <span> Service number 4</span>
      </div>
    
      <ol class="mentions"></ol>
    </main>

    JS Fiddle demo.

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search