[loki-editor commit] r665 - in trunk/src: . contexts

0 views
Skip to first unread message

codesite...@google.com

unread,
Dec 4, 2008, 2:45:52 PM12/4/08
to loki-c...@googlegroups.com
Author: enaeseth
Date: Thu Dec 4 11:39:06 2008
New Revision: 665

Modified:
trunk/src/context.js
trunk/src/contexts/visual.js
trunk/src/editor.js
trunk/src/theme.js

Log:
Theme loading is done! Bless my stars.

Modified: trunk/src/context.js
==============================================================================
--- trunk/src/context.js (original)
+++ trunk/src/context.js Thu Dec 4 11:39:06 2008
@@ -53,7 +53,6 @@
});

Loki.builtinContexts = {};
-Loki.defaultContext = null;

#import "contexts/visual.js"
#import "contexts/loading.js"

Modified: trunk/src/contexts/visual.js
==============================================================================
--- trunk/src/contexts/visual.js (original)
+++ trunk/src/contexts/visual.js Thu Dec 4 11:39:06 2008
@@ -172,5 +172,3 @@
}, this);
}
});
-
-Loki.defaultContext = "visual";

Modified: trunk/src/editor.js
==============================================================================
--- trunk/src/editor.js (original)
+++ trunk/src/editor.js Thu Dec 4 11:39:06 2008
@@ -48,11 +48,16 @@
errorLog: null,

// var: ({String => Loki.Context}) contexts
+ // All contexts loaded into the editor.
contexts: null,

// var: ({String => Loki.Plugin}) plugins
+ // All plugins loaded into the editor.
plugins: null,

+ // var: (Loki.Theme) theme
+ // The editor's theme.
+
// Constructor: Editor
// Creates a new instance of the Loki editor, replacing a textarea on the
// document with itself. If the textarea belongs to a form, Loki will
@@ -99,7 +104,7 @@
this._createUI(settings);

this.defaultContext = settings.defaultContext
- || settings.default_context || Loki.defaultContext;
+ || settings.default_context || Loki.Editor.DEFAULT_CONTEXT;

this.addEventListener("context_add", function context_added(name, ctx) {
if (!this.plugins)
@@ -112,8 +117,7 @@
}, this);
}, this);

- // Switch to the loading context, which will call our _loadPlugins
- // method.
+ // Switch to the loading context, which will call our _load method.
this.switchContext("loading");
},

@@ -235,6 +239,8 @@
focus: function focus() {
var ret;

+ if (!this.activeContext)
+ return false;
if (typeof(this.activeContext.focus) != 'function')
return false;

@@ -244,7 +250,8 @@
},

_createUI: function _create_editor_ui(settings) {
- this.theme = new Loki.Theme(settings.theme || "light");
+ this.theme = Loki.Theme.get(settings.theme ||
+ Loki.Editor.DEFAULT_THEME);
this.theme.applyToOwnerDocument(this);

this.root = this._createRoot();
@@ -315,12 +322,12 @@

function loaded(plugin_classes, failed) {
var plugins = {}, fail_count = 0, pfn;
- var dependent_processors = [];
+ this._dependent_processors = [];

Loki.Object.enumerate(plugin_classes, function(id, plugin_class) {
var plugin = new plugin_class(this);
if (typeof(plugin.processDependents) == "function") {
- dependent_processors.push(plugin);
+ this._dependent_processors.push(plugin);
}
plugins[id] = plugin;
}, this);
@@ -343,20 +350,7 @@
this.log(pfn);
}

- this.switchContext(this.defaultContext);
-
- base2.forEach(dependent_processors, function(plugin) {
- plugin.processDependents(plugin.getDependents());
- }, this);
-
- Loki.Object.enumerate(plugins, function(id, plugin) {
- base2.forEach(plugin.contexts, function(context_name) {
- this._pluginUsesContext(plugin, context_name);
- }, this);
-
- if (typeof(plugin.setup) == "function")
- plugin.setup();
- }, this);
+ this._loadTheme();
}

var selector = (this.settings.plugins || "default") + " + core";
@@ -364,7 +358,50 @@
base2.bind(loaded, this));
},

- _pluginUsesContext: function plugin_uses_context(plugin, context_name) {
+ _loadTheme: function _editor_load_theme() {
+ function theme_load_finished(status, theme, message) {
+ if (status == "success") {
+ load_plugin_themes.call(this);
+ } else {
+ this.log("warn", message);
+ // Do something desperate.
+ if (theme.id != Loki.Editor.DEFAULT_THEME) {
+ this.theme = Loki.Theme.get(Loki.Editor.DEFAULT_THEME);
+ this._loadTheme();
+ }
+ }
+ }
+
+ function load_plugin_themes() {
+ this.theme.loadPluginContent(this, plugin_themes_loaded, this);
+ }
+
+ function plugin_themes_loaded(status, theme, loaded_plugins) {
+ this._loaded();
+ }
+
+ this.theme.load(theme_load_finished, this);
+ },
+
+ _loaded: function _editor_loaded() {
+ this.switchContext(this.defaultContext);
+
+ base2.forEach(this._dependent_processors, function(plugin) {
+ plugin.processDependents(plugin.getDependents());
+ }, this);
+ delete this._dependent_processors;
+
+ Loki.Object.enumerate(this.plugins, function(id, plugin) {
+ base2.forEach(plugin.contexts, function(context_name) {
+ this._pluginUsesContext(plugin, context_name);
+ }, this);
+
+ if (typeof(plugin.setup) == "function")
+ plugin.setup();
+ }, this);
+ },
+
+ _pluginUsesContext: function _plugin_uses_context(plugin, context_name) {
var context = this.contexts[context_name];
if (!context)
return;
@@ -373,3 +410,11 @@
}
});
Loki.Class.mixin(Loki.Editor, Loki.EventTarget);
+
+// const: DEFAULT_THEME
+// The theme that Loki editors will use by default.
+Loki.Editor.DEFAULT_THEME = 'light';
+
+// const: DEFAULT_CONTEXT
+// The context that Loki editors will use by default.
+Loki.Editor.DEFAULT_CONTEXT = 'visual';

