I have this function:
var save = document.getElementById('savethis'+this.parentNode.childNodes[1].id);
save.addEventListener('click', savethis.bind(this), false);
function savethis() {
this.removeEventListener('click', edit);
var a = this.childNodes[0].childNodes[0].id;
console.log(a);
var b = document.getElementById(a);
console.log(document.getElementById(a).id.replace('minedit',''));
console.log(b.value);
this.innerHTML = b.value;
this.parentNode.cells[4].className = 'text-center min-edit';
setTimeout(function() {this.addEventListener('click',edit);},1);
}
In another function:
var minedit = document.getElementsByClassName('min-edit');
for (var m=0;m<minedit.length;m++){
minedit[m].addEventListener('click', edit);
}
function edit(){
var avalue = this.innerHTML;
console.log(avalue);
if (this.className.indexOf('input-open')>=0){
}
else {
this.className += ' input-open';
var content = '';
content += '<div class="input-group editable-input"><input type="text" id="minedit'+this.parentNode.childNodes[1].id+'" value="'+parseFloat(avalue).toFixed(2)+'" class="form-control"><span class="input-group-addon editable-input" id="savethis'+this.parentNode.childNodes[1].id+'"><i class="ion-android-done" ></i></span><span class="input-group-addon editable-input"><i class="ion-android-close" id="close"></i></span></span></div>';
this.innerHTML = content;
valuenow = document.getElementById('minedit'+this.parentNode.childNodes[1].id).value;
id = document.getElementById('minedit'+this.parentNode.childNodes[1].id).id;
var save = document.getElementById('savethis'+this.parentNode.childNodes[1].id);
save.addEventListener('click', savethis.bind(this), false);
}
}
function savethis() {
this.removeEventListener('click', edit);
var a = this.childNodes[0].childNodes[0].id;
var b = document.getElementById(a);
this.innerHTML = b.value;
this.parentNode.cells[4].className = 'text-center min-edit';
setTimeout(function() {this.addEventListener('click',edit);},1);
}
As you can see in the fiddle, the opening and closing of the input box works on the first click, but on the second click I get an error saying
TypeError: this.className is undefined
pointing to this line:
if (this.className.indexOf('input-open')>=0){
I totally don't get why className could possibly be undefined, as I define it's name within the savethis function.
Can someone explain and help?
scope is wrong
setTimeout(function() {this.addEventListener('click',edit);},1);
this is the document when this runs, not the element.
var that = this;
setTimeout(function() {that.addEventListener('click',edit);},1);
or use bind() with modern browsers
setTimeout( (function() {this.addEventListener('click',edit);}).bind(this),1);
Related
Can anyone please give me an idea on how to view the actual image resource on a div tag:
This is the complete script:
var smileys = [];
smileys[":)"] = "happy.png";
smileys[":D"] = "laugh.png";
smileys[":3"] = "meow.png";
smileys[":{"] = "must.png";
smileys[":V"] = "pac.png";
smileys[":("] = "sad.png";
smileys[":O"] = "surprised.png";
smileys[":?"] = "wat.png";
function RegExpEscape(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function replaceEmoticons(str) {
for (var key in smileys) {
var re = new RegExp("(?:^|\\s)" + RegExpEscape(key) + "(?=$|\\s)", 'g');
var str2 = "<img src='images/smileys/" + smileys[key] + "'/>";
//alert(re);
//alert(str2);
var inputName = document.getElementById("input");
alert(inputName);
str = str.html().replace(re, str2);
}
return (str);
}
var delay = (function() {
var timer = 0;
return function(callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
update();
function update() {
$('#result').text(replaceEmoticons($('#input').val()));
}
$('#input').keyup(function() {
delay(update, 250);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Input :</h4>
<textarea id="input">
Hello how are you all doing today? :)
</textarea>
<hr>
<h4>Result :</h4>
<div id="result">
</div>
When I inspect element no error was found on the console!
Kindly Assist!
Note that the javascript code is executing before the DOM is loaded. When you load page, after loading the code is executing and #input doesn't exist yet. Put it in a $(document).ready, or in a onload event.
$(document).ready(function() {
//your stuff
});
EDIT
See that fiddle: https://jsfiddle.net/aoaugpaf/
In this function:
function replaceEmoticons(str) {
for (var key in smileys) {
var re = new RegExp("(?:^|\\s)" + RegExpEscape(key) + "(?=$|\\s)", 'g');
var str2 = "<img src='images/smileys/" + smileys[key] + "'/>";
//alert(re);
//alert(str2);
var inputName = document.getElementById("input");
alert(inputName);
str = str.html().replace(re, str2);
}
return (str);
}
str doesn't have an html() method since it's the value of an input as you wrote here:
$('#result').text(replaceEmoticons($('#input').val()));
Simply remove the html() method and everything will work.
Here's a fiddle I've made for you.
Because $().val() returns String and string has no method .html()
Edit function replaceEmoticons:
str = str.replace(re, str2);
It works: http://jsfiddle.net/au419fkh/
I am extremely new to javascript and so I apologize in advance for any problems with the way I am asking my quesion. I am trying to post data and have a warning pop up if all fields are not filled out. And one of the fields is a radio type. Here is a link to a jsfiddle with my script http://jsfiddle.net/J2yWQ/64/
Here is what I have at the moment
function emailWarning() {
var check = document.getElementById("check");
check.className = 'show';
}
function validateEmail(xem) {
var re = /\S+#\S+\.\S+/;
return re.test(xem);
}
function postData() {
email = 'email'+document.getElementById('email').value;
var tt = validateEmail(email);
if (tt == true) {
xmlhttp.open('POST', 'payment.php', true);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send(myProps.join("&"));
} else {
emailWarning();
}
}
function insert() {
try {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
var myProps = [];
function addProp(id) {
var value = encodeURIComponent(document.getElementById(id).value);
myProps.push(id + "=" + value);
}
addProp('child_name');
addProp('age');
addProp('hometown');
addProp('boy_girl');
addProp('first_name');
addProp('last_name');
addProp('email');
addProp('address1');
addProp('address2');
addProp('city');
addProp('state');
addProp('zip');
addProp('country');
var flagInvalid = false;
var tempArray = document.getElementsByClassName("required");
for (var i = 0; i < tempArray.length; i++) {
if (tempArray[i].value == "") {
flagInvalid = true;
break;
}
}
if (flagInvalid == false) {
postData();
} else {
var log = document.getElementById("log");
log.className = 'show';
var log1 = document.getElementById("log1");
log1.className = 'show';
var log2 = document.getElementById("log2");
log2.className = 'show';
var log3 = document.getElementById("log3");
log3.className = 'show';
var log4 = document.getElementById("log4");
log4.className = 'show';
var log5 = document.getElementById("log5");
log5.className = 'show';
var log6 = document.getElementById("log6");
log6.className = 'show';
var log7 = document.getElementById("log7");
log7.className = 'show';
var log8 = document.getElementById("log8");
log8.className = 'show';
var log9 = document.getElementById("log9");
log9.className = 'show';
var log0 = document.getElementById("log0");
log0.className = 'show';
var logA = document.getElementById("logA");
logA.className = 'show';
}
} catch (e) {
alert('An error occured in inert: ' + e);
}
}
The problem is easily catched when addProp body is changed to this:
function addProp(id) {
var el = document.getElementById(id);
if (el) {
myProps.push(id + "=" + encodeURIComponent(el.value));
}
else {
alert('Not found: ' + id);
}
}
Both boy_girl and email IDs are not present in this HTML:
Boy: <input type="radio" name="boy_girl" id="boy_girl_b" value="boy"/>
Girl:<input type="radio" name="boy_girl" id="boy_girl_g" value="girl"/></li>
...
<input type="text" name="email" id="check" maxlength="64" class="required" />
You can fix it with something like this:
function addProp(name) {
var els = document.getElementsByName(name);
if (els.length) {
myProps.push(name + "=" + encodeURIComponent(els[0].value));
}
else {
alert('Not found: ' + name);
}
}
But in fact, it's only the beginning of the story. myProps are local to insert function yet referenced in postData function; you show validation error signs for all the fields no matter what fields were actually filled... Besides, your code is a bit WET - for example, all these
var log = document.getElementById("log");
log.className = 'show';
var log1 = document.getElementById("log1");
log.className = 'show';
...
... can be easily transformed into this:
var showValidationError = function(id) {
var el = document.getElementById(id);
if (el) {
el.className = 'show';
}
else {
alert('Missing element #' + id);
}
}
...
showValidationError('log');
for (var i = 1; i < 10; i++) {
showValidationError('log' + i);
}
I do understand that you're quite fresh with JS; but it's not about freshness, it's about organizing your code.
I am betting one of the addProp lines is not correct.
Debug this, see what is the last id before the error is thrown.
function addProp(id) {
console.log(id);
var value = encodeURIComponent(document.getElementById(id).value);
myProps.push(id + "=" + value);
}
And when you do that, you will find out that the line
addProp('boy_girl');
will fail since there is no id
<span id="log4" class="hidden" style="color:red"><b>*</b></span>
Boy: <input type="radio" name="boy_girl" id="boy_girl_b" value="boy"/>
Girl:<input type="radio" name="boy_girl" id="boy_girl_g" value="girl"/></li>
So let us change the function to check for id, and than check for the name if the id does not exist.
function addProp(id) {
var input = document.getElementById(id);
if (!input) {
input = document.forms[0][id];
}
var value = encodeURIComponent(input.value);
myProps.push(id + "=" + value);
}
Change it so myProps is outside of the function.
var myProps = []; //<--- Added this line
function insert() {
try {
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
myProps = []; //<---- Changed this line
function addProp(id) {
var input = document.getElementById(id);
if(!input) {
input = document.forms[0][id];
}
console.log(input);
var value = encodeURIComponent(input.value);
myProps.push(id + "=" + value);
}
addProp('child_name');
if you get such error:
always check all your document.getElementById if they don't return null
var node = document.getElementById('someid');
if(node){
do something;
}
but mark that
var node = document.getElementById('someid').value;
or
var node = document.getElementById('someid');
if(node.value){
do something;
}
can still throw the error "can't read property of null", as you don't check if node really exists
Make sure that you're designed IDs are existing on the page!
For example boy_girl does not exist! Only boy_girl_band boy_girl_g
The same applies for the mail. This one has the id check instead of mail.
Use Opera dragonfly or anything alike for basic troubleshooting
function B(sName) {
this.name = sName;
}
B.prototype = {
instanceCreatButtonCount: 0,
funA: function () { // alert instance's name
alert(this.name);
},
funB: function () { // create a button which clikced can alert this instance's name through funA;
var that = this;
B.prototype.instanceCreatButtonCount++;
var id = "_id" + that.instanceCreatButtonCount;
var str = "<button id='" + id + "' >clike me</button>";
var a = document.getElementById("btns");
a.innerHTML += str;
var btn = document.getElementById(id);
btn.onclick = function () {
that.funA();
};
}
};
var b1 = new B("Jim");
var divB1 = document.getElementById("b1");
divB1.onclick = function () {
b1.funB();
}
var b2 = new B("Dad");
var divB2 = document.getElementById("b2");
divB2.onclick = function () {
b2.funB();
}
After I click divB1, I create a button through b1.funB().
After I click divB2, I create a button througb b2.funB().
Why can only newest button alert name ? I find that other button's onclick function is null.
When you use a.innerHTML += str to append a new element, the entire subtree of a gets removed before the new elements are added again; the removal also unbinds any events you have added before.
It's better to use proper DOM functions in this case, i.e. var btn = document.createElement(), etc. and a.appendChild(btn).
Fiddle provided by #ShadowWizard: http://jsfiddle.net/qR6e8/
I added onkeyup javascript for a dynamically added textbox in javascript... But it doesnt seem to work....
var cell4 = row.insertCell(3);
cell4.setAttribute('align','center')
var e3 = document.createElement('input');
e3.type = 'text';
e3.name = 'txtqt' + iteration;
e3.id = 'txtqt' + iteration;
e3.onkeyup = totalAmount(event,this,'tblsample');//Adding this lines doesnt work
e3.size = 10;
cell4.appendChild(e3);
But when i used
e3.onkeyup = totalAmount;
It worked... Here is my javascript function,
function totalAmount(e,obj,tblid)
{
var tbl = document.getElementById(tblid);
//alert(tbl);
var tblRows = tbl.rows.length;
//alert(tblRows);
var result =0;
var str1;
if (obj != null) {
str1 = obj.id;
} else {
str1 = this.id;
}
var lastChar = str1.substring(5,str1.length);
//alert(lastChar);
if(str1=='txtqt'+lastChar)
{
var str2 = 'txtup'+lastChar;
var str3 = 'txtAmount'+lastChar;
var txtDeduct = document.getElementById(str1).value;
var txtAmt = document.getElementById(str2).value;
var txtTotal = document.getElementById(str3);
var totRes = txtAmt*txtDeduct;
//var res = formatNumber(totRes,2)
txtTotal.value = totRes.toFixed(2)
document.getElementById('txttotAmount').value = totRes.toFixed(2);
for(i=1;i<=tblRows;i++)
{
//alert(tblRows);
txtTotID = 'txtAmount'+i;
if(document.getElementById(txtTotID).value!='')
{
result =parseFloat(result) + parseFloat(document.getElementById(txtTotID).value);
//var res= formatNumber(result,2)
document.getElementById('txtTotalAmount').value = result.toFixed(2);
document.getElementById('txttotAmount').value = result.toFixed(2);
//document.getElementById('txtTotalAmount').value = result;
}
}
}
}
You need to wrap your function call in an anonymous function:
e3.onkeyup = function(event){ totalAmount(event,this,'tblsample'); }
But an even better way to do it, to allow for cross browser compatibility would be to use an addEvent function:
function addEvent(obj,type,fn){
if (obj.addEventListener){
obj.addEventListener(type,fn,false);
} else if(obj.attachEvent){
obj["e"+type+fn]=fn;
obj[type+fn]=function(){
obj["e"+type+fn](window.event);
};
obj.attachEvent("on"+type,obj[type+fn]);
};
};
And then add the event using that function:
addEvent(e3,'keyup',function(event){ totalAmount(event,this,'tblsample'); });
Just a much better way to handle events. I would recommend you switch to this method.
onkeyup is a function. If you pass it the return value of totalAmount(event,this,'tblsample'); it won't work (unless it returns a function).
e3.onkeyup = totalAmount; is probably enough.
then inside totalAmount..
function totalAmount(event) {
alert(this); // this is the e3 object
}
So if you need the this and the 'tblsample' arguments, I suggest you add them to the e3 object so that you can access them through the this keyword inside the totalAmount function:
e3.otherScope = this;
e3.tblid = 'tblsample;
e3.onkeyup = totalAmount;
and..
function totalAmount(event) {
alert(this); // this is the e3 object
alert(this.otherScope); // the `this` object in the other scope
alert(this.tblid); // 'tblsample'
}
Or you can simply just do
var otherScope = this;
e3.onkeyup = function(event) {
totalAmount(event, otherSope, 'tblsample');
};
What I have is a single textbox. If the user hits the maxlength of it, I want to create a new textbox and then change focus to it so they can continue typing.
To accomplish this, I am trying to dynamically create textboxes that have an onkeyup event tied to them. To do this I am using document.createElement and the creation of the element works. The problem is that I can't get the parameters (the id of the current textbox and the id of the one to be created) to pass correctly and they are simply variables. Before I pass them I can test them and they are fine, but in the method they are null.
Here is my code:
<script type="text/javascript">
var i = 2;
function CreateTextbox() {
var box = document.getElementById(divCreateTextbox);
var curr = 'txt' + i;
var next = 'txt' + (i + 1);
var inp = document.createElement('input')
inp.type = 'text';
inp.name = 'textfield';
inp.maxlength = '10';
inp.id = curr;
inp.setAttribute('onkeyup', 'moveOnMax(inp.id, next)');
inp.onkeyup = function() { moveOnMax(inp.id, next); };
box.appendChild(inp);
box.innerHTML += "<br />";
i++;
return next;
}
function moveOnMax(field, nextFieldID) {
if (field.value.length >= field.maxLength) {
if (document.getElementById(nextFieldID) == null) {
var id = CreateTextbox();
if (document.getElementById(id) != null) {
document.getElementById(id).focus();
}
else
alert("problem...");
}
}
}
</script>
<div id="divCreateTextbox">
I am pretty new to Javascript, so if this is completely fubar'd, I apologize.
Any help is appreciated.
<script type="text/javascript">
getId = function(){
var id = 1;
return function(){
id++;
}
}();
function CreateTextbox() {
var box = document.getElementById("divCreateTextbox");
var curr = 'txt' + getId();
var inp = document.createElement('input');
inp.type = 'text';
inp.name = 'textfield';
inp.setAttribute("maxlength",'10');
inp.setAttribute("id",curr);
box.appendChild(inp);
inp.setAttribute('onkeyup','moveOnMax(this)');
box.appendChild(document.createElement("br"));
inp.focus();
}
function moveOnMax(s){
if(s.value.length >= parseInt(s.getAttribute("maxlength"))-1){
s.blur();
CreateTextbox();
}
}
</script>
<div id="divCreateTextbox"></div>
<script>
window.onload = function(){
CreateTextbox()
}
</script>
</html>
The problem you have is related to the scope of inp. When you use the var keyword you scoped it to that block.
Try this code:
inp.onkeyup = function() {
var local_inp_id = inp.id;
var local_next = next;
return function(){
moveOnMax(inp_id, next);
}
}();