Is there a way to make jQuery output *actual markup*? - javascript

When using jQuery to dynamically build markup, it sometimes becomes useful to have it return the actual HTML that it's generating as a string, rather than as a bunch of jQuery objects. Is there a way to do this? For example, here:
$("<strong></strong>").text("Hi there!");
I want to be able to extract the plain-text string
"<strong>Hi there!</strong>"
so that I can cache it remotely. Is there a way to do this?

Yes, you can use the html() function
i.e.
$("").text("Hi There!").html();
Will return 'Hi There!'
Keep in mind this uses innerHTML, so
$("<div><b>Foo</b></div>").html();
will return
<b>Foo</b>
As a result you'll need to wrap your code in a surrounding div or span.

You can use a outerHTML plugin for that. Here is one:
jQuery.fn.outerHTML = function(s) {
return (s)
? this.before(s).remove()
: jQuery("<p>").append(this.eq(0).clone()).html();
}
Usage:
alert($("<strong></strong>").text("foo").outerHTML());
// alerts <strong>foo</strong>

Just call .html() to get HTML from any element, including generated ones. This is from a Chrome developer tool session:
> $("<div><span>blerg</span></div>")
Object
> $("<div><span>blerg</span></div>").html()
<span>blerg</span>
You can see, the first one returned an object, the second returns text.

Related

Why is innerHTML returning 'undefined'?

I'm trying to catch the "value" inside this div, which is editable:
<div class="editable-div" contentEditable="true">Hey</div>
I figured I could do this simply via JavaScript:
var changedText = $('.editable-div').innerHtml
However, this variable will always return "undefined", which confuses me.
Can someone enlighten me on how to reach this "value"?
It is jQuery - you have to use:
$('.editable-div').html()
A jQuery wrapped object is actually not the raw DOM node, but essentially an array of raw DOM nodes that can be acted upon with jQuery specific methods, such as .html(). If you want to interact with the DOM node, you can retrieve it by either iterating through the list or getting the element of that list if you know which one it is:
$('div').each(function(index, element) {
element.innerHTML // ...
}
$('div').get(0).innerHTML
$('div')[0].innerHTML
Note that while it is "kind of" like an array, in that you can get DOM nodes using the array syntax of $('div')[0], you can't treat it like an array in Javascript. In other words, you can't do this:
$('div').forEach(function(element) {
element.innerHTML
}
innerHtml is used with javascript selector and you are using jQuery. so replace innerHtml with .html() or .text() function.
Use this:
var changedText = $('.editable-div').html();
innerHtml is DOM. try $('.editable-div')[0].innerHtml

Is there a direct way of appending text to a DOM element with jQuery?

Is there a more direct way of writing the following in jQuery?
var $b = $('b');
$b.text($b.text() + ', World!!');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<b>Hello</b>
This seams like something jQuery would have existing functionality for, as vanilla JavaScript can do it by direct access to the property.
document.querySelector('b').innerText += ', World!!';
I looked into the .append() method, however it appears that it isn't designed for appending text, even though it works:
$('b').append(', World!!');
Also the Additional Notes section warns of XSS vulnerabilities when using .append(), as it can potentially execute code.
No. As you have already pointed out, the cleanest way is by modifying the property directly.
To do that in jQuery you can get the DOM element reference from within the object:
var $b = $('b');
$b[0].innerText += ', World!!';
JSFiddle
Or,
You could pass a function to .text(), which isn't any 'cleaner' but can be very helpful if you want to use the context:
var $b = $('b');
$b.text(function(_,v){
return v += ', World!!';
});
JSFiddle
Or,
If it really bugs you, introduce your own jQuery method:
jQuery.fn.appendText = function(a){
return this.each(function(){
$(this).text(function(_,v){
return v += a;
});
});
};
For use like so:
$b.appendText(', World!!');
JSFiddle
'This seams like something jQuery would have existing functionality for, as vanilla JavaScript can do it by direct access to the property.'
Is probably exactly why jQuery doesn't implement its own method to do so. Why waste valuable bytes with a method that will carry out something that is so easily done with vanilla JavaScript?
use text()
$('b').text("Hello");
We need to be aware that this method escapes the string provided as
necessary so that it will render correctly in HTML. To do so, it calls
the DOM method .createTextNode(), which replaces special characters
with their HTML entity equivalents (such as < for <)
When you use .text() jQuery uses createTextNode internally, which escapes all special characters.

jQuery object html() doesn't work ... but innerHtml does

I have an object that should be a valid jQuery object. When I look at the variable in FireBug it contains all the jQuery functions I'd expect (clone, remove, removeat, etc.). However, I don't see html() as a valid function and when I do this:
stringValue = myjQueryObject.html();
It does fail, saying html() is not a function. However if I do something like this:
stringValue = myjQueryObject[0].innerHTML;
It will correctly pass back the object, minus the parent div and text (which I would expect, seeing as how it is just getting the innerHtml). What do am I missing here?
As noted below, it was an external library that was generating myjQueryObject that had previously returning a valid jQuery object and was updated ... incorrectly. For posterity's sake, I've updated my unit tests to verify that the external library returns a correct jQuery object, make sure this doesn't return null or undefined:
myjQueryObject.jquery
Thanks all! Had a bit of a freakout when my code suddenly broke this morning.
Either something is modifying the jQuery object prototype, or you have a different library loaded.
Take your object, and test for the jQuery version like this:
alert( myjQueryObject.jquery ); // should give the jQuery version number
EDIT:
Additionally, you state that there's a removeAt method. jQuery doesn't have one of those, unless you mean removeAttr().
Are you sure it's a jquery object? Wrap it in $() again and .html() should exist.
it's [0].innerHTML or .get(0).innerHTML, in that innerHTML is a property not a method.
You should make sure that jquery exists by doing alert( jQuery == $) and you can check for the .jquery property.
That's odd; try $(myjQueryObject).html();. If that works, the object isn't really a jQuery node.
If you still can't figure out why the object lost the html() method, post the code which creates it. Then, we might be able to help.
How are you setting myjQueryObject?
<div id='myElement'></div>
//Good Javascript, Incorrect jQuery
myjQueryObject = document.getElementById('myElement');
myjQueryObject.innerHTML = '<b>My HTML Here</b>';
//Correct jQuery
myjQueryObject = $('#myElement');
myjQueryObject.html('<b>My HTML Here</b>');
//Compact Version of Correct jQuery
$('#myElement').html('<b>My HTML Here</b>');

bookmarklet: inserting text into textarea with js?

What I am doing wrong?
javascript:document.getElementsByTagName('textarea').innerHTML='inserted';
I want to create a bookmarklet to insert simple text to a textarea on a given webpage.
Use the value property rather than innerHTML and make sure your code evaluates to undefined, which you can do by wrapping it in a function with no return statement. If you don't do this, the contents of the page will be replaced with whatever your code evaluates to (in this case, the string 'inserted').
javascript:(function() {document.getElementsByTagName('textarea')[0].value = 'inserted';})();
Update 14 January 2012
I failed to spot the fact that the original code was treating document.getElementsByTagName('textarea') as a single element rather than the NodeList it is, so I've updated my code with [0]. #streetpc's answer explains this in more detail.
Unlinke getElementById, getElementsByTagName has an sat Elements because it returns an array array-like NodeList of the matching elements. So you'll have to access one of the elements first, let's say the first one for simplicity:
javascript:void((function(){document.getElementsByTagName('textarea')[0].value='inserted'})())
Also, as mentioned by others, value property rather than innerHTML here.
In case anyone wonders how to use the currently focused text field, use the following:
document.activeElement.value = "...";
In jQuery you have to use if this way:
for single element -> $('#element_id').html('your html here')
for all text areas -> $('textarea').val('your html here')
I have to confess that I`m not sure why it works this way but it works. And use rameworks, they will save you time and nerves.

Weird Behaviour in jQuery's html method

Any good reason why $("p").html(0) makes all paragraphs empty as opposed to contain the character '0'?
Instead of assuming I found a bug in jQuery, it's probably a misunderstanding on my part.
jQuery only accepts a string as an argument for the val parameter of the html() method. If you pass a number like you are it will call the html() method override that sets the contents of the element but the value of the argument will end up being null or an empty string.
Try this:
$("p").html((0).toString())
Relevant documentation
I guess that at some point, it checks if (newContent == false), and doesn't continue with adding any content? I tried looking at the source, but got a bit lost...
I also guess that this would not be counted as a bug, since the function calls for a string, and if "0" is passed (as a string), it works as expected.
A workaround would be to do this:
var myNum = 0;
$('p').html('' + myNum);
The code performing the html call was within someone else's plugin and rather than modify it, making upgrading it tedious, I just wrote the following tiny plugin that modifies the html method to do as spoon16 recommended.
(function($) {
var oldHtml = $.fn.html;
$.fn.html = function (content) {
oldHtml.apply(this, [content.toString()]);
}
})(jQuery);
It's a little bit of a hack, but it's working for me and doesn't require me to modify the Plugin I'm using.
I just thought someone else might like to see this.
Try using text() instead html().
I geuss you missed part of how jQuery works,
$('p')
returns all paragraphs and the html( val ) function:
Set the html contents of every matched element. This property is not available on XML documents (although it will work for XHTML documents).
http://docs.jquery.com/Attributes/html#val
So if you just want to set the contents for the first p use
$("P").eq(0).html( 'something' );
or to get the html:
$("P").eq(0).html();
http://docs.jquery.com/Core/eq#position
more on jQuery selectors here:
http://docs.jquery.com/Selectors

Categories

Resources