Author: bree Date: Mon Apr 17 16:57:53 2006 New Revision: 2860 Added: azax/branches/plugin/plugins/json/ azax/branches/plugin/plugins/json/__init__.py azax/branches/plugin/plugins/json/browser/ azax/branches/plugin/plugins/json/browser/jsonkukit.js azax/branches/plugin/plugins/json/config.py azax/branches/plugin/plugins/json/configure.zcml azax/branches/plugin/plugins/json/interfaces.py azax/branches/plugin/plugins/json/utils.py Modified: azax/branches/plugin/plugins/configure.zcml azax/branches/plugin/plugins/registry.py Log: Added JSON plugin support
- it is loaded only as an option - tested with demo1 (change tag contents) and two_select on: Mozilla, IE6, Konqueror3.5.2, Opera8 - tested With and Without the presence of Json * only problem: IE breaks two_select in any way, that's an IE bug, http://support.microsoft.com/default.aspx?scid=kb;en-us;276228 Modified: azax/branches/plugin/plugins/configure.zcml ============================================================================== --- azax/branches/plugin/plugins/configure.zcml (original) +++ azax/branches/plugin/plugins/configure.zcml Mon Apr 17 16:57:53 2006 @@ -6,6 +6,8 @@ <!-- XXX concatresource is now included locally. --> <include package=".concatresource" /> + <include package=".json" /> + <!-- example plugin registration <azax:registerCommand Added: azax/branches/plugin/plugins/json/__init__.py ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/__init__.py Mon Apr 17 16:57:53 2006 @@ -0,0 +1,5 @@ +'''\ +Module init +''' + +from utils import getJsonAddonFiles Added: azax/branches/plugin/plugins/json/browser/jsonkukit.js ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/browser/jsonkukit.js Mon Apr 17 16:57:53 2006 @@ -0,0 +1,93 @@ + +/* +* Supplemental script for json +* +* This gets included when json plugins are registered. +* +* We overwrite notifyServer and at one point we return to the +* normal execution chain (after results are received) +*/ + +kukit.makeJsonMethod = function(url, callback, error, timeout) { + // Constructing a json method call handler. + // It is more steps because the input is not in the form + // how the JSON-RPC logic would require it. + var pieces = url.split('/'); + var methodName = pieces.pop(); + var base = pieces.join('/'); + var proxy = new JSONRPC(base); + proxy.addMethod(methodName, callback, error, timeout); + return proxy[methodName]; +} + +kukit.notifyServer = function(url, target) { + // sending form + var form_data = kukit.extractFormQuery(target).toDict(); + // XXX set a standard 4 sec timeout... a sane choice + var method = kukit.makeJsonMethod(url, jsonCallback, jsonError, 4000); + var method_with_parms = partial(method, PythonKw(form_data)); + kukit.requestManager.notifyServer(method_with_parms, url); +} + +function jsonCallback(result) { + kukit.requestManager.receivedResult(); + var command_processor = new kukit.CommandProcessor(); + command_processor.parseCommands(result); + command_processor.executeCommands(); +} + +function jsonError(result) { + kukit.requestManager.receivedResult(); + alert('ERROR ' + result); +} + +/* Command execution */ + +kukit.CommandProcessor.prototype.parseCommand = function(command) { + // For the sake of old commands compatibility, we need to convert + // all the commands to DOM. + var new_params = {}; + for (var name in command.params) { + var param = command.params[name]; + + // + // now convert to dom + // + + //param = "<option>test_xmlentity</option><option>tic</option><option>tac toe</option>"; + // ***BROKEN*** param = "<option>test_htmlentity</option><option>tic</option><option>tac toe</option>"; + //param = "<option>test_utf8</option><option>tic</option><option>tacűtoe</option>"; + + // This is a good solution since it does not do magic to + // our html - BUT html is parsed as xml + // so we currently preprocess it to remove html entities + // from it. + // + var root_txt = '<html xmlns="http://www.w3.org/1999/xhtml"><div>' + param + '</div></html>'; + var doc = (new DOMParser()).parseFromString(root_txt, "text/xml"); + var root = doc.getElementsByTagName('div')[0]; + + // This would be the perfect solution: insert our stuff + // into the main document that is, since it is html, + // will parse html in correctly. But the problem is + // that is also sensitive to context which we have not + // at this point yet. So: <option> will not work since + // we have no embedding select, etc... + // -->> gets broken with both MOZILLA and IE + // + //var root = document.createElement('html'); + //root.innerHTML = param; + // + // XXX Sarissa bug; html docs would not have a + // working serialize, and so importNodes would fail on them. + // XXX Fixed in: Revision 1.23 - Sun Jul 10 18:53:53 2005 UTC + // use at least 0.9.6.1 + + new_params[name] = root; + //alert(Sarissa.serialize(root)); + } + command.params = new_params; + // Add the command. + this.addCommand(command); +} + Added: azax/branches/plugin/plugins/json/config.py ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/config.py Mon Apr 17 16:57:53 2006 @@ -0,0 +1,7 @@ + +try: + import Products.jsonserver +except ImportError: + HAS_JSON = False +else: + HAS_JSON = True Added: azax/branches/plugin/plugins/json/configure.zcml ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/configure.zcml Mon Apr 17 16:57:53 2006 @@ -0,0 +1,31 @@ +<configure xmlns="http://namespaces.zope.org/zope" + xmlns:browser="http://namespaces.zope.org/browser" + xmlns:five="http://namespaces.zope.org/five"> + + <!-- We do not import things directly from jsonserver, as + its presence is optional. We import these locally + and if the import fails, blind stubs are provided + for the necessary interfaces and factories. This + ensures that this zcml will always execute. + XXX But this should actually be done via + features / conditionals from here. + --> + + <!-- View that renders the command --> + <adapter + for="Products.azax.interfaces.IAzaxCommands + .interfaces.IJsonRequest" + provides="zope.interface.Interface" + factory=".utils.JsonCommandView" + name="render" + /> + + <!-- Json representation of commands --> + <adapter + for="Products.azax.interfaces.IAzaxCommand + .interfaces.IJSONWriter" + provides=".interfaces.IJSONStreamWriteable" + factory=".utils.AzaxCommandWriter" + /> + +</configure> Added: azax/branches/plugin/plugins/json/interfaces.py ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/interfaces.py Mon Apr 17 16:57:53 2006 @@ -0,0 +1,42 @@ +# -*- coding: ISO-8859-15 -*- +# Copyright (c) 2005 +# Authors: +# Godefroid Chapelle <[EMAIL PROTECTED]> +# Tarek Ziad� <[EMAIL PROTECTED]> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as published +# by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# + +from config import HAS_JSON +from zope.interface import Interface + +if HAS_JSON: + from Products.jsonserver.interfaces import IJsonRequest + from Products.jsonserver.minjson.interfaces import IJSONStreamWriteable, IJSONWriter +else: + # If jsonserver is not present, we just define interfaces + # that noone implements so the adapters will never be looked up. + # This is because the zcml will try to import these. + # XXX occasionally this should be done from the zcml, + # via features/conditionals! + + class IJsonRequest(Interface): + 'Interface never to be implemented' + + class IJSONStreamWriteable(Interface): + 'Interface never to be implemented' + + class IJsonWriter(Interface): + 'Interface never to be implemented' Added: azax/branches/plugin/plugins/json/utils.py ============================================================================== --- (empty file) +++ azax/branches/plugin/plugins/json/utils.py Mon Apr 17 16:57:53 2006 @@ -0,0 +1,56 @@ +'''\ +Supplemental support for json plugins +''' + +import os.path +import zope.component +from zope.interface import implements +from zope.publisher.browser import TestRequest +from config import HAS_JSON +from interfaces import IJSONStreamWriteable + +def getJsonAddonFiles(): + 'Gets the addon javascript files for json' + files = [] + if HAS_JSON: + # Add the jsonserver files + request = TestRequest() + # use the files already registered to that concat resource + jsonrpc = zope.component.getResource('jsonrpc.js', request) + files.extend(jsonrpc.context.context.getPathList()) + # add the json kukit support file + plugins_dir = os.path.split(globals()['__file__'])[0] + files.append(os.path.join(plugins_dir, 'browser', 'jsonkukit.js')) + return files + +class JsonCommandView(object): + '''View of a command for JSON requests. + + We siply return the commands since they + will be transparently rendered for JSON, + via the writer adapter hooks. + ''' + + def __init__(self, context, request): + self.context = context + self.request = request + + def render(self): + return self.context + +class AzaxCommandWriter(object): + 'Writes a command to JSON' + implements(IJSONStreamWriteable) + + def __init__(self, context, writer): + self.context = context + self.writer = writer + + def __jsonwrite__(self): + writer = self.writer + # All is written as a dict + d = dict(self.context.__dict__) + # params are converted to a dict from a list. + # Also get rid of "none" params that were only a hack for xml + d['params'] = dict([(param.name, param.content) for param in d['params'] if param.name != 'none']) + writer.write_repr(d) Modified: azax/branches/plugin/plugins/registry.py ============================================================================== --- azax/branches/plugin/plugins/registry.py (original) +++ azax/branches/plugin/plugins/registry.py Mon Apr 17 16:57:53 2006 @@ -5,6 +5,7 @@ # concatresource is an embedded product but interface is aliased to Products import concatresource from Products.concatresource.interfaces import IConcatResourceAddon +from json import getJsonAddonFiles def getRegistry(context=None): 'Convenience method to get or create the registry.' @@ -75,4 +76,10 @@ self.getRegistered(plugintype, name) def getAddonFiles(self): - return self.jsfiles.keys() + try: + files = self._addon_files + except AttributeError: + # Lazy setup of addon files + self._addon_files = files = getJsonAddonFiles() + files.extend(self.jsfiles.keys()) + return files -- http://lists.nuxeo.com/mailman/listinfo/z3lab-checkins