Fixes #1116 - `select.get('value')` on select elements where the <option> elements...
[mootools.git] / Source / Class / Class.js
blob220e3cd6de82bf7bcc8ccc9fc20e827f6c482ae5
1 /*
2 ---
4 name: Class
6 description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
8 license: MIT-style license.
10 requires: [Array, String, Function, Number]
12 provides: Class
14 ...
17 (function(){
19 var Class = this.Class = new Type('Class', function(params){
20         if (instanceOf(params, Function)) params = {initialize: params};
22         var newClass = function(){
23                 reset(this);
24                 if (newClass.$prototyping) return this;
25                 this.$caller = null;
26                 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
27                 this.$caller = this.caller = null;
28                 return value;
29         }.extend(this).implement(params);
31         newClass.$constructor = Class;
32         newClass.prototype.$constructor = newClass;
33         newClass.prototype.parent = parent;
35         return newClass;
36 });
38 var parent = function(){
39         if (!this.$caller) throw new Error('The method "parent" cannot be called.');
40         var name = this.$caller.$name,
41                 parent = this.$caller.$owner.parent,
42                 previous = (parent) ? parent.prototype[name] : null;
43         if (!previous) throw new Error('The method "' + name + '" has no parent.');
44         return previous.apply(this, arguments);
47 var reset = function(object){
48         for (var key in object){
49                 var value = object[key];
50                 switch (typeOf(value)){
51                         case 'object':
52                                 var F = function(){};
53                                 F.prototype = value;
54                                 object[key] = reset(new F);
55                         break;
56                         case 'array': object[key] = value.clone(); break;
57                 }
58         }
59         return object;
62 var wrap = function(self, key, method){
63         if (method.$origin) method = method.$origin;
64         var wrapper = function(){
65                 if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
66                 var caller = this.caller, current = this.$caller;
67                 this.caller = current; this.$caller = wrapper;
68                 var result = method.apply(this, arguments);
69                 this.$caller = current; this.caller = caller;
70                 return result;
71         }.extend({$owner: self, $origin: method, $name: key});
72         return wrapper;
75 var implement = function(key, value, retain){
76         if (Class.Mutators.hasOwnProperty(key)){
77                 value = Class.Mutators[key].call(this, value);
78                 if (value == null) return this;
79         }
81         if (typeOf(value) == 'function'){
82                 if (value.$hidden) return this;
83                 this.prototype[key] = (retain) ? value : wrap(this, key, value);
84         } else {
85                 Object.merge(this.prototype, key, value);
86         }
88         return this;
91 var getInstance = function(klass){
92         klass.$prototyping = true;
93         var proto = new klass;
94         delete klass.$prototyping;
95         return proto;
98 Class.implement('implement', implement.overloadSetter());
100 Class.Mutators = {
102         Extends: function(parent){
103                 this.parent = parent;
104                 this.prototype = getInstance(parent);
105         },
107         Implements: function(items){
108                 Array.from(items).each(function(item){
109                         var instance = new item;
110                         for (var key in instance) implement.call(this, key, instance[key], true);
111                 }, this);
112         }
115 })();