How to get postid from the body class wordpress [duplicate] - javascript

There are several divs on my page with classes my_widget-2, my_widget-8, etc.
What JavaScript or jQuery code can I use to get the number "2" (ie. the number that appends the first matching widget)?
Note: If I were to write this question again, I would change the order of these class names and ask for a way to get "8" in order to avoid giving the impression that I want the smaller number.

$( "[class*='my_widget']" ).each ( function () {
var elClasses = $( this ).attr ( 'class' ).split ( ' ' );
for ( var index in elClasses ) {
if ( elClasses[index].match ( /^my_widget-\d+$/ ) ) {
var classNum = elClasses[index].split ( '-' )[1];
alert ( classNum );
break;
}
}
} );
Use the "attributeContains" selector to get all elements that have a class my_widget-*, and then loop trough all the classes the element has searching for you class. Once you find it, extract the number part.

This should do the trick:
$("[class^='my_widget']").each(function() {
var classParts = $(this).attr('class').split('-');
var number = classParts.pop();
});
Please note that it will only work if there is a singular class, otherwise you'd get something like 8 otherclass as a result.

Basic JS approach:
<div id="x" class="widget-2 lang-日本語">foo</div>
function Element_getClassArgument(el, name) {
var classes= el.className.split(' ');
var prefix= name+'-';
for (var i= classes.length; i-->0;)
if (classes[i].substring(0, prefix.length)==prefix)
return classes[i].substring(prefix.length);
return null;
}
Element_getClassArgument(document.getElementById('x'), 'widget'); // 2
If you wanted to include whitespace characters, or a hyphen in a name, you'd have to introduce an encoding scheme of some sort, for example encodeURIComponent. But often you can get away without that.
Wrapping in something with $ in the name is left as an exercise for the reader. :-)

If you want to get the DIV elements with a class my_widget-2, use this selector:
$("div.my_widget-2")
But if you want to get all DIV elements with a class of the form my_widget-N where N is an arbitrary number, try this:
$("div[class]").each(function() {
var matches = this.className.match(/(?:^|\s+)my_widget-(\d+)(?:\s+|$)/g);
if (matches !== null) {
alert(matches);
}
})

Try
element.attr('class').match(/my_widget-(\d+)/)[1]
It should return the column number as a string so just run parseInt() on it

Related

Jquery remove nth class from element

I want to remove a dynamically assigned class from an element but do not know the name of that class.
For example if I have:
<div id="myDiv" class="foo bar unknown"></div>
In this case the unknown class will always be in position 3.
How can I achieve this using Jquery?
more Info:
function hideMyDiv(){
var rnd=Date.now();
$('#myDiv').addClass(rnd);
setTimeout(function(){
$('.'+rnd).hide();
},10000);
}
function overRide(){
$('#myDiv').3rdClass().remove();
}
You are doing something wrong here, order of classes shouldn't matter.
But anyway you can do this
var parts = $('#myDiv').attr('class').split(' ');
$('#myDiv').removeClass(parts[2]);
Try writing a small helper method that will take the DOM element.
function removeClass(elem) {
var c = elem.className.split(' '),
cName;
if (c && c.length > 0) {
cName = c.splice(0, c.length - 1);
elem.className = cName.join(' ');
}
};
You can always enforce the condition you want to use.
Check Fiddle
Do this with jquery:
var _classes = $('a#somelink').attr('class').split(" ");
then you can loop thru that array and remove the one you want.
In one line
$('#myDiv').removeClass($('#myDiv').attr('class').split(' ')[2]);
Explained:
$('#myDiv') //jQuery selector
.removeClass //removed the named class
$('#myDiv') //jQuery selector
.attr('class') //get the class attribute of the element
.split(' ') //split it into an array, with the perpetrator being a blank space aka ' '
[2] //get the 3rd item in the array, remember it counts from 0, aka 0, 1, 2, 3, 4 ...

Find and replace specific text characters across a document with JS

