Below code is a representation of my widget. Here I am trying to access variables which are passed from another js.
define(["dojo/_base/declare",
"dojo/_base/lang"], function(declare, lang,){
return declare("myapplication.viewer.js.dynamicview",null,{
getTextBoxValue:null,
constructor : function(args){
alert("inside constructor");
console.log("args",args);
}
});
});
This is my js from where I am calling my widget.
var abc={};
abc.title="helloworld";
var viewerWidget = new myapplication.viewer.js.dynamicview({getTextBoxValue:abc});
Here I am passing an object to my widget variable.
But the problem is that in my widget, args variable in constructor is undefined. I am not sure where I am doing wrong.
Need to get value from my js to my widget.
You are mixin properties of your widget. That is a step later in your widget. See widget lifecycle here.
Your best option is to use postMixInProperties and not the constructor for this particular situation.
You can use "dojo/_base/lang" (mixin) to add new properties to the instance of your class,
use the mixin function (lang.mixin()):
constructor : function(args){
//below add new properties to the current instance
lang.mixin(this, args);
alert("inside constructor");
console.log("args",args);
}
Use mixin in order to "extend" your dojo class with the properties or routines as you wish.
A full example here;
https://jsfiddle.net/tsb3g6f9/9/
More resources here:
https://dojotoolkit.org/reference-guide/1.10/dojo/_base/lang.html
require(['dojo/_base/declare', 'dojo/_base/lang'], function(declare, lang) {
var MyClass = declare(null, {
constructor: function(args) {
lang.mixin(this, args);
},
action: function() {
alert(this.a);
}
});
var obj = {
a: 100
}
var thomas = new MyClass(obj);
thomas.action();
});
Related
I wrote a JS simple class:
// JS simple class
class myClass
{
constructor(init=0) { this.var = init; }
add(n) { this.var+=n; return this; }
sub(n) { this.var-=n; return this; }
}
The class can be used with method chaining:
// Works well
obj1 = new myClass(0);
obj1.add(5);
obj1.sub(2);
console.log (obj1.var);
// Method chaining, works well
obj2 = new myClass(0);
obj2.add(9).sub(4).add(3);
console.log (obj2.var);
I would like to create a closure for convenience, thus the class could be used without explicitly creating a new object. For example, I would like something like:
obj(0).add(5).sub(2);
When calling obj(0), a new instance of the class is created. I wrote the following closure, but the following does not work:
// Closure instantiating the class
var obj = function(init)
{
var obj = new myClass(init)
return { add:this.add, sub:this.sub };
}
When calling obj(0).add(3);, the following error is displayed in the console:
Uncaught TypeError: obj(...).add is not a function at window.onload ((index):58)
I don't know how to do this, and I'm even not sure the closure is the right tool.
Note that I already have a working solution without class (with closures), but I would like to keep my class.
I made a JSFiddle here
Your fonction should return the new object:
// Closure instantiating the class
var obj = function(init)
{
return new myClass(init);
}
I updated the fiddle : https://jsfiddle.net/48mr2t5y/
I have a commercial application that has an existing JavaScript object structure using prototype chains. I have had success extending this API by adding more methods to the prototypes of objects. However, I realize that it would be best to add a namespace in front of my methods in case the application vendor decides to name a new method the same as one of my methods in a future release.
If I have an existing object called State, I would add a method called getPop like so:
State.prototype.getPop = function(){return this.pop;};
var Washington = new State('Washington',7000000);
Washington.getPop(); //returns 7000000
What I want to do is add a namespace called 'cjl' before my custom method to avoid name collision so that I can call it like so:
Washington.cjl.getPop();
I tried:
State.prototype.cjl = {};
State.prototype.cjl.getPop = function(){return this.pop;};
The problem is this. It doesn't point to the instance but instead points to the 'cjl' object.
I tried various methods, including using .bind() but none of them seemed to work. I finally found an answer here: Is it possible to organise methods on an object's prototype into namespaces? This works using the Object.defineProperty() method. The problem is the commercial application only works in compatibility mode in IE which doesn't support the Object.defineProperty() method for non-DOM elements.
Is there another way to accomplish this? I don't want to have to call multiple functions, which is the result of some techniques, e.g.:
Washington.cjl().getPop();
You could namespace in the following way, reading your comments I see that you can't change the original constructor so you'll have to replace the original with your own and save the original in a closure.
Every state instance will have it's own cjl instance but that only has a reference to current State instance, all the cjl functions are shared as they exist only once:
[UPDATE]
Forgot to get State.prototype in myState's prototype chain.
//the original constructor
function State(name, pop){
this.name=name;this.pop=pop;
}
State.org="original constructor";
//original constructor is available through
// closure and window.State is replaced with
// your constructor having the cjl namespace
(function(State){
//cjl namespace
function cjl(stateInstance){
this.stateInstance=stateInstance;
};
//cjl functions
cjl.prototype.getPopInThousands=function(){
//do not use this, instead use this.stateInstance
return this.stateInstance.pop/1000;
}
function myState(){
//apply State constructor
State.apply(this,arguments);
//create a clj instance, all methods
// are on cjl.prototype so they're shared
this.cjl = new cjl(this);
}
//inherit from State (use polyfil for older browsers)
myState.prototype = Object.create(State.prototype);
//replace window.State with your constructor
window.State=myState;
}(State))
var s = new State("Wasington", 7000000);
console.log(s.cjl.getPopInThousands());
//non standard, name
console.log("constructor name",s.constructor.name);
console.log("constructor tostring",s.constructor.toString());
More on constructor functions and prototype can be found here: https://stackoverflow.com/a/16063711/1641941
I have to agree with friend and cookie that pre fixing the function names may be the better solution but if you want to use the same methods for an object named Country then you may think of using the previous code as you can re use the cjl object.
Instead of defining State.prototype.cjl outside of the function, try to set the cjl "namespace" inside the constructor function.
function State(){
var thisObject = this;
this.cjl = {
getPop: function(){
return thisObject.pop;
}
};
}
Then you can do Washington.cjl.getPop();.
Try:
var State = function(name, pop) {
this.name = name;
this.pop = pop;
};
State.prototype.cjl = function(method) {
return this.cjlDefs[method].apply(this, Array.prototype.slice.call(arguments, 1) );
};
State.prototype.cjlDefs = {
getPop: function() {return this.pop;}
};
var Washington = new State('Washington', 80000);
console.log( Washington.cjl('getPop') );
https://jsfiddle.net/ghbjhxyh/
Or another shape if you prefer:
var State = function(name, pop) {
this.name = name;
this.pop = pop;
};
State.prototype.cjl = function(method) {
this.cjlDefs.obj = this;
return this.cjlDefs;
};
State.prototype.cjlDefs = {
assertObj: function() { /* Make sensible assertion */ },
getPop: function() { this.assertObj(); return this.obj.pop; }
};
var Washington = new State('Washington', 75000);
console.log( Washington.cjl().getPop() ); // 75000
https://jsfiddle.net/7vjrz2mn/
I'm using dojo declare to build out a presenter file.
In the constructor, I'm passing in params which is an object literal having one attribute called product. Then I have other methods inside of product. When then calling other methods, the this variable is the window instead of the current object.
Below is the code that I'm using:
define([
'dojo/_base/declare'
], function(declare) {
var ProductComparePresenter = declare("ProductComparePresenter", [], {
constructor: function(params) {
declare.safeMixin(this, params);
},
monthlyPremium: function() {
console.log(this.product);
}
});
return ProductComparePresenter;
});
In this example this is the window and there of course is no product. Is there something I'm overlooking?
Thanks.
I am using:
var ReportsServiceCall = function () { };
ReportsServiceCall.prototype = new ServiceCall();
With this code, is the ServiceCall a fresh instance each time a new ReportsServiceCall is created? I need it to be so.
Nope
As you have it written, the prototype is only setup once. However, that's not a very good way to write it.
I would write it like this
var ReportsServiceCall = function () {
// parent constructor; optional
ServiceCall.call(this);
};
// setup prototype; see comment below
ReportsServiceCall.prototype = Object.create(ServiceCall.prototype, {
constructor: {
value: ReportsServiceCall,
enumerable: false,
writable: true,
configurable: true
}
});
Note: Aside from setting super_, this is how node.js is doing vanilla inheritance in their util.inherits function.
This is very effective technique once you understand how it works.
With this code, is the ServiceCall a fresh instance each time?
No and it's not a good way to setup inheritance. At the moment you are calling new ServiceCall, you actually don't want to create an instance of ServiceCall (which arguments would you pass if the constructor requires parameters?). All you really want is add ServiceCall's prototype to ReportsServiceCall's prototype chain.
You should use Object.create instead and call the superclass constructor inside the child class constructor:
var ReportsServiceCall = function () {
ServiceCall.call(this);
};
ReportsServiceCall.prototype = Object.create(ServiceCall.prototype);
See Benefits of using `Object.create` for inheritance for an extended explanation of this pattern.
IMHO not, as you are setting the prototype just once
The prototype is only a single object that will be shared by all of the instances of ReportsServiceCall. If you need the ServiceCall constructor to be called for each ReportsServiceCall instance, you can do this:
function ReportsServiceCall() {
ServiceCall.call(this);
};
ReportsServiceCall.prototype = new ServiceCall();
ReportsServiceCall.prototype.constructor = ReportsServiceCall;
Not really.
A ReportsServiceCall is a ServiceCall, but create a ReportsServiceCall with new doesn't make it have its own properties which assigned in the constructor of ServiceCall.
Look at the following example:
var ServiceCall=function () {
this.Id=Math.random();
};
var ReportsServiceCall=function () {
};
ReportsServiceCall.prototype=new ServiceCall();
var x=new ReportsServiceCall();
var y=new ReportsServiceCall();
alert(x.Id===y.Id); // true .. so, what Id for?
One of the solutions is:
var ReportsServiceCall=function () {
ServiceCall.apply(this, arguments);
};
I'm struggling with how best to combine javascript Classes and jQuery plugins. This question isn't very specific, what I'm hoping for is pointers to more resources.
Basically, I want to store state data and private methods in a class, and then extend each jQuery object which I call my plugin on to have those private methods and properties. Such that inside the plugin I can call methods directly off the jQuery object.
I read jQuery plugin design pattern (common practice?) for dealing with private functions, specifically David's answer, however this initializes a new Class each time, and thus can't be used to save the state of the object.
I also found http://fuelyourcoding.com/jquery-plugin-design-patterns-part-i/, which recommends creating a class and then storing it in .data().
I think ideally what I want to end up with is code that looks like
(function( $ ){
var methods = {
init : function( options ) { // Initialize each object with a state and private methods },
show : function( ) {
// testFoo() is a private method that checks the element's state
if(this.testFoo()){
// Relying on jQuery's html() method
this.html() = this.fooTemplate();
}
}
};
// Boiler plate plugin from http://docs.jquery.com/Plugins/Authoring
$.fn.myPlugin = function( method ) {
// Method calling logic
if ( methods[method] ) {
return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method === 'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.myPlugin' );
}
};
})( jQuery );
Finally, it doesn't seem like I can bake the private methods into the plugin directly because methods like "testFoo()" will return a boolean, and therefore aren't chainable.
Thoughts? Am I approaching this the right way? Is there another design pattern I should be using? Perhaps not using jQuery plugin architecture at all?
Here's a proposed solution. It combines few different approaches (John Resig's inheritance model and Alex Saxton's plugin inheritance model).
Define your inheritable plugin:
(function ($) {
My.Plugin = Class.extend({
/*
* Initialization (constructor)
*/
init: function (element, meta) {
var $meta = $.extend({ name: "pluginName" }, meta);
// Call the base constructor
this._super(element, $meta);
// TODO: Add custom initialization code like the following:
// this._testButton = $('.testButton', element).get(0);
},
/*
* Public methods
*/
show: function() {
alert('This is a public method');
},
/*
* Private methods
*/
// DEMO: Overriding the base _paint method:
_paint: function () {
// "this._super()" is available in all overridden methods
// and refers to the base method.
this._super();
alert('TODO: implement myPlugin._paint!');
}
});
// Declare this class as a jQuery plugin
$.plugin('my_plugin', My.Plugin);
})(jQuery);
Define Base class
(function () {
var initializing = false, fnTest = /xyz/.test(function () { xyz; }) ? /\b_super\b/ : /.*/;
// The base Class implementation (does nothing)
this.Class = function () { };
// Create a new Class that inherits from this class
Class.extend = function (prop) {
var _super = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the init constructor)
initializing = true;
var prototype = new this();
initializing = false;
// Copy the properties over onto the new prototype
for (var name in prop) {
// Check if we're overwriting an existing function
prototype[name] =
typeof prop[name] == "function"
&& typeof _super[name] == "function"
&& fnTest.test(prop[name])
? (function (name, fn) {
return function () {
var tmp = this._super;
// Add a new ._super() method that is the same method
// but on the super-class
this._super = _super[name];
// The method only need to be bound temporarily, so we
// remove it when we're done executing
var ret = fn.apply(this, arguments);
this._super = tmp;
return ret;
};
})(name, prop[name])
: prop[name];
}
// The dummy class constructor
function Class() {
// All construction is actually done in the init method
if (!initializing && this.init)
this.init.apply(this, arguments);
}
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.constructor = Class;
// And make this class extendable
Class.extend = arguments.callee;
return Class;
};
})();
Plugin Creation
(function ($) {
// The "inheritance plugin" model
// [http://alexsexton.com/?p=51][1]
$.plugin = function (name, object) {
$.fn[name] = function (options) {
var instance = $.data(this, name, new object(this, options));
return instance;
};
};
})(jQuery);
Calling your plugin from javascript:
$('#someElem').my_plugin({options: {}, data: {} /* you can modify your plugin code to accept anything */}).show();
Note:
Private methods here are marked as _methodName. It's pure convention. If you really want to hide them, you can use module pattern (google for it or here's one for starters: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth)
Is this what you're looking for?