Do you know inheritance in createjs? - createjs

Anyone have any experience with inheritance and createjs. I am trying to extend the createjs.Container class with my button class but I am getting the following error in my browser console. Eveything seems to be working fine which makes me think the problem must be when the page loads. I have played around with the order that I load my scripts but it still produces the error. Below is the structure of my class.
TypeError: this.Container_constructor is not a function
(function() {
function Button(bmp, w, h) {
this.Container_constructor();
this.setup();
}
var p = createjs.extend(Button, createjs.Container);
p.setup = function() {
//code here
} ;
window.Button = createjs.promote(Button, "Container");
}());

After further poking around the problem is actually in my StartBtn class that extends my Button class. This is my working version.
(function() {
function StartButton(bmp, w, h) {
this.Container_constructor();
this.bmp = bmp;
this.width = w;
this.height = h;
this.setup();
}
var p = createjs.extend(StartButton, Button);
window.StartButton = createjs.promote(StartButton, "Button");
}());
Then just instantiate the StartButton and add it to the stage.
this.startBtn = new StartButton(loader.getResult('btn_start'), 227, 50);
this.addChild(this.startBtn)

Related

How can I access to the field in javascript class

Sorry, if it is duplicate, but I didn't find explanation.
How can I create field in js class? to define in the future...
class Polygon {
//var whyNot; This makes false
constructor(height, width) {
this.height = height;
this.width = width;
}
calcArea() {
return this.height * this.width;
}
}
Your understanding of JS objects is a little off... you create a variable that calls the function which is its own constructor. Then you modify the object to contain functions you wish to invoke later. like this https://jsfiddle.net/programndial/vonc5af5/
<input type="button" id="testButton" value="Test" />
function Polygon(height, width) {
this.height = height;
this.width = width;
Polygon.prototype.calcArea = function(string) {
return this.height * this.width;
}
}
testButton.onclick = function() {
var newPoly = new Polygon(10, 25);
alert(newPoly.calcArea());
}
The answer is (partially) in your question.
We will assume from the code and the link in your comment that you use a recent version of Javascript : ES6 or ES2015.
You can create them in the constructor method as in the code you provided.
class Polygon {
constructor(height, width) {
//height and width will be fields of Polygon
this.height = height;
this.width = width;
//...and whyNot too!
this.whyNot = 42;
}
...
Of course, since ES6 is compatible the previous versions of Javascript you still can use constructor methods, object literals...
Check this answer.
Constructors in JavaScript objects
You don't have a 'class' in javascript, you define the object as a function. you define inheritable functions as prototypes. pretty much you would use 'prototype' keyword for oop behavior.

How to add css style to custom image node in JavaScript InfoVis ToolKit

I have created custom nodes for my force directed InfoVis graph in which I display a user's image. I want to now add style to the image, such as adding a border and making it a circle. I tried adding css class as follows, but it's not working.
img.className = myClass;
here's my custom node code:
//Custom nodes
$jit.ForceDirected.Plot.NodeTypes.implement({
'customImage':
{
'render': function (node, canvas)
{
var ctx = canvas.getCtx();
var img = new Image();
var pos = node.getPos();
img.onload = function ()
{
ctx.drawImage(img, pos.x - 16, pos.y - 16);
}
var n = _nodes[node.id];
if (n && n.imageUrl)
{
var size = 52;
var url = n.imageUrl.replace("{width}", size).replace("{height}", size);
img.src = url;
img.className = myClass;
}
else
{
img.src = '../Images/UserNoImage.png';
}
},
'contains': function (node, pos)
{
var npos = node.pos.getc(true),
dim = node.getData('dim');
return this.nodeHelper.square.contains(npos, pos, dim);
}
}
});
You can apply CSS styles to the html elements. The custom node which you have defined is simply drawing image on the canvas. The node does not correspond to any html element.
Hence before you call function drawImage you should make sure that the image is customized to your requirement, only then you call drawImage. In this case infovis does not know anything about css, all that it does is call drawImage which simply draws an image on the canvas.
Thus, the question you should tackle is, how do you apply css to the image so that its customized to your requirement. And this question is independent of infovis.

angularjs with oop inheritance in action

Abstract
I'm working on an application that uses angular as a client side framework, angular currently rocks and I'm really happy using it, though now I find that I use to much copy and paste code that I would like to organize into class hierarchy. For example dialogs share a common set of functionality, they need to be opened, closed, the code that provides typeahead functionality is also a first candidate to inherit from some parent BaseTypeaheadClass, though one thing I didn't find in angular is a standard way of organising these hierarchies. Both controllers, services, providers use ordinary javascript functions underneath which can be extended by the means of prototype, so my question is:
Question
What is the angular way of organising my class functions, are there any standard mechanisms that will allow to derive one class from another
P.S.
My guesses on the problem:
Define implementation of base classes as services, as a result they will be easily injected into any controller or other services where that specific class will be needed
Define OOP service and provide methods such as define, derive, etc. that will be used to create base / derived classes
Edit
Some time has passed from time when I was initially asking my question. Since then I have come out with approach that I'm successfully using in several projects, that I like very much and want to share with everyone.
Currently angular doesn't provide any constructs for organising class hierarchies and it's a pity since more or less large application can't suffice only Model/View/Controller/... constructs, it has to organise it's code into OOP objects.
I'm working in the field of web-development for quite a long time already and I haven't seen even one enterprise project that was taking advantage of OOP with JavaScript massively. What I seen was huge and nicely organised server side / database side logic + close to infinite javascript spaghetti greased with zoo of frameworks and libraries on client side.
No MVVM, MVP frameworks such as knockout.js, backbone, other... are capable of replacing the OOP as such. If you are not using core principles of oriented programming such as Classes, Objects, Inheritance, Abstraction, Polymorphism you are in deep trouble, what you will end up is a mega long javascript spaghetti.
Regarding Angular I think it is a framework very much different from knockout.js / backbone.js / any other MVV-anything frameworks but according to my practice also it is not a silver bullet capable of replacing OOP. When I'm trying not to use the OOP with Angular I end up with duplicate logic located mostly in controllers. And unfortunately there is no (I have found no) clean and angular-way of beating that problem.
But I have successfully (I think) solved that problem.
I've used compact, zero-dependency lib that just implements John Resig's Simple JavaScript Inheritance (https://github.com/tracker1/core-js/blob/master/js-extensions/040-Class.js). With the help of that library I was able to create / inherit / create abstract methods / override them, in other words do everything that I've accustomed to on server side.
Here is an example usage:
Application.factory('SomeChildObject', ['$http', 'SomeParentClass', function ($http, SomeParentClass) {
var SomeChildClass = SomeParentClass.extend({
init: function() { // Constructor
this._super.init(123, 231); // call base constructor
},
someFunction: function() {
// Notice that your OOP now knows everything that can be injected into angular service, which is pretty cool :)
$http({method: 'GET', url: '/someUrl'}).then(function(){
this._super.someFunction(); // call base function implementation
});
}
});
// return new SomeChildClass(); // We are not returning instance here!
return SomeChildClass; // Service is a function definition not an instance of an object
}]);
// So now we can both use this service in angular and have the ability to extend it using the `extend` method call, like so:
Application.controller('MegaController', ['$scope', 'SomeChildClass', function ($scope, SomeChildClass) {
$scope.someObject = new SomeChildClass();
}]);
OOP + Angular play together very nicely, objects created under angular context can take advantage of dependency injection via services automatically, so you don't have to inject instances into your OOP constructors and this fact makes your OOP hierarchy very slim and free of irrelevant stuff that needs to be (and is) handled by angular.js
So play with this approach and give feedback here with results you gained or problems you encountered,
Another edit
Recently I've faced few problems with original Class.js implementation, as follows:
1) If you will be passing a reference to your instance methods as callbacks to other methods, these methods might work not the way you expect them to work. They will loose reference to this. In such case you will be expecting to see your current object inside this but it will be either top level Window or some other context object depending on how the callback calls your method. It happens due to JavaScript architecture. In order to fight this problem a special ClassMember function is provided which instructs Class to bind your method to object context when it is being created (check Usage below for further guidance).
2) Obviously original Class.js implementation doesn't know anything about angular type of controller method declarations i.e.
Class.extend('YourClassDisplayName', {
ctor: function () {
// Some useful constructor logic
},
controller: ['$scope', '$attrs', function ($scope, $attrs) {
// Do something with $scope and $attrs
}]
});
Current implementation understands above syntax
3) When using above approach without appropriate handling it would break angular $$annotate'on process so referring to above example it would make impossible to inject $scope and $attrs into into ClassMember method, or overridden method which is using this.base(...) calls. So this is also fixed.
Gotchas:
1) When using this.base(...) within async operation handler (something like $http.get(..., function() { self.base(...); })) please note that this.base(...) call has a limited lifetime and as soon as the method returns this.base(...) stops existing. So you should save reference to base method explicitly if you are planning to call base methods in asynchronous fashion. i.e:
...
var self = this;
var base = this.base;
...
$http.get(..., function () {
base.call(self, ...); // or base.apply(self, ...), or base() if you don't care about `this`
})
I've resolved all of the above problems (except one gotcha which can not be resolved due to JavaScript architecture) and would like to share with everyone, hope you will benefit from it:
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*
* Inspired by base2 and Prototype
* Angular adaptations by Denis Yaremov http://github.com/lu4
* Usage:
---------------------------------
var X = Class.extend('X', {
ctor: function () {
this.name = "I'm X";
},
myOrdinaryMethod: function (x, y, z) {
console.log([this.name, x, y, z]);
},
myClassMemberMethod: ClassMember(function (x, y, z) {
console.log([this.name, x, y, z]);
})
});
var Y = Class.extend('Y', {
ctor: function () {
this.name = "I'm Y";
},
myOrdinaryMethod: function (x, y, z) {
console.log([this.name, x, y, z]);
},
myClassMemberMethod: ClassMember(function (x, y, z) {
console.log([this.name, x, y, z]);
})
});
var x = new X();
var y = new Y();
x.myClassMemberMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"]
y.myClassMemberMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"]
x.myOrdinaryMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"]
y.myOrdinaryMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"]
y.theirOrdinaryMethod = x.myOrdinaryMethod;
y.theirClassMemberMethod = x.myClassMemberMethod;
y.theirOrdinaryMethod('a', 'b', 'c'); // ["I'm Y", "a", "b", "c"]
y.theirClassMemberMethod('u', 'v', 'm'); // ["I'm X", "u", "v", "m"]
*/
angular.module('app').factory('ClassMember', function () {
return function ClassMember(fn) {
if (this instanceof ClassMember) {
this.fn = fn;
} else {
return new ClassMember(fn);
}
};
});
angular.module('app').factory('Class', function (ClassMember) {
var runtime = { initializing: false },
fnTest = /xyz/.test(function() { xyz; }) ? /\bbase\b/ : /.*/,
FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,
STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var toString = Object.prototype.toString;
// The base Class implementation (does nothing)
function Class() { };
Class.members = { };
// Create a new Class that inherits from this class
Class.extend = function extend(displayName, properties) {
var array;
var targetMembers = {};
var sourceMembers = this.members;
for (var memberName in sourceMembers) {
if (sourceMembers.hasOwnProperty(memberName)) {
targetMembers[memberName] = sourceMembers[memberName];
}
}
var base = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the ctor constructor)
runtime.initializing = true;
var prototype = new this();
runtime.initializing = false;
// Copy the properties over onto the new prototype
for (var name in properties) {
if (properties.hasOwnProperty(name)) {
// Check if we're overwriting an existing function
var property = properties[name];
// Support angular's controller/service/factory declaration notation
if (toString.call(property) === '[object Array]') {
array = property;
var item = array[array.length - 1];
if (toString.call(item) === '[object Function]' || item instanceof ClassMember) {
property = array[array.length - 1];
} else {
array = null;
}
} else {
array = null;
}
var isClassMember = property instanceof ClassMember;
if (isClassMember) {
property = property.fn;
}
if (typeof property === "function") {
if (typeof base[name] === "function" && fnTest.test(property)) {
property = (function (propertyName, fn) {
var args = fn.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1];
return (new Function('propertyName', 'fn', 'base', 'return function (' + args + ') {\n\
var prevBase = this.base;\n\
var hasBase = "base" in this;\n\
\n\
// Add a new .base() method that is the same method\n\
// but on the super-class\n\
\n\
this.base = base[propertyName];\n\
\n\
// The method only need to be bound temporarily, so we\n\
// remove it when we\'re done executing\n\
var ret = fn.call(this' + (!!args ? (', ' + args) : args) + ');\n\
\n\
if (hasBase) {\n\
this.base = prevBase;\n\
} else {\n\
delete this["base"];\n\
}\n\
return ret;\n\
}'))(propertyName, fn, base);
})(name, property);
}
if (isClassMember) {
targetMembers[name] = property;
} else if (name in targetMembers) {
delete targetMembers[name];
}
if (array) {
array[array.length - 1] = property;
property = array;
}
prototype[name] = property;
} else {
prototype[name] = property;
}
}
}
var membersArray = [];
for (var i in targetMembers) {
if (targetMembers.hasOwnProperty(i)) {
membersArray.push({ name: i, fn: targetMembers[i] });
}
}
// All construction is actually done in the ctor method
var ChildClass = (new Function("runtime", "members", "FN_ARGS", "STRIP_COMMENTS", "return function " + (displayName || "Class") + "() {\n\
if (!runtime.initializing && this.ctor)\n\
{\n\
var length = members.length;\n\
for (var i = 0; i < length; i++)\n\
{\n\
var item = members[i];\n\
this[item.name] = (function (me, fn) {\n\
var args = fn.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1];\n\
return args ? (new Function('me', 'fn', 'return function (' + args + ') { return fn.call(me, ' + args + '); }'))(me, fn) : function () { return fn.call(me); };\n\
})(this, item.fn);\n\
\n\
}\n\
this.ctor.apply(this, arguments);\n\
}\n\
}"))(runtime, membersArray, FN_ARGS, STRIP_COMMENTS);
ChildClass.members = targetMembers;
// Populate our constructed prototype object
ChildClass.prototype = prototype;
// Enforce the constructor to be what we expect
ChildClass.prototype.constructor = ChildClass;
// And make this class extendable
ChildClass.extend = extend;
return ChildClass;
};
return Class;
});
Another edit
Eventually I've stumbled upon another problem related to original John Resig's implementation in relation to angular, and the problem is related to angular's annotation process (used for dependency injection) which uses Function.prototype.toString() and some Regex'es for the purpose of extracting the names of dependencies. And the problem with original implementation is that it doesn't expect this and so you are not able to declare methods that accept dependencies, so I've tweaked the implementation a little bit to deal with previously described problem and here it is:
/* Simple JavaScript Inheritance
* By John Resig http://ejohn.org/
* MIT Licensed.
*
* Inspired by base2 and Prototype
* Angular adaptations by Denis Yaremov http://github.com/lu4
* Usage:
---------------------------------
var X = Class.extend('X', {
ctor: function () {
this.name = "I'm X";
},
myOrdinaryMethod: function (x, y, z) {
console.log([this.name, x, y, z]);
},
myClassMemberMethod: ClassMember(function (x, y, z) {
console.log([this.name, x, y, z]);
})
});
var Y = Class.extend('Y', {
ctor: function () {
this.name = "I'm Y";
},
myOrdinaryMethod: function (x, y, z) {
console.log([this.name, x, y, z]);
},
myClassMemberMethod: ClassMember(function (x, y, z) {
console.log([this.name, x, y, z]);
})
});
var x = new X();
var y = new Y();
x.myClassMemberMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"]
y.myClassMemberMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"]
x.myOrdinaryMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"]
y.myOrdinaryMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"]
y.theirOrdinaryMethod = x.myOrdinaryMethod;
y.theirClassMemberMethod = x.myClassMemberMethod;
y.theirOrdinaryMethod('a', 'b', 'c'); // ["I'm Y", "a", "b", "c"]
y.theirClassMemberMethod('u', 'v', 'm'); // ["I'm X", "u", "v", "m"]
*/
angular.module('homer').factory('Class', function () {
function ClassMember(fn) {
if (this instanceof ClassMember) {
this.fn = fn;
return this;
} else {
return new ClassMember(fn);
}
}
function ClassEvent() {
if (this instanceof ClassEvent) {
return this;
} else {
return new ClassEvent();
}
}
var runtime = { initializing: false },
fnTest = /xyz/.test(function () { xyz; }) ? /\bbase\b/ : /.*/,
fnArgs = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,
stripComments = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var toString = Object.prototype.toString;
// The base Class implementation (does nothing)
function Class() { };
Class.events = {};
Class.members = {};
// Create a new Class that inherits from this class
Class.extend = function Extend(displayName, properties) {
var array;
var targetEvents = {};
var sourceEvents = this.events;
var targetMembers = {};
var sourceMembers = this.members;
for (var eventName in sourceEvents) {
if (sourceEvents.hasOwnProperty(eventName)) {
targetEvents[eventName] = sourceEvents[eventName];
}
}
for (var memberName in sourceMembers) {
if (sourceMembers.hasOwnProperty(memberName)) {
targetMembers[memberName] = sourceMembers[memberName];
}
}
var base = this.prototype;
// Instantiate a base class (but only create the instance,
// don't run the ctor constructor)
runtime.initializing = true;
var prototype = new this();
runtime.initializing = false;
// Copy the properties over onto the new prototype
for (var name in properties) {
if (properties.hasOwnProperty(name)) {
// Check if we're overwriting an existing function
var property = properties[name];
// Support angular's controller/service/factory declaration notation
if (toString.call(property) === '[object Array]') {
array = property;
var item = array[array.length - 1];
if (toString.call(item) === '[object Function]' || item instanceof ClassMember) {
property = array[array.length - 1];
} else {
array = null;
}
} else {
array = null;
}
var isClassMember = property instanceof ClassMember;
if (isClassMember) {
property = property.fn;
}
var isClassEvent = property instanceof ClassEvent;
if (isClassEvent) {
property = (function() {
function Subscriber(fn) {
Subscriber.listeners.push(fn.bind(this));
};
Subscriber.listeners = [];
Subscriber.fire = function() {
var listeners = Subscriber.listeners;
for (var i = 0; i < listeners.length; i++) {
var result = listeners[i].apply(this, arguments);
if (result !== undefined) return result;
}
return void 0;
}
return Subscriber;
})();
}
if (typeof property === "function") {
if (typeof base[name] === "function" && fnTest.test(property)) {
property = (function (propertyName, fn) {
var args = fn.toString().replace(stripComments, '').match(fnArgs)[1];
return (new Function('propertyName', 'fn', 'base', 'return function (' + args + ') {\n\
var prevBase = this.base;\n\
var hasBase = "base" in this;\n\
\n\
// Add a new .base() method that is the same method\n\
// but on the super-class\n\
\n\
this.base = base[propertyName];\n\
\n\
// The method only need to be bound temporarily, so we\n\
// remove it when we\'re done executing\n\
var ret = fn.call(this' + (!!args ? (', ' + args) : args) + ');\n\
\n\
if (hasBase) {\n\
this.base = prevBase;\n\
} else {\n\
delete this["base"];\n\
}\n\
return ret;\n\
}'))(propertyName, fn, base);
})(name, property);
}
if (isClassEvent) {
targetEvents[name] = property;
} else {
delete targetEvents[name];
}
if (isClassMember) {
targetMembers[name] = property;
} else if (name in targetMembers) {
delete targetMembers[name];
}
if (array) {
array[array.length - 1] = property;
property = array;
}
prototype[name] = property;
} else {
prototype[name] = property;
}
}
}
var eventsArray = [];
for (var targetEventName in targetEvents) {
if (targetEvents.hasOwnProperty(targetEventName)) {
eventsArray.push({ name: targetEventName, fn: targetEvents[targetEventName] });
}
}
var membersArray = [];
for (var targetMemberName in targetMembers) {
if (targetMembers.hasOwnProperty(targetMemberName)) {
membersArray.push({ name: targetMemberName, fn: targetMembers[targetMemberName] });
}
}
// All construction is actually done in the ctor method
var ChildClass = (new Function("runtime", "events", "members", "FN_ARGS", "STRIP_COMMENTS", "return function " + (displayName || "Class") + "() {\n\
if (!runtime.initializing && this.ctor)\n\
{\n\
var length = members.length;\n\
var bind = function (me, $$fn$$) {\n\
var args = $$fn$$.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1];\n\
var result = args ? (new Function('me', '$$fn$$', 'return function (' + args + ') { return $$fn$$.apply(me, arguments); }'))(me, $$fn$$) : function () { return $$fn$$.apply(me, arguments); };\n\
return result;\n\
};\n\
for (var i = 0; i < length; i++)\n\
{\n\
var item = members[i];\n\
var fn = item.fn;\n\
var name = item.name;\n\
var property = this[name] = bind(this, fn);\n\
if (fn.fire) {\n\
property.fire = bind(this, fn.fire);\n\
}\n\
if (fn.listeners) {\n\
property.listeners = fn.listeners;\n\
}\n\
}\n\
\n\
var length = events.length;\n\
for (var i = 0; i < length; i++)\n\
{\n\
var item = events[i];\n\
var fn = item.fn;\n\
var name = item.name;\n\
var property = this[name] = bind(this, fn);\n\
if (fn.fire) {\n\
property.fire = bind(this, fn.fire);\n\
}\n\
if (fn.listeners) {\n\
property.listeners = fn.listeners;\n\
}\n\
}\n\
this.ctor.apply(this, arguments);\n\
}\n\
}"))(runtime, eventsArray, membersArray, fnArgs, stripComments);
ChildClass.members = targetMembers;
// Populate our constructed prototype object
ChildClass.prototype = prototype;
// Enforce the constructor to be what we expect
ChildClass.prototype.constructor = ChildClass;
// And make this class extendable
ChildClass.extend = Extend;
ChildClass.event = ClassEvent;
ChildClass.member = ClassMember;
return ChildClass;
};
Class.member = ClassMember;
Class.event = ClassEvent;
return Class;
});
Your guesses sounds perfectly applicable.
You can reuse functionality defined in parent controllers by simply calling methods attached to the parent scope:
HTML
<div ng-controller="ParentCtrl">
<!-- Something here ... -->
<div ng-controller="ChildCtrl">
<!-- Something here ... -->
</div>
<!-- Something here ... -->
</div>
JavaScript
function ParentCtrl($scope) {
$scope.parentMethod = function () {
//method body
};
}
function ChildCtrl($scope) {
$scope.childMethod = function () {
//functionality
$scope.parentMethod();
//functionality
};
}
If you want to use the JavaScript approach with prototype inheritance you can use:
var myApp = angular.module('myApp',[]);
function Parent($scope) {
$scope.name = 'Superhero';
$scope.clickParent = function() {
$scope.name = 'Clicked from base controller';
}
}
function Child($scope, $injector) {
debugger;
$injector.invoke(Parent, this, {$scope: $scope});
$scope.name = 'Superhero Child';
$scope.clickChild = function(){
$scope.clickParent();
}
}
Child.prototype = Object.create(Parent.prototype);
http://jsfiddle.net/mhevery/u6s88/12/
For services, for example, you can use:
(function () {
function ParentService(arg1) {
this.arg1 = arg1;
}
function ChildService(arg1, arg2) {
ParentService.call(this, arg1);
this.arg2 = arg2;
}
ChildService.prototype = new ParentService();
app.service('ChildService', ChildService);
}());
Also check this discussion and the blog post about inheritance in AngularJS I posted.
Let me give you my opinion on Angular / inheritance situation.
You don't do class/prototypical inheritance in Angular.js. It can be hard to test, and that is a problem. For those, who are looking for 'inheritance' in Angular, I recommend this:
Your base class is the controller. The controller is an abstract model anyways, so it is perfect for that purpose. Use a $scope.init() function in your controller, but don't call it from there!
If you want to 'extend' your controller's functionality, use directives. In you directive link() function, call the controller's $scope.init(). (when compiling, angular runs controllers first, and directive link functions after). If scope had a $scope.name='base', in the directive link you will be able to redefine $scope.name=child, and after that, run $scope.init().
But wait! But this only allows a single-level inheritance. - Yes, thats true. But if you are looking for multilevel inheritance, you should use Services.
Multilevel inheritance is nothing else, but sharing the same code in a hierarchical class structure. For this purpose, use Services, and throw in these services with the dependency injector into your directives. Soo easy. This should be easy to accomplish, easy to understand, and tests run smooth.
Directives are very powerful tools, because you can dynamically combine partials with controllers.
I think your guesses are pretty good and I played with a few approaches like that, but they all turned out more verbose than I had hoped.
I had a problem where I had developed a complex dialog as a tab in our admin interface, but I wanted an almost identical dialog in a popup in the user section, but the data would be populated from a different source and there would be a few additional buttons. Basically a great candidate for classical inheritance. For the UI side I used a template which was included in two places with different controllers. But to avoid duplicating the complex UI logic in the controllers I wanted to use inheritance.
The scope inheritance method relies somewhat on the structure of the application and wasn't appropriate because the two UIs were in effectively different applications. The approach of putting reused code into services would end up being verbose as I would have needed to have each controller method call an equivalent method on the service. So I used the following simple approach to JavaScript inheritance:
/**
* Effective base class for Thing Controllers.
* This should be considered abstract since it does not define
* $scope.readData() or $scope.saveData() which may be called from its
* other functions.
*/
function BaseThingController($scope, $http){
$scope.data = []; // local data store;
$scope.validateForm(){...}
$scope.edit(){...}
$scope.cancel(){...}
$scope.reset(){...}
$scope.otherMethod1(){...}
$scope.otherMethod2(){...}
$scope.otherMethod3(){...}
}
/**
* AdminThingController effectively extends BaseThingController
*/
function AdminThingController($scope, $http){
// Calling BaseThingController as a function defines all the needed
// functions and properties in our scope.
BaseThingController($scope, $http)
$scope.readData(){
// $scope.data = data from admin data source
}
$scope.saveData(newData){
// save to special admin service
}
// initialize local data
$scope.readData()
}
/**
* UserThingController effectively extends BaseThingController
*/
function UserThingController($scope, $http){
// Calling BaseThingController as a function defines all the needed
// functions and properties in our scope.
BaseThingController($scope, $http)
$scope.readData(){
// $scope.data = data from user data source
}
$scope.saveData(newData){
// save to user service
}
/**
* Overriding base class behaviour here
*/
$scope.otherMethod1(){...}
// initialize local data
$scope.readData()
}
So I've not used prototype inheritance as the $scope is readily available. But I have gained all the behaviour from the base controller and only added or overridden what I want to. My views could be configured with either controller and would work with no modifications.