I'm wondering if there is a lightweight way I could use JavaScript or jQuery to sniff out a specific text character across a document; say € and find all instances of this character. And then! Write an ability to replace all instances of this with say a $.
I found this snippet for starters:
var str = 'test: '';
str = str.replace(/'/g, "'");
Essentially; I am wanting a solution for a one page document. Grab all instances of X and make it XY. Only text characters.
How about this, replacing # with $:
$("body").children().each(function () {
$(this).html( $(this).html().replace(/#/g,"$") );
});
http://jsfiddle.net/maximua/jp96C/1/
ECMAScript 2015+ approach
Pitfalls when solving this task
This seems like an easy task, but you have to take care of several things:
Simply replacing the entire HTML (e.g. using innerHTML) causes the affected subtree of the DOM to be entirely deleted and replaced, however event listeners are attached to the existing, now deleted elements, so they’re deleted with them. Similarly, WeakMap entries for the existing elements will all be deleted. This is because all of these things need the exact references to the elements or nodes; a replaced innerHTML will create entirely new references and discard the old ones.
Replacing the HTML may also replace <script> or <style> contents, or HTML tag or attribute names, which is not always desired.
Changing the HTML may result in an xss attack.
You may want to replace attribute values, e.g. for title and alt, in a controlled manner as well, but those all-or-nothing approaches as well as regexes are ill-equipped to do so.
Guarding against xss attacks generally can’t be solved by using the approaches below. E.g. if a fetch call reads a URL from somewhere on the page, then sends a request to that URL, the functions below won’t stop that, since this scenario is inherently unsafe.
Replacing the text contents of all elements
This basically selects all elements that contain normal text, goes through their child nodes — among those are also text nodes —, seeks those text nodes out and replaces their contents.
You can optionally specify a different root target, e.g. replaceOnDocument(/€/g, "$", { target: someElement });; by default, the <body> is chosen.
const replaceOnDocument = (pattern, string, {target = document.body} = {}) => {
// Handle `string` — see the last section
[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].forEach(({childNodes: [...nodes]}) => nodes
.filter(({nodeType}) => nodeType === Node.TEXT_NODE)
.forEach((textNode) => textNode.textContent = textNode.textContent.replace(pattern, string)));
};
replaceOnDocument(/€/g, "$");
Replacing text nodes, element attributes and properties
Now, this is a little more complex: you need to check three cases: whether a node is a text node, whether it’s an element and its attribute should be replaced, or whether it’s an element and its property should be replaced. A replacer object provides methods for text nodes and for elements.
Before replacing attributes and properties, the replacer needs to check whether the element has a matching attribute; otherwise new attributes get created, undesirably. It also needs to check whether the targeted property is a string, since only strings can be replaced, or whether the matching property to the targeted attribute is not a function, since this may lead to an xss attack.
In the example below, you can see how to use the extended features: in the optional third argument, you may add an attrs property and a props property, which is an iterable (e.g. an array) each, for the attributes to be replaced and the properties to be replaced, respectively.
You’ll also notice that this snippet uses flatMap. If that’s not supported, use a polyfill or replace it by the reduce–concat, or map–reduce–concat construct, as seen in the linked documentation.
const replaceOnDocument = (() => {
const replacer = {
[Node.TEXT_NODE](node, pattern, string){
node.textContent = node.textContent.replace(pattern, string);
},
[Node.ELEMENT_NODE](node, pattern, string, {attrs, props} = {}){
attrs.forEach((attr) => {
if(typeof node[attr] !== "function" && node.hasAttribute(attr)){
node.setAttribute(attr, node.getAttribute(attr).replace(pattern, string));
}
});
props.forEach((prop) => {
if(typeof node[prop] === "string" && node.hasAttribute(prop)){
node[prop] = node[prop].replace(pattern, string);
}
});
}
};
return (pattern, string, {target = document.body, attrs: [...attrs] = [], props: [...props] = []} = {}) => {
// Handle `string` — see the last section
[
target,
...[
target,
...target.querySelectorAll("*:not(script):not(noscript):not(style)")
].flatMap(({childNodes: [...nodes]}) => nodes)
].filter(({nodeType}) => replacer.hasOwnProperty(nodeType))
.forEach((node) => replacer[node.nodeType](node, pattern, string, {
attrs,
props
}));
};
})();
replaceOnDocument(/€/g, "$", {
attrs: [
"title",
"alt",
"onerror" // This will be ignored
],
props: [
"value" // Changing an `<input>`’s `value` attribute won’t change its current value, so the property needs to be accessed here
]
});
Replacing with HTML entities
If you need to make it work with HTML entities like ­, the above approaches will just literally produce the string ­, since that’s an HTML entity and will only work when assigning .innerHTML or using related methods.
So let’s solve it by passing the input string to something that accepts an HTML string: a new, temporary HTMLDocument. This is created by the DOMParser’s parseFromString method; in the end we read its documentElement’s textContent:
string = new DOMParser().parseFromString(string, "text/html").documentElement.textContent;
If you want to use this, choose one of the approaches above, depending on whether or not you want to replace HTML attributes and DOM properties in addition to text; then simply replace the comment // Handle `string` — see the last section by the above line.
Now you can use replaceOnDocument(/Güterzug/g, "Güter­zug");.
NB: If you don’t use the string handling code, you may also remove the { } around the arrow function body.
Note that this parses HTML entities but still disallows inserting actual HTML tags, since we’re reading only the textContent. This is also safe against most cases of xss: since we’re using parseFromString and the page’s document isn’t affected, no <script> gets downloaded and no onerror handler gets executed.
You should also consider using \xAD instead of ­ directly in your JavaScript string, if it turns out to be simpler.
My own suggestion is as follows:
function nativeSelector() {
var elements = document.querySelectorAll("body, body *");
var results = [];
var child;
for(var i = 0; i < elements.length; i++) {
child = elements[i].childNodes[0];
if(elements[i].hasChildNodes() && child.nodeType == 3) {
results.push(child);
}
}
return results;
}
var textnodes = nativeSelector(),
_nv;
for (var i = 0, len = textnodes.length; i<len; i++){
_nv = textnodes[i].nodeValue;
textnodes[i].nodeValue = _nv.replace(/£/g,'€');
}
JS Fiddle demo.
The nativeSelector() function comes from an answer (posted by Anurag) to this question: getElementsByTagName() equivalent for textNodes.
I think you may be overthinking this.
My approach is simple.
Enclose you page with a div tag:
<div id="mydiv">
<!-- you page here -->
</div>
In your javascript:
var html=document.getElementById('mydiv').innerHTML;
html = html.replace(/this/g,"that");
document.getElementById('mydiv').innerHTML=html;
Similar to #max-malik's answer, but without using jQuery, you can also do this using document.createTreeWalker:
button.addEventListener('click', e => {
const treeWalker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
while (treeWalker.nextNode()) {
const node = treeWalker.currentNode;
node.textContent = node.textContent.replace(/#/g, '$');
}
})
<div>This is an # that we are # replacing.</div>
<div>This is another # that we are replacing.</div>
<div>
<span>This is an # in a span in # div.</span>
</div>
<br>
<input id="button" type="button" value="Replace # with $" />
Vanilla JavaScript solution:
document.body.innerHTML = document.body.innerHTML.replace(/Original/g, "New")
The best would be to do this server-side or wrap the currency symbols in an element you can select before returning it to the browser, however if neither is an option, you can select all text nodes within the body and do the replace on them. Below i'm doing this using a plugin i wrote 2 years ago that was meant for highlighting text. What i'm doing is finding all occurrences of € and wrapping it in a span with the class currency-symbol, then i'm replacing the text of those spans.
Demo
(function($){
$.fn.highlightText = function () {
// handler first parameter
// is the first parameter a regexp?
var re,
hClass,
reStr,
argType = $.type(arguments[0]),
defaultTagName = $.fn.highlightText.defaultTagName;
if ( argType === "regexp" ) {
// first argument is a regular expression
re = arguments[0];
}
// is the first parameter an array?
else if ( argType === "array" ) {
// first argument is an array, generate
// regular expression string for later use
reStr = arguments[0].join("|");
}
// is the first parameter a string?
else if ( argType === "string" ) {
// store string in regular expression string
// for later use
reStr = arguments[0];
}
// else, return out and do nothing because this
// argument is required.
else {
return;
}
// the second parameter is optional, however,
// it must be a string or boolean value. If it is
// a string, it will be used as the highlight class.
// If it is a boolean value and equal to true, it
// will be used as the third parameter and the highlight
// class will default to "highlight". If it is undefined,
// the highlight class will default to "highlight" and
// the third parameter will default to false, allowing
// the plugin to match partial matches.
// ** The exception is if the first parameter is a regular
// expression, the third parameter will be ignored.
argType = $.type(arguments[1]);
if ( argType === "string" ) {
hClass = arguments[1];
}
else if ( argType === "boolean" ) {
hClass = "highlight";
if ( reStr ) {
reStr = "\\b" + reStr + "\\b";
}
}
else {
hClass = "highlight";
}
if ( arguments[2] && reStr ) {
reStr = reStr = "\\b" + reStr + "\\b";
}
// if re is not defined ( which means either an array or
// string was passed as the first parameter ) create the
// regular expression.
if (!re) {
re = new RegExp( "(" + reStr + ")", "ig" );
}
// iterate through each matched element
return this.each( function() {
// select all contents of this element
$( this ).find( "*" ).andSelf().contents()
// filter to only text nodes that aren't already highlighted
.filter( function () {
return this.nodeType === 3 && $( this ).closest( "." + hClass ).length === 0;
})
// loop through each text node
.each( function () {
var output;
output = this.nodeValue
.replace( re, "<" + defaultTagName + " class='" + hClass + "'>$1</" + defaultTagName +">" );
if ( output !== this.nodeValue ) {
$( this ).wrap( "<p></p>" ).parent()
.html( output ).contents().unwrap();
}
});
});
};
$.fn.highlightText.defaultTagName = "span";
})( jQuery );
$("body").highlightText("€","currency-symbol");
$("span.currency-symbol").text("$");
Use split and join method
$("#idBut").click(function() {
$("body").children().each(function() {
$(this).html($(this).html().split('#').join("$"));
});
});
here is solution
In javascript without using jquery:
document.body.innerText = document.body.innerText.replace('actualword', 'replacementword');
You can use:
str.replace(/text/g, "replaced text");
For each element inside document body modify their text using .text(fn) function.
$("body *").text(function() {
return $(this).text().replace("x", "xy");
});
As you'll be using jQuery anyway, try:
https://github.com/cowboy/jquery-replacetext
Then just do
$("p").replaceText("£", "$")
It seems to do good job of only replacing text and not messing with other elements
str.replace(/replacetext/g,'actualtext')
This replaces all instances of replacetext with actualtext
Here is something that might help someone looking for this answer:
The following uses jquery it searches the whole document and only replaces the text.
for example if we had
overpopulation
and we wanted to add a span with the class overpop around the word overpopulation
<span class="overpop">overpopulation</span>
we would run the following
$("*:containsIN('overpopulation')").filter(
function() {
return $(this).find("*:contains('" + str + "')").length == 0
}
).html(function(_, html) {
if (html != 'undefined') {
return html.replace(/(overpopulation)/gi, '<span class="overpop">$1</span>');
}
});
the search is case insensitive searches the whole document and only replaces the text portions in this case we are searching for the string 'overpopulation'
$.extend($.expr[":"], {
"containsIN": function(elem, i, match, array) {
return (elem.textContent || elem.innerText || "").toLowerCase().indexOf((match[3] || "").toLowerCase()) >= 0;
}
});

jQuery: Getting "secondary" class

I'm using jQuery to loop through some elements in a document. These elements are of type <tr> with class .input-row. Some of the elements can also have a secondary class (for example .input-area).
I use $(".input-row").each() to loop through the elements, but how can I determine if the $(this)-element has a "secondary" class and if so, get the name of this?
$(".input-row").each(function(){
$.each($(this).attr('class').split(/\s+/), function(i, v){
if(v !== 'input-row'){
alert(v);
}
});
});
You can get the list of all classes using attr, and you could simply get rid of the the class you used to select the elements:
$(".input-row").each(function() {
var allClasses = $(this).attr("class"),
otherClasses = allClasses.replace("input-row", "");
});
If the element has more than two classes, then you will be left with a list of the other classes. To separate them, you could split on the spaces.
You can get all the classes on the element and then remove the one you know exists('input-row'), then you will be left with any other classes on that element.
$('.input-row').each(function() {
var classes = $.trim($(this).attr('class').replace('input-row', ''));
if (classes.length > 1) {
alert(classes) // Names of all of the remaining classes
}
}
If you want to get them individually, you can do classes.split(' ') to get an array.
I prefer a declarative approach. You know which classes there can be, so write cases for them:
$(".input-row.input-area").each( /* ... */ );
$(".input-row.input-field").each( /* ... */ );
If you for some reason don't know the class name, you can extract it along the lines of:
$(".input-row").each(function () {
var myClasses = this.className.split(" ");
$.each(myClasses, function (i, className) {
if (className != 'input-row') {
alert(className);
}
});
});
I'd go for this
var otherClasses = $('.input-row').attr('class').split(' ');
otherClasses.splice($.inArray("input-row", otherClasses),1);
Simply doing this
var otherClasses = $('.input-row').attr('class').replace('input-row', '').split(' ');
Will give you an extra string in the array with an empty value in it, because of the space behind "input-row"
You could also do something like this to detect the number of classes:
var nc = $('#myId').attr('class').split(' ').length;
Then if nc is greater than 1:
$('#myID').attr('class').split(' ')[1]
should return the 'secondary' class
See a fiddle

Removing a class from an HTML element using JavaScript

I am attempting to remove a class from an html tag using JavaScript but I have no idea where to start. I have searched but to no avail. While I am decently fluent in jQuery, I am not in JavaScript and I need to use JavaScript in this instance Anything I have found thus far would need to be adjusted for my own use, which I have not been successful at. Hopefully someone can explain it in a fool-proof way.
The element the class is attached to is the "ul" tag. The class is named "nojavaScript" and is only applied to this single instance of the "ul" tag. While as I said the class is only used once in the page, the "ul" tag is used in other instances with different classes or ids.
If it would make it easier for the JavaScript, I can change the class to an id.
I hope I have given you enough to go on. I will include an example of the html code below.
<ul id="lines_list" class="nojavaScript"></ul>
As I mentioned, if it's easier to remove an id than a class, I can make the current id a class, and the current class an id. But essentially it's the "nojavaScript" that needs to be removed.
Thanks!
Here's a pure js solution:
var ulArr = document.getElementsByClassName('nojavaScript');
for (var i = 0; i < ulArr.length; i++) {
ulArr[i].className = ulArr[i].className.replace('nojavaScript','');
}
First you select all elements with the given class name, then iterate over the result and replace the given class in the className attribute with an empty string.
UPDATE:
Here's a more robust solution that turns the removal into a parameterized function and handles stripping extra whitespaces from the beginning, end, and middle of the className attribute.
function removeClass(elem, className) {
//declare some regexes to help us strip the extra whitespace
var trimLeft = /^\s+/,
trimRight = /\s+$/,
stripDouble = /\s+/g;
//remove the class, strip extra whitespace, and reassign className
elem.className = elem.className.replace(className, '').replace(trimLeft, '').replace(trimRight, '').replace(stripDouble, ' ');
}
//declare name of class to remove and get an array of elements with that class
var toRemove = 'nojavaScript',
elArr = document.getElementsByClassName(toRemove);
//iterate over elements and remove the class
for (var i = 0; i < elArr.length; i++) {
removeClass(elArr[i], toRemove);
}
Here's a live demo ->
try this:
document.getElementById("lines_list").className = "";
function removeCSSClass(element, className) {
var cssClass = ' ' + element.className + ' ';
var index = cssClass.indexOf(' ' + className + ' ');
if (index >= 0) {
var newClass = cssClass.substr(0, index) + ' ' + cssClass.substr(index + className.length + 1);
element.className = newClass;
}
}
UPDATE: code now works in all occassions
function removeClassFromElement(el,className){
var classes = el.getAttribute('class').split(/[ ]+/g);
var class = "";
for(var i in classes)
if(classes[i] != className)
class += classes[i] + " ";
el.setAttribute('class',class);
}
removeClassFromElement(document.getElementById('lines_list'),'nojavaScript');
Here's a non regex method that is considerate of multiple classes on an element.
function removeClass(element, cssClass) {
var classes = element.className.split(' ');
var j = classes.length;
while (j--) {
if (classes[j] === cssClass) {
classes.splice(j, 1);
}
}
element.className = classes.join(' ');
}
var lines_list = document.getElementById('lines_list');
removeClass(lines_list, 'nojavaScript');
It splits on spaces to isolate whole class names whereas doing a simple search for the class name string and replacing with nothing might eat part of a longer class name.
Class name modification should be done on the className property with a RegExp replace to avoid clobbering other classNames which should stay:
var ele = document.getElementById( 'lines_list' );
ele.className = ele.className.replace( /(?:^|\s)nojavaScript(?:\s|$)/gm, ' ' );
http://jsfiddle.net/JAAulde/nWzaZ/3/
(genercized class names: http://jsfiddle.net/JAAulde/nWzaZ/2/ )
Without this regex, you either wipe the entire className, or you overkill and possibly take out a portion of foonojavaScript as well (you know, if you had such an odd class :P ). While this might not really be likely, it's good practice for when you run into code that might not be as specific.
This solution allows you to have as many classes on the element as you want, as similar as you desire, without worry of how you format them other than as specified by the W3C. No maintenance issues :).
(The RegExp specifically looks for your class preceded by start of string or white-space, and followed by white-space or end of string)
(This assumes you already have a handle on how to get the element(s) from the DOM in the first place.)

reading attr class, but I need only one of them

I have a div that has many classes. I select them all with
$('#mydiv').attr('class'); //outputs 'redball blueball greenbrick whitesquare'
What I actually need is the class that starts with 'red' so I really want to output only 'redball'. Is there an easy way to do this?
Like has already been said, split on spaces and find your matching class. Here's an example function:
<script language="javascript">
$(document).ready(function() {
var list = $('#mydiv').attr('class').split(/\s+/);
for (i = 0; i < list.length; i++) {
if (/red.*/.test(list[i])) {
alert(list[i]);
}
}
});
</script>
try to extract it with a regular expression:
split the output into an array an while itreating the array values try to test with some regulr expression (like this: /red[a-zA-Z09]*/)
hope it helps you
You can try the .hasClass() method to help you decide.
if( $( '#myDiv' ).attr( 'class' ).hasClass( 'redball' ) ) {
// call method to serve the redball...
}
Alternatively, using .split() and regex as suggested by the others can also work -- depends on how you want to use your output.
BONUS:
But for efficiency sake, it's better to cache the DOM object in a local variable and access that if you need to do more with the element. This is so that Javascript doesn't have to go back to the DOM tree and fetch the same object every time you want to use it.
var myDiv = $( '#myDiv' ); // store the <div> object in the variable
var classNames = myDiv.attr( 'class' );
switch( classNames ) {
case 'redball':
serveBall( 'red' );
break;
case 'blueball':
serveBall( 'blue' );
break;
.....
}

Categories

Resources