[Prototype-core] Re: Feature suggestion: getClassName
> > Personnally, I fail to see the point of a getClassName() function... > but it could be useful in some cases. (--to the OP) Keep in mind that > the concept of "Classes" in JS is not as straightforeward as in pure > Java (or other OO languages); because of it's loose-type syntax, any > anonymous function can be transformed into an object. For example : > Completely agree with you in principle regarding general Javascript, but with regards Class.create and inheritance functionality Prototype is surely trying to imitate traditional OO and therefore having some of the common helper functions may be useful. By the way, your getClassName code is great, perfect for my needs. Combining that into the namespace stuff will be great for my project. On a related note, anyone have any ideas how I could get rid of the eval in the code I submitted? as the removal of an eval overhead should allow for the combining of the include functionlity into the package function, removing the need of a seperate include method. Many thanks for your help. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Feature suggestion: getClassName
Thanks Yanick, will look at your code in a few mins. In the meantime here is some code that I added to provide OO namespace functionality I need for a project we're working on (please bear in mind that my javascript skills have rarely gone beyond the odd piece of DOM manipulation and as such it is probably not the most elegant of solutions): getClassName() getNamespace() package(namespace) include(namespace) --- Test Scipt // function to output debug info function out(obj) { alert(obj.getClassName() + " : "+obj.getNamespace()); } // define the classes Class.create('org.protoypejs.Foo', { initialize: function() { out(this); } }); Class.create('org.protoypejs.Bar', org.protoypejs.Foo, { }); Class.create('Yahoo', { initialize: function() { out(this); } }); Class.create('LiveSearch', Yahoo, { }); // create some test objects in // the org.protoypejs namespace var test1 = new org.protoypejs.Foo(); var test2 = new org.protoypejs.Bar(); // create some objects in the // local namespace objects var test3 = new Yahoo(); var test4 = new LiveSearch(); // change the package // (the namespace for new class definitions) package("org.protoypejs"); // create classes called Ho and Hum Class.create('Ho', { initialize: function() { out(this); } }); Class.create('Hum', org.protoypejs.Ho, { initialize: function() { out(this); } }); var test5 = new org.protoypejs.Ho(); var test6 = new org.protoypejs.Hum(); // include a namespace include("org.protoypejs"); var test7 = new Ho(); var test8 = new Hum(); --- Modifications to prototype.js var Prototype = { Version: '1.6.0.2', Package: '', Browser: { IE: !!(window.attachEvent && !window.opera), Opera: !!window.opera, WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) }, BrowserFeatures: { XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, SpecificElementExtensions: document.createElement('div').__proto__ && document.createElement('div').__proto__ !== document.createElement('form').__proto__ }, ScriptFragment: ']*>([\\S\\s]*?)<\/script>', JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, emptyFunction: function() { }, K: function(x) { return x } }; if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false; /* * Set the default namespace for new class declarations * * package("org.prototypejs"); * * Class.create('TestClass1', { }); * Class.create('TestClass2', { }); * * will define two classes org.prototypejs.TestClass1 * and org.prototypejs.TestClass2. Alternatively you * could define the classes using: * * package(""); * * Class.create('org.prototypejs.TestClass1', { }); * Class.create('org.prototypejs.TestClass2', { }); */ function package(ns) { Prototype.Package = ns; } /* * Include a namespace into the global namespace * * This allows you to access classes within a namespace * from within the global scope. For example: * * package(""); * Class.create('org.prototypejs.TestClass1', { }); * * // long winded * var myTestClass1 = new org.prototypejs.TestClass1(); * * // better * include("org.prototypejs"); * var myTestClass1 = new TestClass1(); */ function include(ns) { var nsParts = ns.split("."); for (var c in window.org.protoypejs) { // could add a check here to see // if we're overwriting something // in the global namespace... // need to get rid of this eval... window[c] = eval(ns+"."+c); } } /* Based on Alex Arnell's inheritance implementation. */ var Class = { create: function() { var parent = null, properties = $A(arguments); // some new variables var fullClassName = ""; var className = ""; var namespace = ""; if(Object.isString(properties[0])) { if(Prototype.Package=="") { fullClassName = properties.shift(); } else { fullClassName = Prototype.Package+"."+properties.shift(); } } if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } Object.extend(klass, Class.Methods); klass.superclass = parent; klass.subclasses = []; // extract classname and namespace and add to window if(fullClassName!="") { className=fullClassName.substring(fullClassName.lastIndexOf(".") +1); namespace=fullClassName.substring(0, fullClassName.lastIndexOf(".")); var nsParts
[Prototype-core] Re: Feature suggestion: getClassName
On Feb 21, 6:44 am, Tobie Langel <[EMAIL PROTECTED]> wrote: > Hi, > > That unfortunately doesn't solve the problem for namespaced classes: > > var Vehicles = {}; > > Class.create('Vehicle.Cars', {}); > > Best, > > Tobie > No, but this might (just wrote this draft in 10 minutes... could be optimized/fixed, but it works for this test case) Class.getClassName = function(obj) { // recusrivity check (increase rMax for deeper namespacing) var rMax = 3, rCur = 0; var cName = ''; function _objScan(baseName, cClass) { if ( rCur < rMax ) { rCur++; for (var c in cClass) { if ( !(cName.length > 0 && c=='superclass') && typeof(cClass[c]) == 'function' ) { className = baseName + (baseName.length > 0 ? '.' : '') + c; try { if ( obj instanceof cClass[c] && (cName.length==0 || (className.length > cName.length) ) ) { //alert( "cName = " + cName + "(" + cName.length + "), className = " + className + "(" + className.length + "), className.startsWith(cName) = " + className.startsWith(cName) ); cName = className; } _objScan(className, cClass[c]); } catch (e) { //alert(e + " on " + className + " (" + cClass[c] + ")"); } } } rCur--; } }; _objScan('',window); return cName || '{unknown}'; }; Vehicule = Class.create({ initialize: function() { } }); Vehicule.Country = Class.create(Vehicule, { initialize: function($super, country) { $super(); this.name = name; }, getCountry: function() { return this.country } }); Vehicule.Country.Manufacturer = Class.create(Vehicule.Country, { initialize: function($super, country, name) { $super(country); this.name = name; }, getName: function() { return this.name; } }); alert( Class.getClassName(new Vehicule()) ); // --> Vehicule alert( Class.getClassName(new Vehicule.Country('USA')) ); // --> Vehicule.Country alert( Class.getClassName(new Vehicule.Country.Manufacturer('USA', 'Ford')) ); // --> Vehicule.Country.Manufacturer --- Personnally, I fail to see the point of a getClassName() function... but it could be useful in some cases. (--to the OP) Keep in mind that the concept of "Classes" in JS is not as straightforeward as in pure Java (or other OO languages); because of it's loose-type syntax, any anonymous function can be transformed into an object. For example : var foo = new (function(bleh) { this.bleh = function() { return bleh; } })("bar"); alert( foo.bleh() ); // --> "bar" Therefore, the suggested Class.getClassName function in this post is this : alert( Class.getClassName( foo ) ); // --> {unknown} In conclusion, and IMHO, you should not rely on such functions in your Web application. Not until the W3C releases a new JS standard with native Class implementation. Hope this clears out things a bit. -yanick --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Feature suggestion: getClassName
Hi Tobias, By namespaced classes do you mean support for classes named like: com.google.MyTestClass com.yahoo.MyTestClass ? If thats the case then I did add some more fuctionality to support this together with a Prototype.Namespace variable that allows you to set the current namespace so you don't have to refer to classes by their full name. The code is probably nowhere near suitable for addition to Prototype as-is but I'll post it up when I get home for you to look at anyway. Regards Gareth On Feb 21, 11:44 am, Tobie Langel <[EMAIL PROTECTED]> wrote: > Hi, > > That unfortunately doesn't solve the problem for namespaced classes: > > var Vehicles = {}; > > Class.create('Vehicle.Cars', {}); > > Best, > > Tobie > > On Feb 21, 12:10 pm, GarethAtFlignet <[EMAIL PROTECTED]> > wrote: > > > > > > > As prototype provides a convenient OO approach to javascript coding > > through its object inheritance model it would be 'really' useful if > > you could query the name of the current class through a getClassName() > > method or similar like you can in many other languages. > > > There is a post at: > > >http://groups.google.com/group/rubyonrails-spinoffs/browse_thread/thr... > > > which discusses an approach to achieve this and seems backward > > compatible. > > > Code and usage below. Any chance of including 'something' like this in > > a future release? > > > --- > > > Usage: > > > > > Class.create("Vehicle", { }); > > Class.create("Car", Vehicle, { });// Car extends Vehicle > > Class.create("Passat", Car, { }); // Passat extends Car > > > // create one of each > > var v = new Vehicle(); > > var c = new Car(); > > var p = new Passat(); > > > alert(v.getClassName()); > > alert(c.getClassName()); > > alert(p.getClassName()); > > > > > --- > > > Class rewrite: > > > var Class = { > > create: function() { > > > var parent = null, properties = $A(arguments); > > > // retrieve the class name > > var className = ""; > > if(Object.isString(properties[0])) { > > className = properties.shift(); > > } > > > // get the parent > > if (Object.isFunction(properties[0])) > > parent = properties.shift(); > > > function klass() { > > this.initialize.apply(this, arguments); > > } > > > Object.extend(klass, Class.Methods); > > klass.superclass = parent; > > klass.subclasses = []; > > > // reference the class by name > > if(className!="") { > > window[className] = klass; > > } > > > // store the classname as klass.constructor.className > > // and add a method getClassName() to all classes > > klass.className = className; > > klass.prototype.constructor.addMethods({ > > getClassName: function() { > > return this.constructor.className; > > } > > }); > > > if (parent) { > > var subclass = function() { }; > > subclass.prototype = parent.prototype; > > klass.prototype = new subclass; > > parent.subclasses.push(klass); > > } > > > for (var i = 0; i < properties.length; i++) > > klass.addMethods(properties[i]); > > > if (!klass.prototype.initialize) > > klass.prototype.initialize = Prototype.emptyFunction; > > > klass.prototype.constructor = klass; > > > return klass; > > } --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---
[Prototype-core] Re: Feature suggestion: getClassName
Hi, That unfortunately doesn't solve the problem for namespaced classes: var Vehicles = {}; Class.create('Vehicle.Cars', {}); Best, Tobie On Feb 21, 12:10 pm, GarethAtFlignet <[EMAIL PROTECTED]> wrote: > As prototype provides a convenient OO approach to javascript coding > through its object inheritance model it would be 'really' useful if > you could query the name of the current class through a getClassName() > method or similar like you can in many other languages. > > There is a post at: > > http://groups.google.com/group/rubyonrails-spinoffs/browse_thread/thr... > > which discusses an approach to achieve this and seems backward > compatible. > > Code and usage below. Any chance of including 'something' like this in > a future release? > > --- > > Usage: > > > Class.create("Vehicle", { }); > Class.create("Car", Vehicle, { }); // Car extends Vehicle > Class.create("Passat", Car, { }); // Passat extends Car > > // create one of each > var v = new Vehicle(); > var c = new Car(); > var p = new Passat(); > > alert(v.getClassName()); > alert(c.getClassName()); > alert(p.getClassName()); > > > --- > > Class rewrite: > > var Class = { > create: function() { > > var parent = null, properties = $A(arguments); > > // retrieve the class name > var className = ""; > if(Object.isString(properties[0])) { > className = properties.shift(); > } > > // get the parent > if (Object.isFunction(properties[0])) > parent = properties.shift(); > > function klass() { > this.initialize.apply(this, arguments); > } > > Object.extend(klass, Class.Methods); > klass.superclass = parent; > klass.subclasses = []; > > // reference the class by name > if(className!="") { > window[className] = klass; > } > > // store the classname as klass.constructor.className > // and add a method getClassName() to all classes > klass.className = className; > klass.prototype.constructor.addMethods({ > getClassName: function() { > return this.constructor.className; > } > }); > > if (parent) { > var subclass = function() { }; > subclass.prototype = parent.prototype; > klass.prototype = new subclass; > parent.subclasses.push(klass); > } > > for (var i = 0; i < properties.length; i++) > klass.addMethods(properties[i]); > > if (!klass.prototype.initialize) > klass.prototype.initialize = Prototype.emptyFunction; > > klass.prototype.constructor = klass; > > return klass; > } --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype: Core" group. To post to this group, send email to prototype-core@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-core?hl=en -~--~~~~--~~--~--~---