development.ini | 17 docs/_static/moksha-architecture.png |binary docs/conf.py | 8 moksha/api/menus/default.py | 1 moksha/api/menus/widgets.py | 1 moksha/api/widgets/chat/__init__.py | 2 moksha/api/widgets/chat/chat.py | 28 - moksha/api/widgets/chat/controllers/__init__.py | 1 moksha/api/widgets/chat/controllers/chat.py | 110 ++++ moksha/api/widgets/chat/static/bootstrap.js | 431 ---------------- moksha/api/widgets/chat/static/chat.css | 119 ++++ moksha/api/widgets/chat/static/index.html | 9 moksha/api/widgets/chat/static/themes/dojo/chrome.js | 83 +++ moksha/api/widgets/chat/static/themes/dojo/gui.js | 19 moksha/api/widgets/chat/static/themes/dojo/index.html | 226 ++++++++ moksha/api/widgets/chat/static/themes/dojo/style.css | 151 +++++ moksha/api/widgets/chat/static/themes/simple/chrome.js | 83 +++ moksha/api/widgets/chat/static/themes/simple/gui.js | 216 ++++++++ moksha/api/widgets/chat/static/themes/simple/index.html | 58 ++ moksha/api/widgets/chat/static/themes/simple/style.css | 151 +++++ moksha/api/widgets/chat/templates/bootstrap.mak | 420 +++++++++++++++ moksha/api/widgets/chat/templates/chat.mak | 31 + moksha/api/widgets/feed/live.py | 2 moksha/controllers/root.py | 15 moksha/middleware/middleware.py | 21 moksha/streams/demo/demostream.py | 2 moksha/templates/widget.mak | 3 moksha/templates/widgetcontainer.mak | 7 orbited.cfg | 1 setup.py | 3 30 files changed, 1748 insertions(+), 471 deletions(-)
New commits: commit 64d974bb47bf8bbc3c6c6605d34f4e0c0a4e888f Merge: 8beb002... d299d2f... Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:08:10 2009 -0500
Merge branch 'master' of git+ssh://git.fedorahosted.org/git/moksha
commit 8beb002390520492912c877800fc183d5a7f19bc Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:07:51 2009 -0500
Some minor tweaks
diff --git a/docs/conf.py b/docs/conf.py index 0dfe727..c774831 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -155,7 +155,7 @@ code_path = test_path = os.path.dirname(os.path.abspath(__file__)) + os.path.sep # # Enable the ToscaWidgets WidgetBrowser # -try: - extensions.append("widgetbrowser.sphinx_ext") -except ImportError: - print "Unable to import the WidgetBrowser; skipping." +#try: +# extensions.append("widgetbrowser.sphinx_ext") +#except ImportError: +# print "Unable to import the WidgetBrowser; skipping." diff --git a/moksha/api/menus/default.py b/moksha/api/menus/default.py index 920440c..a420036 100644 --- a/moksha/api/menus/default.py +++ b/moksha/api/menus/default.py @@ -32,6 +32,7 @@ class MokshaContextMenu(MokshaContextualMenu): <a href="https://fedorahosted.org/moksha/">Wiki</a> """
+ class MokshaDefaultMenu(MokshaMenu): menus = ['Moksha', 'Applications', 'Widgets', 'Fedora']
diff --git a/moksha/api/menus/widgets.py b/moksha/api/menus/widgets.py index 97c3618..48db2e9 100644 --- a/moksha/api/menus/widgets.py +++ b/moksha/api/menus/widgets.py @@ -44,7 +44,6 @@ class MokshaMenuBase(Widget): 'hasImages', 'fadeTime', 'adjustLeft', 'adjustTop', 'opacity', 'shadow', 'fadeInTime', 'fadeOutTime', 'overflow', 'effect']
- rootMenuSelector = 'rootVoices' menuSelector = 'menuContainer' callback = '/appz/menu' diff --git a/moksha/api/widgets/feed/live.py b/moksha/api/widgets/feed/live.py index bf16e2d..3f3c0c1 100644 --- a/moksha/api/widgets/feed/live.py +++ b/moksha/api/widgets/feed/live.py @@ -37,4 +37,4 @@ class LiveFeedWidget(LiveWidget):
def update_params(self, d): super(LiveFeedWidget, self).update_params(d) - d['feed'] = Feed(d['id'], url=d.get('url', 'http://lewk.org/rss')) + d['feed'] = Feed(d['id'], url=d.get('url', 'http://doggdot.us/rss')) diff --git a/moksha/streams/demo/demostream.py b/moksha/streams/demo/demostream.py index f8b38c5..ab47a6b 100644 --- a/moksha/streams/demo/demostream.py +++ b/moksha/streams/demo/demostream.py @@ -19,7 +19,7 @@ class MokshaDemoDataStream(PollingDataStream): n = 0
# Feed demo specific variables - feed_entries = Feed(url='http://lewk.org/rss%27).entries() + feed_entries = Feed(url='http://doggdot.us/rss%27).entries() i = 0
def poll(self):
commit 49400c85b418c7676e52fd1ed00213594931bbd5 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:06:49 2009 -0500
Add the chat app and widget to our entrypoints
diff --git a/setup.py b/setup.py index d86914d..5892dcd 100644 --- a/setup.py +++ b/setup.py @@ -53,11 +53,12 @@ setup(
[moksha.application] menu = moksha.api.menus.controllers:MokshaMenuController + chat = moksha.api.widgets.chat.controllers:ChatController
[moksha.widget] liveflot = moksha.api.widgets.flot:LiveFlotWidget livefeed = moksha.api.widgets.feed.live:LiveFeedWidget - #chat = moksha.api.widgets.chat:LiveChatWidget + chat = moksha.api.widgets.chat:LiveChatWidget #livegraph = moksha.examples.livegraph:LiveGraphWidget #grid = moksha.api.widgets:Grid
commit 5a250a608711f7ddd8bfdeef402aa47c1102cd75 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:06:35 2009 -0500
Clean up our orbited configuration
diff --git a/orbited.cfg b/orbited.cfg index c943345..6006d84 100644 --- a/orbited.cfg +++ b/orbited.cfg @@ -8,7 +8,6 @@ stomp://:61613
[access] * -> localhost:61613 -* -> localhost:9999 * -> irc.freenode.net:6667
[global]
commit 3c5e7213c0e56773e738db1621832445479889ba Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:06:03 2009 -0500
Allow /widgets to render without the container chrome.
diff --git a/moksha/controllers/root.py b/moksha/controllers/root.py index b51cdfb..95cac52 100644 --- a/moksha/controllers/root.py +++ b/moksha/controllers/root.py @@ -18,7 +18,8 @@
import moksha
-from tg import expose, flash, require, tmpl_context, redirect, validate +from tg import (expose, flash, require, tmpl_context, redirect, validate, + override_template) from tg.controllers import WSGIAppController from repoze.what import predicates
@@ -40,15 +41,17 @@ class RootController(BaseController): def index(self): tmpl_context.menu_widget = moksha.menus['default_menu'] tmpl_context.contextual_menu_widget = moksha.menus['contextual_menu'] - return {'title': 'Moksha'} + return dict(title='Moksha')
- @expose('mako:moksha.templates.widget') - def widgets(self, widget, **kw): + @expose('mako:moksha.templates.widgetcontainer') + def widgets(self, widget, chrome=True, **kw): tmpl_context.widget = moksha.get_widget(widget) + if not chrome or not getattr(tmpl_context.widget, 'visible', True): + override_template(self.widgets, 'mako:moksha.templates.widget') + return dict(options={}) tmpl_context.container = container kw['id'] = widget + '_container' - return {'title': moksha._widgets[widget]['name'], - 'container_options': kw} + return dict(title=moksha._widgets[widget]['name'], container_options=kw)
@expose('moksha.templates.login') def login(self, **kw): diff --git a/moksha/templates/widget.mak b/moksha/templates/widget.mak index 57e436f..a66cfcd 100644 --- a/moksha/templates/widget.mak +++ b/moksha/templates/widget.mak @@ -1,7 +1,6 @@ <html> <head></head> <body> - ${tmpl_context.container(content=tmpl_context.widget, title=title, - **container_options)} + ${tmpl_context.widget(**options)} </body> </html>
commit c31faf7968ef53af0d15c9917785111e34046313 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:04:24 2009 -0500
Add a default chat configuration to our development.ini
diff --git a/development.ini b/development.ini index bdb6165..78962c9 100644 --- a/development.ini +++ b/development.ini @@ -38,6 +38,23 @@ stomp_pass = guest # Optional AMQP Broker. #amqp_broker = guest/guest@localhost
+# Moksha chat configuration + +# Use a built-in IRC server +#chat.backend = irc://localhost:9999 +#chat.builtin = true +chat.backend = irc://irc.freenode.net:6667 +chat.rooms = default +chat.default.staticRoomName = moksha +chat.default.roomAssignmentMode = static +chat.default.display.greeting = Moksha Chat +#chat.default.display.floating = true +#chat.default.display.floatingToggle = false +#chat.default.display.width = 400 +#chat.default.display.height = 300 +#chat.default.display.theme = simple +#chat.default.display.resizable = true + [server:main] use = egg:Paste#http host = localhost
commit 212c3c946fd05152c0d7c3f98332a273730623d9 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:03:43 2009 -0500
Add a widgetcontainer mako template
diff --git a/moksha/templates/widgetcontainer.mak b/moksha/templates/widgetcontainer.mak new file mode 100644 index 0000000..57e436f --- /dev/null +++ b/moksha/templates/widgetcontainer.mak @@ -0,0 +1,7 @@ +<html> + <head></head> + <body> + ${tmpl_context.container(content=tmpl_context.widget, title=title, + **container_options)} + </body> +</html>
commit 78bc597ed13968bd484ef92b6472aad40f9d6105 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:03:20 2009 -0500
Improve our moksha-architecture image
diff --git a/docs/_static/moksha-architecture.png b/docs/_static/moksha-architecture.png index 6d6001c..43a0e3c 100644 Binary files a/docs/_static/moksha-architecture.png and b/docs/_static/moksha-architecture.png differ
commit 7c8ccb1ec23b3ae4052808f6479257a953f71aca Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 17:02:36 2009 -0500
Add a live chat widget
diff --git a/moksha/api/widgets/chat/__init__.py b/moksha/api/widgets/chat/__init__.py index a5db829..ea5396b 100644 --- a/moksha/api/widgets/chat/__init__.py +++ b/moksha/api/widgets/chat/__init__.py @@ -1 +1 @@ -from chat import LiveChatWidget +from chat import LiveChatWidget, LiveChatFrameWidget diff --git a/moksha/api/widgets/chat/chat.py b/moksha/api/widgets/chat/chat.py index 2fb1b35..d05a2ff 100644 --- a/moksha/api/widgets/chat/chat.py +++ b/moksha/api/widgets/chat/chat.py @@ -16,10 +16,34 @@ # Copyright 2008, Red Hat, Inc. # Authors: Luke Macken lmacken@redhat.com
-from tw.api import Widget, JSLink +from tw.api import Widget, JSLink, CSSLink +from tw.jquery import jquery_js + +from moksha.api.widgets.orbited import orbited_js + +irc2_js = JSLink(filename='static/irc2.js', + javascript=[orbited_js], + modname=__name__) + +willowchat_js = JSLink(filename='static/willowchat.js', + javascript=[jquery_js, irc2_js], + modname=__name__) + +gui_js = JSLink(filename='static/gui.js', + javascript=[willowchat_js], + modname=__name__) + +willowchat_css = CSSLink(filename='static/style.css', modname=__name__) +
class LiveChatWidget(Widget): params = ['bootstrap'] - bootstrap = JSLink(filename='static/bootstrap.js', modname=__name__) + bootstrap = JSLink(link='/appz/chat/bootstrap') template = '<div id="willowchat" reposition="true">${bootstrap}</div>' visible = False + + +class LiveChatFrameWidget(Widget): + template = 'mako:moksha.api.widgets.chat.templates.chat' + javascript = [orbited_js, willowchat_js, irc2_js, gui_js, jquery_js] + css = [willowchat_css] diff --git a/moksha/api/widgets/chat/controllers/__init__.py b/moksha/api/widgets/chat/controllers/__init__.py new file mode 100644 index 0000000..67c0135 --- /dev/null +++ b/moksha/api/widgets/chat/controllers/__init__.py @@ -0,0 +1 @@ +from chat import ChatController diff --git a/moksha/api/widgets/chat/controllers/chat.py b/moksha/api/widgets/chat/controllers/chat.py new file mode 100644 index 0000000..05f5565 --- /dev/null +++ b/moksha/api/widgets/chat/controllers/chat.py @@ -0,0 +1,110 @@ +# This file is part of Moksha. +# +# Moksha is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Moksha 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 Moksha. If not, see http://www.gnu.org/licenses/. +# +# Copyright 2008, Red Hat, Inc. +# Authors: Luke Macken lmacken@redhat.com + +import logging +log = logging.getLogger(__name__) + +import urlparse +urlparse.uses_netloc.append('irc') + +from tg import expose, tmpl_context, config +from pylons import request + +from moksha.lib.base import BaseController +from moksha.api.widgets.chat import LiveChatFrameWidget + +chat_frame_widget = LiveChatFrameWidget('chat_frame') + + +class ChatController(BaseController): + + def __init__(self, *args, **kw): + super(ChatController, self).__init__(*args, **kw) + self.config = {} + backend = config.get('chat.backend') + if not backend: + log.info('No `chat.backend` defined; disabling chat functionality') + return + backend = urlparse.urlparse(backend) + self.config['backendProtocol'] = backend.scheme + self.config['backendAddr'] = [backend.hostname, backend.port] + self.config['startBuiltin'] = config.get('chat.builtin', False) + self.config['rooms'] = {} + display_opts = { + 'floating': True, 'floatingToggle': False, 'width': 400 , + 'height': 300, 'theme': 'simple', 'resizable': True, + 'greeting': 'Moksha Chat', + } + for room in config['chat.rooms'].replace(',', ' ').split(): + self.config['rooms'][room] = {'display': {}} + for display_opt, default in display_opts.items(): + self.config['rooms'][room]['display'][display_opt] = \ + config.get('chat.%s.display.%s' % (room, display_opt), + default) + self.config['rooms'][room]['roomAssignmentMode'] = \ + config.get('chat.%s.roomAssignmentMode' % room, 'static') + self.config['rooms'][room]['staticRoomName'] = \ + config.get('chat.%s.staticRoomName' % room, room) + + log.debug('Chat config = %r' % self.config) + + @expose('mako:moksha.templates.widget') + def index(self, *args, **kw): + tmpl_context.widget = chat_frame_widget + return dict(options={}) + + @expose('mako:moksha.api.widgets.chat.templates.bootstrap', + content_type='text/javascript') + def bootstrap(self, *args, **kw): + return dict(host=request.headers['host']) + + @expose('json') + def rooms(self, roomClass='default', op=None, jsonp=None): + opts = None + if op: + opts = self.jsonp(getattr(self, 'op_%s' % op, + self.op_not_found)(roomClass), jsonp) + else: + opts = self.jsonp([False, ["op not specified"]], jsonp) + return opts + + def jsonp(self, result, jsonp=None): + result = str(result).replace('True', 'true').replace('False', 'false') + if jsonp: + result = jsonp + '(' + result + ')' + return result + + def op_info(self, roomClass): + if roomClass not in self.config['rooms']: + return [False, ['unknown room class: ' + roomClass]] + info = self.config['rooms'][roomClass] + displayInfo = info.get('display', {}) + opts = {} + opts.update(displayInfo) + mode = info.get('roomAssignmentMode', 'static') + if mode == 'static': + opts['roomId'] = info.get('staticRoomName', 'default') + elif mode == 'referrer': + opts['roomId'] = request.headers.get('referer', 'default') + opts['protocol'] = self.config['backendProtocol'] + opts['addr'] = self.config['backendAddr'] + print "op_info returning [True, %r]" % opts + return [True, opts] + + def op_not_found(self): + return [False, ['unrecognized op']] diff --git a/moksha/api/widgets/chat/static/bootstrap.js b/moksha/api/widgets/chat/static/bootstrap.js deleted file mode 100644 index ea0ac1f..0000000 --- a/moksha/api/widgets/chat/static/bootstrap.js +++ /dev/null @@ -1,431 +0,0 @@ -(function() { -var gatherOptions = function(roomOptions, container) { - console.log('grandma'); - var opts = {} - var containerOptions = [ 'width', 'height', 'roomClass', 'reposition', 'theme' ] - for (var key in roomOptions) { - opts[key] = roomOptions[key] - } - for (var i = 0; i < containerOptions.length; ++i) { - var key = containerOptions[i] - var option = container.getAttribute(key) - if (option) { - opts[key] = option - } - } - if (!opts.roomId) { - var roomId = container.getAttribute('roomId') - opts.roomId = roomId ? roomId : 'default' - } - if (!opts.width) { - opts.width = 350; - } - if (!opts.height) { - opts.height = 240; - } - if (!opts.theme) { - opts.theme = 'simple' - } - if (!opts.greeting) { - opts.greeting = "Willow Chat" - } - return opts -} - -var loaded = function() { - if (!window.WillowChat) { - WillowChat = {} - } - if (!WillowChat.util) { - WillowChat.util = {} - } - var container = document.getElementById('willowchat'); - if (!container) { - container = document.createElement('div'); - container.setAttribute('id', 'willowchat'); - } - - - var roomClass = container.getAttribute('roomClass'); - var roomClass= roomClass ? roomClass : 'default' - s = document.createElement('script') - //var baseurl = 'http://' + WillowChat.hostHeader - // @@ HACK - var baseurl = 'http://localhost:8080'; - var orbitedurl = 'http://localhost:8007'; - s.src = orbitedurl + '/rooms?jsonp=WillowChat.util.optionsCallback&op=info&roomClass=' + roomClass - - WillowChat.util.optionsCallback = function(result) { - success = result[0] - if (!success) { - throw new Error("Failed: " + result[1]) - } - room = result[1] - var opts = gatherOptions(room, container); - ifr = document.createElement('iframe') - ifr.src = baseurl + '/toscawidgets/resources/moksha.live.chat.chat/static/index.html?json=1&opts=' + escape(JSON.stringify(opts)) - ifr.style.border = "0px"; - ifr.style.width = "100%"; - ifr.style.height = "100%"; - var chromeCallback = function() { - container.appendChild(ifr) - chrome = new WillowChat.chrome.map[opts.theme](container, opts) - } - var s = document.createElement('script') - // TODO: whats the deal with this? Can't we do any better? - s.src = baseurl + '/toscawidgets/resources/moksha.live.chat.chat/static/chrome.js?ienocache=' + Math.floor(Math.random()*10000) - if (s.addEventListener) { - s.addEventListener('load', chromeCallback, false) - } - else if (s.attachEvent) { - s.attachEvent('onreadystatechange', function() { - if (s.readyState == "loaded") { - chromeCallback() - } - }) - } - if (true) { - var k = 3 + 3 - } -// var d = document.createElement('div') -// d.innerHTML = 'go' -// document.body.appendChild(d) - document.getElementsByTagName('head')[0].appendChild(s) - } - document.getElementsByTagName('head')[0].appendChild(s) - -} - - -$(document).ready(function() { - loaded(); -}); - -/* -if (window.addEventListener) { - window.addEventListener('load', loaded, false); -} -else if (window.attachEvent) { - window.attachEvent('onload', loaded); -} -*/ - -})(); -if (!this.JSON) { - -// Create a JSON object only if one does not already exist. We create the -// object in a closure to avoid creating global variables. - - JSON = function () { - - function f(n) { - // Format integers to have at least two digits. - return n < 10 ? '0' + n : n; - } - - Date.prototype.toJSON = function (key) { - - return this.getUTCFullYear() + '-' + - f(this.getUTCMonth() + 1) + '-' + - f(this.getUTCDate()) + 'T' + - f(this.getUTCHours()) + ':' + - f(this.getUTCMinutes()) + ':' + - f(this.getUTCSeconds()) + 'Z'; - }; - - String.prototype.toJSON = - Number.prototype.toJSON = - Boolean.prototype.toJSON = function (key) { - return this.valueOf(); - }; - - var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - escapeable = /[\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, - gap, - indent, - meta = { // table of character substitutions - '\b': '\b', - '\t': '\t', - '\n': '\n', - '\f': '\f', - '\r': '\r', - '"' : '\"', - '\': '\\' - }, - rep; - - - function quote(string) { - -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can safely slap some quotes around it. -// Otherwise we must also replace the offending characters with safe escape -// sequences. - - escapeable.lastIndex = 0; - return escapeable.test(string) ? - '"' + string.replace(escapeable, function (a) { - var c = meta[a]; - if (typeof c === 'string') { - return c; - } - return '\u' + ('0000' + - (+(a.charCodeAt(0))).toString(16)).slice(-4); - }) + '"' : - '"' + string + '"'; - } - - - function str(key, holder) { - -// Produce a string from holder[key]. - - var i, // The loop counter. - k, // The member key. - v, // The member value. - length, - mind = gap, - partial, - value = holder[key]; - -// If the value has a toJSON method, call it to obtain a replacement value. - - if (value && typeof value === 'object' && - typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - -// If we were called with a replacer function, then call the replacer to -// obtain a replacement value. - - if (typeof rep === 'function') { - value = rep.call(holder, key, value); - } - -// What happens next depends on the value's type. - - switch (typeof value) { - case 'string': - return quote(value); - - case 'number': - -// JSON numbers must be finite. Encode non-finite numbers as null. - - return isFinite(value) ? String(value) : 'null'; - - case 'boolean': - case 'null': - -// If the value is a boolean or null, convert it to a string. Note: -// typeof null does not produce 'null'. The case is included here in -// the remote chance that this gets fixed someday. - - return String(value); - -// If the type is 'object', we might be dealing with an object or an array or -// null. - - case 'object': - -// Due to a specification blunder in ECMAScript, typeof null is 'object', -// so watch out for that case. - - if (!value) { - return 'null'; - } - -// Make an array to hold the partial results of stringifying this object value. - - gap += indent; - partial = []; - -// If the object has a dontEnum length property, we'll treat it as an array. - - if (typeof value.length === 'number' && - !(value.propertyIsEnumerable('length'))) { - -// The object is an array. Stringify every element. Use null as a placeholder -// for non-JSON values. - - length = value.length; - for (i = 0; i < length; i += 1) { - partial[i] = str(i, value) || 'null'; - } - -// Join all of the elements together, separated with commas, and wrap them in -// brackets. - - v = partial.length === 0 ? '[]' : - gap ? '[\n' + gap + - partial.join(',\n' + gap) + '\n' + - mind + ']' : - '[' + partial.join(',') + ']'; - gap = mind; - return v; - } - -// If the replacer is an array, use it to select the members to be stringified. - - if (rep && typeof rep === 'object') { - length = rep.length; - for (i = 0; i < length; i += 1) { - k = rep[i]; - if (typeof k === 'string') { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } else { - -// Otherwise, iterate through all of the keys in the object. - - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = str(k, value); - if (v) { - partial.push(quote(k) + (gap ? ': ' : ':') + v); - } - } - } - } - -// Join all of the member texts together, separated with commas, -// and wrap them in braces. - - v = partial.length === 0 ? '{}' : - gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + - mind + '}' : '{' + partial.join(',') + '}'; - gap = mind; - return v; - } - } - -// Return the JSON object containing the stringify and parse methods. - - return { - stringify: function (value, replacer, space) { - -// The stringify method takes a value and an optional replacer, and an optional -// space parameter, and returns a JSON text. The replacer can be a function -// that can replace values, or an array of strings that will select the keys. -// A default replacer method can be provided. Use of the space parameter can -// produce text that is more easily readable. - - var i; - gap = ''; - indent = ''; - -// If the space parameter is a number, make an indent string containing that -// many spaces. - - if (typeof space === 'number') { - for (i = 0; i < space; i += 1) { - indent += ' '; - } - -// If the space parameter is a string, it will be used as the indent string. - - } else if (typeof space === 'string') { - indent = space; - } - -// If there is a replacer, it must be a function or an array. -// Otherwise, throw an error. - - rep = replacer; - if (replacer && typeof replacer !== 'function' && - (typeof replacer !== 'object' || - typeof replacer.length !== 'number')) { - throw new Error('JSON.stringify'); - } - -// Make a fake root object containing our value under the key of ''. -// Return the result of stringifying the value. - - return str('', {'': value}); - }, - - - parse: function (text, reviver) { - -// The parse method takes a text and an optional reviver function, and returns -// a JavaScript value if the text is a valid JSON text. - - var j; - - function walk(holder, key) { - -// The walk method is used to recursively walk the resulting structure so -// that modifications can be made. - - var k, v, value = holder[key]; - if (value && typeof value === 'object') { - for (k in value) { - if (Object.hasOwnProperty.call(value, k)) { - v = walk(value, k); - if (v !== undefined) { - value[k] = v; - } else { - delete value[k]; - } - } - } - } - return reviver.call(holder, key, value); - } - - -// Parsing happens in four stages. In the first stage, we replace certain -// Unicode characters with escape sequences. JavaScript handles many characters -// incorrectly, either silently deleting them, or treating them as line endings. - - cx.lastIndex = 0; - if (cx.test(text)) { - text = text.replace(cx, function (a) { - return '\u' + ('0000' + - (+(a.charCodeAt(0))).toString(16)).slice(-4); - }); - } - -// In the second stage, we run the text against regular expressions that look -// for non-JSON patterns. We are especially concerned with '()' and 'new' -// because they can cause invocation, and '=' because it can cause mutation. -// But just to be safe, we want to reject all unexpected forms. - -// We split the second stage into 4 regexp operations in order to work around -// crippling inefficiencies in IE's and Safari's regexp engines. First we -// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we -// replace all simple value tokens with ']' characters. Third, we delete all -// open brackets that follow a colon or comma or that begin the text. Finally, -// we look to see that the remaining characters are only whitespace or ']' or -// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. - - if (/^[],:{}\s]*$/. -test(text.replace(/\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). -replace(/"[^"\\n\r]*"|true|false|null|-?\d+(?:.\d*)?(?:[eE][+-]?\d+)?/g, ']'). -replace(/(?:^|:|,)(?:\s*[)+/g, ''))) { - -// In the third stage we use the eval function to compile the text into a -// JavaScript structure. The '{' operator is subject to a syntactic ambiguity -// in JavaScript: it can begin a block or an object literal. We wrap the text -// in parens to eliminate the ambiguity. - - j = eval('(' + text + ')'); - -// In the optional fourth stage, we recursively walk the new structure, passing -// each name/value pair to a reviver function for possible transformation. - - return typeof reviver === 'function' ? - walk({'': j}, '') : j; - } - -// If the text is not JSON parseable, then a SyntaxError is thrown. - - throw new SyntaxError('JSON.parse'); - } - }; - }(); -} diff --git a/moksha/api/widgets/chat/static/chat.css b/moksha/api/widgets/chat/static/chat.css new file mode 100644 index 0000000..fe0d13f --- /dev/null +++ b/moksha/api/widgets/chat/static/chat.css @@ -0,0 +1,119 @@ +#signin_popup { + width:220pt; + padding:2em; + padding-bottom:3em; + text-align:center; + background-color: #A4C9D6; + color:#0E3541; + border: 5pt solid #195263; + position:absolute; + top:80pt; + left:100pt; + z-index:2; +} +#nickname { + width:90pt; +} +#absorb_clicks { + position:absolute; + top:0; + left:0; + width:300pt; + height:200pt; +} + +.chatbox { + width:490pt; + font: 100% Verdana, sans-serif; + background-color:#24758E; + padding:5pt; + position:relative; +} +.chatbox .left_column { + width: 360pt; +} +.chatbox .chathistory { + width:100%; + height:217pt; + overflow: auto; + background-color: white; +} +.chatbox .chathistory div { + background-color:#ffffee; + padding:.2em; + padding-left:1.5em; + text-indent: -1em; + border-bottom: 1px dotted #ccc; +} +.chatbox .chathistory .message .user { + width:5em; + font-weight: bold; + color:#DD7200; + padding-right:.2em; + text-align:right; +} +.chatbox .chathistory .message.self .user{ + color: #B42600; +} +.chatbox .chathistory .message.mentioned{ + background-color: #d5c5ff; +} +.chatbox .chathistory .message.private{ + background-color: #ccc; +} +.chatbox .chathistory .message.ctcp { + background-color: #f0f; +} +.chatbox .chathistory .action, +.chatbox .chathistory .action .user { + color: #D68850; + font-style:italic; +} +.chatbox .chathistory .action.self, +.chatbox .chathistory .action.self .user { + color: #A94C3B; + font-style:italic; +} +.chatbox .chathistory .informative { + font-size: 85%; + font-style: italic; + color:#999; + text-align:center; + padding:.3em; +} + +.chatbox .chatbox_input { + width:100%; + height:30pt; + margin:0; + margin-top:3pt; + padding:0; + border:0; + font-family: Verdana, sans-serif; +} + +.chatbox .user_list { + float:right; + position: absolute; + padding:0; + margin:0; + right:5pt; + top:5pt; + background-color:white; + width:127pt; + height:250pt; + overflow:auto; +} +.chatbox .user_list .user_entry{ + padding:.2em; + padding-left:8pt; + border-bottom: 1px dotted #ccc; +} + +#events { + visibility:hidden; + border:0; + width:0; + height:0; +/* display:none;*/ +} diff --git a/moksha/api/widgets/chat/static/index.html b/moksha/api/widgets/chat/static/index.html index 70e3f11..d4277bf 100644 --- a/moksha/api/widgets/chat/static/index.html +++ b/moksha/api/widgets/chat/static/index.html @@ -1,10 +1,9 @@ <!-- @@ HACK --> -<script src="http://localhost:9000/static/Orbited.js"></script> -<script src="/toscawidgets/resources/moksha.live.chat.chat/static/irc2.js"></script> -<script src="/toscawidgets/resources/moksha.live.chat.chat/static/willowchat.js"></script> -<script src="/toscawidgets/resources/moksha.live.chat.chat/static/gui.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script> <script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script> -<link rel="stylesheet" type="text/css" href="/toscawidgets/resources/moksha.live.chat.chat/static/style.css"></link> +<link rel="stylesheet" type="text/css" href="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/style.css"></link> <script> TCPSocket = Orbited.TCPSocket document.domain = document.domain; diff --git a/moksha/api/widgets/chat/static/themes/dojo/chrome.js b/moksha/api/widgets/chat/static/themes/dojo/chrome.js new file mode 100644 index 0000000..770701f --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/dojo/chrome.js @@ -0,0 +1,83 @@ +(function() { +/* Boilerplate + */ +if (!window.WillowChat) { + Willowchat = {} +} + +if (!WillowChat.chrome) { + WillowChat.chrome = {} +} + +if (!WillowChat.chrome.map) { + WillowChat.chrome.map = {} +} + + +WillowChat.chrome.map.dojo = WillowChat.chrome.DojoChrome = function(container, opts) { + /* Set configured height + */ + container.style.width = opts.width + 'px' + container.style.height = opts.height + 'px' + container.style.background = "white"; + var toggles = document.createElement('div') + toggles.setAttribute('id', 'willowchatToggles') + var floatToggle = document.createElement('div') + floatToggle.setAttribute('id', 'willowchatFloat') + floatToggle.innerHTML = "↑" + var minToggle = document.createElement('div') + minToggle.setAttribute('id', 'willowchatMin') + minToggle.innerHTML = "-" + floatToggle.setAttribute('style', "float: left;") + minToggle.setAttribute('style', "float: left;") + var toggleElements = [ minToggle, floatToggle] + for (var i = 0; i < 2; ++i) { + var t = toggleElements[i] + t.style.width = "20px" + t.style.height = "20px" + t.style.textAlign = "center" + t.style.border = "1px solid black" + t.style.padding = "2px" + t.style.color = "white" + t.style.fontWeight = "bold" + t.style.background = "#005522" + t.style.cursor = "pointer" + t.style.cssFloat = "left" + t.style.styleFloat = "left" + t.style.display = "none" + } + container.appendChild(toggles) + toggles.appendChild(floatToggle) + toggles.appendChild(minToggle) + + /* Should it be floating? + */ + if (opts.floating) { + container.style.position = 'absolute'; + container.style.bottom = '0'; + container.style.right = '0'; + minToggle.style.display = "block" + toggles.style.position = "absolute" + toggles.style.top = "1px" + toggles.style.left = "1px" + if (opts.reposition) { + container.parentNode.removeChild(container) + document.body.appendChild(container) + + } + } + else { + var ifr = container.getElementsByTagName('iframe')[0] + toggles.style.marginBottom="-10px" + ifr.style.marginTop="10px" + container.removeChild(ifr) + container.appendChild(ifr) +// toggles.style.marginBottom = "-5px"; + } + if (opts.floatingToggle) { + floatToggle.style.display = "block" + } + toggles.style.border = "1ps solid yellow" +} + +})(); \ No newline at end of file diff --git a/moksha/api/widgets/chat/static/themes/dojo/gui.js b/moksha/api/widgets/chat/static/themes/dojo/gui.js new file mode 100644 index 0000000..b042620 --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/dojo/gui.js @@ -0,0 +1,19 @@ + + +if (!window.WillowChat) { + Willowchat = {} +} + +if (!WillowChat.guis) { + WillowChat.guis = {} +} + +if (!WillowChat.guis.map) { + WillowChat.guis.map = {} +} + +var willowConnection = null; +WillowChat.guis.map.dojo = WillowChat.guis.DojoGui = function(wc, opts) { + console.log("Neat? ", wc, opts); + willowConnection = wc; +} diff --git a/moksha/api/widgets/chat/static/themes/dojo/index.html b/moksha/api/widgets/chat/static/themes/dojo/index.html new file mode 100644 index 0000000..fe50981 --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/dojo/index.html @@ -0,0 +1,226 @@ +<html> + <head> + <link rel="stylesheet" type="text/css" href="style.css"> +<script src="http://localhost:9000/static/Orbited.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script> +<script src="gui.js"></script> + <script> + TCPSocket = Orbited.TCPSocket + document.domain = document.domain +/* Orbited.system.enabled = true; + Orbited.loggers['Orbited.XSDR'].enabled = false + Orbited.loggers['Orbited.CometSession'].enabled = true + Orbited.loggers['Orbited.TCPSocket'].enabled = true + Orbited.loggers['XSDRBridge'].enabled = true + Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true + Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true + Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true + Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true + Orbited.loggers['WC.c.IRCClient'].enabled = true +*/ + </script> + + + <link rel="stylesheet" + href="http://o.aolcdn.com/dojo/1.2/dijit/themes/soria/soria.css%22%3E + <!-- load Dojo, and all the required modules --> + + <script type="text/javascript"> + + djConfig = { + isDebug: true, + baseUrl: "./", + xdWaitSeconds: 10, + parseOnLoad: true + }; + </script> + + <script src="http://o.aolcdn.com/dojo/1.2/dojo/dojo.xd.js" ></script> + + <script> + + dojo.require("dijit.layout.BorderContainer"); + dojo.require("dijit.layout.AccordionContainer"); + dojo.require("dijit.layout.ContentPane"); + dojo.require("dijit.layout.TabContainer"); + + dojo.require("dijit.form.TextBox"); + dojo.require("dijit.form.Button"); + dojo.require("dijit.Dialog"); + + + var username = null; + var roomMembers = []; + + dojo.addOnLoad(function() { + dijit.byId("logindialog").show(); + console.log("hi?", willowConnection); + + + var mssageBox = dojo.byId("messageBox"); + dojo.connect(mssageBox, "keyup", function(e) { + var key = e.charCode || e.keyCode || 0 + if (key == dojo.keys.ENTER) { + var msg = mssageBox.value; + willowConnection.sendMessage(msg) + willowConnection.onMessage(username, msg); + mssageBox.value = ""; + }; + }); + + + }); + + function login(nickname) { + username = nickname; + willowConnection.connect( { + username: nickname + }); + + + + + willowConnection.onConnect = function(data) { + /* This is somewhat important -- without this IE can run into some + * issues with reconnecting + */ + + window.onbeforeunload = function() { + if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) { + return 'Are you sure you want to quit and lose the chat connection?'; + } + }; + window.onunload = function() { + if (willowConnection.readyState == willowConnection.READY_STATE_CONNECTED) { + willowConnection.disconnect(); + } + } + + + // $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history"); + for (var i = 0; i < willowConnection.presence.length; ++i) { + addName(willowConnection.presence[i]); + console.log("who?", willowConnection.presence[i]); + } + updateMembers(); + console.log('connected', data, willowConnection.presence) + } + willowConnection.onMessage = function(sender, message) { + console.log('msg', sender, message); + chatArea.domNode.innerHTML += "<div>" + sender + ": " + message + "</div>"; + scrollDown(); + /* var messagediv = $('<div class="message"></div>'); + + if (sender == username) { + messagediv.addClass("self"); + } + if (isSubstring(username, message)) { + messagediv.addClass("mentioned"); + } + messagediv.html('<span class="user">' + sender + ':</span> ' + + sanitize(message)) + .appendTo("#history"); + scrollDown();*/ + } + willowConnection.onAction = function(s, m) { console.log('action', s, m); } + + willowConnection.onJoin = function(joiner) { + console.log('join', joiner); + addName(joiner); + updateMembers(); + chatArea.domNode.innerHTML += "<span class='user'>" + joiner + "</span> has joined<br/>"; + scrollDown(); + } + + willowConnection.onLeave = function(leaver) { + console.log('leave', leaver); + var idx = -1; + for(var i = 0; idx > -1 && i < roomMembers.length; i++) { + if(leaver == roomMembers[i]) { + idx = i; + } + } + roomMembers.splice(i, 1); + _updateMemberDisplay(); + } + + willowConnection.onDisconnect = function() { console.log('disconneted'); roomMembers = []; _updateMemberDisplay(); dijit.byId("logindialog").show();} + willowConnection.onUsernameTaken = function() { + console.log('onUsernameTaken', username); + username += '_' + try { + willowConnection.rename(username); + console.log('rename sent'); + } + catch(e) { + console.log('rename failed:', e) + } + } + + + + + + } + + function addName(name) { + roomMembers.push(name); + // presenceContainer.domNode.innerHTML += name + "<br/>"; + } + + + function updateMembers() { + roomMembers.sort(); + _updateMemberDisplay(); + } + + function _updateMemberDisplay() { + presenceContainer.domNode.innerHTML = ""; + for(var i = 0; i < roomMembers.length; i++) { + var member = roomMembers[i]; + presenceContainer.domNode.innerHTML += member + "<br/>"; + } + } + + function scrollDown() { + chatArea.domNode.scrollTop = chatArea.domNode.scrollHeight; + } + + function logout() { + willowConnection.disconnect(); + } + + + + + </script> + + + </head> + <body class="soria" > + <div dojoType="dijit.Dialog" id="logindialog" title="Chat" + execute="login(arguments[0]['name'] ? arguments[0]['name'] : 'guest');"> + <label for="name">Nickname: </label> + <input dojoType=dijit.form.TextBox type="text" maxlength="16" name="name" id="name" value=""> + <button dojoType=dijit.form.Button type="submit">OK</button> + </div> + + <div> + <div dojoType="dijit.layout.BorderContainer" style="width:100%; height:100%"> + <div dojoType="dijit.layout.ContentPane" region="top" style="border:1px solid gray; height: 20px; background: #eee;"> + WillowChat now with Dojo <button dojoType=dijit.form.Button onClick="logout();" style="font-size:10px;" type="submit">Leave</button> + </div> + <div dojoType="dijit.layout.ContentPane" region="left" jsId="presenceContainer" style="width: 100px; border:1px solid gray; background: #eee;" splitter="true" minSize="0" maxSize="250"> + + </div> + <div dojoType="dijit.layout.ContentPane" region="center" jsId="chatArea" style="border:1px solid gray; background: #eee;" > + + </div> + <div dojoType="dijit.layout.ContentPane" region="bottom" style="height: 50px; border:1px solid gray; background: #eee;" > + <textarea id="messageBox" style="width:90%"></textarea> + </div> + </div> + </div> +</html> diff --git a/moksha/api/widgets/chat/static/themes/dojo/style.css b/moksha/api/widgets/chat/static/themes/dojo/style.css new file mode 100644 index 0000000..29f0a19 --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/dojo/style.css @@ -0,0 +1,151 @@ +html, body { + padding: 0px; + margin: 0px; + border: none; + _overflow: hidden; + } +#presenceToggle { + border: 1px solid black; + position: absolute; + right: 1px; + top: 1px; + padding: 2px; + background: #005522; + color: white; + font-weight: bold; + cursor: pointer; +} +#presenceToggle:hover { +} +#presence { + float: right; + border: 1px solid gray; + width: 130px; + height: 83%; + margin-left: 3px; + margin-bottom: 0px; + overflow: hidden; +} +#presenceTitle { + text-decoration: underline; +} +#presenceList { + overflow: auto; + height: 90%; +} +#history { + border: 1px solid gray; + height: 83%; + overflow: auto; + margin-bottom: 0px; +} +#historySpacer { + border: 1px solid red; +} +#inputBar { + margin-top: 0px; + height: 15%; +} +#inputBar textarea { + width: 100%; + height: 100%; + border: 1px solid gray; +} + + + +#popup { + position: absolute; + height: 100%; + width: 70%; + left: 15%; + z-index: 2; +} + +#popupOuter { + height: 100%; + width: 100%; + overflow: hidden; + position: relative; +} +#popupOuter[id] {display: table; position: static;} + +#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/ +#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;} + +#popupContent {position: relative; top: -50%} /* for explorer only */ +/* optional: #popupContent[id] {position: static;} */ + +#popupContent { + font-size: 120%; + text-align:center; + background: #005522; + color: white; + border: 5pt solid #50A572; + padding: 8px; + padding-bottom: 20px; + width: 100%; +} +#popupContent p { + font-size: 150%; +} + +#absorbClicks { + position:absolute; + top:0; + left:0; + width:100%; + height:100%; +} + + +#history div { + background-color:#eeffee; + padding:.2em; + padding-left:1.5em; + text-indent: -1em; + border-bottom: 1px dotted #ccc; +} +#history .message .user { + width:5em; + font-weight: bold; + color:#DD7200; + padding-right:.2em; + text-align:right; +} +#history .message.self .user{ + color: #B42600; +} +#history .message.mentioned{ + background-color: #d5c5ff; +} +#history .message.private{ + background-color: #ccc; +} +#history .message.ctcp { + background-color: #f0f; +} +#history .action { + color: #D68850; + font-style:italic; +} +#history .action { + color: #A94C3B; + font-style:italic; +} +#history .informative { + font-size: 85%; + font-style: italic; + color:#999; + text-align:center; + padding:.3em; +} +#presenceList .user_entry { + font-size: 90%; + padding:.2em; + padding-left:8pt; + border-bottom: 1px dotted #ccc; +} + + + diff --git a/moksha/api/widgets/chat/static/themes/simple/chrome.js b/moksha/api/widgets/chat/static/themes/simple/chrome.js new file mode 100644 index 0000000..4379ce6 --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/simple/chrome.js @@ -0,0 +1,83 @@ +(function() { +/* Boilerplate + */ +if (!window.WillowChat) { + Willowchat = {} +} + +if (!WillowChat.chrome) { + WillowChat.chrome = {} +} + +if (!WillowChat.chrome.map) { + WillowChat.chrome.map = {} +} + + +WillowChat.chrome.map.simple = WillowChat.chrome.SimpleChrome = function(container, opts) { + /* Set configured height + */ + container.style.width = opts.width + 'px' + container.style.height = opts.height + 'px' + container.style.background = "white"; + var toggles = document.createElement('div') + toggles.setAttribute('id', 'willowchatToggles') + var floatToggle = document.createElement('div') + floatToggle.setAttribute('id', 'willowchatFloat') + floatToggle.innerHTML = "↑" + var minToggle = document.createElement('div') + minToggle.setAttribute('id', 'willowchatMin') + minToggle.innerHTML = "-" + floatToggle.setAttribute('style', "float: left;") + minToggle.setAttribute('style', "float: left;") + var toggleElements = [ minToggle, floatToggle] + for (var i = 0; i < 2; ++i) { + var t = toggleElements[i] + t.style.width = "20px" + t.style.height = "20px" + t.style.textAlign = "center" + t.style.border = "1px solid black" + t.style.padding = "2px" + t.style.color = "white" + t.style.fontWeight = "bold" + t.style.background = "#005522" + t.style.cursor = "pointer" + t.style.cssFloat = "left" + t.style.styleFloat = "left" + t.style.display = "none" + } + container.appendChild(toggles) + toggles.appendChild(floatToggle) + toggles.appendChild(minToggle) + + /* Should it be floating? + */ + if (opts.floating) { + container.style.position = 'absolute'; + container.style.bottom = '0'; + container.style.right = '0'; + minToggle.style.display = "block" + toggles.style.position = "absolute" + toggles.style.top = "1px" + toggles.style.left = "1px" + if (opts.reposition) { + container.parentNode.removeChild(container) + document.body.appendChild(container) + + } + } + else { + var ifr = container.getElementsByTagName('iframe')[0] + toggles.style.marginBottom="-10px" + ifr.style.marginTop="10px" + container.removeChild(ifr) + container.appendChild(ifr) +// toggles.style.marginBottom = "-5px"; + } + if (opts.floatingToggle) { + floatToggle.style.display = "block" + } + toggles.style.border = "1ps solid yellow" +} + +})(); diff --git a/moksha/api/widgets/chat/static/themes/simple/gui.js b/moksha/api/widgets/chat/static/themes/simple/gui.js new file mode 100644 index 0000000..2b5083f --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/simple/gui.js @@ -0,0 +1,216 @@ +(function() { + +if (!window.WillowChat) { + console.log('no willochat found in gui?'); + Willowchat = {} +} + +if (!WillowChat.guis) { + WillowChat.guis = {} +} + +if (!WillowChat.guis.map) { + WillowChat.guis.map = {} +} +var ENTER_KEY = 13 +WillowChat.guis.map.simple = WillowChat.guis.SimpleGui = function(wc, opts) { + var self = this; + self.presenceShown = true; + var logger = Orbited.getLogger('WillowChatTest'); +// logger.enabled = true; + var username = null; + var presence = {} + + $('#nickname').focus(); + $('#nickname').keypress( function(e) { + var key = e.charCode || e.keyCode || 0 + if (key == ENTER_KEY) { + self.connect(); + }; + }); + $('#chatboxInput').keypress(function(e) { + var key = e.charCode || e.keyCode || 0; + if (key == ENTER_KEY) { + self.sendMessage(); + return false; + }; + }); + $("#popupContent p").html(opts.greeting) + $("#presenceToggle").click(function() { + if (self.presenceShown) { + self.presenceShown = false; + $("#presence").hide() + $("#presenceToggle").html('←'); + } + else { + self.presenceShown = true; + $("#presence").show(); + $("#presenceToggle").html('→'); + } + if (wc.readyState == wc.READY_STATE_CONNECTED) { + $('#chatboxInput').focus(); + } + else { + $('#nickname').focus(); + } + }) + var scrollDown = function() { + var box = $('#history')[0] + box.scrollTop = box.scrollHeight; + } + var isSubstring = function (sub, str) { + // case insensitive substring test + return str.toLowerCase().indexOf(sub.toLowerCase()) >= 0; + }; + var sanitize = (function(str) { + // See http://bigdingus.com/2007/12/29/html-escaping-in-javascript/ + var MAP = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + var repl = function(c) { return MAP[c]; }; + return function(s) { + return s.replace(/[&<>'"]/g, repl); + }; + })(); + + // TODO: test this out + var userRenamed = function(oldname, newname) { + $("<div class='informative rename'></div>") + .html("<span class='user'>" + oldname + "</span> is now known as " + + "<span class='user'>" + newname + "</span>") + .appendTo("#history"); + scrollDown(); + $("#user_" + oldname) + .attr("id", "user_" + newname) + .html(newname); + } + + var addName = function (name) { + presence[name] = 1 + $('<div class="user_entry" id="user_' + name + '">' + name + '</div>') + .appendTo("#presenceList"); + }; + + var removeName = function (name) { + delete presence[name]; + $(".user_list #user_" + name).remove() + }; + + var sortNames = function () { + $('#presenceList').empty(); + var list = []; + for (var user in presence) { + list.push(user); + }; + list.sort() + for (var i=0; i < list.length; i++) { + var user = list[i]; + $('<div class="user_entry" id="user_' + user + '">' + user + '</div>') + .appendTo("#presenceList"); + }; + }; + self.connect = function() { + username = $("#nickname").val(); + if (!username) { + logger.debug('please enter a username'); + return + } + $('#popup, #absorbClicks').hide(); + $('#chatboxInput').focus(); + $('#chatboxInput').val('') + + connected = true; + wc.connect( { + username: username + }) + wc.onConnect = function(data) { + /* This is somewhat important -- without this IE can run into some + * issues with reconnecting + */ + + window.onbeforeunload = function() { + if (wc.readyState == wc.READY_STATE_CONNECTED) { + return 'Are you sure you want to quit and lose the chat connection?'; + } + }; + window.onunload = function() { + if (wc.readyState == wc.READY_STATE_CONNECTED) { + wc.disconnect(); + } + } + + + $("<div class='informative'>Entered ChatRoom</div>").appendTo("#history"); + for (var i = 0; i < wc.presence.length; ++i) { + addName(wc.presence[i]); + } + sortNames(); + logger.debug('connected', data, wc.presence) + } + wc.onMessage = function(sender, message) { + logger.debug('msg', sender, message); + var messagediv = $('<div class="message"></div>'); + + if (sender == username) { + messagediv.addClass("self"); + } + if (isSubstring(username, message)) { + messagediv.addClass("mentioned"); + } + messagediv.html('<span class="user">' + sender + ':</span> ' + + sanitize(message)) + .appendTo("#history"); + scrollDown(); + } + wc.onAction = function(s, m) { logger.debug('action', s, m); } + + wc.onJoin = function(joiner) { + logger.debug('join', joiner); + addName(joiner); + sortNames(); + $("<div class='informative join'></div>") + .html("<span class='user'>" + joiner + '</span> has joined') + .appendTo("#history"); + scrollDown(); + } + wc.onLeave = function(leaver) { + logger.debug('leave', leaver); + removeName(leaver); + $("<div class='informative part'></div>") + .html("<span class='user'>" + leaver + '</span> left') + .appendTo("#history"); + scrollDown(); + } + wc.onDisconnect = function() { logger.debug('disconneted'); } + wc.onUsernameTaken = function() { + logger.debug('onUsernameTaken', username); + username += '_' + try { + wc.rename(username); + logger.debug('rename sent'); + } + catch(e) { + logger.debug('rename failed:', e) + } + } + } + self.sendMessage = function() { + var msg = $('#chatboxInput').val(); + wc.sendMessage(msg) + $('#chatboxInput').val(''); + // the WillowChat server will not echo our message back, so simulate a send. + wc.onMessage(username, msg) + } + self.sendAction = function() { + var msg = getMessage() + wc.sendAction(msg); + logger.debug('action', username, msg) + } + +} +})() + diff --git a/moksha/api/widgets/chat/static/themes/simple/index.html b/moksha/api/widgets/chat/static/themes/simple/index.html new file mode 100644 index 0000000..ee659cf --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/simple/index.html @@ -0,0 +1,58 @@ +<html> + <head> + <link rel="stylesheet" type="text/css" href="style.css"> +<!-- @@ HACK --> +<script src="http://localhost:9000/static/Orbited.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/irc2.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/willowchat.js"></script> +<script src="/toscawidgets/resources/moksha.api.widgets.chat.chat/static/gui.js"></script> +<script src="/toscawidgets/resources/tw.jquery.base/static/javascript/jquery-1.2.6.pack.js"></script> + <script src="gui.js"></script> + <script> + TCPSocket = Orbited.TCPSocket + document.domain = document.domain + +/* Orbited.system.enabled = true; + Orbited.loggers['Orbited.XSDR'].enabled = false + Orbited.loggers['Orbited.CometSession'].enabled = true + Orbited.loggers['Orbited.TCPSocket'].enabled = true + Orbited.loggers['XSDRBridge'].enabled = true + Orbited.loggers['Orbited.CometTransports.LongPoll'].enabled = true + Orbited.loggers['Orbited.CometTransports.XHRStream'].enabled = true + Orbited.loggers['Orbited.CometTransports.HTMLFile'].enabled = true + Orbited.loggers['Orbited.CometTransports.SSE'].enabled = true + Orbited.loggers['WC.c.IRCClient'].enabled = true +*/ + </script> + + </head> + <body> +<div id="popup"> +<div id="popupOuter"> + <div id="popupMiddle"> + <div id="popupContent"> + <p>Greeting</p> + <label for="nickname">Nickname:</label> + <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" /> + </div> + </div> +</div> +</div> + + + <div id="absorbClicks"></div> + <div id="presenceToggle"> + → + </div> + <div id="presence"> + <div id="presenceTitle">Presence</div> + <div id="presenceList"> + </div> + </div> + <div id="history"> + </div> + <div id="inputBar"> + <textarea id="chatboxInput"></textarea> + </div> + </body> +</html> diff --git a/moksha/api/widgets/chat/static/themes/simple/style.css b/moksha/api/widgets/chat/static/themes/simple/style.css new file mode 100644 index 0000000..29f0a19 --- /dev/null +++ b/moksha/api/widgets/chat/static/themes/simple/style.css @@ -0,0 +1,151 @@ +html, body { + padding: 0px; + margin: 0px; + border: none; + _overflow: hidden; + } +#presenceToggle { + border: 1px solid black; + position: absolute; + right: 1px; + top: 1px; + padding: 2px; + background: #005522; + color: white; + font-weight: bold; + cursor: pointer; +} +#presenceToggle:hover { +} +#presence { + float: right; + border: 1px solid gray; + width: 130px; + height: 83%; + margin-left: 3px; + margin-bottom: 0px; + overflow: hidden; +} +#presenceTitle { + text-decoration: underline; +} +#presenceList { + overflow: auto; + height: 90%; +} +#history { + border: 1px solid gray; + height: 83%; + overflow: auto; + margin-bottom: 0px; +} +#historySpacer { + border: 1px solid red; +} +#inputBar { + margin-top: 0px; + height: 15%; +} +#inputBar textarea { + width: 100%; + height: 100%; + border: 1px solid gray; +} + + + +#popup { + position: absolute; + height: 100%; + width: 70%; + left: 15%; + z-index: 2; +} + +#popupOuter { + height: 100%; + width: 100%; + overflow: hidden; + position: relative; +} +#popupOuter[id] {display: table; position: static;} + +#popupMiddle {position: absolute; top: 50%;} /* for explorer only*/ +#popupMiddle[id] {display: table-cell; vertical-align: middle; position: static;} + +#popupContent {position: relative; top: -50%} /* for explorer only */ +/* optional: #popupContent[id] {position: static;} */ + +#popupContent { + font-size: 120%; + text-align:center; + background: #005522; + color: white; + border: 5pt solid #50A572; + padding: 8px; + padding-bottom: 20px; + width: 100%; +} +#popupContent p { + font-size: 150%; +} + +#absorbClicks { + position:absolute; + top:0; + left:0; + width:100%; + height:100%; +} + + +#history div { + background-color:#eeffee; + padding:.2em; + padding-left:1.5em; + text-indent: -1em; + border-bottom: 1px dotted #ccc; +} +#history .message .user { + width:5em; + font-weight: bold; + color:#DD7200; + padding-right:.2em; + text-align:right; +} +#history .message.self .user{ + color: #B42600; +} +#history .message.mentioned{ + background-color: #d5c5ff; +} +#history .message.private{ + background-color: #ccc; +} +#history .message.ctcp { + background-color: #f0f; +} +#history .action { + color: #D68850; + font-style:italic; +} +#history .action { + color: #A94C3B; + font-style:italic; +} +#history .informative { + font-size: 85%; + font-style: italic; + color:#999; + text-align:center; + padding:.3em; +} +#presenceList .user_entry { + font-size: 90%; + padding:.2em; + padding-left:8pt; + border-bottom: 1px dotted #ccc; +} + + + diff --git a/moksha/api/widgets/chat/templates/__init__.py b/moksha/api/widgets/chat/templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/moksha/api/widgets/chat/templates/bootstrap.mak b/moksha/api/widgets/chat/templates/bootstrap.mak new file mode 100644 index 0000000..a01cfd0 --- /dev/null +++ b/moksha/api/widgets/chat/templates/bootstrap.mak @@ -0,0 +1,420 @@ +(function() { +var gatherOptions = function(roomOptions, container) { + var opts = {} + var containerOptions = [ 'width', 'height', 'roomClass', 'reposition', 'theme' ] + for (var key in roomOptions) { + opts[key] = roomOptions[key] + } + for (var i = 0; i < containerOptions.length; ++i) { + var key = containerOptions[i] + var option = container.getAttribute(key) + if (option) { + opts[key] = option + } + } + if (!opts.roomId) { + var roomId = container.getAttribute('roomId') + opts.roomId = roomId ? roomId : 'default' + } + if (!opts.width) { + opts.width = 350; + } + if (!opts.height) { + opts.height = 240; + } + if (!opts.theme) { + opts.theme = 'simple' + } + if (!opts.greeting) { + opts.greeting = "Willow Chat" + } + return opts +} + +var loaded = function() { + if (!window.WillowChat) { + console.log('creating new willowchat?'); + WillowChat = {} + } + if (!WillowChat.util) { + WillowChat.util = {} + } + var container = document.getElementById('willowchat'); + if (!container) { + container = document.createElement('div'); + container.setAttribute('id', 'willowchat'); + } + + + var roomClass = container.getAttribute('roomClass'); + var roomClass= roomClass ? roomClass : 'default' + s = document.createElement('script') + var baseurl = 'http://' + WillowChat.hostHeader + s.src = baseurl + '/appz/chat/rooms?jsonp=WillowChat.util.optionsCallback&op=info&roomClass=' + roomClass + + WillowChat.util.optionsCallback = function(result) { + success = result[0] + if (!success) { + throw new Error("Failed: " + result[1]) + } + room = result[1] + var opts = gatherOptions(room, container); + ifr = document.createElement('iframe') + var staticurl = baseurl + '/toscawidgets/resources/moksha.api.widgets.chat.chat/static' + ifr.src = '/appz/chat/index?json=1&opts=' + escape(JSON.stringify(opts)) + ifr.style.border = "0px"; + ifr.style.width = "100%"; + ifr.style.height = "100%"; + var chromeCallback = function() { + container.appendChild(ifr) + chrome = new WillowChat.chrome.map[opts.theme](container, opts) + } + var s = document.createElement('script') + // TODO: whats the deal with this? Can't we do any better? + s.src = staticurl + '/themes/' + opts.theme + '/chrome.js?ienocache=' + Math.floor(Math.random()*10000) + if (s.addEventListener) { + s.addEventListener('load', chromeCallback, false) + } + else if (s.attachEvent) { + s.attachEvent('onreadystatechange', function() { + if (s.readyState == "loaded") { + chromeCallback() + } + }) + } + if (true) { + var k = 3 + 3 + } +// var d = document.createElement('div') +// d.innerHTML = 'go' +// document.body.appendChild(d) + document.getElementsByTagName('head')[0].appendChild(s) + } + document.getElementsByTagName('head')[0].appendChild(s) + +} + +$(document).ready(function(){ + if (!window.WillowChat) { WillowChat = {} }; WillowChat.hostHeader = "${host}"; + loaded(); +}); + +})(); +if (!this.JSON) { + +// Create a JSON object only if one does not already exist. We create the +// object in a closure to avoid creating global variables. + + JSON = function () { + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + Date.prototype.toJSON = function (key) { + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapeable = /[\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\b', + '\t': '\t', + '\n': '\n', + '\f': '\f', + '\r': '\r', + '"' : '\"', + '\': '\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapeable.lastIndex = 0; + return escapeable.test(string) ? + '"' + string.replace(escapeable, function (a) { + var c = meta[a]; + if (typeof c === 'string') { + return c; + } + return '\u' + ('0000' + + (+(a.charCodeAt(0))).toString(16)).slice(-4); + }) + '"' : + '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// If the object has a dontEnum length property, we'll treat it as an array. + + if (typeof value.length === 'number' && + !(value.propertyIsEnumerable('length'))) { + +// The object is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : + gap ? '[\n' + gap + + partial.join(',\n' + gap) + '\n' + + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : + gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + + mind + '}' : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// Return the JSON object containing the stringify and parse methods. + + return { + stringify: function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }, + + + parse: function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\u' + ('0000' + + (+(a.charCodeAt(0))).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[],:{}\s]*$/. +test(text.replace(/\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). +replace(/"[^"\\n\r]*"|true|false|null|-?\d+(?:.\d*)?(?:[eE][+-]?\d+)?/g, ']'). +replace(/(?:^|:|,)(?:\s*[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + } + }; + }(); +} diff --git a/moksha/api/widgets/chat/templates/chat.mak b/moksha/api/widgets/chat/templates/chat.mak new file mode 100644 index 0000000..a3ab679 --- /dev/null +++ b/moksha/api/widgets/chat/templates/chat.mak @@ -0,0 +1,31 @@ +<script> + TCPSocket = Orbited.TCPSocket + document.domain = document.domain; +</script> + +<div id="popup"> +<div id="popupOuter"> + <div id="popupMiddle"> + <div id="popupContent"> + <p>Greeting</p> + <label for="nickname">Nickname:</label> + <input type="text" id="nickname" maxlength="16" style="width: 10em;" value="" /> + </div> + </div> +</div> +</div> + + <div id="absorbClicks"></div> + <div id="presenceToggle"> + → + </div> + <div id="presence"> + <div id="presenceTitle">Presence</div> + <div id="presenceList"> + </div> + </div> + <div id="history"> + </div> + <div id="inputBar"> + <textarea id="chatboxInput"></textarea> + </div>
commit 1d1937d6bcd43ae87cac9e20e3cd262ae89ec14e Merge: 3b2f959... faf2bc2... Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 16:06:22 2009 -0500
Merge branch 'master' of git+ssh://git.fedorahosted.org/git/moksha
commit 3b2f959d62ac45a7747977c2370f3c2b391b3343 Author: Luke Macken lmacken@redhat.com Date: Mon Feb 2 13:01:53 2009 -0500
More load_renderers cleanups in our Middleware
diff --git a/moksha/middleware/middleware.py b/moksha/middleware/middleware.py index 6f4c6a7..a24f5e6 100644 --- a/moksha/middleware/middleware.py +++ b/moksha/middleware/middleware.py @@ -238,7 +238,12 @@ class MokshaMiddleware(object): self.menus[menu_entry.name] = menu_class(menu_entry.name)
def load_renderers(self): - """ Load our template renderers with our application paths """ + """ Load our template renderers with our application paths. + + We are currently overloading TG2's default Mako renderer because + the default `escape` filter causes our widgets to show up as escaped HTML. + + """ #template_paths = config['pylons.paths']['templates'] #moksha_dir = os.path.abspath(__file__ + '/../../../') #for app in [{'path': moksha_dir}] + self.apps.values(): @@ -258,7 +263,6 @@ class MokshaMiddleware(object): """ def __init__(self, input_encoding, output_encoding, imports, default_filters): - print "\n\nusing dotted template lookups!\n\n" self.input_encoding = input_encoding self.output_encoding = output_encoding self.imports = imports @@ -303,9 +307,6 @@ class MokshaMiddleware(object): config['pylons.app_globals'].mako_lookup = DottedTemplateLookup( input_encoding='utf-8', output_encoding='utf-8', imports=[], default_filters=[]) - # @@: these cause problems when displaying headers/footers - #imports=['from webhelpers.html import escape'], - #default_filters=['escape'])
else: # if no dotted names support was required we will just setup @@ -314,18 +315,8 @@ class MokshaMiddleware(object): directories=self.paths['templates'], module_directory=self.paths['templates'], input_encoding='utf-8', output_encoding='utf-8', - imports=['from webhelpers.html import escape'], - default_filters=['escape'], filesystem_checks=self.auto_reload_templates)
- #from genshi.template import TemplateLoader - #def template_loaded(template): - # "Plug-in our i18n function to Genshi." - # template.filters.insert(0, Translator(ugettext)) - #config['pylons.app_globals'].genshi_loader = TemplateLoader( - # search_path=template_paths, auto_reload=False, - # callback=template_loaded) - def load_configs(self): """ Load the configuration files for all applications.
moksha-commits@lists.fedorahosted.org