[Prototype-core] Re: Feature suggestion: getClassName

2008-02-22 Thread GarethAtFlignet

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:

  script
  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());
  /script

  ---

  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

2008-02-22 Thread Yanick

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

2008-02-22 Thread GarethAtFlignet

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: 'script[^]*([\\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 = fullClassName.split(.);

  

[Prototype-core] Re: Feature suggestion: getClassName

2008-02-22 Thread GarethAtFlignet


 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

2008-02-21 Thread Tobie Langel

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:

 script
 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());
 /script

 ---

 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
-~--~~~~--~~--~--~---