I have a problems with object's manipulation in javascript
My code:
SearchField = function(){
this.Init = function()
{
this.input = this.view.getElementsByTagName("input");
this.input[0].onkeyup = this.UpdateEvent2;
self = this;
}
this.UpdateEvent = function(){
this.OnUpdate();
}
this.UpdateEvent2 = this.UpdateEvent.bind(this);
this.OnUpdate = function(){
alert("Hello world from direct object");
};
}
Some explanations for this code: I used a bind method to pass as argument the Object itself, instead of event object.
So, I have a function OnUpdate with some code inside.
After Instantiation of my Object in some other part of my code I have some other lines:
...
targetController.prototype[targetMethodName] = function(targetController){
alert("core");
return selfController[selfMethodName](targetController);
}
...
Where targetController is a reference to my object and targetMethodeName is a method OnUpdate(). Then I try to assign a new function to this method, in other words, try to Substitute the original method OnUpdate with another method from another object. (It dosen't metter 'couse it dosen't work in anyway, even invoking alert("core").)
So, when I try to call this method like this: MyObject.OnUpdate() - result is an alert window with "Hello world from direct object".
The first quastion is how can I substitute this method by another one?
But, there's some interesting behavior if I assign this method directly to the event handler like this:
SearchField = function(){
this.Init = function()
{
this.input = this.view.getElementsByTagName("input");
this.input[0].onkeyup = this.OnUpdate;
self = this;
}
this.OnUpdate = function(){
alert("Hello world from direct object");
};
}
In this case everything works perfectly, so I have an alert window with "core" inside and another method from another object invoked with right arguments...
So, the second quastion is ... what's wrong in the first variant??? I don't want to assign my method directly to the event handler! I whant to call this method in any part of my code! How to do this?
P.S. As you can see I tried to do this with self instead of this and so on... Nothing helps!
Looks like you are trying to overwrite a keyup function after the class is created?
One way you could do this is to init with the original function, then overwrite it:
<div id="field">
<input type="text" value="search1" />
</div>
<div id="field2">
<input type="text" value="search2" />
</div>
<script>
var SearchField = function (id) {
this.init = function () {
var me = this;
this.el = document.getElementById(id);
this.input = this.el.getElementsByTagName('input');
this.input[0].addEventListener('keyup', function (e) {
me.onKeyUp(e);
});
self = this;
}
this.onKeyUp = function (e) {
console.log('onKeyUp');
};
this.init();
};
var search1 = new SearchField('field');
var search2 = new SearchField('field2');
// overwrite the key up function
search2.onKeyUp = function(e) {
console.log('onKeyUp2');
};
</script>
http://jsfiddle.net/kmturley/CHK96/
Related
On my index.html, I have this code,
$(document).ready(function() {
var self = this;
var submit = function() {
alert("Test");
}
const form = new Form(self.submit);
})
In my Form.js, I have this code,
class Form() {
constructor(func) {
var self = this;
// ...
$("submitBtn").click(function(e) {
e.preventDefault();
self.func();
});
// ...
}
}
Why my function is not executing after the submitBtn is clicked?
I used self to get the "this" value. I cant use "new Form(self.submit())" because It will execute the function once the line is read.
Your submit function is a local variable, not a property of this. Thus you need:
const form = new Form(submit);
Similarly, in your constructor, func doesn't have anything to do with self; it should just be
func();
Pointy answers the question. I just want to add that constructor is a place where you usually declare and initialize instance properties, and it's better to register click event in a class method, something like:
class Form{
constructor(){}
click(func){
$("submitBtn").click((e)=>{
e.preventDefault();
func();
});
}
}
Also you dont need to cache the scope var self = this as long as you use arrow function. This answer could be useful Advantages of using prototype, vs defining methods straight in the constructor?
I'm wondering how to setup a shorthand function for a shorthand selector in javascript. I apologise if that isn't the correct termonolgy.
Example:
var abc = function (selector) {
return document.querySelector(selector);
};
Allows you to:
var temp = abc('#someID').value;
What I'm wondering is how do you go about creating a custom .something (in a similar fashion to how jQuery have .val)?
For example calling:
abc('#someID').doSomething;
The the doSomething command allowing you to update the value (or pull it back) in a similar fashion to .val etc.
Thank you in advance.
Well, this is a very nice JS code-design question.
Let's try to create a simple jQuery implementation. For this, we should first scope things up.
jQuery function is a wrapper. It will hold a reference to the node in the DOM, and it will provide an array functions that will "operate" on the node.
Most of the functions (setters, for being more specific) should return a pointer to the wrapper itself, so you can chain operations.
You can define the wapper first, by defining your function.
// Here we define the constructor.
var q = function(selector){
this._node = document.querySelector(selector);
// Add more private stuff here if you like
};
//Now we can add functionality to the function prototype.
q.prototype.hide = function(){
this._node.style.visibility = 'hidden';
return this;
};
q.prototype.show = function(){
this._node.style.visibility = 'visible';
return this;
};
q.prototype.val = function(){
return this._node.value;
};
q.prototype.click = function(callback){
this._node.onclick = callback;
return this;
};
// This is just for not having to call new every-time we want a new instance
var $q = function(selector){
return new q(selector);
};
Now let's play a bit
<label for="name"> Hey I'm a text box</label>
<input id="name" value="" />
<button id="clickMe"> Click me </button>
We will attach a click handler to the button, when the user clicks, we display the value that the textbox contains, then we hide the text box. All in a single line (chained commands).
$q('#clickMe').click(function(){
alert($q('#name').hide().val());
});
See JsFiddle https://jsfiddle.net/4Lfangj4/
To make that, you must return an object (easiest solution) or extend the prototype (advanced solution).
Returning an object
You can return the doSomething() method:
var abc = function (selector) {
return {
doSomething: function() {caller()},
dom: document.querySelector(selector);
}
};
And it works:
var temp = abc("#someID").dom.value;
var doSome = abc("#someID").doSomething();
Extending prototype
You can add a function to the object prototype:
var abc = function(sel){
return document.querySelector(sel);
}
abc.prototype.doSomething = function() {
caller();
};
And it works
var temp = new abc("#someID");
temp.doSomething(); //doSomething() method
temp.value; // value attribute of element
Jquery keeps your selection in an internal property and decorates that property with methods that can help with is DOM presence.
Almost every time it returns the same object so you can chain method calls.
The point is that you cannot avoid keeping a reference to the selected DOM element and the decoration part
A simple example about selection and manipulating the DOM element
note here i store a reference to document.querySelector and document.querySelectorAll which are pretty much as good as jquery selection mechanism (Sizzle)
var MyWrapper = (function(){
var $ = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);
var slice = Array.prototype.slice;
var selection;
var that = {
select: select,
remove: remove,
html: html
};
function select(selector){
selection = $(selector);
return that;
}
function remove(){
selection.parentNode.removeChild(selection);
return undefined;
}
function html(htmlstring){
if(typeof htmlstring == 'undefined'){
return selection.innerHTML;
} else {
selection.innerHTML = htmlstring;
return that;
}
}
return that;
}())
of course jQuery is a much complex and sophisticated library for all kind of use cases but the above code can get you started
I have a javascript object which I would like to be able to handle some interactive features. It's a bit tricky to describe the scenario in a simple way so hopefully it'll not get all out of hand here.
my object looks something like
myobject = function() {
this.initialize = function() {
// HERE this = the myobject instance
var test = document.createElement('div');
test.onmousedown = this.mousedown;
}
this.mousedown = function(e) {
// HERE this = the calling div-element
}
}
So my problem is basically that this will not be an myobject instance when this.mousedown(e) is called, it will rather be the caller (if the terminology is correct?) in this case it is the div I created and put in a variable called test above.
I would like to have access to the instance on which the method is being run (as I believe that to be the mousedown method I created).
This far I have had some ideas which I have tried out:
create a data- attribute on the div containing the this object and operate on that.
sending the this pointer as an argument along with e to this.mousedown(e)
It's all I can think of now hope it makes sence.
You could create a copy when you first instantiate the object:
var myobject = function() {
var self = this;
this.initialize() {
// HERE this = the myobject instance
var test = document.createElement('div');
test.onmousedown = this.mousedown;
}
this.mousedown(e) {
// HERE this = the calling div-element
// use self instead of this
}
}
The simplest solution is to make a 'self' var that you refer to in the callback:
myobject = funciton() {
var self = this;
this.initialize() {
//use self to refer to myobject
self.mousedown(e);
}
this.mousedown(e) {
}
}
I have a function name in a string:
var func = "doTest";
I need this function to be applied to the current instance ("this");
So I need it to call:
this.doTest();
How can I do this? I cannot go via window.
Thanks,
Wesley
Just use the construct of object[functionName]();, like so:
function Person() {};
Person.prototype.speak = function() { alert('ohai'); };
var john = new Person, action = 'speak';
john[action]();
Alternative style:
var Person = {
speak: function() { alert('ohai'); },
speakDelegate: function() { var action = 'speak'; this[action](); }
};
Person.speakDelegate();
this[func]();
No need to .call or .apply since context is held in the reference.
For example:
var obj = {
doTest: function(){ console.log(this); },
fn: function(){ var name='doTest'; this[name](); }
};
obj.fn(); // logs the object, proving this has the correct context.
Try the following
var funcObj = this["doTest"];
funcObj.apply(this);
What this does is grab the member named doTest from this. It then executes the function via apply and tells javascript to bind this as this within the function. I think the example is a bit less confusing if you consider the same code on a non-this value
var obj = {
doTest: function() {
console.log("doTest called");
}
};
var doTestFunc = obj["doTest"];
doTestFunc.apply(obj);
In this case the method doTest will be executed with the value obj as this
If you are using jquery you can just do:
$(this)[func]()
I want to use values of the calling object within the jquery code block, but 'this' is mapped to the jquery object and not eh caller! How to solve this PLEASE?
// class
myClass = function (){
// member object
this._localVars = {
_elementClass:'.elem-class',
_dots:null,
_dotStatus:null
};
// member function
this.func1 = function() {
$(this._elementClass).each(function(_index, _element){
// this._localVars._dots[_index] = _element; ... this line throws an error 'this._localVars' is undefined ... as 'this' is html element here and not an object of the calling class
});
};
};
Please suggest how can I use the 'this' inside the jquery code block to refer the variables/objects of the class and not HTML/jQuery.
Thanks
Try saving this object into a local variable
var myObject = this;
$(this._elementClass).each(function(_index, _element){
myObject._localVars._dots[_index] = _element;
});
You can use the jQuery.proxy method to set the value of this that you want.
You pass your function as the first parameter, and the current this as the second.
myClass = function (){
this._localVars = {
_elementClass:'.elem-class',
_dots:[],
_dotStatus:null
};
this.func1 = function() {
$(this._localVars._elementClass).each( $.proxy(function(_index, _element) {
this._localVars._dots[_index] = _element;
}, this));
};
};
var cl = new myClass();
cl.func1();
console.log(cl._localVars._dots);