I want to check if mydiv have or don't have a class, if it don't have it, add whatever it is inside the var newClass. I am attempting to do it like this, but it is not working:
var newClass="classToBeAdded";
if(document.getElementById("mydiv").className.indexOf(/(?:^| )(newClass)(?:$| )/)==-1){
document.getElementById("mydiv").className+=" "+newClass;
}
Use this:
var newClass = "classToBeAdded";
var d = document.getElementById("mydiv");
var r = new RegExp(" " + newClass + " ");
if (r.test(" " + d.className + " "))
// do something here
Or, similarly:
var d = document.getElementById("mydiv");
if ((" " + d.className + " ").indexOf(" " + newClass + " ") != -1)
// do something here
The spaces are added before and after the className string so that we'll match the target class no matter where it appears in the string.
Some tests
Assume the following function:
function hasClass(str, name) {
return (" " + str + " ").indexOf(" " + name + " ") != -1;
}
Tests:
hasClass("target", "target") // true
hasClass("test target test1", "target") // true
hasClass("test1 target", "target") // true
hasClass("target test1", "target") // true
hasClass("test1", "target") // false
You can use javascript property of dom element
document.getElementById("mydiv").classList
it returns array of assigned class names
You should probably use a library to abstract these kind of issues for you.
The rule of thumb is you should focus on your domain specific problems rather than re-inventing the wheel.
jQuery .hassClass is a good candidate
Related
Trying to get this string I have in JavaScript to appear in a paragraph in my HTML page by mousing over another paragraph.
function showInfo()
{
for (i = 0; i < object2; i = i + 1)
{
var myParagraph = "Name of Business: " + info.insurance[i].name + "\nState: " + info.insurance[i].state + "\nDiscount: " + info.insurance[i].discount + "\n" + "(" + i + 1 + "of" + object2 + ")"
}
}
myDiscount.addEventListener("mouseover", showInfo, false);
myDiscount.addEventListener("mouseout", showInfo, false);
<p id="discount">Show me the discounts!</p>
<p id="myP"></p>
If you want to show the next element of the info.insurance array each time you mouse over the paragraph, you shouldn't be using a for loop. That will do it all at once, not once for each mouseover. You need to put the counter in a global variable, and just increment it each time you call the function.
Yuo show it by assigning it to the innerHTML of the paragraph. You also need to use <br> rather than \n to make newlines (unless the style of the paragraph is pre).
var insurance_counter = 0;
function showInfo() {
var myParagraph = "Name of Business: " + info.insurance[insurance_counter].name + "<br>State: " + info.insurance[insurance_counter].state + "<br>Discount: " + info.insurance[insurance_counter].discount + "<br>(" + (insurance_counter + 1) + "of" + object2 + ")";
document.getElementById("myP").innerHTML = myParagraph;
insurance_counter++;
if (insurance_counter >= object2) { // wrap around when limit reached
insurance_counter = 0;
}
}
I'm working on a proof of concept feature to add the ability to hide part of a web page loaded in a webview, and I can't get it working...
I have something like this in a UIWebview extension, calling it when the webview finishes loading:
let dummyStyle = "var dummyStyle = document.createElement('style'); dummyStyle.innerHTML = 'div {display: none;}'; document.body.appendChild(dummyStyle); "
let classToHide = "content"
let jsHideString = "var e = document.body.getElementByClassName('\(classToHide)'); e.style = dummyStyle; e.style.display = 'none';"
self.stringByEvaluatingJavaScriptFromString(dummyStyle + jsHideString)
The main issue seems to be (checked with safari/chrome developer tools) that the document element doesn't have a style property. Even if I set it manually in the console, it doesn't update when e.style.display = 'none'.
Besides searching for the element id or class, I want to keep the assumptions about the end user web page to a minimum.
Thanks for reading my question!
Edit with working solution:
let classToHide = "content"
let jsHideString = " " +
" var e = document.body.getElementsByClassName(\"\(classToHide)\")[0];" +
"e.style.display = \"none\";"
let DOMContentLoadedNotification = " " +
"var addL = function addListener(obj, eventName, listener) { " +
"if (obj.addEventListener) { " +
"alert('added listener');" +
"obj.addEventListener(eventName, listener, false); " +
"} else { " +
"alert('attactch event');" +
"obj.attachEvent(\"on\" + eventName, listener); " +
"};" +
"};" +
"var completion = function finishedDCL() { " +
"alert('finishedDCL');" +
jsHideString +
"};" +
"if (document.readyState == \"complete\" || document.readyState == \"loaded\") { " +
"alert('document already loaded');" +
jsHideString +
"} else {" +
"alert('document not loaded');" +
"addL(document, \"DOMContentLoaded\", completion()); " +
"};"
print("Webview: \(self.stringByEvaluatingJavaScriptFromString(DOMContentLoadedNotification))")
Don't generate the stylesheet, just manipulate directly the .style property of the DOM node.
Set nodeReference.style.display = 'none'
The problem with no style property must be that you don't wait for the DOM to be ready. Watch for the DOMContentLoaded event.
https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
I have a string for ex "adlkup.db.com" and I want to validate the string for ".com" at the end of the string.
var x = "adlkup.db.com";
So I am trying something like
/.com$/.test(x)
and the . is interpreting to some other regex which finds a single character, except newline or line terminator
A period in a regular expression matches any character.
To make it literal, you need to escape it:
/\.com$/.test('stackoverflow.com'); // true
/\.com$/.test('stackoverflowcom'); // false
Alternatively, as Racil Hilan points out in the comments, you can also use the .lastIndexOf() method in order to check:
var string = 'stackoverflow.com';
string.lastIndexOf('.com') === string.length - 4; // true
or using the .substr() method:
'stackoverflow.com'.substr(-4) === '.com'; // true
In ECMAScript 6 this is done with endsWith:
x.endsWith(".com");
There is a polyfill for old browsers.
After reading your comments, I think you can use this better than the regex:
var value1 = "adlkup.db.com";
var value2 = "adlkup.db.com.w3Schools";
var value3 = ".com";
document.write(value1 + " " + endWithCom(value1) + "<br/>");
document.write(value2 + " " + endWithCom(value2) + "<br/>");
document.write(value3 + " " + endWithCom(value3) + "<br/>");
function endWithCom(text){
if(text.length < 5)
return false;
return (text.substr(-4) == ".com");
}
And you can easily convert it to generic function so you can pass it any ending you want to check:
var value1 = "adlkup.db.com";
var value2 = "adlkup.db.com.w3Schools";
var value3 = ".com";
var value4 = "adlkup.db.org";
document.write(value1 + " " + endWithButNotEqual(value1, ".com") + "<br/>");
document.write(value2 + " " + endWithButNotEqual(value2, ".com") + "<br/>");
document.write(value3 + " " + endWithButNotEqual(value3, ".com") + "<br/>");
document.write(value4 + " " + endWithButNotEqual(value4, ".org") + "<br/>");
function endWithButNotEqual(text, ending){
if(text.length <= ending.length)
return false;
return (text.substr(-ending.length) == ending);
}
I have the following code that returns the url of each of the links in the function:
var nav_link;
$('#nav_what-we-do').find('.top-dropdown').find('a').each(function(index, elem) {
console.log("Descendant: " + elem.tagName + " " + elem.href);
the_link = $(this);
nav_link = elem.href.split('#');
if (nav_link[0] === '/what-we-do/') {
the_link.attr('href','#'+nav_link[1]);
the_link.click(function() {
var tab_id = $(this).attr('href');
selectTab(tab_id);
return false;
});
}
});
The console prints links like:
Descendant: A http://localhost/testsite/what-we-do/#solutions
Descendant: A http://localhost/testsite/what-we-do/#features
Descendant: A http://localhost/testsite/what-we-do/features/test
Descendant: A http://localhost/testsite/what-we-do/solutions/test2
Now I want only those links that contain the hash(#) and split them using this hash.
Then I want to check if array(0) contains the characters "/what-we-do/".
I have tried to split the links like this:
nav_link = elem.href.split('#');
but the IF part is not working.
Can someone tell me what I am doing wrong.
EDIT
According to suggestions from T.J.
$('#nav_what-we-do').find('.top-dropdown').find('a').each(function(index, elem) {
//console.log("Descendant: " + elem.tagName + " " + elem.href);
var the_link = elem.href,
hashIndex = the_link.split("#");
if(hashIndex.length == 2) {
console.log(hashIndex);
console.log("Descendant: " + elem.tagName + " " + elem.href);
console.log('First part is: ' + hashIndex[0].indexOf("/what_we_do/"));
}
if (hashIndex.length == 2 && hashIndex[0].indexOf("/what_we_do/") !== -1) {
the_link.attr('href', "#" + hashIndex[1]);
the_link.attr('href', the_link.substring(hashIndex));
the_link.click(function() {
var tab_id = $(this).attr('href');
selectTab(tab_id);
return false;
});
}
});
If I print in console I get:
["http://localhost/testsite/what-we-do/", "solutions"] site_javascript.js:133
Descendant: A http://localhost/testsite/what-we-do/#solutions site_javascript.js:134
First part is: -1 site_javascript.js:135
["http://localhost/testsite/what-we-do/", "features"] site_javascript.js:133
Descendant: A http://localhost/testsite/what-we-do/#features site_javascript.js:134
First part is: -1
Where first part should be the value hashIndex[0].indexOf("/what_we_do/")
What could be going on since hashIndex has the string /what-we-do/?
I think you probably want:
var nav_link;
$('#nav_what-we-do').find('.top-dropdown').find('a').each(function(index, elem) {
console.log("Descendant: " + elem.tagName + " " + elem.href);
var the_link = elem.href,
hashIndex = the_link.indexOf("#");
if (hashIndex !== -1 && the_link.indexOf("/what-we-do/") !== -1) {
the_link.attr('href', the_link.substring(hashIndex));
the_link.click(function() {
var tab_id = $(this).attr('href');
selectTab(tab_id);
return false;
});
}
});
(Note that I declared the_link; if it's already declared somewhere outside the iterator function, you could remove that, but it seems like it should be a local.)
Or alternately (since technically, the above would match if the /what-we-do/ were after the hash):
var nav_link;
$('#nav_what-we-do').find('.top-dropdown').find('a').each(function(index, elem) {
console.log("Descendant: " + elem.tagName + " " + elem.href);
var the_link = elem.href,
split = the_link.split("#");
if (split.length === 2 && split[0].indexOf("/what-we-do/") !== -1) {
the_link.attr('href', "#" + split[1]);
the_link.click(function() {
var tab_id = $(this).attr('href');
selectTab(tab_id);
return false;
});
}
});
There I've limited it so that if there is a hash after the first hash, it's not a match.
This is failing because you're checking an entire, absolute path (http://.....) against just a token of it (/what-we-do/).
There's several ways around this - the easiest is probably to check whether the token you're looking for is IN the URL (rather than is exactly equal to it, as currently).
if (nav_link.indexOf('#') != -1 && nav_link[0].indexOf('/what-we-do/') != -1) {
...
The above screengrab is from Firefox. The cursor is hovering over the yellow spot at the left hand side of the image. It is an <img> element (well actually it's an image together with an image map containing a single circular <area> element, but I assume this distinction is unimportant) that has been created and styled in JavaScript, including the application of a title attribute (constructed by cutting and gluing strings). How can I get this to behave and show the intended character, an en dash, instead of –? It works for innerHTML (the text "Barrow-In-Furness" in the top middle-left is a div that was also created using JavaScript, and its innerHTML set.)
Edit: In response to question of Domenic: Here is the JavaScript function that builds and applies the title attribute (in addition to performing other jobs):
var StyleLinkMarker = function (LinkNumber, EltA, EltI) {
var AltText = LocationName[LinkStart[LinkNumber]] +
" to " +
LocationName[LinkEnd[LinkNumber]];
if (!EltA) {
EltA = document.getElementById("link_marker_area" + LinkNumber);
EltI = document.getElementById("link_marker_img" + LinkNumber);
}
if (LinkStatus[LinkNumber] === 9) {
var CanBuyLinkCode = BoardPreviewMode ? 0 : CanBuyLink(LinkNumber);
if (CanBuyLinkCode === 0) {
EltI.src = ImagePath + "icon-buylink-yes.png";
AltText += " (you can buy this " + LinkAltTextDescription + ")";
} else {
EltI.src = ImagePath + "icon-buylink-no.png";
AltText += " (you cannot buy this " + LinkAltTextDescription;
AltText += CanBuyLinkCode === 1 ?
", because you aren't connected to it)" :
", because you would have to buy coal from the Demand Track, and you can't afford to do that)";
}
} else if ( LinkStatus[LinkNumber] === 8 ||
(LinkStatus[LinkNumber] >= 0 && LinkStatus[LinkNumber] <= 4)
) {
EltI.src = ImagePath + "i" + LinkStatus[LinkNumber] + ".png";
if (LinkStatus[LinkNumber] === 8) {
AltText += " (orphan " + LinkAltTextDescription + ")";
} else {
AltText += " (" +
LinkAltTextDescription +
" owned by " +
PersonReference(LinkStatus[LinkNumber]) +
")";
}
} else {
throw "Unexpected Link Status";
}
EltA.alt = AltText;
EltA.title = AltText;
};
LocationName is as follows:
var LocationName = [
"Barrow–In–Furness", "Birkenhead", "Blackburn", "Blackpool",
"Bolton", "Burnley", "Bury", "Colne",
"Ellesmere Port", "Fleetwood", "Lancaster", "Liverpool",
"Macclesfield", "Manchester", "The Midlands", "Northwich",
"Oldham", "Preston", "Rochdale", "Scotland",
"Southport", "Stockport", "Warrington & Runcorn", "Wigan",
"Yorkshire"
];
You aren't setting the title attribute, you are setting the title property, which expects text and not HTML (although the setAttribute method also expects a text string).
Generally speaking, when dealing with DOM manipulation, you provide text and not HTML. .innerHTML is the notable exception to this rule.
Here's an easy way to convert from HTML to text:
function convertHtmlToText(value) {
var d = document.createElement('div');
d.innerHTML = value;
return d.innerText;
}
Your code could then be updated to this:
EltA.title = convertHtmlToText(AltText);