Target search results number in variable - javascript

I'm trying to target the number of search results on our website for each search term so that I can see how many results each one pulls in.
I'm working off of this article, but I can't get the javascript function correct to pull out the number (which could be as high as 2000) and put it into a variable.
<div class="search-results-text"><strong>732 results</strong> found for ‘<strong>search term</strong>’</div>
Hoping someone can help me out with the javascript function that would grab that number before "results". Thanks!

You would probably get away with a custom Javascript variable like this:
function() {
return document.querySelector('.search-results-text strong').innerText.split(" ")[0];
}
The querySelector with the CSS selector gets the Element, innerText is the text without the markup, the split splits the string up by whitespace, which gives you an array, and the first element of that array is your number (array are index starting with zero, so [0] refers to the first element).
This is not particularly elegant (for one you probably want to add some sort of error handling), and you could actually replace document.querySelector('.search-results-text strong').innerText with a DOM type variable in GTM (which by default returns the text of the element).
I don't think you can get the number with CSS selectors alone.

Related

Is it possible to remove an entry from a NodeList without converting it to an array or destroying the DOM node?

Okay, so I'm working on a method that accepts any form of iterable as its argument. I'd like to perform what amounts to a splice on the parameter, but - and this is the crucial bit - without changing its Symbolic Type. That is to say, I'd like the return value's Symbol to match that of the input (NodeList, DOMTokenList, HTMLCollection, etc.)
Contrived Example:
let iterableList = document.querySelectorAll('p');
// Result: Nodelist(5): p, p.body, p.body, p, p
Assumptions
Assume I wish to remove those two <p class="body"> tags (from the COLLECTION, NOT the DOM).
Assume iterableList is user-provided (e.g. I cannot simply alter the query to read p:not(.body))
Assume we do not know what kind of iterator is the input (i.e. in this example, by virtue of the fact it was a querySelectorAll that produced our results, it is a NodeList. Conversely, if it had been a getElementsByTagName it would be a HTMLCollection. Or any of a half dozen others)
Assume the return value should have the same Symbol as the input.
Assume I chose this example because the results are live nodes (and we know the subset could have come from a querySelectorAll('p:not(.body)'), so we know the subset is possible)
1. Now, obviously I can convert the symbol to an Array...
...through any number of means. I could then remove the two offending nodes, again by a variety of tactics. The problem is then my return value is an Array, and I've killed off the live node correspondence within the browser.
2. I could clone just the desired nodes...
...into a document fragment or similar, then re-query the fragment to return just the subset, but then I'd be targeting clones of the DOM nodes in question, not really those themselves, plus it would shake free any event bindings they had once had.
3a. I could insert a DOM node, append the array nodes I wish to keep, then query THAT, then put them back again, and destroy the inserted node...
... which keeps the nodes in tact (replete with any events bound to them) and even auto-remaps their xPaths to their original DOM locations...
3b. ...or even use the unique attributes of each node to attempt to dynamically construct a selector that matched only those I wished to keep...
...but because I don't know the Symbolic Type of iterator the collection is prior to receiving it, I would need a massive collection of such workarounds to conditionally handle each of the possibilities (and that's entirely notwithstanding the fact it'd be a bicycle-tire-with-a-banana solution that I'D never let through code review, either).
So I guess my question is:
Is there a way to modify, selectively clone, or even iteratively construct such an output? I don't need to perform any operation other than REMOVING one or more of the offending nodes; no edits or inserts.
A for...of statement will let one iterate them without conversion to the Array prototype, although I'm not aware of a way to call the Iterator constructors on the fly, even if I could figure out a way to move one of the live nodes from one collection to the other (the spread operator coerces the collection into an array).
Anyone know any good voodoo for this one? Or am I just SOL here?

Google App Script to Append Value from one Cell to String of Numbers in another Cell

I’ve been trying to figure out how to write a script which will take the value from one cell and append it to the end of a string of numbers in another cell of that same row. The newly appended number needs to be separated by a comma from the previously appended value, and the whole string needs to be wrapped between brackets. EX. [2,3,3,4.5,2.5,2.1,1.3,0.4]. The script will need to loop through all of the rows containing data on a named sheet beginning with the third row.
The above image is obviously just an example containing only two rows of data. The actual spreadsheet will contain well over a thousand rows, so the operation must be done programmatically and will run weekly using a timed trigger.
To be as specific as I can, what I need help with is to first know if something like the appending is even possible in Google App Scripts. I've spent hours searching and I can't seem to find a way to append a new value (ex. cell A3) to the current string (ex. cell B3) without overwriting it completely.
In full disclosure; I'm a middle school teacher trying to put something together for my school.
To be as specific as I can, what I need help with is to first know if something like the appending is even possible in Google App Scripts.
Seeing the expected result, it's inserting rather than appending, as the string should be added before the last character (]). Anyway, yes, this is possible by using JavaScript string handling methods.
Use getValue() to the get the cell values, both the Current GPA and the GPA History.
One way is to use replace
Example using pure JavaScript:
var currentGPA = 3.5
var gpaHistory = '[2,3.1,2.4]';
gpaHistory = gpaHistory.replace(']',','+currentGPA+']');
console.info(gpaHistory)
Once you get the modified gpaHistory, use setValue(gpaHistory) to add this value to the spreadsheet.

