I have the following Code
var page = '<h1>Hello!</h1><p>FOO</p><span class="username">this is ur name</span><p>sample text</p>';
when I alert $(page).html() i get Hello! and when I wrap the contents of the page in a div and alert $(page).html() I get the whole html contents.
What I am trying to accomplish here is I have a page string with html template and I am trying to find a class username in it and i am getting null.
I am confused with this happens
Here is a small fiddle of the issue
http://jsfiddle.net/6TSuq/1/
When you call $(page) you construct a jQuery object which contains 4 elements; for each of the HTMLElements that aren't nested in your string.
console.log($(page).map(function () {
return this.nodeName;
}).toArray());
// ["H1", "P", "SPAN", "P"]
html() returns the innerHTML of the first element in this jQuery object; which is why you only see "Hello!".
To find the .username you should use the filter() method, which searches within the jQuery object for elements which match the given selector.
alert($(page).filter('.username').text()); // "this is ur name", kthx.
See your updated fiddle here; http://jsfiddle.net/6TSuq/15/
Bare in mind that in future, you might have nested elements such as this;
var page = "<h1><span class='username'>Foo</span></h1>";
In this circumstance, filter()ing for .username will yeild no results; as the jQuery object $(page) does not contain the .username element; it contains a h1, which has a descendant which is a .username. Therefore here you'd need to use;
alert($(page).find('.username').text());
For reference, see find(), filter() and map()
A very simple way to do this is:
var elem = $('<h1>Hello!</h1><p>FOO</p><span class="username">this is ur name</span><p>sample text</p>').filter('.username').get(0);
console.log($(elem).html()); // returns this is ur name
jsFiddle example
You need to convert your string to a jQuery object first in order to use any jQuery method on it.
Related
I am trying to use javaScript to determine if an element with a specific class name exists on an html page. The element in question is only sometimes loaded on the page.
When I use document.getElementsByClassName('element-in-question').innerHTML = "Hello"
It will work when the element exists, but when it doesn't exist, it will return as "cannot set property of innerHTML of undefined and the rest of the code will not run.
Is there a way to check if an element exists, and only modify it when it does without breaking the rest of the code?
Thanks for the help
You can also use document.querySelector which will return the first element within the document if it exists, if not, it returns null.
const targetElement = document.querySelector('.element-in-question');
if (targetElement) {
targetElement.innerText = 'Hi there!';
}
<div class="element-in-question"></div>
Tip: If you're just adding text consider using innerText instead of innerHTML.
Just wrap you code with if statement :
const elemts = document.getElementsByClassName('element-in-question');
if(elemts.length) {
// this actually need to be elemts[0].innerHTML
elemts.innerHTML = "Hello"
}
Note: document.getElementsByClassName will return array/collection of elements so if you really know that there is no other elements keep using it otherwise switch to getElementById.
as per documentation:
The getElementsByClassName() method returns a collection of all
elements in the document with the specified class name, as an
HTMLCollection object.
It's very simple with the condition IF
If you want to get elements by class, the function will return an array (a collection of all elements in the document with the specified class name), so you will check as following :
if (document.getElementsByClassName('class-in-question').length > 0) {
// Existed
}
If you want to get an element by specified id, the function will return an objet HTML with that id, so you will check as following :
if (document.getElementById('id-in-question')) {
// Existed
}
I'm trying to highlight all occurrences of an array of words anywhere on the page, regardless of their parent element.
I've adapted the following question's solution and it works great if I know the selector to use the function on. However, the words could appear in ANY selector, so I'm trying to use a wildcard selector, but it's not working.
(function($) {
var keywords = ['Breathalyzer', 'Marijuana', 'Alcohol'];
function highlightWords(element) {
full_text = element.html();
$.each(keywords, function(i) {
full_text = full_text.replace(RegExp(keywords[i], "gi"), "<span class='highlighttext'>"+keywords[i]+"</span>");
});
element.html(full_text);
}
highlightWords($("*"));
})(jQuery);
I'm using a regexp that's case insensitive so that it matches the search terms regardless of case. And I'm expecting the function to wrap all matched terms in <span class="highlighttext"></span> but it's not working...
EDIT: I guess I should add that I'm not getting any sort of errors in the console
Answer:
There are a few things that need to be changed for this to work as you'd expect:
$("*") returns a collection. It's an array of elements, not a single element. Therefore passing the array into a function expecting a single element will not work.
Solution:
We can fix the above by using JQuery's .each function to iterate over each item in the collection and then calling your highlight function.
We have to adjust your highlightWords function to be on the receiving end of the each method.
Solution:
We change the parameters to match what's passed
in. This is why instead of element, we use index, element.
.html is a JQuery method. We need to be sure that the element variable that we receive contains this method or we won't be able to use it.
Solution:
Since the element is not a JQuery object, we wrap the element within a JQuery object by passing the element variable in as a selector. element = $(element);
Working Code:
(function($) {
var keywords = ['Breathalyzer', 'Marijuana', 'Alcohol'];
function highlightWords(index, element) {
element = $(element);
full_text = element.html();
$.each(keywords, function(i) {
full_text = full_text.replace(RegExp(keywords[i], "gi"), "<span class='highlighttext'>"+keywords[i]+"</span>");
});
element.html(full_text);
}
$("*").each(highlightWords);
})(jQuery);
.highlighttext {
color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<p>Hello Alcohol</p>
<p>This is a test of <code>marijuana</code></p>
<small>Maybe we should get a Breathalyzer?</small>
<h3>No, no, we should get more Alcohol.</h3>
</div>
var a = $('#txta').val();
console.log(a);
result is complete html code from this url
Now I want to get content of all #artikal-naziv tags (there are 96)
var b = a.find("#artikal-naziv").text();
console.log(b);
Result:
Uncaught TypeError: a.find is not a function
Any help?
Actually you are calling .find() on a string and not in a DOM element.
Because from $('#txta').val() you are getting a string, that's why you got Uncaught TypeError: a.find is not a function, because string doesn't have .find() method.
You should change it to:
var a = $('#txta');
Then you can write:
var b = a.find("#artikal-naziv").text();
Note:
Now I want to get content of all #artikal-naziv tags (there are 96)
You can't set the same id #artikal-naziv for multiple elements (96), the id should be unique in the page.
Another thing .val() call assumes that your element is a form element, you can't call .val() on a div or a span, if it isn't a form element use .html() instead.
Because "a" is not a jQuery object - it's usually a string containing value of the returned element (txta).
Use $(a).find(...) instead - that will probably do it.
Ref link: https://stackoverflow.com/a/3532381/3704489
As per what I can make out of your description, you are getting HTML as string using var a = $('#txta').val();. If this is true, you will have to create an in-memory element and set this string as its HTML.
Then you will have an in-memory DOM section that you can query on.
You can try something like this:
var html = '<span><p id="artikal-naziv">bla bla</p></span>';
var $tempElement = $('<div>').html(html);
console.log($tempElement.find('#artikal-naziv').text());
// or using vanilla JS
var tempElement = document.createElement('div');
tempElement.innerHTML = html;
console.log(tempElement.querySelector('#artikal-naziv').textContent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
.val() takes out the value from the element....Whereas all DOM operations are done on the element... because function like .find() , .hide() , .show() , .closest() etc are used with the element not the value
The Following modifications should work...
var a = $('#txta'); // $("#ID") returns the element
console.log(a.val()); // $("#ID").val() returns the value
the result is complete html code from this URL
Now I want to get content of all #artikal-naziv tags (there are 96)
var b = a.find("#artikal-naziv").text(); // .find() easily works on element
console.log(b);
Simply use .find to find children and .closest to find parents:
<div class='a'>
<div class='b'>
<div class='c'></div>
<div class='c'></div>
<div class='c'></div>
</div>
</div>
js:
var a = $('.b');
a.find('.c'); // Will return all the objects with the class c
a.closest('.a'); // Will return the first parent with the class a
According to jQuery's API StartsWith selector is intended to be used on the entire document.
For example,
var $elements = $( "span[id^='MJXc']" );
will find all <span>s in the DOM that have IDs starting with 'MJXc'.
But what if I have an array of elements stored in a variable and I want to select only those elements that start with ... out of that array? Can I still use the StartsWith selector?
The following doesn't seem to work and gives out Uncaught SyntaxError: Unexpected token (
var $elements = $arrayofelements.( "span[id^='MJXc']" );
I did not add or remove any brackets, I just stuck a variable in front of the selector.
$arrayofelements looks like this in console:
0:span#MJXc-Node-7.mjx-mrow
1:span#MJXc-Node-28.mjx-mi
2:span.mjx-base
3:span#MJXc-Node-34.mjx-mi
Ideally, I would like to get elements 0, 1, and 3 reuturned, skipping element 2 as it doesn't have ID starting with 'MJXc'.
Use the .filter() method in JQuery.
$arrayOfElements.filter('span[id^=MJXc]');
Like most JQuery methods, it takes a selector. It returns a new JQuery object containing only the elements that matched the selector (in this case, a span with an ID starting with MJXc).
// get only the spans inside #parent div
$spansToFilter = $('#parent').children();
$filteredSpans = $spansToFilter.filter('[id^=MJXc]');
// prove we've filtered out the span with no matching ID
$filteredSpans.each(function(i, item) {
console.log(item);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="MJXc-Node-7.mjx-mrow">(external skip)</span>
<div id="parent">
<span id="MJXc-Node-7.mjx-mrow">A</span>
<span id="MJXc-Node-28.mjx-mi">B</span>
<span class=".mjx-base">(skip C)</span>
<span id="MJXc-Node-34.mjx-mi">D</span>
</div>
What you tried didn't work because in Javascript whatever.() would be invalid; You'd be trying to call a function with no name. In JQuery and javascript, you are always calling methods on the previous object in the chain obj.method(). Those methods are returning new JQuery objects which have the same set of methods, which is what allows the chaining to be possible. All the methods JQuery objects have are listed in the JQuery documentation, including .filter(), .find(), .children(), etc.
javascript specific answer:
from your $elements array, you can simply check whether the id of your element startsWith() a particular prefix or not. It it does, then you can simply push it into new array.
var $selectedElements = [];
for(var i=0; i<$elements.length; i++)
if($elements[i].id.startsWith("MJXc"))
$selectedElements.push($elements[i]);
I was writing a "pluginable" function when I noticed the following behavior (tested in FF 3.5.9 with Firebug 1.5.3).
$.fn.computerMove = function () {
var board = $(this);
var emptySquares = board.find('div.clickable');
var randPosition = Math.floor(Math.random() * emptySquares.length);
emptySquares.each(function (index) {
if (index === randPosition) {
// logs a jQuery object
console.log($(this));
}
});
target = emptySquares[randPosition];
// logs a non-jQuery object
console.log(target);
// throws error: attr() not a function for target
board.placeMark({'position' : target.attr('id')});
}
I noticed the problem when the script threw an error at target.attr('id') (attr not a function). When I checked the log, I noticed that the output (in Firebug) for target was:
<div style="width: 97px; height: 97px;" class="square clickable" id="8"></div>
If I output $(target), or $(this) from the each() function, I get a nice jQuery object:
[ div#8.square ]
Now here comes my question: why does this happen, considering that find() seems to return an array of jQuery objects? Why do I have to do $() to target all over again?
[div#0.square, div#1.square, div#2.square, div#3.square, div#4.square, div#5.square, div#6.square, div#7.square, div#8.square]
Just a curiosity :).
.find() returns not an array of jQuery objects, but one jQuery object containing an array of DOM elements (a jQuery object, at it's core, is a wrapper around a DOM element array).
When you're iterating through, each element you're on is a DOM element. So, it needs to be wrapped in $(this) to become jQuery object and have access to those methods.
Also as a side note: The id attribute can't begin with a number, since it's invalid HTML you may or may not experience strange behavior, especially cross-browser (this rule applies for any invalid HTML).
No, the find method doesn't return an array of jQuery objects. You are creating a jQuery object for each element here:
console.log($(this));
If you log the value without creating a jQuery object from it:
console.log(this);
you will see that it's an element, not a jQuery object.
When you access the jQuery object as an array, you get an element. If you want a jQuery object you have to create one from the element.