Issue passing 'this' into Javascript function - javascript

Slightly confused by this problem. I have written this function to replace punctuation in input elements:
function punctuationReplace(element){
var elementToChange = document.getElementById(element);
elementToChange.value = elementToChange.value.replace(/\"/g, '');
elementToChange.value = elementToChange.value.replace(/\'/g, '');
elementToChange.value = elementToChange.value.replace(/&/g, 'and');
elementToChange.value = elementToChange.value.replace(/</g, '');
elementToChange.value = elementToChange.value.replace(/>/g, '');
}
<input type="text" id="IPR_FNM1" name="IPR_FNM1" value="" maxlength="30" size="31" placeholder="Forename 1" onblur="punctuationReplace(this)"/>
When I manually run the function in the browser console with the relevant ID as the argument, it works. And when inside the function I add the line alert(element.id);, I get an alert containing the correct element ID. So I am confused as to why the above punctuationReplace function won't work when I call it using onblur="punctuationReplace(this)".
I'm sure there is a simple solution but no idea what it is.

If you pass in this in that fashion, you already have a reference to the element, so no need to call getElementById.
function punctuationReplace(element){
var elementToChange = element; //document.getElementById(element);
elementToChange.value = elementToChange.value.replace(/\"/g, '');
elementToChange.value = elementToChange.value.replace(/\'/g, '');
elementToChange.value = elementToChange.value.replace(/&/g, 'and');
elementToChange.value = elementToChange.value.replace(/</g, '');
elementToChange.value = elementToChange.value.replace(/>/g, '');
}

Stop using inline event handlers, and the issue solves itself
document.getElementById('IPR_FNM1').addEventListener('blur', punctuationReplace, false);
function punctuationReplace(){
this.value = this.value.replace(/("|'|<|>)/g, '').replace(/&/g, 'and')
}

this is a reference to a DOM element. It is not a string containing an ID.
You are trying to use it as an argument to getElementById but when it is stringified (to "[Object object]") there isn't a matching ID in the document, so you get null.
You already have the element. You don't need to search the DOM for it.
Remove the line var elementToChange = document.getElementById(element); and change the other references to element.

You don't need to create a var just keep using element. Like this:
http://jsfiddle.net/0xuf64zb/1
function punctuationReplace(element){
element.value = element.value.replace(/\"/g, '');
element.value = element.value.replace(/\'/g, '');
element.value = element.value.replace(/&/g, 'and');
element.value = element.value.replace(/</g, '');
element.value = element.value.replace(/>/g, '');
}
And indeed stop using inline calls!

this already have an reference to element you want. You don't need to get it again using getElementById. Just put it straight to your variable:
var elementToChange = element;

Related

object HTMLDivElement to string [duplicate]

Imagine I have the following HTML:
<div><span><b>This is in bold</b></span></div>
I want to get the HTML for the div, including the div itself. Element.innerHTML only returns:
<span>...</span>
Any ideas? Thanks
Use outerHTML:
var el = document.getElementById( 'foo' );
alert( el.outerHTML );
Expanding on jldupont's answer, you could create a wrapping element on the fly:
var target = document.getElementById('myElement');
var wrap = document.createElement('div');
wrap.appendChild(target.cloneNode(true));
alert(wrap.innerHTML);
I am cloning the element to avoid having to remove and reinsert the element in the actual document. This might be expensive if the element you wish to print has a very large tree below it, though.
First, put on element that wraps the div in question, put an id attribute on the element and then use getElementById on it: once you've got the lement, just do 'e.innerHTML` to retrieve the HTML.
<div><span><b>This is in bold</b></span></div>
=>
<div id="wrap"><div><span><b>This is in bold</b></span></div></div>
and then:
var e=document.getElementById("wrap");
var content=e.innerHTML;
Note that outerHTML is not cross-browser compatible.
old question but for newcomers that come around :
document.querySelector('div').outerHTML
You'll want something like this for it to be cross browser.
function OuterHTML(element) {
var container = document.createElement("div");
container.appendChild(element.cloneNode(true));
return container.innerHTML;
}
If you want a lighter footprint, but a longer script, get the elements innerHTML and only create and clone the empty parent-
function getHTML(who,lines){
if(!who || !who.tagName) return '';
var txt, ax, str, el= document.createElement('div');
el.appendChild(who.cloneNode(false));
txt= el.innerHTML;
ax= txt.indexOf('>')+1;
str= txt.substring(0, ax)+who.innerHTML+ txt.substring(ax);
el= null;
return lines? str.replace(/> *</g,'>\n<'): str;
//easier to read if elements are separated
}
var x = $('#container').get(0).outerHTML;
as outerHTML is IE only, use this function:
function getOuterHtml(node) {
var parent = node.parentNode;
var element = document.createElement(parent.tagName);
element.appendChild(node);
var html = element.innerHTML;
parent.appendChild(node);
return html;
}
creates a bogus empty element of the type parent and uses innerHTML on it and then reattaches the element back into the normal dom
define function outerHTML based on support for element.outerHTML:
var temp_container = document.createElement("div"); // empty div not added to DOM
if (temp_container.outerHTML){
var outerHTML = function(el){return el.outerHTML||el.nodeValue} // e.g. textnodes do not have outerHTML
} else { // when .outerHTML is not supported
var outerHTML = function(el){
var clone = el.cloneNode(true);
temp_container.appendChild(clone);
outerhtml = temp_container.innerHTML;
temp_container.removeChild(clone);
return outerhtml;
};
};
var el = document.getElementById('foo');
el.parentNode.innerHTML;

extending Element.prototype, issue with anchor

Consider the following:
JS
Element.prototype.text = function(str) {
this.textContent = str;
return this;
}
let div = document.createElement('div').text('div text'); //Works fine
let a = document.createElement('a').text('anchor text'); //Blows up
document.body.append(div, a);
The function I added to the prototype works fine On div or any other element I tried except the anchor element, and when I print the prototype chain for anchor element I do find the it has Element in it as expected.
Any idea why this does not work with the Anchor element in every browser i tried?
The problem is that:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement#Properties
HTMLAnchorElement.text
Is a DOMString being a synonym for the Node.textContent property.
So, HTMLAnchorElement.prototype.text is shadowing your custom Element.prototype.text.
Another problem is that HTMLAnchorElement.prototype.text is a setter - you cannot simply reassign it, eg
HTMLAnchorElement.prototype.text = function(str){
this.textContent = str
return this
}
because that will invoke the setter, resulting in Illegal Invocation. You'll have to delete the text property on the prototype first, and then assign to HTMLAnchorElement.prototype:
Element.prototype.text = function(str){
this.textContent = str
return this
}
delete HTMLAnchorElement.prototype.text;
HTMLAnchorElement.prototype.text = function(str){
this.textContent = str
return this
}
let div = document.createElement('div').text('div text')
let a = document.createElement('a').text('anchor text')
document.body.append(div,a)
This blows up because anchor tag doesn't have a text property/field, so it fails to set it. Create the element first, then create the text and attach it to the link.
var anchortext = document.createTextNode("your text here");
a.appendChild(anchortext);

jQuery append element if it doesn't exist, otherwise replace

Here's a short piece of code:
var $el = $("#something").find(".test");
if (!$el.length) {
$("#something").append('<div class="test">somecontent</div>');
} else {
$el.replaceWith('<div class="test">somenewcontent</div>');
}
I couldn't find a method appendOrReplaceWith or anything similar.
Any ideas how can I make it shorter?
I believe that:
$("#something").appendOrReplace('<div class="test">sometext</div>');
would be much easier to read, but no such method is available yet.
Just remove it first then append.
$(".test").remove();
$("#something").append('<div class="test">somecontent</div>');
Mandatory vanilla answer. It may not be shorter, but it's faster.
Get the element, grab all subelements with the class "test", create your div, check the subelements length, and if length is truthy, set the innerHTML to the div. Else, append it.
var el = document.getElementById("something");
var subel = el.getElementsByClassName("test");
var div = document.createElement("div");
div.className = "test"
if (subel.length) {
div.textContent = "somenewcontent";
while(el.hasChildNodes()) el.removeChild(el.lastChild); //remove child nodes
el.appendChild(div);
} else {
div.textContent = "somecontent";
el.appendChild(div);
}
Adding a method like findOrAppend to jQuery could be useful:
$.fn.findOrAppend = function(selector, content) {
var elements = this.find(selector);
return elements.length ? elements : $(content).appendTo(this);
}
Then you can chain text, replaceWith, empty etc. as needed:
$("#something")
.findOrAppend(".test", "<div class='test'>")
.text("newcontent");
First of all you should cache your selectors:
var $som = $('#something');
var $ele = $(".test",$som);
var newHtml = '<div class="test">somecontent</div>';
if (!$el[0]) $som.append( newHtml );
else $ele.replaceWith( newHtml );
but you already did it really fine, (beside not caching repeated selectors), and me, trying to make it smaller could be a**-kicked for not using {} for my if and else :)
I would do this
var $s = $("#something"), $t = $s.find(".test"), c = 'New content';
( $t[0] ? $t:$s)[( $t[0] ? 'html':'append')](( $t[0] ? c :$('<div>',{class:'test'}).append(c)));

JavaScript - getElementById not understanding my input

So I have this code:
window.onload = make_buttons ('"calc"');
function make_buttons (id) {
console.log (id);
var input = document.createElement("INPUT");
document.getElementById(id).appendChild(id.input);
for (var i = 0;i < 10; i++){
var btn = document.createElement ("BUTTON");
var t = document.createTextNode (i);
btn.appendChild(t);
document.getElementById(id).appendChild(id.btn);
}
};
Basicly I insert the id of the div element in the make_buttons () function and then it should create everything that I ask it to create for me.
But for some reason this method throws me an error which says that getElementById is given a NULL value. The console.log (id) shows that id is "calc" getElementByID should have "calc" inside of the (). Why is it so?
Also when I have created all thoes buttons, can I just add a .onclick= after the .append.Child() to make it have a on click event also?
1) The console always display quotes for strings, that doesn't mean that your string contains quotes. Your id is calc, not "calc".
2) As noticed by Felix, you're assigning to window.onload the result of the function instead of the function.
Replace
window.onload = make_buttons ('"calc"');
with
window.onload = function(){ make_buttons ('calc'); }
problem is id.input on document.getElementById(id).appendChild(id.input);
You are passing string as id. but appending id.input in parent element which is incorrect.
This might work for you, try using the body on load
<body onload="make_buttons('calc');">
</body>
You haven't assigned the ID to the input you're creating. The input is in the document, but it doesn't have the ID you're passing at the time you're trying to access it.

jQuery, Looping through paragraphs and getting text

So basically with jQuery, I am trying to loop through 3 paragraphs containing tweets. The 3 paragraphs are all of class .tweet-text
For some reason, in the following code, $test2 will be set properly to the first tweet's text, but in the each loop, the js crashes whenver i try to set str. Why is this?
var $tweets = $(".sidebar-tweet .tweet-text");
var $test2 = $tweets.text();
alert($test2);
$tweets.each(function(i, $tweet){
var str = $tweet.text();
alert(str);
});
I've been trying to debug this with Firebug but to no avail. Thanks for the help.
var $tweets = $(".sidebar-tweet .tweet-text");
$tweets.each(function(i, current){
var str = $(current).text();
alert(str);
});
The issue was that the current object is not by defalt a jquery object, you must wrap it $(current) ... to use the jquery methods
try this instead
var str = $(this).text();
Because $tweet will be a regular javascript object, not a jQuery object. You'll need to wrap it like:
var str = $($tweet).text();
The second argument to the .each method is not a jquery object, but the actual DOM element.
So you need to wrap it in jQuery again..
var $tweets = $(".sidebar-tweet .tweet-text");
var $test2 = $tweets.text();
alert($test2);
$tweets.each(function(i, tweet){
var str = $(tweet).text();
alert(str);
});
demo: http://jsfiddle.net/gaby/xjmZy/

Categories

Resources