Good Evening,
I am having trouble with modifying the date value in my test object. The oninput event seems to only fire once when the document is loaded. The oninput event does not seem to fire when the date is changed.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
var TestObj = new function(){
this.date = "2014-01-01";
this.LoadMenu = function() {
var newDateInput = document.createElement('input');
newDateInput.type = "date";
newDateInput.value = this.date;
document.getElementById("container").appendChild(newDateInput);
newDateInput.oninput = this.updateDate(newDateInput.value);
};
this.updateDate = function (newDate){
this.date = newDate;
alert(this.date);
document.getElementById("outputBox").innerHtml = this.date;
};
};
</script>
</head>
<body onload="TestObj.LoadMenu();">
<div id="container">
<div id="outputBox">Test</div>
</div>
Chrome: 34.0.1847.116
This is caused because of the way you are trying to associate the handler function of your event, in your code you have:
newDateInput.oninput = this.updateDate(newDateInput.value);
but what you might want is:
newDateInput.oninput = this.updateDate;
Also, if you want this to work properly you might want to declare the newDateInput in the outer scope (in the scope of the "class").
I think what you want to do is something like this:
var TestObj = new function(){
this.date = "2014-01-01";
var newDateInput;
this.LoadMenu = function() {
newDateInput = document.createElement('input');
newDateInput.type = "date";
newDateInput.value = this.date;
document.getElementById("container").appendChild(newDateInput);
newDateInput.oninput = this.updateDate;
};
this.updateDate = function (event){
this.date = newDateInput.value;
alert(this.date);
document.getElementById("outputBox").innerHTML = this.date + '';
};
};
Please let me know if that works for you.
Related
I have few textarea on which I want to get the default text selected when I tabbing upon it.
For a single textarea I've found a script which I adapted to my situation but is not an elegant solution.
How can I shorten it.
<script type="text/javascript">
var textBox1 = document.getElementById("textarea_1");
var textBox2 = document.getElementById("textarea_2");
var textBox3 = document.getElementById("textarea_3");
textBox1.onfocus = function() {
textBox1.select();
// Work around Chrome's little problem
textBox1.onmouseup = function() {
// Prevent further mouseup intervention
textBox1.onmouseup = null;
return false;
};
};
textBox2.onfocus = function() {
textBox2.select();
textBox2.onmouseup = function() {
textBox2.onmouseup = null;
return false;
};
};
textBox3.onfocus = function() {
textBox3.select();
textBox3.onmouseup = function() {
textBox3.onmouseup = null;
return false;
};
};
</script>
You can add a dedicated class name and refactor the code to be more generic using class name as selector an make it work for multiple textareas like this:
// Add the class 'auto-selectable' to the desired <texarea/> elements
var textBoxes = document.getElementByClassName('auto-selectable');
for(var i = 0; i < textBoxes.length; i++) {
var textBox = textBoxes[i];
textBox.select();
// Work around Chrome's little problem
textBox.onmouseup = function() {
// Prevent further mouseup intervention
textBox.onmouseup = null;
return false;
};
}
a small correction to Plamen's answer: Elements not Element
var textBoxes = document.getElementsByClassName('auto-selectable');
instead of:
var textBoxes = document.getElementByClassName('auto-selectable');
My JavaScript object create some HTML elements (two buttons for example) and after user click on these buttons I should call some method of this object. So the question is how I can refer JS object in HTML element to call its method?
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Title Goes Here</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function myObj(){
this.a = null;
this.setA = function(a){
this.a = a;
}
this.requestA = function(){
$( "body" ).append($('<input><button onclick="referenceToMyObject.setA($(this).prev().val());">Set A</button>'));
}
return this;
}
</script>
</head>
<body>
<script>
var myObjInst = myObj();
myObjInst.requestA();
</script>
</body>
Creating the event handler inline (onclick="foo()") won’t allow you to reference the object, and is discouraged in any case because you should avoid evaluating strings as code. In addition, your code bypasses JavaScript’s idea of objects somewhat. You can reformulate it as follows:
function MyObj() {
this.a = null;
}
MyObj.prototype.setA = function(a) {
const old = this.a;
this.a = a;
console.log("Updated a from", old, "to", this.a);
};
MyObj.prototype.requestA = function() {
const input = $("<input type='text'>");
const button = $("<button>Set A</button>");
button.click((e) => {
this.setA($(e.target).prev().val());
});
const body = $("body");
body.append(input);
body.append(button);
};
$(document).ready(() => {
const myObjInst = new MyObj();
myObjInst.requestA();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Here, we use button.click to define the event handler and new MyObj() to instantiate the object. Apart from that, I cleaned up the code a bit and added a bit of logging so you can see what’s going on.
You could still define setA and requestA within the constructor, as you do in your example. I chose to define them on the prototype since their behaviour is the same across instances.
Try this and please let me know if this works for you.
(working example in JSFiddle https://jsfiddle.net/galeroy/9nocztk4/1/)
<!doctype html>
<html>
<head>
<script>
var myObject = {
createButton: function(){
var p = document.getElementById('par')
var b = document.createElement('button');
b.innerHTML = 'click me';
b.setAttribute('onclick', 'myObject.myMethod()'); // this is the important part
p.appendChild(b);
},
myMethod: function(){
alert("Button created by object, when clicked, calls another method in the same object")
}
}
function init(){
myObject.createButton();
}
</script>
</head>
<body onload="init()">
<p id="par"></p>
</body>
</html>
I don't understand why function alert() fires before setting style to indicator in this code:
JavaScript:
var MyClass = function()
{
th = this;
th.func = function(){alert('yes');};
th.Click = function(){
document.getElementById('indicator').style.color = "#0f0";
document.getElementById('indicator').innerHTML = "YES";
th.func(); // here it fires before above style changing
};
th.Start = function()
{
var a = document.getElementById('button1');
a.addEventListener('click', th.Click, false);
};
th.Init = function()
{
th.Start();
};
}
var a = new MyClass().Init();
Html:
<button id='button1'>Click Me</button>
<div id='indicator' style='color:#f00'>NO</div>
I want it to fire after.
That is because of the Single Threaded Nature of the Javascript. The alert / modal window actually stops everything else from running until it is dismissed.
That includes the changing of color. Javascript actually says hey browser start changing colors and moves on but as it hits an alert the changing of colors or whatever processes that happen will be paused and it will not start continuing again until the modal window aka alert is dismissed. A workaround might be to do something like this: codepen
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<button id='button1'>Click Me</button>
<div id='indicator' style='color:#f00'>NO</div>
<script type="text/javascript">
var MyClass = function() {
th = this;
th.func = function() { window.alert('yes'); };
th.Click = function() {
document.getElementById('indicator').style.color = "#0f0";
document.getElementById('indicator').innerHTML = "YES";
// The setTimeout fix
// ====
setTimeout(th.func, 100);
};
th.Start = function()
{
var a = document.getElementById('button1');
a.addEventListener('click', th.Click, false);
};
th.Init = function()
{
th.Start();
};
}
var a = new MyClass().Init();
</script>
</body>
</html>
A bad title and this might not be the best way to do what I'm trying to do (still learning javascript) but I'm trying to wrap a object using a delegate. The object in this case is an XMLHttpRequest.
var wrapper = function() {
this._delegate = /* get the delegate */
this._delegate.onreadystatechange = function() {
wrapper.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
if(wrapper.onreadystatechange) {
wrapper.onreadystatechange();
}
};
return this;
}
The above is a simplification but when problem is that when I add an onreadystatefunction to the wrapper object like:
wrapper.onreadystatechange = function() {alert("hi)};
and the wrapper._delegate.onreadystatechange function is called, wrapper.onreadystatechange is always undefined and the alert popup never comes up. I think I'm getting my scope stuff wrong but I'm not exactly sure how to fix this. Would appreciate other suggestions but I would also like to know how to fix what I'm doing wrong. Thanks!
EDIT
Yup it was an incomplete example. sorry about that. I realized after trying to rewrite it into a complete example what my cause my issue. It seems if I don't have the outer "WRAP_FUNCTION" then it will work fine. I had written something like
WRAP_FUNCTION = (function() {
var originalXMLHttpRequest = window.XMLHttpRequest;
var wrapper = function() {
if(wrapper.wrapped) {
this._delegate = new originalXMLHttpRequest;
} else {
this._delegate = new window.XMLHttpRequest
}
this._delegate.onreadystatechange = function() {
wrapper.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
if(wrapper.onreadystatechange) {
wrapper.onreadystatechange();
}
};
return this;
};
wrapper.prototype.open = function(method, url, async) {
this._delegate.open(method, url, async);
}
wrapper.prototype.send = function() {
this._delegate.send();
}
wrapper.wrapped = true;
return wrapper;
}
window.XMLHttpRequest = WRAP_FUNCTION;
HTML code:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script src="xmlhttp.js"></script>
<script type="text/javascript">
(function() {
var test = new XMLHttpRequest();
test.open("GET", "xmlhttp.js", true);
test.onreadystatechange=function()
{
if (test.readyState==4 && test.status==200)
{
alert("yay");
}
};
test.send();
})();
</script>
</body>
</html>
Try this.
var wrapper = function() {
// in this time var wrapper not yet defined completly
// if you want use wrapper on the finction
// need to use this instead of wrapper
var self= this;
this._delegate = /* get the delegate */
this._delegate.onreadystatechange = function() {
//this means _delegate is in this time
//if you want to use this(wrapper)
//set the value out of function
//like var self= this
//wrapper.readyState = this.readyState;
self.readyState = this.readyState;
/* stuff that synchronizes wrapper goes here */
//if(wrapper.onreadystatechange) {
// wrapper.onreadystatechange();
//}
if(self.onreadystatechange) {
self.onreadystatechange();
}
};
return this;
}
I have problem with two classes and a jquery call. Unfortunatly if a call a method in one class it thinks it is the other one.
Here in detail:
I am writing a form, where the user can write down two customer numbers in two different input fields. The website will query each customernumber via jQuery AJAX and display details from the customer numbers.
So I wrote a class for not duplicating the code and assigning the behaviour to each input field.
CustomerData = function(settings){
this.name = '';
this.street = '';
this.zipcode ='';
this.town = '';
this.inputField = settings.inputfield;
this.init();
}
CustomerData.prototype.init = function() {
this.associateClassWithUi();
}
//here I assign the class with the inputfield via jQuery
CustomerData.prototype.associateClassWithUi = function() {
_this = this;
console.log("associate " +this.inputField);
$(this.inputField).focus(function() {
console.log(' focus on '+_this.inputField);
});
$(this.inputField).blur(function() {
customerId = $(this).val();
console.log("blur event " + _this.inputField);
if(customerId != ''){
_this.main(customerId);
} else {
_this.setEmpty();
_this.propertiesToUi();
}
});
}
I am defining the classes this way:
var DataCustomer1 = new CustomerData({
inputField: '#customer1'
});
var DataCustomer2 = new CustomerData({
inputField: '#customer2'
});
console.log gives me the following:
associate #customer1
associate #customer2
But clicking on the input fields (#customer1 and #customer2) I always get this
focus on #customer2
focus on #customer2
focus on #customer2
Of course if I change the order of instantiation
var DataCustomer2 = new CustomerData(...);
var DataCustomer1 = new CustomerData(...);
each of them thinks he is customer1
What am I missing?
Use var _this = this; otherwise it is being declared globally and overwritten each time.
When you declare a variable without var then it always becomes global. If you have this HTML:
<ul>
<li id="customer1">Customer 1</li>
<li id="customer2">Customer 2</li>
</ul>
The following code works as expected:
CustomerData = function(settings){
this.inputField = settings.inputField;
this.init();
}
CustomerData.prototype.init = function() {
this.associateClassWithUi();
}
CustomerData.prototype.associateClassWithUi = function() {
var _this = this;
console.log("associate " +this.inputField);
$(this.inputField).click(function() {
console.log('click on '+_this.inputField);
});
}
var DataCustomer1 = new CustomerData({
inputField: '#customer1'
});
var DataCustomer2 = new CustomerData({
inputField: '#customer2'
});
You can find more information about JavaScripts variables here