i'm having some problems with jQuery
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.filter("h1,h2").map(function(id) {
$(this).wrap('<span color="red"/>');
});
alert(foo.html());
});
This code outputs
<h1>Bar</h1><p>Hi</p><h1>Baz</h2><p>bye</p>
The span's are nowhere to be seen. What am I doing wrong?
It doesn't have any effect because .filter() filters elements at that level, you could need .find() to get descendants like this:
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.find("h1,h2").wrap('<span color="red"/>');
alert(foo.html());
});
You can test it out here. Also note you should use .each() instead of .map() for looping...but there's no need here, since you can just call .wrap() directly.
You don't want to use filter here, you want to use find. Also, why are you using map?
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h2><p>bye</p></div>");
foo.find("h1,h2").wrap('<span color="red"/>');
alert(foo.html());
});
Live test
First off: your markup is invalid (Baz is wrapped by an opening h1 and a closing h2). But the .map reference says you need to return the value.
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
var bar = foo.find("h1,h2").map(function(id) {
return $(this).wrap('<span color="red"/>');
});
});
You need .find() instead of .filter() since the heading elements are nested.
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.find("h1,h2").wrap('<div color="red"/>');
Also, I changed it to wrap using a <div> instead of a <span> since I don't think it is valid to have a <span> wrapped around heading elements.
Related
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>
I am trying to perform an action to other elements than the $(this) item
$('.items').click(function(){
var myitem = $(this);
$(".items").each(function() {
if (myitem == $(this)){
break;
} else {
//perform action
}
});
});
Where did I go wrong? Is there any better method?
Try to use the .not() function to filter out the current element,
$('.items').click(function(){
$('.items').not(this).each(function(){
//perform action here.
});
});
What went wrong?
When using the jQuery method (a.k.a. $) a new instance of the jQuery object is created, containing a list of elements matching your selector along side with a rich prototype of jQuery's methods.
Your mistake was to try and compare two different instances.
What you could have done was to compare the elements themselves by making the following changes:
// change this:
var myitem = $(this);
// to this:
var myitem = this;
// change this:
if (myitem == $(this)){
// to this:
if (myitem == this){
Unless you intend to use the jQuery object functionality there's no reason to initiate a new instance. Simply use the element itself when possible. It's a best practice to avoid such use cases. Performance wise.
Best solution
But the best solution in your case is what was mentioned in all other answers, using jQuery's not method to exclude the element from the newly created instance.
Using.not() to avoid
Try this
$(".items").not($(this)).each(function() {
});
OR
As per your code
$(".items").not(myitem).each(function() {
});
you can use not() to ignore the element which is clicked:
$(".items").not(this).each(function() {
});
I have several <select> boxes all using the same prefix and I would like to set up a recursive function to essentially do the work for me.
$('[id^="by_"]').change(function(e)
{
var elem = e;
console.log(e.value);
});
Based on this code is my intention pretty clear? Am I on the right track?
console prints out: undefined
I think you're on the right track - the selector you're using matches a prefix of "by_", and you're binding the change event to all of them. Make sure you put this in $(document).ready or similar. Are you having any problems with this code? Instead of using the e parameter, I would just use this inside of the function to refer to the element and $(this) to get the jQuery object of it. So to get the value, you'd use:
this.value
// or
$(this).val()
(ignore the e and elem stuff, although it wouldn't be a bad idea to store $(this) in something like elem so you can have a reference to it instead of re-creating the jQuery object every time you need it)
When using callbacks to events with jQuery, the (first) parameter of the callback is an event object that explains many things about the event that occurred ( http://api.jquery.com/category/events/event-object/ ) and does not hold the element - that's what this is for!
e in your code is the event object which has no value property, you should use this instead:
$('[id^="by_"]').change(function(e) {
var elem = this;
console.log(this.value);
});
Or if you want to use event object, you can use target property:
e.target.value
Since you're already using jQuery, why not something like this:
$('[id^="by_"]').change(function(e)
{
var $elem = $( this );
console.log( $elem.val() );
});
Isn't it more something like that:
$('[id^="by_"]').change(function()
{
console.log($('option:selected',this).val());
});
jsfiddle
I'm reformatting some really bad HTML using jQuery. I need to splice sibling <font> elements together. I tried this code:
$('font+font').each(function() {
this.html().appendTo( this.prev() );
this.remove();
});
but it gave me this error: TypeError: 'undefined' is not a function (evaluating 'this.html()')
Here's a sample of the HTML:
<font>This fragment </font><font>is actually one element.</font>
Update
I updated my code with $(this), but it still isn't working. When I run this code
$('font+font').each(function() {
$(this).html().appendTo( $(this).prev() );
$(this).remove();
});
I get this error: TypeError: 'undefined' is not a function (evaluating '$(this).html().appendTo( $(this).prev() )')
this has to be wrapped in a jQuery object, before you can use jQuery methods on it.
.html() returns a string. You cannot use jQuery methods on a string without wrapping. Use $this.prev().append( $this.html() ) instead.
When using $(this) more than once, it's wise to store $(this) in a temporary variable. It's the convention to prefix jQuery objects with a dollar sign.
Code:
$('font+font').each(function() {
var $this = $(this);
$this.prev().append( $this.html() );
$this.remove();
});
When you use an each statement, it returns this as a DOM element, not a jQuery object. .html() must be called on a jQuery object. So the first part of your fix is to convert this into a jQuery element with the $ symbol.
$(this).html(); //don't use this.html();
The second problem is that html() returns a string. You can't call AppendTo() on a string, only a jQuery object. Since you are working with .html() I'll assume that you want the string contents and not the full contents. If that were the case, Rob's answer is more appropriate.
this.textContent = $(this).prev().html() + this.textContent; // prepend siblings content
The final code ends up looking like this:
$('font+font').each(function() {
this.textContent = $(this).prev().html() + this.textContent;
$(this).prev().remove();
});
http://jsfiddle.net/b6vLL37k/1
You need to use $(this) not this
You need to use $(this) for jQuery to help you.
I wasn't able to fix your code. How about something like this:
var text = '';
$('font').each(function() {
text += $(this).text();
});
console.log($('<p />').text(text));
I want to get the id of a single <span> element during iteration.
Example scenario:
I have a few ids which start with AAA and end with BBB. The middle characters can vary:
<span id="AAA-LS-BBB">hi1</span>
<span id="AAA-LAS-BBB">hi2</span>
<span id="AAA-LBS-BBB">hi3</span>
<span id="AAA--LCS--BBB">hi4</span>
Here, first 3 digits of span id and last 3 digits of span id is same...only in middle it will vary. I want to generalized method to know ...each id using... $("#id").attr("id")
so, here
I am trying to find out iteration like below,
I want to write one iterator method to get the current id
$("span[id^='AAA-***-BBB']").each(function(){
var a = $("this").attr("id");
});
Hope my requirements are clear.
how ti use regular expression here.. to find out id?
Use .filter() combined with a regex:
$('span[id]').filter(function () {
return /^AAA.*BBB$/.test(this.id);
}).each(function () {
alert(this.id);
});
Alternatively, since you are using a .each() already, you can simply add an if condition inside it:
$('span[id]').each(function () {
if (/^AAA.*BBB$/.test(this.id)) {
alert(this.id);
}
});
Update: It looks like you can also combine both the Attribute-Starts-With and Attribute-Ends-With selectors on the same attribute:
$('div[id^="AAA"][id$="BBB"]').each(function () {
alert(this.id);
});
(See example: http://jsfiddle.net/2pz8X/)
Combining fellow contributors' suggestions, and making the regex more specific:
// first, at least get all <div>'s with id's that start with 'AAA'
$("div[id^='AAA']").filter(function(){
var regexp = /^A{3}(.*)B{3}$/; // regex
return (this.id.match(regexp));
});
This will return all the div's that you need to target.
Sample # http://jsfiddle.net/4ZNWJ/
Try this:
$("span[id^='AAA']").each(function(){
alert($(this).id);
});