Javascript wizards wanted for Zope project
Hi, I'm working on the VisualZope project and have run into some problems with javascript. Since it isn't my native language (python is) I was wondering if some javascript wizards are interested in getting their names in the credits. The problem is: how do I get a form to talk to an object in another frame? ie: <input value=".." ... onchange="mywidget.setAttribute('property', value-of-inputbox)> where mywidget is a javascript function defined in another (loaded) frame. Also, how can I "call" a html page without causing a reload: function jsZDOMsetAttribute(name, value){ call("getWidget/setAttribute?name=name&value=value") } For further information on this problem please see http://163.182.196.200/zwiki/VisualZope - jsZDOM reflecter part. Thanks in advance, Anthony Pfrunder
At 11:45 AM 11/17/99 +1000, Anthony Pfrunder wrote:
The problem is: how do I get a form to talk to an object in another frame? ie:
<input value=".." ... onchange="mywidget.setAttribute('property', value-of-inputbox)>
where mywidget is a javascript function defined in another (loaded) frame.
top.otherFrameName.objectName.method()
Also, how can I "call" a html page without causing a reload:
function jsZDOMsetAttribute(name, value){ call("getWidget/setAttribute?name=name&value=value") }
Create a "hidden" frame, i.e., one that is either zero width or zero height. Set the document.location.href of this frame to the URL you want to call. Note that this is asynchronous, however, and to find out if the page has been loaded, you'll need to make that page have an onLoad function to call back the original frame and say it's loaded (if you need it to do that). Depending on the complexity of your app, you may want/have to also have the caller implement a timeout to catch errors, and/or set up your Zope error page to have Javascript in it that signals an error back to that page. (Whew.)
The following example works in IE 4 and 5. Our company has standardized on IE so I have not yet tested this with Netscape but it should work there too. This is a a variation on a line out of an active page.: <input type=text name=address size=40 name=address maxlength=40 value=<dtml-var "_.string.strip(address)" null=''> onChange="opener.document.ContactForm.address.value=this.value"> This updates a field in the browser window that opened the window this code is in. Have also used nothing but javascipt in a child window to update fields in a parent window. The child form on load updates all the fields in the window that called it and then closes itself. This is handy when you have a complex data entry form with a lot of javascript functions (money formatting, autocalcs, ...)and a number of large select lists (some with 100 plus items). Using this routine, when you save a change to the form, you don't have to waste pipe space reloading the form, you just update the data. __________________________________________________________________ Jim Sanford . Database Engineer / \ / Accelerated Technology, Inc. / / 720 Oak Circle Drive East / / \ Mobile, AL 36609 / / \ Voice: 334-661-5770 fax: 334-661-5788 / \ E-Mail: jsanford@atinucleus.com Web: http://www.atinucleus.com Source Code, No Royalties, Any CPU...It just make sense ! __________________________________________________________________ ----- Original Message ----- From: Anthony Pfrunder <s341625@student.uq.edu.au> To: <zope@zope.org>; <zope-dev@zope.org> Sent: Tuesday, November 16, 1999 7:45 PM Subject: [Zope-dev] Javascript wizards wanted for Zope project
Hi,
I'm working on the VisualZope project and have run into some problems with javascript. Since it isn't my native language (python is) I was wondering if some javascript wizards are interested in getting their names in the credits.
The problem is: how do I get a form to talk to an object in another frame? ie:
<input value=".." ... onchange="mywidget.setAttribute('property', value-of-inputbox)>
where mywidget is a javascript function defined in another (loaded) frame.
Also, how can I "call" a html page without causing a reload:
function jsZDOMsetAttribute(name, value){ call("getWidget/setAttribute?name=name&value=value") }
For further information on this problem please see http://163.182.196.200/zwiki/VisualZope - jsZDOM reflecter part.
Thanks in advance,
Anthony Pfrunder
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://lists.zope.org/mailman/listinfo/zope-dev No cross posts or HTML encoding! (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
OOPS. Should have been: ...value="<dtml-var "_.string.strip(address)" null="">"...
After studying Jeffrey Shell's ZLDAP package, and the current ZODB system, in the light of recent conversations with Jim Fulton, a few lightbulbs went on with respect to the usefulness of multi-database Zopelications. For example, wouldn't it be keen if regular Zope objects could 'store' object attributes that were actually LDAP entries? Or SQL database records? That would be pretty awesome. The cool thing about the ZLDAP stuff is that the LDAP Connection object, itself a database, is actually a persistent object stored in the regular ZODB. That suggests a clean and sensible way to integrate multi-database Zopes: any given Zope installation must store connections to other databases as persistent objects within its "root" database. That is, any Persistent object in a particular Zopelication should have a _p_jar attribute which either points to the REQUEST-owned Connection, or to an jar which meets this criterion (recursively). This means that one could, at least in theory, reach any database in a multidatabase system by following an ever-expanding tree of database references. Now, if this property is followed, then it is possible for an object in any database to refer to any object which is located "downstream" in the tree. That is, an object O1 in database DB1 can reference object O2 in database DB2 so long as DB2 is reached by way of a persistent object stored in DB1, or a database thus referenced by DB1, recursively. (Upstream references are not possible without a global database naming system; however, there is nothing about my suggested implementation that prevents a global naming scheme from later being used either together with, or in place of, this model.) Due to this tree-oriented nature, this multidatabase model is most appropriate to Zopelications which provide for local needs in a local database, but need to reference other, shared databases or legacy systems. (Note: this model does not support multi-database undo, which requires a global naming mechanism for databases and transactions, so that data integrity can be maintained by refusing to undo transactions unless all databases which were involved can undo it.) Anyway... making references work. Initially, to test this concept, a simple mode of implementation at the application level is to provide a getReference function. If I want to store an object in one of my attributes, I would say: self.attribute = getReference(self,object) The function would look something like: def getReference(source,target): tgt_jar = target._p_jar # note: fails if we can't make reference if tgt_jar is source._p_jar or tgt_jar is None: return target return RemoteReference(getReference(source,tgt_jar),target._p_oid) This recursively builds a dereferencing object which, when retrieved from my self.attribute later, will return the object from the correct database. The RemoteReference class is as follows (or equivalent in C): class RemoteReference(ExtensionClass.Base): def __init__(self,jar,oid): self.jar, self.oid = jar,oid def __of__(self,parent): object = self.jar[self.oid] if hasattr(object,'__of__'): return object.__of__(parent) return object The RemoteReference class simply refers to a jar (which must be a persistent object) and an oid to be retrieved from the jar. When a RemoteReference is retrieved from an object, it will replace itself with the result of retrieving that oid from that jar, and call __of__ on that result. (Note that if the jar itself can be referenced by a RemoteReference, and it will be unpacked when we do self.jar to use it. Thus, a reference "two databases deep" (or more) will be properly unpacked.) Notice that this works even if a portion of a database tree is isolated and used as a root unto itself, since anything stored in a given database can only reference objects in itself, or in databases referenced from it. In order for this protocol to work, one need only do two things: * Any database which wishes to be referenceable must be able to have Connection-like objects stored as Persistent objects. * When storing a reference to another object, one must call getReference(self,object) and store the result, AND, self must already be assigned a _p_jar. The first requirement burdens database implementors, but it is not that far out of the question. It merely needs a Persistent object which can delegate its behavior to a "real" Connection object of some kind. The second requirement burdens those who would store foreign references, and seems a bit more severe, although it seems that often one will know when one is trying to do this. This application-level restriction could be eased by extending databases' persistent_id mechanism (used w/cPickle) to return a RemoteReference as the oid of an object stored in a foreign jar. When they are asked for an object whose oid is a RemoteReference object, they can simply return the RemoteReference itself, or automatically dereference it. The latter has the potential problem of perhaps unnecesarily waking up currently dormant databases, but I suspect it is unlikely to be a real problem in practice. (Note that any such waking-up will be bounded by the depth of the database tree which is currently in use, and also that this mechanism does not preclude the future use of RemoteReferences based on a global naming scheme, or of cyclical references under such a scheme.) To sum up, this seems like a reasonably workable approach to cross-database references in Zope where such references proceed from private "roots" to shared "leaves" of a database tree. It is incrementally implementable, and does not initially require changing any part of the existing Zope framework. But, with additional effort, it can be scaled up to provide better ease-of-use and generality. Creating a "database" that can take advantage of the protocol could be almost as simple as making a Persistent object whose __getitem__ method calls an SQL method to retrieve something from a database, then sets object._p_jar=self and object._p_oid=retrieval_key. Presto, you now have an SQL record which can be "pointed to" by ZODB objects, which need not concern themselves with the details of SQL involved. At this point, all sorts of application ideas begin bubbling through my head, ranging from having counter-type objects stored in suitable storages, to having "storage-managed object pools", a concept Ty and I have been batting around for some time as a means of reducing certain types of write-contention in large applications, and for taking advantage of BerkeleyDB and other databases' native indexing facilities. Anyway, further applications are left as an exercise for the reader. :) Comments?
At 05:58 17/11/99 , Phillip J. Eby wrote:
After studying Jeffrey Shell's ZLDAP package, and the current ZODB system, in the light of recent conversations with Jim Fulton, a few lightbulbs went on with respect to the usefulness of multi-database Zopelications. For example, wouldn't it be keen if regular Zope objects could 'store' object attributes that were actually LDAP entries? Or SQL database records? That would be pretty awesome.
I believe that Jim Fulton has let his mind wander over this already. The general implementation wasn't hard, he said, the problems arise in the details. How, for example, do you remove unreferenced objects from any such database? How do you find out if an otherwise unreferenced object in one database, is not referenced by another one. Also, IIRC, there is an issue with caching and connections, and the question of when to close a connection to a referenced database. But as I was experiencing some jet-lag at the time, and didn't bring a memo recording when I spoke with Jim, I don't remember the full details. -- Martijn Pieters, Web Developer | Antraciet http://www.antraciet.nl | Tel: +31-35-7502100 Fax: +31-35-7502111 | mailto:mj@antraciet.nl http://www.antraciet.nl/~mj | PGP: http://wwwkeys.nl.pgp.net:11371/pks/lookup?op=get&search=0xA8A32149 ------------------------------------------
At 10:43 AM 11/17/99 +0100, Martijn Pieters wrote:
At 05:58 17/11/99 , Phillip J. Eby wrote:
Also, IIRC, there is an issue with caching and connections, and the question of when to close a connection to a referenced database. But as I was experiencing some jet-lag at the time, and didn't bring a memo recording when I spoke with Jim, I don't remember the full details.
Actually, this is (fairly) straightforward to handle since the connections themselves are Persistent and subject to caching. Implementing such a connection as a Persistent object can be anywhere from very easy to moderately complex, depending on the nature of the database backing it. Manipulation of _p_changed may be necessary. I point to ZLDAP as an example of one that works, although I don't think it will currently work correctly if the LDAPConnection is deactivated by the cache machinery during a transaction.
I believe that Jim Fulton has let his mind wander over this already. The general implementation wasn't hard, he said, the problems arise in the details. How, for example, do you remove unreferenced objects from any such database? How do you find out if an otherwise unreferenced object in one database, is not referenced by another one.
Like cross-database undo, cross-database garbage collection also requires a global naming scheme. However, the point of my proposal wasn't to create a full multi-database Zope implementation, but rather, a tool for providing database-independent referencing, making it possible for an object's place in the Zope URL hierarchy to be independent of its physical database location - a mechanism roughly analagous to a hard-link, but still breakable like a symlink. This hard-link mechanism improves over symlinks by having a signifcantly lesser performance penalty for dereferencing, better transparency of usage, and by allowing a reference to be independent of the target object's acquisition hierarchy. (Since it will be treated as belonging to the hierarchy of the object that points to it, not the hierarchy it originally came from.) An example usage: suppose you create a UserFolder that lets you paste arbitrary objects into it as users, and it stores them using getReference(). You could, within the same folder, paste references to users stored in relational databases, LDAP databases, and perhaps "person" objects from some other part of the same ZODB. The UserFolder wouldn't care where they came from. This might seem a contrived example, but in dealing with some of the "legacy" environments I deal with, such a thing could be quite handy in allowing only hand-selected individuals access to a Zope installation, but without requiring password maintenance to be part of the Zope application itself.
I know you have been given many answers, but I'll bud in anyway. I've done way too much JavaScript, I like to think I know it's pitfalls. At 02:45 17/11/99 , Anthony Pfrunder wrote:
The problem is: how do I get a form to talk to an object in another frame? ie:
<input value=".." ... onchange="mywidget.setAttribute('property', value-of-inputbox)>
where mywidget is a javascript function defined in another (loaded) frame.
You can just refer to it's name via the frameset that defines it, like parent.nameofotherframe,mywidget.setAttribute(), but you can never be sure that the other frame has been loaded. To get around this problem, I use an asynchronous message broker in the parent frame. The calling frame checks for a boolean property on it's parent to check wether or not it is capable of doing the messaging, then calling a method on this parent that'll pass on the message to the receiving frame: onLoad="if (parent.bIsTop) parent.setMenu('foo')" The receiving frame sets a boolean flag on the same parent frame to signal it is ready to receive messages: onLoad="if (parent.bIsTop) parent.bNavLoaded = true;" You can now use setTimeout, and a counter, to pass the message on. As long as bNavLoaded (the flag indicating messages can be passed on) is false, and we haven't tried too many times yet, wait a specified time and try again. A real life example using two way message passing is used on http://www.marantz.com/, in both the Hifi and Professional sections (altough I don't think the Professional section is live yet). In the Hifi section, the navigation frame signals the right hand frame on mouse-over events to show descriptions of the menu choices, and the right hand frame, when deeper into the site, signals the navigation frame to tell it what menu option to display. This way the user can use te back and forward buttons of his browser to step through it's browsing history, and the navigation menu follows suit.
Also, how can I "call" a html page without causing a reload:
function jsZDOMsetAttribute(name, value){ call("getWidget/setAttribute?name=name&value=value") }
For further information on this problem please see http://163.182.196.200/zwiki/VisualZope - jsZDOM reflecter part.
For this one you'll need a hidden frame (width or height of 0), or you could use a hidden DynDuo Layer and use it's load method: http://www.dansteinman.com/dynduo/en/dynlayer-common.html You should be able to then also read attributes from the server with this. Just have the server return a page with javascript in it that does the trick. Just remember, that you cannot wait for the page to load and expect it to return a value, you'll have to write something asynchronous (and non-blocking, Navigator's Javascript implementation is single threaded, use setTimeout) to retrieve the value. -- Martijn Pieters, Web Developer | Antraciet http://www.antraciet.nl | Tel: +31-35-7502100 Fax: +31-35-7502111 | mailto:mj@antraciet.nl http://www.antraciet.nl/~mj | PGP: http://wwwkeys.nl.pgp.net:11371/pks/lookup?op=get&search=0xA8A32149 ------------------------------------------
participants (4)
-
Anthony Pfrunder -
Jim Sanford -
Martijn Pieters -
Phillip J. Eby