jQuery this.html() returns undefined - javascript

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));

Related

Object [object HTMLAnchorElement] has no method 'attr'

I'm examining a DOM element using console.log. The DOM element is an anchor:
When I try to access its id and output it using either of the following lines:
console.log($this.attr(data-id));
or
console.log($this.data('id'));
I get an error:
Object [object HTMLAnchorElement] has no method 'attr'
('data' in the second case)
Does an anchor element not have the attr or data methods, or is my mistake something else?
That looks like its because your this reference is not a jquery object.
Try these instead:
$(this).data('id')
$(this).attr('data-id')
It is telling you exactly what the problem is. .data and .attr are jQuery functions. If your want to get an attribute value using a javascript object do the following, after giving an id to your element:
console.log(document.getElementById("a").getAttribute("data-id"));
jsFiddle: http://jsfiddle.net/hescano/pFdEj/
Something else is wrong in your page, then. The following does work:
$(this).data("id")
http://jsfiddle.net/RQw8E/
How are you using $(this)?
Works for me:
HTML
Click
JavaScript
$(".videoimage").click(function() {
var dataID = $(this).data("id");
var dataIDAttr = $(this).attr("data-id");
console.log(dataID);
console.log(dataIDAttr);
});
JSFiddle
Are you sure you attached some sort of event to the function that calls these statements?
You could also use vanilla JS
var anchorArr = document.getElementsByTagName("a");
for (var i = 0; i < anchorArr.length; i++) {
if(anchorArr[i].getAttribute("class")==="videoimage") {
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//quick and dirty, there are better ways to do this
console.log(anchorArr[i].getAttribute("data-id"));
}
}
jsFiddle

jQuery syntax not setting object property

My jQuery question I beleive is pretty simple, which is driving me insane that I can't get it.
I have an object with a property "content", I want to be able to take that object, manipulate the property "content" with jQuery and then overwrite the value with the new value jQuery creates.
Example:
o.content = "<div><span>hello</span></div>";
$('div', o.content).addClass('test');
At this point I want o.content to be equal to <div class='test'><span>hello</span></div>
I can not for the life of me figure out the syntax. Any help is really appreciated.
This will give you a string <div class="test"><span>hello</span></div> if this is what you want:
$(o.content).addClass('test').wrap('<div>').parent().html();
Parse the html in o.content, add the class, append the parsed html to a new <div>, and get the html of the new div:
o.content = "<div><span>hello</span></div>";
var el = $(o.content).addClass('test');
o.content = $("<div>").append(el).html();
Edit: This assumes you want o.content to still contain a string, rather than a jQuery object. In that case, it's simpler:
o.content = $(o.content).addClass('test');
from the docs of the jquery function, context must be
A DOM Element, Document, or jQuery to use as context
Your context (o.content) is a string. Also, the jQuery function is not able to select the entire context, it can only select elements in that context.
Try this instead:
// make o.content a jquery element, not a string
o.content = $("<div><span>hello</span></div>");
// select on something inside the context (inside the div), not the div itself
$('span', o.content).addClass('test');
http://jsfiddle.net/JfW4Q/
I don't think you can lookup an element from a string like that.. I would rather do it like below,
var content = "<span>hello</span>";
content = $('<div/>', {class: 'test'}).html(content)
DEMO: http://jsfiddle.net/k4e5z/
You want the following
o.content = "<div><span>hello</span></div>";
// Create a jQuery object you can call addClass on
var docFragment = $(o.content);
docFragment.addClass('test');
// Since there's no outerHTML in jQuery, append it to another node
var wrapper = $('div');
docFragment.appendTo(wrapper);
// The HTML of the wrapper is the outerHTML of docFragment
console.log(wrapper.html()); // outputs <div class='test'><span>hello</span></div>
Why not do it all in one line:
var o = {};
o.content = $( "<div></div>" ) // create element
.addClass('test') // add class
.html( '<span>hello</span>' ); // append content
Fiddle: http://jsfiddle.net/kboucher/eQmar/
o.content = $("<div><span>hello</span></div>");
o.content.addClass('test');
o.content is a jQuery object in this example, as opposed to just a string. Here's a demo on jsfiddle: http://jsfiddle.net/cvbsm/1/

select html element id using jquery and .change()

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

Adding span to numbers using Jquery

So I have been dabbling around in jQuery a bit this week. Trying to add some cool things to a wordpress theme I am currently working on.
With the help of this wonderful site, I received the following JS to wrap a span around numbers in a certain div. All was well until I started implementing more JS to find out this is actually causing my other JS to break.
//add span to numbers
var elem = document.getElementById('passage');
elem.innerHTML = elem.innerHTML.replace(/\b(\d+)\b/g, '<span>$1</span>');
However, I was informed since I am using jQuery, to take "document.getElementById" out and end up with this:
//add span to numbers
var elem = $( 'passage' );
elem.innerHTML = elem.innerHTML.replace( /\b(\d+)\b/g, '<span>$1</span>' );
I figured this would solve the situation with no luck. Any ideas of why this isn't working? Thanks
My end result is to be able to style numbers like this site does for their Bible verses: http://marshill.com/media/the-seven/lukewarm-in-laodicea-comfort-and-convenience-before-christ#scripture
If you're selecting by the id you need the CSS-alike id selector:
var elem = $('#passage');,
To select by class:
var elems = $('.className');
Using the $('#passage') selector, you end up with a jQuery object, rather than a DOM-node, so $('#passage').innerHTML (or elem.innerHTML) returns an error: Uncaught TypeError: Cannot call method 'replace' of undefined in Chromium 19.
To work around that, you can 'drop' back to a DOM-node with:
elem.innerHTML = $('#passage')[0].innerHTML.replace(/*...*/);
Or instead use jQuery:
elem.html(function(i,oldHTML){
return oldHTML.replace( /\b(\d+)\b/g, '<span>$1</span>' );
});​
JS Fiddle demo.
References:
jQuery selectors.
html().
For the first line, when working with ids, you want to prepend the string with a pound symbol; that is, $('#passage').
For the second line, note that doing $('#passage') returns a jQuery object, so you can't use standard methods on it. You should be using jQuery methods. The equivalent for innerHTML is .html().
So you would want to do the following:
//add span to numbers
var elem = $( '#passage' );
elem.html(elem.html().replace( /\b(\d+)\b/g, '<span>$1</span>' ));
A little ugly, but it gets the job done. David's answer is slightly more eloquent.

jQuery .wrap() question

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.

Categories

Resources