Following is my javaScript code.
var myObjfn = {
before : function(){
console.log("before");
},
loadA: function(){
console.log("loadA");
},
loadB: function(){
console.log("loadB");
},
loadC: function(){
console.log("loadC");
}
}
Whenever I call myObjfn.loadA(), it should call myObjfn.before() method before executing loadA method. Same for loadB() & loadC(). I don't want to explicitly call before() method in all loadA,loadB and loadC methods. Is there any option to achive this in javascript ?
You could do something like this. Which creates a wrapper function for each function in the object except the before function.
var myObjfn = { ... };
Object.keys(myObjfn).forEach(key => {
if (key === "before") return;
var oldFunc = myObjfn[key];
myObjfn[key] = function() {
myObjfn.before();
return oldFunc.apply(this, arguments);
};
});
myObjfn.loadA();
// "before"
// "loadA"
Related
I want to implement the debounce function on Ext.Button, so I extended it and override the onClick function, like this:
MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
var args = e;
clearTimeout(this.timeoutDebounce);
this.timeoutDebounce = setTimeout(function(){
MyButton.superclass.onClick.apply(that, [args])
}, this.debounce);
}
});
Debounce is a parameter passed on the x-type declaration.
The problem here is that the "args" parameter I'm passing to onClick has changed when it's called from "click" to "mouvemove" and it doesn't fire the events it should.
Is there a way to record the "e" parameter received in the function to pass to onClick on superclass?
The function passed to setTimeout must be wrapped in order to keep the value presented in current scope:
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
}
}
Also, e is passed by reference, so you need to create a copy of it. Using ExtJS, you can use Ext.apply method:
Ext.apply({}, e);
The full code should be:
var MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
// you can also use call since you know the arguments:
// MyButton.superclass.onClick.call(that, args);
}
}
clearTimeout(this.timeoutDebounce);
var copy = Ext.apply({}, e);
this.timeoutDebounce = setTimeout(createCallback(copy), this.debounce);
}
});
You should clone the object:
var args = Ext.apply({}, e);
this.timeoutDebounce = setTimeout((function(args){
return function(){MyButton.superclass.onClick.apply(that, [args])};
})(args), this.debounce);
I wanted to call the run function that should call the other and action will be done on the base of element_id
NGL = {}
NGL.SceneBuilder = function() {
var yamlFile = 'http://example.com/main.yaml'
var parseYaml = function() {
}
var buildScene = function() {
// other code
simulationStarted(element_id);
}
return {
run: function(element_id) {
parseYaml();
buildScene(element_id);
}
}
}
NGL.SceneBuilder.run('#someid');
You're not executing your factory so NGL.SceneBuilder is a function, not an object having the run property. Call the function :
NGL.SceneBuilder = (function() {
...
})(); // <<===
Note also that you forget to declare the element_id parameter in buildScene but maybe is it just for the question.
Okay so we have a project ongoing, and it is to be passed today. But I have a problem.
This is the sample code:
output.js
var MapPrintDialog = Class.create();
MapPrintDialog.prototype = {
// 他の画面からテンプレート情報を更新するために呼ばれる。
comboReload : function() {
var val = tempComb.getValue();
tempComb.store.load({
callback: function(result, o) {
if (this.store.data.keys.indexOf(val) == -1) {
this.setValue(this.store.data.keys[0]);
this.fireEvent("select", this);
}
}.createDelegate(tempComb)
});
},
initialize : function(){
this.define();
},
define : function(){
var DrawPrintAreaFrame = function(mode, noUpdateStatusBarText){
var cs = getCurrentSetting();
if (mode == "init" || mode == "edit"){
PrintController.DrawMapPrintArea(cs.center.x, cs.center.y, cs.scale, cs.result.PrintMaps[0].Width, cs.result.PrintMaps[0].Height, cs.result.PageRowCount, cs.result.PageColumnCount, mode);
}
else if (mode == "delete"){
PrintFrameManager.ClearPrintFrame();
}
if (noUpdateStatusBarText) {
gisapp.noUpdateStatusBarText = true;
}
gisapp.refreshMap();
}
}
Now my problem is, how will I call "DrawPrintAreaFrame" from another js file?
I tried:
MapPrintDialog.prototype.define().DrawPrintAreaFrame("edit");
MapPrintDialog.prototype.define.DrawPrintAreaFrame("edit");
MapPrintDialog.define().DrawPrintAreaFrame("edit");
MapPrintDialog.define.DrawPrintAreaFrame("edit");
MapPrintDialog.DrawPrintAreaFrame("edit");
DrawPrintAreaFrame("edit");
but it gives me an error lol. How will I fix this? Please don't be too harsh, I just started learning javascript but they gave me an advanced project which isn't really "beginner" friendly XD
EDIT ----------------------
Okay now i tried to modify it like this:
var MapPrintDialog = Class.create();
MapPrintDialog.prototype = {
// 他の画面からテンプレート情報を更新するために呼ばれる。
comboReload : function() {
var val = tempComb.getValue();
tempComb.store.load({
callback: function(result, o) {
if (this.store.data.keys.indexOf(val) == -1) {
this.setValue(this.store.data.keys[0]);
this.fireEvent("select", this);
}
}.createDelegate(tempComb)
});
},
initialize : function(){
this.DrawPrintAreaFrame("edit");
}
}
function DrawPrintAreaFrame(mode, noUpdateStatusBarText){
var cs = gisapp.getCurrentView();
if (mode == "init" || mode == "edit"){
PrintController.DrawMapPrintArea(cs.center.x, cs.center.y, cs.scale, cs.result.PrintMaps[0].Width, cs.result.PrintMaps[0].Height, cs.result.PageRowCount, cs.result.PageColumnCount, mode);
}
else if (mode == "delete"){
PrintFrameManager.ClearPrintFrame();
}
if (noUpdateStatusBarText) {
gisapp.noUpdateStatusBarText = true;
}
gisapp.refreshMap();
}
But it gives me: Javascript runtime error: Object doesn't support property or method 'DrawPrintAreaFrame'
You have 2 different way:
1- you have to first change it like this:
define : function(){
var DrawPrintAreaFrame = function(mode, noUpdateStatusBarText){
//You function code
}
this.getDrawPrintAreaFrame = function(){
return DrawPrintAreaFrame;
}
}
then create your object using your class:
var obj = new MapPrintDialog();
obj.define();
obj.getDrawPrintAreaFrame().call(obj, "edit");
2- remove the define method and add your function to prototype:
MapPrintDialog.prototype.DrawPrintAreaFrame = function(){
//your function code
}
create your object and simply call your method like this:
var obj = new MapPrintDialog();
obj.DrawPrintAreaFrame("edit");
It's funny, because I said you have 2 ways, and the third one just came up:
3- as far as you use Prototype framework you can use MapPrintDialog.addMethods, which is there to be used to add new instance methods to your class, remove your define and DrawPrintAreaFrame functions and add this:
MapPrintDialog.addMethods({
DrawPrintAreaFrame: function DrawPrintAreaFrame(){
//your code
}
});
or even without removing your method you can use it like:
define : function(){
var DrawPrintAreaFrame = function(mode, noUpdateStatusBarText){
//You function code
}
MapPrintDialog.addMethods({ DrawPrintAreaFrame: DrawPrintAreaFrame });
}
and create your instance and call the method:
var obj = new MapPrintDialog();
obj.DrawPrintAreaFrame("edit");
4- try this if you need your function like a sort of static method, without needing to create a instance:
MapPrintDialog.DrawPrintAreaFrame = function(){
//You function code
}
and call it like this
MapPrintDialog.DrawPrintAreaFrame("edit");
and if you want to define it in runtime, add the whole definition to your define method like this:
define : function(){
MapPrintDialog.DrawPrintAreaFrame = function(){
//You function code
}
}
Overview
I am trying to find the jQuery function that matches a selection attribute value and run that function on the selection.
Example.
$('[data-store="' + key + '"]').each(function() {
var $callback = $(this).attr('data-filter');
if($callback != null) {
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
}
$(this).setValue(value);
});
Problem 1
I'm not sure how to create a jQuery function call from string.
I know I can call the function like this, $(this)'onclick'; however I have no way to check if it exists before trying to call it.
Normally I could do this:
var strfun = 'onclick';
var fn = body[strfun];
if(typeof fn === 'function') {
fn();
}
This seems to fail:
var fn = window['$.fn.nl2br()'];
if(jQuery.isFunction(fn)) {
$(this).fn();
}
EDIT:
I seem to be having success doing this:
if($callback != null) {
var fn = $(this)[$callback]();
if( typeof fn === 'function') {
$(this)[$callback]();
}
}
Problem 2
Using jQuery.isFunction() how do you check if a methods exists? can you do this with jQuery.isFunction()?
Example
Declare function:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
Test if function existe, these options fail:
jQuery.isFunction($.fn.nl2br); // = false
jQuery.isFunction($.fn['nl2br']()); //false
Functions in JavaScript are referenced through their name just like any other variables. If you define var window.foobar = function() { ... } you should be able to reference the function through window.foobar and window['foobar']. By adding (), you are executing the function.
In your second example, you should be able to reference the function through $.fn['nl2br']:
$.fn.nl2br = function() {
return this.each(function() {
$(this).val().replace(/(<br>)|(<br \/>)|(<p>)|(<\/p>)/g, "\r\n");
});
};
console.log(jQuery.isFunction($.fn['nl2br']));
See a working example - http://jsfiddle.net/jaredhoyt/hXkZK/1/
var fn = window['$.fn.nl2br']();
and
jQuery.isFunction($.fn['nl2br']);
Sorry if my question wasn't clear enough. I'll put my code here...
var chain = {
'fn_1' : {
//fn_1 code here
chain.fn_2();},
'fn_2' : {
//fn_2 code here
chain.fn_3();}
...and so on
}
Let's say if i wana call chain.fn_1(), is there a way I can do that without calling chain.fn_2()?
What I can think of right now is a flag, but that would be alot of excess flags probably for each function. Do you guys have any ideas?
If the series of functions each call the next one you're correct, you'd need to have some sort of flag. In all likelihood, what would be best would be to modify your functions so that they return the reference to the object. Then you could chain like so:
var chain = {
'fn_1': function () {
// do something here.
return this;
},
'fn_2': function () {
// do something here.
return this;
},
'fn_3': function () {
// do something here.
return this;
}
};
// call the full chain:
chain.fn_1().fn_2().fn_3();
// call only the middle.
chain.fn_2();
g.d.d.c's answer is best, but if you can't modify the object for some reason, you could do this:
var _oldFn2 = chain.fn_2
chain.fn_2 = function() { return; };
chain.fn_1();
chain.fn_2 = _oldFn2;
var chain = {
fn : ['fn1', 'fn2', 'fn3'],
call : function(name) {
var i = 0, pos = -1, l = this.fn.length;
for(i = 0; i < l; i += 1) {
if(this.fn[i] == name) {
pos = i;
}
if(pos !== -1) {
this[this.fn[i]]();
}
}
},
fn1 : function() {
alert('fn1');
},
fn2 : function() {
alert('fn2');
},
};
chain.call('fn1'); //chain
chain.fn1(); //single