I'm trying to create a library for mobile and I want to be able to call the object as function and object like jquery does.
Example:
var test = function(elm) {
this.ajax = function(opt) { ... }
if ( elm ) {
var elms = document.querySelectorAll(elm);
}
}
and I want to be able to call it like this:
test("#id");
and like this:
test.ajax(opts);
LE:
Thank you guys for your fast responses!
In JavaScript, a function is actually just an object with code attached.
So instead of a plain object:
var test = {};
test.ajax = function() { /* ajax */ };
... use a function:
var test = function() { /* test */ };
test.ajax = function() { /* ajax */ };
In both cases, you can access test.ajax. The extra thing with the function is that you can call test.
Or mabye something like this:
Object.prototype.Test = function( method ) {
var method = method || null;
var elms = null;
/* Methods */
this.ajax = function(opt){
console.log('You called ajax method with options:');
console.log(opt);
}
/* Logic */
if (method in this) this[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
else {
try {
elms = document.querySelectorAll(method);
}
catch(e) {
console.log(e.message);
}
}
}
window.onload = function() {
Test('ajax', {'url':'testurl.com'});
Test('#aid');
}
Related
I would like to add a wrapper function to one of my functions to show extra information.
Below is my wrapper function:
var wrap = function(functionToWarp, before) {
var wrappedFunction = function() {
if (before) before.apply(this, arguments);
result = functionToWrap.apply(this, arguments);
return result;
}
return wrappedFunction;
}
var beforeFunc = function(){
// print extra infos before functionToWarp() triggers.
}
and my function _printSth to wrap:
var Printer = function () {
this._printSth = function (input) {
// print something from input...
}
}
Printer._printSth = wrap(Printer._printSth, beforeFunc);
I have tried to wrap Printer._printSth by calling
Printer._printSth = wrap(Printer._printSth, beforeFunc); or similar codes but failed.
How should I declare my _printSth() to be able to be wrapped?
You could write
function Printer() {
this._printSth = function (input) {
// print something from input...
};
this._printSth = wrap(this._printSth, beforeFunc);
}
or
function Printer() {
this._printSth = wrap(function (input) {
// print something from input...
}, beforeFunc);
}
but that's equivalent to simply writing
function Printer() {
this._printSth = function (input) {
beforeFunc(input);
// print something from input...
};
}
Assuming you rather might want to wrap the method on a specific instance, you'd do
const p = new Printer();
p._printSth = wrap(p._printSth, beforeFunc);
Altering a method is done like that:
Printer.prototype._printSth = wrap(Printer.prototype._printSth, beforeFunc);
I have a very complex class so i decided to break into sub modules and trying to use revealing modules pattern.
I have main class and decided to divide into smaller container function. but in current scenario
But i am not able to access any internal function from outside i.e callSearchResultWithCallBack using searchFinder.Search.callSearchResultWithCallBack(). which pattern should i use to keep this code clean as well have control to call internal function in sub module.
Thanks
var searchFinder;
function SearchFinder() {
me = this;
this.searchResult = null;
this.init = function() {
declareControls();
createAccordian();
addEvents();
fillControls();
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
me.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
}
this.Search = function() {
var url = '';
var searchCriteria = {};
validateAndCreateCriteria();
callSearchResultWithCallBack();
function validateAndCreateCriteria() {
function validateAandGetCategory() {
if (SearchValidation.ValidateZipCode(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
} else if (SearchValidation.ValidateCityState(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
}
}
}
// need to access it outsite
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
}
}
jQuery(function() {
searchFinder = new SearchFinder();
searchFinder.init();
searchFinder.Search.callSearchResultWithCallBack();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
This code has multiple issues, first I will address the fact that for example declareControls is not executing. First declare the function than execute!
this.init = function() {
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
this.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
declareControls();
//createAccordian(); //not defined
addEvents();
fillControls();
}
Now let's look at others problems that will arise.
the me object referring to this is in the scope of searchFinder and does not refer to the same this in the instance of searchFinder.
function jQuery can be replaced by the commonly used $.
searchFinder.Search.callSearchResultWithCallBack() this is never going to work. Since the Search function is an object and callSearchResultWithCallBack isn't a property of this function.
Solution; make it part of the prototype of Search.
Steps:
Move callSearchResultWithCallBack outside the search function.
Add prototype to Search function
Call function via prototype.
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
this.Search.prototype.callSearchResultWithCallBack = callSearchResultWithCallBack;
If you want to fire this function outside of search use this:
searchFinder.Search.prototype.callSearchResultWithCallBack();
Please remember that callSearchResultWithCallBack will throw an error because searchCriteria is undefined.
This fixes your problems for now, but this code has to be revised thoroughly. But this should get you started. http://ejohn.org/blog/simple-javascript-inheritance/
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
}
}
Assume I have executed this js code:
var container=function() {
//do something
}
container.a=function {
//do something 2
}
container.b='34'
Here, in order to change container.a function for example I need to do:
container.a=function() {
//do something 3
}
How do I change the function container() ?
You just assign a function to the variable:
container = function() {
//do something
};
This of course means that you get a new function object, which doesn't have the a and b properties. If you want to keep them, you have to copy them to the new function:
var temp = function() {
//do something
};
temp.a = container.a;
temp.b = container.b;
container = temp;