Add class to <i> if <span> contains text - javascript

Trying to add the class 'checkmark' to an i that has the id 'partnered'
$(document).ready(function () {
jQuery('span:contains("true")').addClass('checkmark');
});
This code works fine, but appends the class directly to where it checks. How can I append this class to a completely different i element?

It's a bit difficult to understand your question, but if i understand it correctly
"add class checkmark to i that has id partnered. How can I append this class to a completely different i element?"
then it's fairly simple
$(document).ready(function () {
$('i[id^="<desired id name>"]').addClass('checkmark');
});
Note: It seems fairly inpractical to have this as an id instead of class from html/css point of view

Use the jQuery parent selector:
$(document).ready(function () {
jQuery('span:contains("true")').parent().addClass('checkmark');
});
Or even safer you could use .closest:
$(document).ready(function () {
jQuery('span:contains("true")').closest('i.someClass').addClass('checkmark');
});

Here's your answer in plain JavaScript:
// Get the element with ID 'partnered'
// Get a <span> element (create one if there's none)
var partnered = Document.prototype.getElementById.call(document, 'partnered'),
span = (
Document.prototype.querySelector.call(document, 'span') ||
Document.prototype.createElement.call(document, 'span')
);
// Custom function
function addClass() {
var args = [... arguments].slice(1),
$args = args.length,
element = arguments[0];
// Loop through arguments to update them
for (var i = 0; i < $args; i += 1)
args[i] = String(args[i]);
// Loop through arguments after updating all of them
for (var i = 0; i < $args; i += 1) {
// Cache the index
var className = args[i];
// Append new class name
element.setAttribute(
'class',
// Get the current class
((element.getAttribute('class') || '')
// Remove existing duplicates of the class to add
.replace(RegExp('\\b' + className + '\\b', '')
// Keep the class attribute tidy
// and add the class
.trim() + ' ' + className).trim()
)
}
}
/* Synchronously
A while loop could work too if you're certain enough.
*/
if (span.textContent || span.innerText)
addClass(partnered, 'checkmarked');
/* Asynchronously */
(function check() {
if (span.textContent || span.innerText)
addClass(partnered, 'checkmarked');
else
typeof requestAnimationFrame == 'function' ?
requestAnimationFrame(check) :
setTimeout(check)
})

Solved using
if ($('span#ispartner:contains("true")').length > 0) {
$("#partnered").addClass("checkmark");
}
Thanks for the help!

Related

Javascript, Click eventlistener doing the same thing with multiple classes

I'm very new to learning JavaScript, and I've tried to read, and look for similar answers, but everything is pointing at jQuery, which I want to avoid using for this problem. I can't quite work out what is jQuery and what still works in JS...
I have set up a function that can grab the innerHTML but I can't seem to assign it to the same classes, else it'll only work on the first instance, and I tried creating multiple classes but essentially they're all the same button with different values...
document.querySelector(".b1").addEventListener("click", writeDisp);
document.querySelector(".b2").addEventListener("click", writeDisp);
document.querySelector(".b3").addEventListener("click", writeDisp);
document.querySelector(".b4").addEventListener("click", writeDisp);
function writeDisp() {
if(dispNum.length < 9){
if(dispNum === "0") {
dispNum = this.innerHTML
} else {
dispNum = dispNum + this.innerHTML};
document.querySelector(".display").textContent = dispNum;
}
}
}
How can I make this more simple. As there are way more .b* classes to add, and I'd rather not have a massive list if possible.
Thanks,
var class_elem = document.querySelectorAll("button[class^='b']");
function writeDisp(){
if(dispNum.length < 9){
if(dispNum === "0"){dispNum = this.innerHTML}else{dispNum = dispNum + this.innerHTML};
document.querySelector(".display").textContent = dispNum;
}
}
for (var i = 0; i < class_elem.length; i++) {
class_elem[i].addEventListener('click', writeDisp, false);
}
//Here your code in javascript only.
If you don't want to use jquery, you can use native document.querySelectorAll API like this
function writeDisp(){
if(dispNum.length < 9){
if(dispNum === "0"){
dispNum = this.innerHTML
} else {
dispNum = dispNum + this.innerHTML
}
document.querySelector(".display").textContent = dispNum;
}
}
// this line will select all html tags that contains a class
// name starting with 'b'
var doms = document.querySelectorAll("[class^=b]");
doms.forEach(function(dom) {
dom.addEventListener('click', writeDisp);
})
Note
querySelectorAll will fetch only those DOM instance in which b* is defined as first class, so in case of multiple class defintion, it will not fetch those DOMs which don't have the desired classname at first. That means if you have a DOM defintion like <div class="a box"></div>, this will be ignored, as here, classname starting with b sits after a class.