Modified: trunk/src/theme.js
==============================================================================
--- trunk/src/theme.js (original)
+++ trunk/src/theme.js Thu Dec 4 11:39:06 2008
@@ -31,15 +31,15 @@

var url = $format("{0}themes/{1}/{1}.json", Loki.baseURL, this.id);
var theme = this;
- new Loki.Request(url, {
+ Loki.request(url, {
method: 'GET',
onSuccess: function received_theme_spec(response) {
var spec;
try {
- spec = response.evaluate();
+ spec = eval("(" + response.getText() + ")");
} catch (e) {
callback.call(context, "failure", theme,
- Loki._("theme:eval failed", theme.id, e));
+ Loki._("theme:eval failed", theme.id, String(e)));
return;
}

@@ -76,6 +76,52 @@
});
},

+ // Method: loadPluginContent
+ loadPluginContent: function load_plugin_content(editor, callback,
context) {
+ var ed_plugins = Loki.Object.keys(editor.plugins);
+ var Array2 = base2.JavaScript.Array2;
+ var needed_plugins = [];
+
+ if (!this.isReady()) {
+ throw new Error("Theme " + this.id + " is not yet ready; cannot " +
+ "load plugin content.");
+ }
+
+ if (!callback)
+ callback = null;
+ if (this.spec.processed_plugins) {
+ base2.forEach(ed_plugins, function(plugin) {
+ if (!Array2.contains(this.spec.processed_plugins, plugin))
+ needed_plugins.push(plugin);
+ }, this);
+ } else {
+ needed_plugins = ed_plugins;
+ }
+
+ if (needed_plugins.length == 0) {
+ callback.call(context, 'success', this, needed_plugins);
+ return;
+ }
+
+ var t, themes = [];
+ for (t = this; t != null; t = t.parent) {
+ themes.push(t.id);
+ }
+
+ var remaining_plugins = needed_plugins.slice(0);
+ function load_done(plugin) {
+ Array2.remove(remaining_plugins, plugin);
+
+ if (remaining_plugins.length == 0)
+ callback.call(context, 'success', this, needed_plugins);
+ }
+
+ base2.forEach(needed_plugins, function(plugin) {
+ var loader = new Loki.Theme.PluginLoader(editor, plugin, themes);
+ loader.loadTheme(load_done);
+ });
+ },
+
// Method: applyToOwnerDocument
// Applies a theme to the editor's owner document.
applyToOwnerDocument: function apply_theme_to_owner_doc(editor) {
@@ -88,11 +134,67 @@

_addStyleSheet: function _theme_add_css(document, file) {
if (/^\.\//.test(file))
- file = $format("themes/{0}/{1}", this.id, file);
+ file = $format("themes/{0}/{1}", this.id, file.substr(2));
return document.addStyleSheet(Loki.baseURL + file);
}
});

+Loki.Theme.PluginLoader = Loki.Class.create({
+ initialize: function PluginThemeLoader(editor, plugin, themes) {
+ // The queue starts with the requested theme and goes up its ancestry.
+ this.editor = editor;
+ this.queue = themes.slice(0); // clone
+ this.plugin = plugin;
+ this.base = $format("{0}plugins/{1}/themes", Loki.baseURL, plugin);
+ },
+
+ loadTheme: function load_plugin_theme(callback, context) {
+ if (!context)
+ context = null;
+
+ if (this.queue.length == 0) {
+ // Nothing more for us to do.
+ callback.call(context, this.plugin);
+ return;
+ }
+
+ var theme = this.queue.shift();
+ var loader = this;
+
+ // Here, we try to fetch the stylesheet using an XMLHttpRequest before
+ // adding it to the document. Why? If a plugin provides styles for a
+ // particular theme, it will import its parent's stylesheet, and we
+ // shouldn't include that parent stylesheet directly. But if not, we
+ // still potentially need to include styles for that plugin from one of
+ // the current theme's ancestors. The only way to check for the presence
+ // of a stylesheet is with an XMLHttpRequest. (Fortunately, it should be
+ // cached after the request, so the actual inclusion should be fast.)
+
+ // For simplicity, we stipulate that if a plugin provides theme styles,
+ // it MUST provide both document.css and owner.css, even if one of
+ // those files merely @imports its parent.
+ Loki.request($format("{0}/{1}/document.css", this.base, theme), {
+ method: 'GET',
+
+ onSuccess: function got_plugin_theme(response) {
+ // Sweet! Include it.
+ var doc = $format("{0}/{1}/document.css", loader.base, theme);
+ var owner = $format("{0}/{1}/document.css", loader.base, theme);
+
+ loader.editor.ownerDocument.addStyleSheet(owner);
+ loader.editor.document.addStyleSheet(doc);
+ callback.call(context, loader.plugin);
+ },
+
+ onFailure: function plugin_theme_download_failed(response) {
+ // We don't really care why... the best response is to always
+ // move down the queue.
+ loader.loadTheme(callback, context);
+ }
+ });
+ }
+});
+
// Function: get
// Gets the Theme object for the given theme ID, creating it if necessary.
//
@@ -109,4 +211,4 @@
return Loki.Theme.cache[id];
}

-Loki.Theme.cache = {};
\ No newline at end of file
+Loki.Theme.cache = {};

Reply all
Reply to author
Forward
0 new messages