Why does .splice always delete the last element?

In the javascript, there are two arrays:tags[] and tags_java[]. I use .splice to delete certain items, which of the same index in the two arrays. The tags[] works fine, but tags_java doesn't, it seems always delete the last item.
Here is the code and the jsfiddle link.
var tag = $(this).text();
var index = $.inArray(tag, tags);
tags.splice(index,1);
tags_java.splice(index,1);
Nah, both don't work, because you're not actually finding the correct index of your tag.
Why not? Because $(this).text() includes the delete mark you added, × - e.g. "Morning×". Since that's not in your tags array, index will be -1. tags.splice(-1, 1); will remove 1 item from the end of the array.
In general, it's never a good idea to use presentation text (i.e. the text of your tag element) as data (e.g. using that text as a lookup value in an array). It's very likely that it'll be broken when something changes in the presentation - like here. So a suggestion would be to store the data (what you need to look up the tags) as data - e.g. using the jQuery-provided data() API - even if it seems redundant.
Here's a quick example - just adding/replacing two lines, which I've marked with comments starting with "JT": JSFiddle
Now, instead of looking up by $(this).text(), we're looking up by the data value "tagValue" stored with $(this).data() - that way, the lookup value is still bound to the element, but we're not relying on presentation text.
If the tag is not in the tags array, $.inArray will return -1, which would then cause the last item to be deleted.
You have to make sure that the item is actually in the array.

Javascript selector engines and built in functions

I have found the following tutorial on creating a selector engine..
http://blog.insicdesigns.com/2010/04/creating-your-own-selector-engine/
In javascript we have functions like
getElementById()
getElementsByTageName()
getElementsByName()
etc,.....But for the same functionality,in their selector engine,they are doing checks like
this.nodes[i].tagName == nm.toUpperCase()
instead of getElementsByTagName.What is the advantage of this approach?...
Also what is the usage of assigning all nodes to a vairiable using
e.getElementsByTagName('*');
There is an inconsistency when you get the tagName property of elements. Some browsers return uppercase and others lowercase. To normalize the output of the value, you have to do one or the other before continuing further operation.
As for e.getElementsByTagName('*');, i recently answered a question where the OP wants to find ALL elements containing an attribute name which has a prefix mce_. The only way to get such elements is to get all elements in the DOM, and inspect their attribute names.
There is also a good application of this getElementsByTagName('*') and that is determining the direct child of an element. For instance, in a very deep DOM. If I were to find certain parent elements based on an attribute and get it's children, normally you would do a recursive search from body downwards to find the parent. This would take a lot of recursive operations. Afterwards, you determine their children.
Another way to do it is to get all tags, determine their parent node, and if they have the parent with the attribute, they are the direct child. This method requires no recursion, only getElementsByTagName('*') and a loop through the nodeList that was returned.
this.nodes[i].tagName == nm.toUpperCase() is part of a method to filter the list of nodes by tag name.... so nothing to do with 'getting elements by their tag name'
the last point is not a real question.. you want to know reasons for "why would you select all nodes"? well you are writing a sector engine....
The following line
this.nodes[i].tagName == nm.toUpperCase()
Is within the function ofTag. It's filtering a set of nodes looking for nodes with the given name.
The next line
e.getElementsByTagName('*');
Retrieves all the children/descendants under a node so you can later filter it like the following
new DOMNodes(Selector.getAll(document)).ofTag('p').hasClass('note');

Simple hashing function that is HTML id-friendly and case sensitive

I get some strings from an external source, and I display them in spans on my page.
I need a way to get back to those strings using document.getElementById() or jQuery's $("#XXXX"), so along with each string I get some sort of an identifier, I use that identifier as the ID of the span.
The problem is that the identifier I get could contain chars like + for example. Which is not allowed as a value for the id attribute http://www.w3schools.com/tags/att_standard_id.asp
Additionally, these identifiers are case-sensitive. So I thought of using a hashing function like SHA or MD5, to hash the identifiers I get, then use them as ids for my spans, and I can apply the hashing function again to find my element.
This seems complicated for such a simple functionality. Is there a better way to do this? or maybe a very simple hashing function that would guarantee id-friendly chars and case-sensitivity? (HTML's id is not case-sensitive, that's another reason to consider hashing functions)
Can you ditch the identifier you get and just implement something simple like this:
var counter = 0;
function uniqueId(){
return "Id" + ++counter;
}
You could just increment the id's with a number and some sort of string to begin the ID.
The span id's would be "a1", "a2" etc.
I'm guessing that the problem is that you're thinking later you'll be getting the same strings and will want to transform them in the same way, and then use these to find the original corresponding elements?
If so, you'll just need to sanitize your strings carefully. A series of regular expressions could help you map from invalid to valid characters, and make the capitals unique. For instance, you could transform "A" into "-a-", and "+" into "-plus-".
A carefully chosen scheme should guarantee that the chances of a collision (i.e. someone giving you a string that looks like an escaped version of another string) should be very small, and in any case, detectable immediately.

Categories

Resources