Get unique selector jQuery

I need to be able to get an unqiue selector for each element on a page.
For example, when I click on an element I want to do something like this:
$(document).click(function(){
var sel = getUniqueSel(this);
});
So, after storing the sel value in a DB I can get that value and simply access the element by
var el = $(sel);
I can't change and don't know anything about the HTML structure of the page and I can't simply add unique ID's (using JS) to every element as this would be inefficient.
Another approach might be to wander up the dom tree and create a path to the element, which you can save and use it later as a selector again, although that might not be bulletproof, but maybe its a point where you can start off.
Edit: Updated the Answer with your suggestion in the comment, now it returns the id if available
Just visit the example on JSBin And click the document twice.
but notice what gets highlighted..
jQuery.fn.getPath = function () {
if (this.length != 1) throw 'Requires one element.';
var path, node = this;
if (node[0].id) return "#" + node[0].id;
while (node.length) {
var realNode = node[0],
name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var siblings = parent.children(name);
if (siblings.length > 1) {
name += ':eq(' + siblings.index(realNode) + ')';
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
};
var sel;
$(document)
.click(function (e, a) {
if (!sel) {
sel = $("#comment-21702402")
.getPath();
alert("Path is: " + sel + ", hiding the Element -> Click again to highlight");
} else {
$(sel)
.css("background-color", "yellow");
}
});
One way to do this is to get all the information you can get on the element that was clicked.
So when you save it to the database you can save it as a text for example:
If the element you clicked on is: <div> I'm a div </div>
$(document).click(function(){
var tagName = $(this).prev().prop('tagName');
var attributes = {};
if( this.length ) {
$.each( this[0].attributes, function( index, attr ) {
attributes[ attr.name ] = attr.value;
} );
}
var elText=$(this).html();
saveToDB(tagName,attributes,elText);
});
You can later find the element using the attributes you have or simply use
$(tagName+'['+attribute+'="'+value+'"]:contains("'+elText+'")')
I think this should help

convert htmlelement to string for comparison javascript

I am using a function that obtains a target element id at onclick. Example, if I click on the text element that has the id of 'help'.
var click = (e && e.target) || (event && event.srcElement);
The var click would contain the ref to the id of "help".
I want to compare the var click to the string 'help' using the if statement below.
if (click == 'about') {do something}
The comparison does not work because the var click is not a string. When I use the alert(click) to debug, it shows click as "object HTMLElement".
How would you compare whether the id 'help' is obtained from var click?
I could write out something like
if (click == document.getElementById('help')) {do something}
but that would make a long statement.
also
if the var click is document.getElementById('help'), how would I create a new var "div" as document.getElementById('helpdiv') by adding the word "div" in the id of the var click?
basically, I want to use the same function to generate dynamic responses to each element that was clicked on, and not having to create a separate function for each element.
if (click.id == 'help'){
var link = click;
var divid = click.id+'div';
var div = document.getElementById(divid);
alert (div.id); //helpdiv string
}
TIA for all your help.
The simplest approach is probably
if (click.id == 'help') { //do something }
The line:
var click = (e && e.target) || (event && event.srcElement);
is not getting the id rather the element itself, use getAttribute to get the id instead.
var id = click.getAttribute('id');
alert(id);
Or simply:
var id = click.id;
alert(id);
So your condition now becomes:
if (id == 'about') {do something}
and
if (id == document.getElementById('help')) {do something}
if (click["id"] != null && click["id"] == "help") { do stuff }
Addressing the last part of your question, you cannot create a new DOM object by modifying your current one like you propose in your question, and I do not understand if you want to locate an already existing object and store it in a variable, or create a new one from scratch, so :
If you want to find a new one, and you know its named like "show" + the id of your current click variable, you can easily do:
if (click["id"] != null) {
var found = document.getElementById("show" + click["id"]);
}
Or if you intend to create a new one :
if (click["id"] != null) {
var created = document.createElement("div"); // replace with whatever you need
created["id"] = "show" + click["id"];
}
I think this is what you're after ...
if (click.id == 'help') { // Test to see if click is the 'help' element
var newEl = document.createElement('div'); // Create a new element
newEl.id = click.id + 'div'; // Set it's id
newEl.innerHTML = 'my help text goes here'; // Set it's content
click.parentElement.appendChild(newEl); // Add it to the document immediately following the 'click' element
}
Be aware that the name of an element is not the same as the element itself. Just making a new element name by appending 'div' to some existing name does not, in and of itself, create a new element. You have to explicitely create a new element object and add it into the document, as shown above.

How to get all elements inside "div" that starts with a known text

I have a div element in an HTML document.
I would like to extract all elements inside this div with id attributes starting with a known string (e.g. "q17_").
How can I achieve this using JavaScript ?
If needed, for simplicity, I can assume that all elements inside the div are of type input or select.
var matches = [];
var searchEles = document.getElementById("myDiv").children;
for(var i = 0; i < searchEles.length; i++) {
if(searchEles[i].tagName == 'SELECT' || searchEles.tagName == 'INPUT') {
if(searchEles[i].id.indexOf('q1_') == 0) {
matches.push(searchEles[i]);
}
}
}
Once again, I strongly suggest jQuery for such tasks:
$("#myDiv :input").hide(); // :input matches all input elements, including selects
Option 1: Likely fastest (but not supported by some browsers if used on Document or SVGElement) :
var elements = document.getElementById('parentContainer').children;
Option 2: Likely slowest :
var elements = document.getElementById('parentContainer').getElementsByTagName('*');
Option 3: Requires change to code (wrap a form instead of a div around it) :
// Since what you're doing looks like it should be in a form...
var elements = document.forms['parentContainer'].elements;
var matches = [];
for (var i = 0; i < elements.length; i++)
if (elements[i].value.indexOf('q17_') == 0)
matches.push(elements[i]);
With modern browsers, this is easy without jQuery:
document.getElementById('yourParentDiv').querySelectorAll('[id^="q17_"]');
The querySelectorAll takes a selector (as per CSS selectors) and uses it to search children of the 'yourParentDiv' element recursively. The selector uses ^= which means "starts with".
Note that all browsers released since June 2009 support this.
Presuming every new branch in your tree is a div, I have implemented this solution with 2 functions:
function fillArray(vector1,vector2){
for (var i = 0; i < vector1.length; i++){
if (vector1[i].id.indexOf('q17_') == 0)
vector2.push(vector1[i]);
if(vector1[i].tagName == 'DIV')
fillArray (document.getElementById(vector1[i].id).children,vector2);
}
}
function selectAllElementsInsideDiv(divId){
var matches = new Array();
var searchEles = document.getElementById(divId).children;
fillArray(searchEles,matches);
return matches;
}
Now presuming your div's id is 'myDiv', all you have to do is create an array element and set its value to the function's return:
var ElementsInsideMyDiv = new Array();
ElementsInsideMyDiv = selectAllElementsInsideDiv('myDiv')
I have tested it and it worked for me. I hope it helps you.
var $list = $('#divname input[id^="q17_"]'); // get all input controls with id q17_
// once you have $list you can do whatever you want
var ControlCnt = $list.length;
// Now loop through list of controls
$list.each( function() {
var id = $(this).prop("id"); // get id
var cbx = '';
if ($(this).is(':checkbox') || $(this).is(':radio')) {
// Need to see if this control is checked
}
else {
// Nope, not a checked control - so do something else
}
});
i have tested a sample and i would like to share this sample and i am sure it's quite help full.
I have done all thing in body, first creating an structure there on click of button you will call a
function selectallelement(); on mouse click which will pass the id of that div about which you want to know the childrens.
I have given alerts here on different level so u can test where r u now in the coding .
<body>
<h1>javascript to count the number of children of given child</h1>
<div id="count">
<span>a</span>
<span>s</span>
<span>d</span>
<span>ff</span>
<div>fsds</div>
<p>fffff</p>
</div>
<button type="button" onclick="selectallelement('count')">click</button>
<p>total element no.</p>
<p id="sho">here</p>
<script>
function selectallelement(divid)
{
alert(divid);
var ele = document.getElementById(divid).children;
var match = new Array();
var i = fillArray(ele,match);
alert(i);
document.getElementById('sho').innerHTML = i;
}
function fillArray(e1,a1)
{
alert("we are here");
for(var i =0;i<e1.length;i++)
{
if(e1[i].id.indexOf('count') == 0)
a1.push(e1[i]);
}
return i;
}
</script>
</body>
USE THIS I AM SURE U WILL GET YOUR ANSWER ...THANKS

Editing all external links with javascript

How can I go through all external links in a div with javascript, adding (or appending) a class and alt-text?
I guess I need to fetch all objects inside the div element, then check if each object is a , and check if the href attributen starts with http(s):// (should then be an external link), then add content to the alt and class attribute (if they don't exist create them, if they do exists; append the wanted values).
But, how do I do this in code?
This one is tested:
<style type="text/css">
.AddedClass
{
background-color: #88FF99;
}
</style>
<script type="text/javascript">
window.onload = function ()
{
var re = /^(https?:\/\/[^\/]+).*$/;
var currentHref = window.location.href.replace(re, '$1');
var reLocal = new RegExp('^' + currentHref.replace(/\./, '\\.'));
var linksDiv = document.getElementById("Links");
if (linksDiv == null) return;
var links = linksDiv.getElementsByTagName("a");
for (var i = 0; i < links.length; i++)
{
var href = links[i].href;
if (href == '' || reLocal.test(href) || !/^http/.test(href))
continue;
if (links[i].className != undefined)
{
links[i].className += ' AddedClass';
}
else
{
links[i].className = 'AddedClass';
}
if (links[i].title != undefined && links[i].title != '')
{
links[i].title += ' (outside link)';
}
else
{
links[i].title = 'Outside link';
}
}
}
</script>
<div id="Links">
<a name="_Links"></a>
FOO
FILE
SomeWhere
SomeWhere 2
SomeWhere 3
ElseWhere 1
ElseWhere 2
ElseWhere 3
BAR
Show/Hide
</div>
If you are on an account on a shared server, like http://big-server.com/~UserName/, you might want to hard-code the URL to go beyond the top level. On the other hand, you might want to alter the RE if you want http://foo.my-server.com and http://bar.my-server.com marked as local.
[UPDATE] Improved robustness after good remarks...
I don't highlight FTP or other protocols, they probably deserve a distinct routine.
I think something like this could be a starting point:
var links = document.getElementsByTagName("a"); //use div object here instead of document
for (var i=0; i<links.length; i++)
{
if (links[i].href.substring(0, 5) == 'https')
{
links[i].setAttribute('title', 'abc');
links[i].setAttribute('class', 'abc');
links[i].setAttribute('className', 'abc');
}
}
you could also loop through all the A elements in the document, and check the parent to see if the div is the one you are looking for
This can be accomplished pretty easily with Jquery. You would add this to the onload:
$("div a[href^='http']").each(function() {
$(this).attr("alt",altText);
var oldClassAttributeValue = $(this).attr("class");
if(!oldClassAttributeValue) {
$(this).attr("class",newClassAttributeValue);
}
});
You could modify this to add text. Class can also be modified using the css function.
My (non-framework) approach would be something along the lines of:
window.onload = function(){
targetDiv = document.getElementById("divName");
linksArray = targetDiv.getElementsByTagName("a");
for(i=0;i=linksArray.length;i++){
thisLink = linksArray[i].href;
if(thisLink.substring(4,0) = "http"){
linksArray[i].className += "yourcontent"; //you said append so +=
linksArray[i].alt += "yourcontent";
}
}
}
This is not tested but I would start like this and debug it from here.

Categories