Commit a86fa637 authored by Romain Courteaud's avatar Romain Courteaud

Fix indentation

parent 55e79740
/*! RenderJs v0.2 */ /*! RenderJs v0.2 */
/*global console, require, $, localStorage, document, jIO */ /*global console, require, $, localStorage, document, jIO */
/*jslint evil: true, white: true */ /*jslint evil: true, indent: 2, maxerr: 3 */
"use strict"; "use strict";
/* /*
* RenderJs - Generic Gadget library renderer. * RenderJs - Generic Gadget library renderer.
...@@ -40,8 +40,8 @@ var RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE = true; ...@@ -40,8 +40,8 @@ var RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE = true;
// fallback for IE // fallback for IE
if (console === undefined || console.log === undefined) { if (console === undefined || console.log === undefined) {
var console = {}; var console = {};
console.log = function () {}; console.log = function () {};
} }
/** /**
...@@ -53,7 +53,7 @@ var RenderJs = (function () { ...@@ -53,7 +53,7 @@ var RenderJs = (function () {
// a variable indicating if current gadget loading is over or not // a variable indicating if current gadget loading is over or not
var is_ready = false, current_gadget; var is_ready = false, current_gadget;
function setSelfGadget (gadget) { function setSelfGadget(gadget) {
/* /*
* Only used internally to set current gadget being executed. * Only used internally to set current gadget being executed.
*/ */
...@@ -62,826 +62,848 @@ var RenderJs = (function () { ...@@ -62,826 +62,848 @@ var RenderJs = (function () {
return { return {
init: function () { init: function () {
/* /*
* Do all initialization * Do all initialization
*/ */
if (RENDERJS_ENABLE_IMPLICIT_GADGET_RENDERING) { if (RENDERJS_ENABLE_IMPLICIT_GADGET_RENDERING) {
RenderJs.bootstrap($('body')); RenderJs.bootstrap($('body'));
}
var root_gadget = RenderJs.GadgetIndex.getRootGadget();
if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND || RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) {
// We might have a page without gadgets.
// Be careful, right now we can be in this case because
// asynchronous gadget loading is not finished
if (root_gadget !== undefined) {
RenderJs.bindReady(
function () {
if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND) {
// examine all Intaction Gadgets and bind accordingly
RenderJs.InteractionGadget.init();
}
if (RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) {
// create all routes between gadgets
RenderJs.RouteGadget.init();
}
}
);
} }
var root_gadget = RenderJs.GadgetIndex.getRootGadget(); }
if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND||RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) { },
// We might have a page without gadgets.
// Be careful, right now we can be in this case because bootstrap: function (root) {
// asynchronous gadget loading is not finished /*
if (root_gadget !== undefined) { * Load all gadgets for this DOM element
RenderJs.bindReady( * (including recursively contained ones)
function () { */
if (RENDERJS_ENABLE_IMPLICIT_INTERACTION_BIND) { var gadget_id, is_gadget;
// examine all Intaction Gadgets and bind accordingly gadget_id = root.attr("id");
RenderJs.InteractionGadget.init(); is_gadget = root.attr("data-gadget") !== undefined;
} // this will make RenderJs fire "ready" event when all gadgets are loaded.
if (RENDERJS_ENABLE_IMPLICIT_ROUTE_CREATE) { RenderJs.setReady(false);
// create all routes between gadgets if (is_gadget && gadget_id !== undefined) {
RenderJs.RouteGadget.init(); // bootstart root gadget only if it is indeed a gadget
} RenderJs.loadGadget(root);
}); }
RenderJs.loadRecursiveGadget(root);
},
loadRecursiveGadget: function (root) {
/*
* Load all contained gadgets inside passed DOM element.
*/
var gadget_list, gadget, gadget_id, gadget_js;
gadget_list = root.find("[data-gadget]");
// register all gadget in advance so checkAndTriggerReady
// can have accurate information for list of all gadgets
gadget_list.each(function () {
gadget = $(this);
gadget_id = gadget.attr("id");
gadget_js = new RenderJs.Gadget(gadget_id, gadget);
RenderJs.GadgetIndex.registerGadget(gadget_js);
});
// Load chilren
gadget_list.each(function () {
RenderJs.loadGadget($(this));
});
},
setGadgetAndRecurse: function (gadget, data) {
/*
* Set gadget data and recursively load it in case it holds another
* gadgets.
*/
// set current gadget as being loaded so gadget instance itself knows which gadget it is
setSelfGadget(RenderJs.GadgetIndex.getGadgetById(gadget.attr("id")));
gadget.append(data);
// reset as no longer current gadget
setSelfGadget(undefined);
// a gadget may contain sub gadgets
RenderJs.loadRecursiveGadget(gadget);
},
getSelfGadget: function () {
/*
* Get current gadget being loaded
* This function must be used with care as it relies on Javascript nature of being a single
* threaded application. Currently current gadget is set in a global RenderJs variable
* before its HTML is inserted into DOM and if multiple threads were running (which is not the case currently)
* this could lead to reace conditions and unreliable getSelfGadget results.
* Additionally this function is available only at gadget's script load time - i.e.
* it can't be used in after that calls. In this case gagdget can save this value internally.
*/
return current_gadget;
},
loadGadget: function (gadget) {
/*
* Load gadget's SPECs from URL
*/
var url, gadget_id, gadget_property, cacheable, cache_id,
i, gadget_index, gadget_index_id,
app_cache, data, gadget_js, is_update_gadget_data_running;
url = gadget.attr("data-gadget");
gadget_id = gadget.attr("id");
gadget_js = RenderJs.GadgetIndex.getGadgetById(gadget_id);
gadget_index = RenderJs.GadgetIndex.getGadgetList();
if (gadget_js === undefined) {
// register gadget in javascript namespace if not already registered
gadget_js = new RenderJs.Gadget(gadget_id, gadget);
RenderJs.GadgetIndex.registerGadget(gadget_js);
}
if (gadget_js.isReady()) {
// avoid loading again gadget which was loaded before in same page
return;
}
// update Gadget's instance with contents of "data-gadget-property"
gadget_property = gadget.attr("data-gadget-property");
if (gadget_property !== undefined) {
gadget_property = $.parseJSON(gadget_property);
$.each(gadget_property, function (key, value) {
gadget_js[key] = value;
});
}
if (url !== undefined && url !== "") {
cacheable = gadget.attr("data-gadget-cacheable");
cache_id = gadget.attr("data-gadget-cache-id");
if (cacheable !== undefined && cache_id !== undefined) {
cacheable = Boolean(parseInt(cacheable, 10));
}
//cacheable = false ; // to develop faster
if (cacheable) {
// get from cache if possible, use last part from URL as
// cache_key
app_cache = RenderJs.Cache.get(cache_id, undefined);
if (app_cache === undefined || app_cache === null) {
// not in cache so we pull from network and cache
$.ajax({
url: url,
yourCustomData: {
"gadget_id": gadget_id,
"cache_id": cache_id
},
success: function (data) {
cache_id = this.yourCustomData.cache_id;
gadget_id = this.yourCustomData.gadget_id;
RenderJs.Cache.set(cache_id, data);
RenderJs.GadgetIndex.getGadgetById(gadget_id).
setReady();
RenderJs.setGadgetAndRecurse(gadget, data);
RenderJs.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
}
});
} else {
// get from cache
data = app_cache;
gadget_js.setReady();
this.setGadgetAndRecurse(gadget, data);
this.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
} }
} else {
// not to be cached
$.ajax({
url: url,
yourCustomData: {"gadget_id": gadget_id},
success: function (data) {
gadget_id = this.yourCustomData.gadget_id;
RenderJs.GadgetIndex.getGadgetById(gadget_id).
setReady();
RenderJs.setGadgetAndRecurse(gadget, data);
RenderJs.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
}
});
}
} else {
// gadget is an inline (InteractorGadget or one using
// data-gadget-source / data-gadget-handler) so no need
// to load it from network
is_update_gadget_data_running = RenderJs.updateGadgetData(gadget);
if (!is_update_gadget_data_running) {
// no update is running so gadget is basically ready
// if update is running then it should take care and set status
gadget_js.setReady();
} }
}, RenderJs.checkAndTriggerReady();
}
},
isReady: function () {
/*
* Get rendering status
*/
return is_ready;
},
setReady: function (value) {
/*
* Update rendering status
*/
is_ready = value;
},
bindReady: function (ready_function) {
/*
* Bind a function on ready gadget loading.
*/
$("body").one("ready", ready_function);
},
checkAndTriggerReady: function () {
/*
* Trigger "ready" event only if all gadgets were marked as "ready"
*/
var is_gadget_list_loaded;
is_gadget_list_loaded = RenderJs.GadgetIndex.isGadgetListLoaded();
if (is_gadget_list_loaded) {
if (!RenderJs.isReady()) {
// backwards compatability with already written code
RenderJs.GadgetIndex.getRootGadget().getDom().
trigger("ready");
// trigger ready on root body element
$("body").trigger("ready");
// this set will make sure we fire this event only once
RenderJs.setReady(true);
}
}
return is_gadget_list_loaded;
},
updateGadgetData: function (gadget) {
/*
* Gadget can be updated from "data-gadget-source" (i.e. a json)
* and "data-gadget-handler" attributes (i.e. a namespace Javascript)
*/
var data_source, data_handler;
data_source = gadget.attr("data-gadget-source");
data_handler = gadget.attr("data-gadget-handler");
// acquire data and pass it to method handler
if (data_source !== undefined && data_source !== "") {
$.ajax({
url: data_source,
dataType: "json",
yourCustomData: {"data_handler": data_handler,
"gadget_id": gadget.attr("id")},
success: function (result) {
var data_handler, gadget_id;
data_handler = this.yourCustomData.data_handler;
gadget_id = this.yourCustomData.gadget_id;
if (data_handler !== undefined) {
// eval is not nice to use
eval(data_handler + "(result)");
gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// mark gadget as loaded and fire a check
// to see if all gadgets are loaded
gadget.setReady();
RenderJs.checkAndTriggerReady();
}
}
});
// asynchronous update happens and respective thread will update status
return true;
}
return false;
},
addGadget: function (dom_id, gadget_id, gadget, gadget_data_handler,
gadget_data_source, bootstrap) {
/*
* add new gadget and render it
*/
var html_string, tab_container, tab_gadget;
tab_container = $('#' + dom_id);
tab_container.empty();
html_string = [
'<div id="' + gadget_id + '"',
'data-gadget="' + gadget + '"',
'data-gadget-handler="' + gadget_data_handler + '" ',
'data-gadget-source="' + gadget_data_source + '"></div>'
].join('\n');
tab_container.append(html_string);
tab_gadget = tab_container.find('#' + gadget_id);
// render new gadget
if (bootstrap !== false) {
RenderJs.bootstrap(tab_container);
}
return tab_gadget;
},
Cache: (function () {
/*
* Generic cache implementation that can fall back to local
* namespace storage if no "modern" storage like localStorage
* is available
*/
return {
ROOT_CACHE_ID: 'APP_CACHE',
getCacheId: function (cache_id) {
/*
* We should have a way to 'purge' localStorage by setting a
* ROOT_CACHE_ID in all browser instances
*/
return this.ROOT_CACHE_ID + cache_id;
},
bootstrap: function (root) { hasLocalStorage: function () {
/* /*
* Load all gadgets for this DOM element * Feature test if localStorage is supported
* (including recursively contained ones)
*/ */
var gadget_id, is_gadget; var mod;
gadget_id = root.attr("id"); mod = 'localstorage_test_12345678';
is_gadget = root.attr("data-gadget") !== undefined; try {
// this will make RenderJs fire "ready" event when all gadgets are loaded. localStorage.setItem(mod, mod);
RenderJs.setReady(false); localStorage.removeItem(mod);
if (is_gadget && gadget_id !== undefined ) { return true;
// bootstart root gadget only if it is indeed a gadget } catch (e) {
RenderJs.loadGadget(root); return false;
}
},
get: function (cache_id, default_value) {
/* Get cache key value */
cache_id = this.getCacheId(cache_id);
if (this.hasLocalStorage()) {
return this.LocalStorageCachePlugin.
get(cache_id, default_value);
} }
RenderJs.loadRecursiveGadget(root); //fallback to javscript namespace cache
}, return this.NameSpaceStorageCachePlugin.
get(cache_id, default_value);
},
set: function (cache_id, data) {
/* Set cache key value */
cache_id = this.getCacheId(cache_id);
if (this.hasLocalStorage()) {
this.LocalStorageCachePlugin.set(cache_id, data);
} else {
this.NameSpaceStorageCachePlugin.set(cache_id, data);
}
},
loadRecursiveGadget: function (root) { LocalStorageCachePlugin: (function () {
/* /*
* Load all contained gadgets inside passed DOM element. * This plugin saves using HTML5 localStorage.
*/ */
var gadget_list, gadget, gadget_id, gadget_js; return {
gadget_list = root.find("[data-gadget]"); get: function (cache_id, default_value) {
/* Get cache key value */
// register all gadget in advance so checkAndTriggerReady if (localStorage.getItem(cache_id) !== null) {
// can have accurate information for list of all gadgets return JSON.parse(localStorage.getItem(cache_id));
gadget_list.each(function () { }
gadget = $(this); return default_value;
gadget_id = gadget.attr("id"); },
gadget_js = new RenderJs.Gadget(gadget_id, gadget);
RenderJs.GadgetIndex.registerGadget(gadget_js);
});
// Load chilren set: function (cache_id, data) {
gadget_list.each(function () { /* Set cache key value */
RenderJs.loadGadget($(this)); localStorage.setItem(cache_id, JSON.stringify(data));
}); }
}, };
}()),
setGadgetAndRecurse: function (gadget, data) { NameSpaceStorageCachePlugin: (function () {
/* /*
* Set gadget data and recursively load it in case it holds another * This plugin saves within current page namespace.
* gadgets.
*/ */
// set current gadget as being loaded so gadget instance itself knows which gadget it is var namespace = {};
setSelfGadget(RenderJs.GadgetIndex.getGadgetById(gadget.attr("id")));
gadget.append(data);
// reset as no longer current gadget
setSelfGadget(undefined);
// a gadget may contain sub gadgets
RenderJs.loadRecursiveGadget(gadget);
},
getSelfGadget: function () {
/*
* Get current gadget being loaded
* This function must be used with care as it relies on Javascript nature of being a single
* threaded application. Currently current gadget is set in a global RenderJs variable
* before its HTML is inserted into DOM and if multiple threads were running (which is not the case currently)
* this could lead to reace conditions and unreliable getSelfGadget results.
* Additionally this function is available only at gadget's script load time - i.e.
* it can't be used in after that calls. In this case gagdget can save this value internally.
*/
return current_gadget;
},
loadGadget: function (gadget) { return {
get: function (cache_id, default_value) {
/* Get cache key value */
return namespace[cache_id];
},
set: function (cache_id, data) {
/* Set cache key value */
namespace[cache_id] = data;
}
};
}())
};
}()),
Gadget: function (gadget_id, dom) {
/*
* Javascript Gadget representation
*/
this.id = gadget_id;
this.dom = dom;
this.is_ready = false;
},
TabbularGadget: (function () {
/*
* Generic tabular gadget
*/
var gadget_list = [];
return {
toggleVisibility: function (visible_dom) {
/* /*
* Load gadget's SPECs from URL * Set tab as active visually and mark as not active rest.
*/ */
var url, gadget_id, gadget_property, cacheable, cache_id, $(".selected").addClass("not_selected");
i, gadget_index, gadget_index_id, $(".selected").removeClass("selected");
app_cache, data, gadget_js, is_update_gadget_data_running; visible_dom.addClass("selected");
visible_dom.removeClass("not_selected");
url = gadget.attr("data-gadget"); },
gadget_id = gadget.attr("id");
gadget_js = RenderJs.GadgetIndex.getGadgetById(gadget_id); addNewTabGadget: function (dom_id, gadget_id, gadget, gadget_data_handler,
gadget_index = RenderJs.GadgetIndex.getGadgetList(); gadget_data_source, bootstrap) {
/*
if (gadget_js === undefined) { * add new gadget and render it
// register gadget in javascript namespace if not already registered */
gadget_js = new RenderJs.Gadget(gadget_id, gadget); var tab_gadget;
RenderJs.GadgetIndex.registerGadget(gadget_js); tab_gadget = RenderJs.addGadget(
} dom_id,
if (gadget_js.isReady()) { gadget_id,
// avoid loading again gadget which was loaded before in same page gadget,
return ; gadget_data_handler,
} gadget_data_source,
bootstrap
);
// we should unregister all gadgets part of this TabbularGadget
$.each(gadget_list,
function (index, gadget_id) {
var gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
gadget.remove();
// update list of root gadgets inside TabbularGadget
gadget_list.splice($.inArray(gadget_id, gadget_list), 1);
}
);
// add it as root gadget
gadget_list.push(tab_gadget.attr("id"));
}
};
}()),
// update Gadget's instance with contents of "data-gadget-property" GadgetIndex: (function () {
gadget_property = gadget.attr("data-gadget-property"); /*
if (gadget_property !== undefined) { * Generic gadget index placeholder
gadget_property = $.parseJSON(gadget_property); */
$.each(gadget_property, function (key, value) { var gadget_list = [];
gadget_js[key] = value;
});
}
if (url !== undefined && url !== "") { return {
cacheable = gadget.attr("data-gadget-cacheable");
cache_id = gadget.attr("data-gadget-cache-id");
if (cacheable !== undefined && cache_id !== undefined) {
cacheable = Boolean(parseInt(cacheable, 10));
}
//cacheable = false ; // to develop faster
if (cacheable) {
// get from cache if possible, use last part from URL as
// cache_key
app_cache = RenderJs.Cache.get(cache_id, undefined);
if (app_cache === undefined || app_cache === null) {
// not in cache so we pull from network and cache
$.ajax({
url: url,
yourCustomData: {
"gadget_id": gadget_id,
"cache_id": cache_id
},
success: function (data) {
cache_id = this.yourCustomData.cache_id;
gadget_id = this.yourCustomData.gadget_id;
RenderJs.Cache.set(cache_id, data);
RenderJs.GadgetIndex.getGadgetById(gadget_id).
setReady();
RenderJs.setGadgetAndRecurse(gadget, data);
RenderJs.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
}
});
} else {
// get from cache
data = app_cache;
gadget_js.setReady();
this.setGadgetAndRecurse(gadget, data);
this.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
}
} else {
// not to be cached
$.ajax({
url: url,
yourCustomData: {"gadget_id": gadget_id},
success: function (data) {
gadget_id = this.yourCustomData.gadget_id;
RenderJs.GadgetIndex.getGadgetById(gadget_id).
setReady();
RenderJs.setGadgetAndRecurse(gadget, data);
RenderJs.checkAndTriggerReady();
RenderJs.updateGadgetData(gadget);
}
});
}
}
else {
// gadget is an inline (InteractorGadget or one using
// data-gadget-source / data-gadget-handler) so no need
// to load it from network
is_update_gadget_data_running = RenderJs.updateGadgetData(gadget);
if (!is_update_gadget_data_running) {
// no update is running so gadget is basically ready
// if update is running then it should take care and set status
gadget_js.setReady();
}
RenderJs.checkAndTriggerReady();
}
},
isReady: function () { getGadgetIdListFromDom: function (dom) {
/* /*
* Get rendering status * Get list of all gadget's ID from DOM
*/ */
return is_ready; var gadget_id_list = [];
}, $.each(dom.find('[data-gadget]'),
function (index, value) {
setReady: function (value) { gadget_id_list.push($(value).attr("id"));
}
);
return gadget_id_list;
},
setGadgetList: function (gadget_list_value) {
/* /*
* Update rendering status * Set list of registered gadgets
*/ */
is_ready = value; gadget_list = gadget_list_value;
}, },
bindReady: function (ready_function) { getGadgetList: function () {
/* /*
* Bind a function on ready gadget loading. * Return list of registered gadgets
*/ */
$("body").one("ready", ready_function); return gadget_list;
}, },
checkAndTriggerReady: function () { registerGadget: function (gadget) {
/* /*
* Trigger "ready" event only if all gadgets were marked as "ready" * Register gadget
*/ */
var is_gadget_list_loaded; if (RenderJs.GadgetIndex.getGadgetById(gadget.id) === undefined) {
is_gadget_list_loaded = RenderJs.GadgetIndex.isGadgetListLoaded(); // register only if not already added
if (is_gadget_list_loaded) { gadget_list.push(gadget);
if (!RenderJs.isReady()) {
// backwards compatability with already written code
RenderJs.GadgetIndex.getRootGadget().getDom().
trigger("ready");
// trigger ready on root body element
$("body").trigger("ready");
// this set will make sure we fire this event only once
RenderJs.setReady(true);
}
} }
return is_gadget_list_loaded; },
},
updateGadgetData: function (gadget) { unregisterGadget: function (gadget) {
/* /*
* Gadget can be updated from "data-gadget-source" (i.e. a json) * Unregister gadget
* and "data-gadget-handler" attributes (i.e. a namespace Javascript)
*/ */
var data_source, data_handler; var index = $.inArray(gadget, gadget_list);
data_source = gadget.attr("data-gadget-source"); if (index !== -1) {
data_handler = gadget.attr("data-gadget-handler"); gadget_list.splice(index, 1);
// acquire data and pass it to method handler
if (data_source !== undefined && data_source !== "") {
$.ajax({
url: data_source,
dataType: "json",
yourCustomData: {"data_handler": data_handler,
"gadget_id": gadget.attr("id")},
success: function (result) {
var data_handler, gadget_id;
data_handler = this.yourCustomData.data_handler;
gadget_id = this.yourCustomData.gadget_id;
if (data_handler !== undefined) {
// eval is not nice to use
eval(data_handler + "(result)");
gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// mark gadget as loaded and fire a check
// to see if all gadgets are loaded
gadget.setReady();
RenderJs.checkAndTriggerReady();
}
}
});
// asynchronous update happens and respective thread will update status
return true;
} }
return false; },
},
addGadget: function (dom_id, gadget_id, gadget, gadget_data_handler, getGadgetById: function (gadget_id) {
gadget_data_source, bootstrap) {
/* /*
* add new gadget and render it * Get gadget javascript representation by its Id
*/ */
var html_string, tab_container, tab_gadget; var gadget;
tab_container = $('#' + dom_id); gadget = undefined;
tab_container.empty(); $(RenderJs.GadgetIndex.getGadgetList()).each(
html_string = [ function (index, value) {
'<div id="' + gadget_id + '"', if (value.getId() === gadget_id) {
'data-gadget="' + gadget + '"', gadget = value;
'data-gadget-handler="' + gadget_data_handler + '" ', }
'data-gadget-source="' + gadget_data_source + '"></div>' }
].join('\n'); );
return gadget;
tab_container.append(html_string); },
tab_gadget = tab_container.find('#' + gadget_id);
// render new gadget
if (bootstrap !== false) {
RenderJs.bootstrap(tab_container);
}
return tab_gadget;
},
Cache: (function () { getRootGadget: function () {
/* /*
* Generic cache implementation that can fall back to local * Return root gadget (always first one in list)
* namespace storage if no "modern" storage like localStorage
* is available
*/ */
return { return this.getGadgetList()[0];
ROOT_CACHE_ID: 'APP_CACHE', },
getCacheId: function (cache_id) {
/*
* We should have a way to 'purge' localStorage by setting a
* ROOT_CACHE_ID in all browser instances
*/
return this.ROOT_CACHE_ID + cache_id;
},
hasLocalStorage: function () {
/*
* Feature test if localStorage is supported
*/
var mod;
mod = 'localstorage_test_12345678';
try {
localStorage.setItem(mod, mod);
localStorage.removeItem(mod);
return true;
} catch (e) {
return false;
}
},
get: function (cache_id, default_value) {
/* Get cache key value */
cache_id = this.getCacheId(cache_id);
if (this.hasLocalStorage()) {
return this.LocalStorageCachePlugin.
get(cache_id, default_value);
}
//fallback to javscript namespace cache
return this.NameSpaceStorageCachePlugin.
get(cache_id, default_value);
},
set: function (cache_id, data) { isGadgetListLoaded: function () {
/* Set cache key value */
cache_id = this.getCacheId(cache_id);
if (this.hasLocalStorage()) {
this.LocalStorageCachePlugin.set(cache_id, data);
} else {
this.NameSpaceStorageCachePlugin.set(cache_id, data);
}
},
LocalStorageCachePlugin: (function () {
/*
* This plugin saves using HTML5 localStorage.
*/
return {
get: function (cache_id, default_value) {
/* Get cache key value */
if (localStorage.getItem(cache_id) !== null) {
return JSON.parse(localStorage.getItem(cache_id));
}
return default_value;
},
set: function (cache_id, data) {
/* Set cache key value */
localStorage.setItem(cache_id, JSON.stringify(data));
}
};
}()),
NameSpaceStorageCachePlugin: (function () {
/*
* This plugin saves within current page namespace.
*/
var namespace = {};
return {
get: function (cache_id, default_value) {
/* Get cache key value */
return namespace[cache_id];
},
set: function (cache_id, data) {
/* Set cache key value */
namespace[cache_id] = data;
}
};
}())
};
}()),
Gadget: function (gadget_id, dom) {
/* /*
* Javascript Gadget representation * Return True if all gadgets were loaded from network or
* cache
*/ */
this.id = gadget_id; var result;
this.dom = dom; result = true;
this.is_ready = false; $(this.getGadgetList()).each(
}, function (index, value) {
if (value.isReady() === false) {
result = false;
}
}
);
return result;
}
};
}()),
GadgetCatalog : (function () {
/*
* Gadget catalog provides API to get list of gadgets from a repository
*/
var cache_id = "setGadgetIndexUrlList";
function updateGadgetIndexFromURL(url) {
// split to base and document url
var url_list = url.split('/'),
document_url = url_list[url_list.length - 1],
d = url_list.splice($.inArray(document_url, url_list), 1),
base_url = url_list.join('/'),
web_dav = jIO.newJio({
"type": "dav",
"username": "",
"password": "",
"url": base_url
});
web_dav.get(document_url,
function (err, response) {
RenderJs.Cache.set(url, response);
});
}
TabbularGadget: (function () { return {
updateGadgetIndex: function () {
/* /*
* Generic tabular gadget * Update gadget index from all configured remote repositories.
*/ */
var gadget_list = []; $.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
return { function (index, value) {
toggleVisibility: function (visible_dom) { updateGadgetIndexFromURL(value);
/* });
* Set tab as active visually and mark as not active rest. },
*/
$(".selected").addClass("not_selected");
$(".selected").removeClass("selected");
visible_dom.addClass("selected");
visible_dom.removeClass("not_selected");
},
addNewTabGadget: function (dom_id, gadget_id, gadget, gadget_data_handler, setGadgetIndexUrlList: function (url_list) {
gadget_data_source, bootstrap) { /*
/* * Set list of Gadget Index repositories.
* add new gadget and render it */
*/ // store in Cache (html5 storage)
var tab_gadget; RenderJs.Cache.set(cache_id, url_list);
tab_gadget = RenderJs.addGadget( },
dom_id, gadget_id, gadget, gadget_data_handler, gadget_data_source, bootstrap
);
// we should unregister all gadgets part of this TabbularGadget getGadgetIndexUrlList: function () {
$.each(gadget_list, /*
function (index, gadget_id) { * Get list of Gadget Index repositories.
var gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id); */
gadget.remove(); // get from Cache (html5 storage)
// update list of root gadgets inside TabbularGadget return RenderJs.Cache.get(cache_id, undefined);
gadget_list.splice($.inArray(gadget_id, gadget_list), 1); },
}
);
// add it as root gadget
gadget_list.push(tab_gadget.attr("id"));
}
};
}()),
GadgetIndex: (function () { getGadgetListThatProvide: function (service) {
/* /*
* Generic gadget index placeholder * Return list of all gadgets that providen a given service.
* Read this list from data structure created in HTML5 local
* storage by updateGadgetIndexFromURL
*/ */
// get from Cache stored index and itterate over it
// to find matching ones
var gadget_list = []; var gadget_list = [];
$.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
return { function (index, url) {
// get repos from cache
getGadgetIdListFromDom: function (dom) { var cached_repo = RenderJs.Cache.get(url);
/* $.each(cached_repo.gadget_list,
* Get list of all gadget's ID from DOM function (index, gadget) {
*/ if ($.inArray(service, gadget.service_list) > -1) {
var gadget_id_list = []; // gadget provides a service, add to list
$.each(dom.find('[data-gadget]'),
function (index, value) {
gadget_id_list.push($(value).attr("id"));}
);
return gadget_id_list;
},
setGadgetList: function (gadget_list_value) {
/*
* Set list of registered gadgets
*/
gadget_list = gadget_list_value;
},
getGadgetList: function () {
/*
* Return list of registered gadgets
*/
return gadget_list;
},
registerGadget: function (gadget) {
/*
* Register gadget
*/
if (RenderJs.GadgetIndex.getGadgetById(gadget.id) === undefined) {
// register only if not already added
gadget_list.push(gadget); gadget_list.push(gadget);
} }
}, }
unregisterGadget: function (gadget) {
/*
* Unregister gadget
*/
var index = $.inArray(gadget, gadget_list);
if (index !== -1) {
gadget_list.splice(index, 1);
}
},
getGadgetById: function (gadget_id) {
/*
* Get gadget javascript representation by its Id
*/
var gadget;
gadget = undefined;
$(RenderJs.GadgetIndex.getGadgetList()).each(
function (index, value) {
if (value.getId() === gadget_id) {
gadget = value;
}
}
); );
return gadget; });
}, return gadget_list;
},
getRootGadget: function () { registerServiceList: function (gadget, service_list) {
/* /*
* Return root gadget (always first one in list) * Register a service provided by a gadget.
*/ */
return this.getGadgetList()[0]; }
}, };
}()),
isGadgetListLoaded: function () { InteractionGadget : (function () {
/* /*
* Return True if all gadgets were loaded from network or * Basic gadget interaction gadget implementation.
* cache */
*/ return {
var result;
result = true;
$(this.getGadgetList()).each(
function (index, value) {
if (value.isReady() === false) {
result = false;
}
}
);
return result;
}
};
}()),
GadgetCatalog : (function () { init: function (force) {
/* /*
* Gadget catalog provides API to get list of gadgets from a repository * Inspect DOM and initialize this gadget
*/ */
var cache_id = "setGadgetIndexUrlList"; var dom_list, gadget_id;
if (force === 1) {
function updateGadgetIndexFromURL(url) { // we explicitly want to re-init elements even if already this is done before
// split to base and document url dom_list = $("div[data-gadget-connection]");
var url_list = url.split('/'), } else {
document_url = url_list[url_list.length-1], // XXX: improve and save 'bound' on javascript representation of a gadget not DOM
d = url_list.splice($.inArray(document_url, url_list), 1), dom_list = $("div[data-gadget-connection]")
base_url = url_list.join('/'), .filter(function () { return $(this).data("bound") !== true; })
web_dav = jIO.newJio({ .data('bound', true);
"type": "dav",
"username": "",
"password": "",
"url": base_url});
web_dav.get(document_url,
function (err, response) {
RenderJs.Cache.set(url, response);
});
} }
dom_list.each(function (index, element) {
RenderJs.InteractionGadget.bind($(element));
});
},
return { bind: function (gadget_dom) {
updateGadgetIndex: function () {
/*
* Update gadget index from all configured remote repositories.
*/
$.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
function(index, value) {
updateGadgetIndexFromURL(value);
});
},
setGadgetIndexUrlList: function (url_list) {
/*
* Set list of Gadget Index repositories.
*/
// store in Cache (html5 storage)
RenderJs.Cache.set(cache_id, url_list);
},
getGadgetIndexUrlList: function () {
/*
* Get list of Gadget Index repositories.
*/
// get from Cache (html5 storage)
return RenderJs.Cache.get(cache_id, undefined);
},
getGadgetListThatProvide: function (service) {
/*
* Return list of all gadgets that providen a given service.
* Read this list from data structure created in HTML5 local
* storage by updateGadgetIndexFromURL
*/
// get from Cache stored index and itterate over it
// to find matching ones
var gadget_list = [];
$.each(RenderJs.GadgetCatalog.getGadgetIndexUrlList(),
function(index, url) {
// get repos from cache
var cached_repo = RenderJs.Cache.get(url);
$.each(cached_repo.gadget_list,
function(index, gadget) {
if ($.inArray(service, gadget.service_list) > -1) {
// gadget provides a service, add to list
gadget_list.push(gadget);
}
}
);
});
return gadget_list;
},
registerServiceList: function (gadget, service_list) {
/*
* Register a service provided by a gadget.
*/
}
};
}()),
InteractionGadget : (function () {
/* /*
* Basic gadget interaction gadget implementation. * Bind event between gadgets.
*/ */
return { var gadget_id, gadget_connection_list,
createMethodInteraction = function (
init: function (force) { original_source_method_id,
/* source_gadget_id,
* Inspect DOM and initialize this gadget source_method_id,
*/ destination_gadget_id,
var dom_list, gadget_id; destination_method_id
if (force===1) { ) {
// we explicitly want to re-init elements even if already this is done before var interaction = function () {
dom_list = $("div[data-gadget-connection]"); // execute source method
} RenderJs.GadgetIndex.getGadgetById(
else { source_gadget_id
// XXX: improve and save 'bound' on javascript representation of a gadget not DOM )[original_source_method_id].
dom_list = $("div[data-gadget-connection]") apply(null, arguments);
.filter(function() { return $(this).data("bound") !== true; }) // call trigger so bind can be asynchronously called
.data('bound', true ); RenderJs.GadgetIndex.getGadgetById(
} destination_gadget_id
dom_list.each(function (index, element) { ).dom.trigger(source_method_id);
RenderJs.InteractionGadget.bind($(element));}); };
}, return interaction;
},
createTriggerInteraction = function (
destination_gadget_id,
destination_method_id
) {
var interaction = function () {
RenderJs.GadgetIndex.getGadgetById(
destination_gadget_id
)[destination_method_id].
apply(null, arguments);
};
return interaction;
};
gadget_id = gadget_dom.attr("id");
gadget_connection_list = gadget_dom.attr("data-gadget-connection");
gadget_connection_list = $.parseJSON(gadget_connection_list);
$.each(gadget_connection_list, function (key, value) {
var source,
source_gadget_id,
source_method_id,
source_gadget,
destination,
destination_gadget_id,
destination_method_id,
destination_gadget,
original_source_method_id;
source = value.source.split(".");
source_gadget_id = source[0];
source_method_id = source[1];
source_gadget = RenderJs.GadgetIndex.
getGadgetById(source_gadget_id);
destination = value.destination.split(".");
destination_gadget_id = destination[0];
destination_method_id = destination[1];
destination_gadget = RenderJs.GadgetIndex.
getGadgetById(destination_gadget_id);
if (source_gadget.hasOwnProperty(source_method_id)) {
// direct javascript use case
original_source_method_id = "original_" +
source_method_id;
source_gadget[original_source_method_id] =
source_gadget[source_method_id];
source_gadget[source_method_id] =
createMethodInteraction(
original_source_method_id,
source_gadget_id,
source_method_id,
destination_gadget_id,
destination_method_id
);
// we use html custom events for asyncronous method call so
// bind destination_gadget to respective event
destination_gadget.dom.bind(
source_method_id,
createTriggerInteraction(
destination_gadget_id,
destination_method_id
)
);
} else {
// this is a custom event attached to HTML gadget
// representation
source_gadget.dom.bind(
source_method_id,
createTriggerInteraction(
destination_gadget_id,
destination_method_id
)
);
}
});
}
};
}()),
bind: function (gadget_dom) { RouteGadget : (function () {
/* /*
* Bind event between gadgets. * A gadget that defines possible routes (i.e. URL changes) between gadgets.
*/ */
var gadget_id, gadget_connection_list, var route_list = [];
createMethodInteraction = function ( return {
original_source_method_id, source_gadget_id,
source_method_id, destination_gadget_id,
destination_method_id) {
var interaction = function () {
// execute source method
RenderJs.GadgetIndex.getGadgetById(
source_gadget_id)[original_source_method_id].
apply(null, arguments);
// call trigger so bind can be asynchronously called
RenderJs.GadgetIndex.getGadgetById(
destination_gadget_id).dom.trigger(source_method_id);
};
return interaction;
},
createTriggerInteraction = function (
destination_gadget_id, destination_method_id) {
var interaction = function () {
RenderJs.GadgetIndex.getGadgetById(
destination_gadget_id)[destination_method_id].
apply(null, arguments);
};
return interaction;
};
gadget_id = gadget_dom.attr("id");
gadget_connection_list = gadget_dom.attr("data-gadget-connection");
gadget_connection_list = $.parseJSON(gadget_connection_list);
$.each(gadget_connection_list, function (key, value) {
var source, source_gadget_id, source_method_id,
source_gadget, destination, destination_gadget_id,
destination_method_id, destination_gadget,
original_source_method_id;
source = value.source.split(".");
source_gadget_id = source[0];
source_method_id = source[1];
source_gadget = RenderJs.GadgetIndex.
getGadgetById(source_gadget_id);
destination = value.destination.split(".");
destination_gadget_id = destination[0];
destination_method_id = destination[1];
destination_gadget = RenderJs.GadgetIndex.
getGadgetById(destination_gadget_id);
if (source_gadget.hasOwnProperty(source_method_id)) {
// direct javascript use case
original_source_method_id = "original_" +
source_method_id;
source_gadget[original_source_method_id] =
source_gadget[source_method_id];
source_gadget[source_method_id] =
createMethodInteraction(
original_source_method_id,
source_gadget_id,
source_method_id,
destination_gadget_id,
destination_method_id
);
// we use html custom events for asyncronous method call so
// bind destination_gadget to respective event
destination_gadget.dom.bind(
source_method_id,
createTriggerInteraction(
destination_gadget_id, destination_method_id
)
);
}
else {
// this is a custom event attached to HTML gadget
// representation
source_gadget.dom.bind(
source_method_id,
createTriggerInteraction(
destination_gadget_id, destination_method_id
)
);
}
});
}
};
}()),
RouteGadget : (function () { init: function () {
/* /*
* A gadget that defines possible routes (i.e. URL changes) between gadgets. * Inspect DOM and initialize this gadget
*/ */
var route_list = []; $("div[data-gadget-route]").each(function (index, element) {
return { RenderJs.RouteGadget.route($(element));
});
init: function () { },
/*
* Inspect DOM and initialize this gadget
*/
$("div[data-gadget-route]").each(function (index, element) {
RenderJs.RouteGadget.route($(element));
});
},
route: function (gadget_dom) {
/*
* Create routes between gadgets.
*/
var body = $("body"),
handler_func, priority,
gadget_route_list = gadget_dom.attr("data-gadget-route");
gadget_route_list = $.parseJSON(gadget_route_list);
$.each(gadget_route_list, function (key, gadget_route) {
handler_func = function () {
var gadget_id = gadget_route.destination.split('.')[0],
method_id = gadget_route.destination.split('.')[1],
gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// set gadget value so getSelfGadget can work
setSelfGadget(gadget);
gadget[method_id].apply(null, arguments);
// reset as no longer needed
setSelfGadget(undefined);
};
// add route itself
priority = gadget_route.priority;
if (priority === undefined) {
// default is 1 -i.e.first level
priority = 1;
}
RenderJs.RouteGadget.add(gadget_route.source, handler_func, priority);
});
},
add: function (path, handler_func, priority) { route: function (gadget_dom) {
/* /*
* Add a route between path (hashable) and a handler function (part of Gadget's API). * Create routes between gadgets.
*/ */
var body = $("body"); var body = $("body"),
body handler_func,
.route("add", path, 1) priority,
.done(handler_func); gadget_route_list = gadget_dom.attr("data-gadget-route");
// save locally gadget_route_list = $.parseJSON(gadget_route_list);
route_list.push({"path": path, $.each(gadget_route_list, function (key, gadget_route) {
"handler_func": handler_func, handler_func = function () {
"priority": priority}); var gadget_id = gadget_route.destination.split('.')[0],
}, method_id = gadget_route.destination.split('.')[1],
gadget = RenderJs.GadgetIndex.getGadgetById(gadget_id);
// set gadget value so getSelfGadget can work
setSelfGadget(gadget);
gadget[method_id].apply(null, arguments);
// reset as no longer needed
setSelfGadget(undefined);
};
// add route itself
priority = gadget_route.priority;
if (priority === undefined) {
// default is 1 -i.e.first level
priority = 1;
}
RenderJs.RouteGadget.add(gadget_route.source, handler_func, priority);
});
},
go: function (path, handler_func, priority) { add: function (path, handler_func, priority) {
/* /*
* Go a route. * Add a route between path (hashable) and a handler function (part of Gadget's API).
*/ */
var body = $("body"); var body = $("body");
body body
.route("go", path, priority) .route("add", path, 1)
.fail(handler_func); .done(handler_func);
}, // save locally
route_list.push({"path": path,
"handler_func": handler_func,
"priority": priority});
},
go: function (path, handler_func, priority) {
/*
* Go a route.
*/
var body = $("body");
body
.route("go", path, priority)
.fail(handler_func);
},
remove: function (path) { remove: function (path) {
/* /*
* Remove a route. * Remove a route.
*/ */
// XXX: implement remove a route when route.js supports it // XXX: implement remove a route when route.js supports it
}, },
getRouteList: function () { getRouteList: function () {
/* /*
* Get list of all router * Get list of all router
*/ */
return route_list; return route_list;
} }
}; };
}()) }())
}; };
}()); }());
// Define Gadget prototype // Define Gadget prototype
RenderJs.Gadget.prototype.getId = function () { RenderJs.Gadget.prototype.getId = function () {
...@@ -915,7 +937,7 @@ RenderJs.Gadget.prototype.remove = function () { ...@@ -915,7 +937,7 @@ RenderJs.Gadget.prototype.remove = function () {
RenderJs.GadgetIndex.unregisterGadget(this); RenderJs.GadgetIndex.unregisterGadget(this);
// gadget might contain sub gadgets so before remove entire // gadget might contain sub gadgets so before remove entire
// DOM we must unregister them from GadgetIndex // DOM we must unregister them from GadgetIndex
this.getDom().find("[data-gadget]").each( function () { this.getDom().find("[data-gadget]").each(function () {
gadget = RenderJs.GadgetIndex.getGadgetById($(this).attr("id")); gadget = RenderJs.GadgetIndex.getGadgetById($(this).attr("id"));
RenderJs.GadgetIndex.unregisterGadget(gadget); RenderJs.GadgetIndex.unregisterGadget(gadget);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment