In this case:
var count = $(count_el).data("count");
$(target).html("hello"+count);
Does it mean that only if we can change the data('count') in the url can we use this dom xss?
like <script>codes</script> etc.
jQuery.data stores the information on the element or object itself (if it is an element it first pulls the data from the data-* tags).
$el = $("<div data-count='1'></div>")
$el.data('count') // 1
$el.data() // {"count":1}
If, however, you are worried about XSS and somehow malicious HTML is embedded in your data tags, you could use .text() instead of .html().
$parent = $("<div></div>");
$child = $("<div data-count='<script>alert(\"malicious code\");</script>'></div>");
count = $child.data('count')
$parent.html(count) // this will run the embedded script
$parent.text(count) // this will not
Related
var strHTML = "<div><img src='/fake/path/fakeImage.jpg'/><span id='target'>text to extract</span></div>";
var dom = $(strHTML);
var extractedText = dom.find("#target").text();
alert(extractedText);
When I convert the HTML string to a jQuery object, jQuery makes GET request to retrieve pictures as you can see in the network tab in the developer tools.
JsFiddle
How can I convert a HTML string to jQuery object without downloading any resources from the parsed string ?
Note : jQuery.parseHTML does not return a jQuery object, you cannot use .find() for example.
I don't think this is possible, since its not jQuery (or javascript) that does the image loading but the browser - as soon as a src attribute is set on an img element the browser will attempt to download it.
One thing you can do is change the element name from img to something else before building the dom, or change the src attribute to something else, for example:
// change the <img> elements to <my_img> to avoid image fetching
strHtml = strHtml.replace(/<img /gi, "<my_img ").replace(/<\/img>/gi, "</my_img>");
// or the 2nd alternative: change the src attribute of images
strHtml = strHtml.replace(/<img([^>]*?) src=/gi, "<img$1 my_src=")
// now its safe to parse into DOM - no images will be fetched
var dom = $(strHtml);
note this simple "search and replace" may replace texts other than the elements you want, but it may be sufficient for your use case.
You can feed it through $.parseXML first:
var strHTML = "<div><img src='/fake/path/fakeImage.jpg'/><span id='target'>text to extract</span></div>";
var dom = $($.parseXML(strHTML));
var extractedText = dom.find("#target").text();
alert(extractedText);
I created a constructor that will handle a custom list control. I created a method in order to allow the user to add elements to the list, and I need to assign event handlers to the click events of the list elements (divs).
A simplified version of the code is here. The list elements are created using the innerHTML property and a string template upon which I substitute specific parts. Later I get the element by it's id and assign it a function in closure:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
var tmp = plantilla.replace('«id»', id);
tmp = tmp.replace('«texto»', texto);
document.body.innerHTML += tmp;
document.getElementById(id).onclick = f(id);
};
};
The problem is that, apparently, the event handler is unasigned to previous created divs, so is only retained by the last one, as it can be tested with the following code:
var p = new prueba;
p.agregar('i1', 'texto1');
console.log(document.getElementById('i1').onclick.toString());//shows the function code
p.agregar('i2', 'texto2');
console.log(document.getElementById('i2').onclick.toString());//shows the function code
console.log(document.getElementById('i1').onclick.toString());//returns 'null' error
p.agregar('i3', 'texto3');
console.log(document.getElementById('i3').onclick.toString());//shows the function code
console.log(document.getElementById('i2').onclick.toString());//returns 'null' error
This happens in Iceweasel as well as in Chromium. It does NOT happen when I add 'onclick = f(«id»)' in the template (which I cannot do here because of the assigned function scope), and neither happens if I use document.createElement. What am I doing wrong?
You destroy elements previously created when you do this:
document.body.innerHTML += tmp;
Instead use insertAdjacentHMTL() if you want to append using HTML markup.
document.body.insertAdjacentHTML("beforeend", tmp);
Now instead of going through this destructive process...
serialize the existing DOM nodes to HTML
concatenate the new HTML fragment to the serialized nodes
destroy the old nodes
recreate the nodes with the new nodes
...it simply creates the new content and places it before the close of the body element.
Basically, remove element.innerHTML += ... from your coding practices. It's never necessary, it's inefficient and it causes problems like what you've described.
FYI, the .insertAdjacentHTML() method receives 4 different string possibilities as the first argument. Each one designates a position relative to the element on which you're calling it.
The strings are...
"beforebegin"
"afterbegin"
"beforeend"
"afterend"
The labels are pretty self-explanatory. They position the new content before the current element, inside the current element at the beginning, inside the current element at the end, or after the current element, respectively.
Your full code will look like this, which I shortened a bit too since the tmp really isn't needed here:
function prueba(){
var plantilla = '<div id="«id»">«texto»</div>';
var f = function(nombre){
return function(){console.log('mi nombre es ' + nombre)};
};
this.agregar = function(id, texto){
document.body.insertAdjacentHTML("beforeend",
plantilla.replace('«id»', id)
.replace('«texto»', texto));
document.getElementById(id).onclick = f(id);
};
};
I am using this code below
var delLink = $('#deleteItem').attr('href');
to get the URL (href) of a link identified by #deleteItem.
The problem occurs when I use JQuery to add new variables onto this URL and I want to see the new dynamically added variables also displayed by the above code.
How can this be done, now it only displays the orginal URL without any of the new variables.
Thanks
delLink contains the result of your query. It is not a reference to href.
// Assigns the value of href to delLink
var delLink = $('#deleteItem').attr('href');
// Changes the href value on the DOM element
$('#deleteItem').attr('href',delLink+','+allVals);
delLink does not know about the update, to update delLink you again need to execute:
delLink = $('#deleteItem').attr('href');
What you could to make it a little easier for you is cache the jQuery object reference to the anchor element in the DOM and simply keep accessing the href attribute from it:
// Create a jQuery object reference to the anchor element in the DOM
var $delLink = $('#deleteItem');
// Changes the href value in on DOM element
var currentHref = $delLink.attr('href');
$('#deleteItem').attr('href', currentHref + ',' + allVals);
// Results are available through your reference
$delLink.attr('href');
I tried to use the method data (jQuery 1.7.1) in this code:
var q = '<div class="form-error-marker"></div>';
var t = $(q).data('message', message).insertAfter(el);
and it does not work.
Note that this works:
var t = $(q).attr('data-message', message).insertAfter(el);
Why does the first variant not work?
EDIT: insertAfter works correctly and new div is added after el (which is instance of one element which I get by getElementById() function; long story short I have a library that I extend).
When I say 'it does not work' I mean that the attribute 'data-message' is not stored.
Using data like that sets an arbitrary piece of data for this node; it doesn't add a new data- attribute. Just add the attribute with the attr function, and then access it with data
var q = $('<div class="form-error-marker"></div>').attr("data-message", message);
Now access it like this:
var message = q.data("message");
Here's a fiddle
When you use jQuery.data you don't change element attributes, instead your data saved in $.cache.
So if you want to change element attributes use jQuery.attr, when you want to save some info use jQuery.data
I am trying to add to all <object>'s on a page a snippet of html. I understand I can access elements by tag name and that I can change the element, but can I simple append to it instead?
In addition, I want to add it to the contents of each tag, not the end of the document. Which of these methods will work?
Assuming no library...
var elementToAppend = document.createElement(tagName); // Your tag name here
// Set attributes and properties on elementToAppend here with
// elementToAppend.attribute = value (eg elementToAppend.id = "some_id")
// You can then append child text and elements with DOM methods
// (createElement or createTextNode with appendChild)
// or with innerHTML (elementToAppend.innerHTML = "some html string")
var objects = document.getElementsByTagName('object');
for(var i = 0; i < objects.length; i++) {
elementToAppend = elementToAppend.cloneNode(true);
objects[i].appendChild(elementToAppend);
}
Using innerHTML or outerHTML as other answers have suggested will likely cause problems for whatever you've embedded with <object>.
appendChild is what you're looking for.