WebView title is sometimes null when it shouldn't be

I'm writing a simple browser in Vala and WebKitGTK+.
One of the things I need to do is set the window's title to that of the webpage title, so I monitor title changes with web_view.notify["title"].connect. However, sometimes the value of title is null, when it obviously shouldn't be.
Some examples I remember:
Search anything in Google. Going to the next results page sets the title to null.
Click on an anchor link (e.g. http://example.com/page.html#section)
In any case, using the Web Inspector shows that the pages do have a title set.
Is this a bug I should report? Or maybe I'm doing something wrong? Here's the code I'm using:
//valac --thread --pkg webkitgtk-3.0 --pkg gtk+-3.0 --vapidir=./ test.vala
//The vapidir folder should have webkitgtk-3.0.vapi and webkitgtk-3.0.deps
using WebKit;
using Gtk;
public class Test : Gtk.Window {
public WebView webview;
public Test () {
this.title = "Test";
this.window_position = Gtk.WindowPosition.CENTER;
this.set_default_size (800, 600);
this.hide_titlebar_when_maximized = false;
this.destroy.connect (() => {
Gtk.main_quit ();
});
var scroll = new ScrolledWindow (null, null);
this.webview = new WebView ();
this.add (scroll);
scroll.add (webview);
webview.settings.enable_developer_extras = true;
webview.notify["title"].connect ((sender, property) => {
if (webview.title != null) {
this.title = webview.title;
stdout.printf (webview.title + "\n");
} else {
stdout.printf ("(null)\n");
}
});
webview.web_inspector.inspect_web_view.connect ((p0) => {
var w = new Window ();
w.window_position = WindowPosition.CENTER;
w.title = "Inspector";
w.set_default_size (800,600);
WebView view = new WebView ();
unowned WebView view2 = view;
w.add (view2);
w.show_all ();
return view2;
});
}
public static int main (string[] args) {
Gtk.init (ref args);
Test app = new Test ();
app.webview.load_uri ("http://google.com");
app.show_all ();
Gtk.main ();
return 0;
}
}
There is a signal called title_changed for that purpose and you should always use the signals provided by webkitgtk instead of the GLib notify feature.
(GLib notify is emitted each time a value changes, even if the change is just for the purpose of clearing the old value, such as in your case.)

JavaScript - run once without booleans

Is there a way to run a piece of JavaScript code only ONCE, without using boolean flag variables to remember whether it has already been ran or not?
Specifically not something like:
var alreadyRan = false;
function runOnce() {
if (alreadyRan) {
return;
}
alreadyRan = true;
/* do stuff here */
}
I'm going to have a lot of these types of functions and keeping all booleans would be messy...
An alternative way that overwrites a function when executed so it will be executed only once.
function useThisFunctionOnce(){
// overwrite this function, so it will be executed only once
useThisFunctionOnce = Function("");
// real code below
alert("Hi!");
}
// displays "Hi!"
useThisFunctionOnce();
// does nothing
useThisFunctionOnce();
'Useful' example:
var preferences = {};
function read_preferences(){
// read preferences once
read_preferences = Function("");
// load preferences from storage and save it in 'preferences'
}
function readPreference(pref_name){
read_prefences();
return preferences.hasOwnProperty(pref_name) ? preferences[pref_name] : '';
}
if(readPreference('like_javascript') != 'yes'){
alert("What's wrong wth you?!");
}
alert(readPreference('is_stupid') ? "Stupid!" : ":)");
Edit: as CMS pointed out, just overwriting the old function with function(){} will create a closure in which old variables still exist. To work around that problem, function(){} is replaced by Function(""). This will create an empty function in the global scope, avoiding a closure.
I like Lekensteyn's implementation, but you could also just have one variable to store what functions have run. The code below should run "runOnce", and "runAgain" both one time. It's still booleans, but it sounds like you just don't want lots of variables.
var runFunctions = {};
function runOnce() {
if(!hasRun(arguments.callee)) {
/* do stuff here */
console.log("once");
}
}
function runAgain() {
if(!hasRun(arguments.callee)) {
/* do stuff here */
console.log("again");
}
}
function hasRun(functionName) {
functionName = functionName.toString();
functionName = functionName.substr('function '.length);
functionName = functionName.substr(0, functionName.indexOf('('));
if(runFunctions[functionName]) {
return true;
} else {
runFunctions[functionName] = true;
return false;
}
}
runOnce();
runAgain();
runAgain();
A problem with quite a few of these approaches is that they depend on function names to work: Mike's approach will fail if you create a function with "x = function() ..." and Lekensteyn's approach will fail if you set x = useThisFunctionOnce before useThisFunctionOnce is called.
I would recommend using Russ's closure approach if you want it run right away or the approach taken by Underscore.js if you want to delay execution:
function once(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
return memo = func.apply(this, arguments);
};
}
var myFunction = once(function() {
return new Date().toString();
});
setInterval(function() {console.log(myFunction());}, 1000);
On the first execution, the inner function is executed and the results are returned. On subsequent runs, the original result object is returned.
What about an immediately invoked anonymous function?
(function () {
// code in here to run once
})();
the code will execute immediately and leave no trace in the global namespace.
If this code is going to need to be called from elsewhere, then a closure can be used to ensure that the contents of a function are run only once. Personally, I prefer this to a function that rewrites itself as I feel doing so can cause confusion, but to each their own :) This particular implementation takes advantage of the fact that 0 is a falsy value.
var once = (function() {
var hasRun = 0;
return function () {
if (!hasRun) {
hasRun++;
// body to run only once
// log to the console for a test
console.log("only ran once");
}
}
})();
// test that the body of the function executes only once
for (var i = 0; i < 5; i++)
once();
Elegant solution from Douglas Crockford, spent some time to understand how it works and stumbled upon this thread.
So the wrapper once return function which is just invokes parameter's function you passed. And taking advantage of closures this construction replaced passed function to empty function, or null in original source, after the first call, so all the next calls will be useless.
This is something very close to all other answers, but it is kinda self containing code and you could use it independently, which is good. I am still trying to grasp all the entire mechanism of replacement, but practically it just works perfectly.
function once (func) {
return function () {
var f = func;
func = null;
return f.apply(this, arguments);
};
}
function hi(name) {
console.log("Hi %s", name);
}
sayonce = once(hi);
sayonce("Vasya");
sayonce("Petya");
for those who are curious here is jsbin transformations
(function (){
var run = (function (){
var func, blank = function () {};
func = function () {
func = blank;
// following code executes only once
console.log('run once !');
};
return function(){
func.call();
};
})();
run();
run();
run();
run();
})();
I just ran into this problem, and ended up doing something like the following:
function runOnce () {
if (!this.alreadyRan) {
// put all your functionality here
console.log('running my function!');
// set a property on the function itself to prevent it being run again
this.alreadyRan = true;
}
}
This takes advantage of the fact that Javascript properties are undefined by default.
In addition, the nature of what happens in the "/* do stuff here */" may leave something around that, when present, must mean that the function has run e.g.
var counter = null;
function initCounter() {
if (counter === null) {
counter = 0;
}
}
If not bound to an event, code is usually ran once