Commit 3b473853 authored by Sven Franck's avatar Sven Franck

app: made link and content element generation generic

parent 1e14661d
...@@ -983,12 +983,26 @@ ...@@ -983,12 +983,26 @@
* @return controlgroup * @return controlgroup
*/ */
factory.widget.controlgroup = function (spec) { factory.widget.controlgroup = function (spec) {
var container, group, direction, contain, label, i18n, target; var container, group, direction, contain, label, i18n, target, generator;
container = document.createDocumentFragment(); container = document.createDocumentFragment();
direction = spec.direction || "vertical"; direction = spec.direction || "vertical";
// label // NOTE: will only be used for dynamic element creation
generator = function (el, wrapper, i) {
// TODO: no!
if (el.center) {
el.text = el.center[0].title;
el.text_i18n = el.center[0].title_i18n;
}
el.iconpos = "right";
return {
"type": "item",
"content": factory.util.generateContentElement("link", el, {})[0]
};
};
// controlgroup label
if (spec.label) { if (spec.label) {
// NOTE: this will always wrap controlgroups!!! // NOTE: this will always wrap controlgroups!!!
i18n = spec.label.title_i18n || spec.label.text_i18n; i18n = spec.label.title_i18n || spec.label.text_i18n;
...@@ -1043,7 +1057,9 @@ ...@@ -1043,7 +1057,9 @@
return { return {
"fragment": target, "fragment": target,
"child_selector": target.querySelector("div.ui-controlgroup-controls") "child_selector": target.querySelector("div.ui-controlgroup-controls"),
"child_constructor": generator,
"child_mapper": spec.map_children
}; };
}; };
...@@ -1596,12 +1612,10 @@ ...@@ -1596,12 +1612,10 @@
// makes carousel elements // makes carousel elements
generator = function (element, wrapper, i) { generator = function (element, wrapper, i) {
var item, config, target, has_link, caption_wrapper, j, len, block, var item, config, target, has_link;
is_img, section, arr, len, k;
config = wrapper.property_dict; config = wrapper.property_dict;
has_link = element.href; has_link = element.href;
len = element.content.length;
item = factory.element({ item = factory.element({
"type": "li", "type": "li",
"direct": {"className": (i === 0 ? "ui-carousel-active" : "")} "direct": {"className": (i === 0 ? "ui-carousel-active" : "")}
...@@ -1616,21 +1630,8 @@ ...@@ -1616,21 +1630,8 @@
target = item; target = item;
} }
// loop over all sections = array (left|center|right...?) // generate contents
for (section in element) { target.appendChild(factory.util.generateContent(element)[0]);
if (element.hasOwnProperty(section)) {
arr = element[section];
if (typeof arr === "object" && arr !== null) {
len = arr.length;
for (k = 0; k < len; k += 1) {
block = arr[k];
target.appendChild(
factory.util.generateCustomElement(block.type, block, element)[0]
);
}
}
}
}
if (has_link) { if (has_link) {
item.appendChild(target); item.appendChild(target);
...@@ -1804,14 +1805,12 @@ ...@@ -1804,14 +1805,12 @@
// generate list item // generate list item
generator = function (element, wrapper, i) { generator = function (element, wrapper, i) {
var divider, static_item, theme, config, auto, last, item, section, var divider, static_item, theme, config, auto, last, item, target, content;
target, block, j, section, len, k, made, class_string, split, arr;
config = wrapper.property_dict; config = wrapper.property_dict;
divider = element.type === "divider" ? true : undefined; divider = element.type === "divider" ? true : undefined;
static_item = (element.href === undefined && !divider) ? true : undefined; static_item = (element.href === undefined && !divider) ? true : undefined;
theme = config.divider_theme || config.theme || "inherit"; theme = config.divider_theme || config.theme || "inherit";
class_string = "";
// autodividers (TODO: does this work?) // autodividers (TODO: does this work?)
if (config.autodividers) { if (config.autodividers) {
...@@ -1837,30 +1836,12 @@ ...@@ -1837,30 +1836,12 @@
target = document.createDocumentFragment(); target = document.createDocumentFragment();
} else { } else {
element.is_main = true; element.is_main = true;
target = factory.util.generateCustomElement("link", element, config)[0]; target = factory.util.generateContentElement("link", element, config)[0];
} }
// loop over all sections = array (left|center|right...?) // generate contents, split button will return [frag1, frag2, class_list]
for (section in element) { content = factory.util.generateContent(element, "ui-li-has-alt");
if (element.hasOwnProperty(section)) { target.appendChild(content[0]);
arr = element[section];
if (typeof arr === "object" && arr !== null) {
len = arr.length;
for (k = 0; k < len; k += 1) {
block = arr[k];
made = factory.util.generateCustomElement(block.type, block, element);
class_string += made[1];
// split
if (made[1] === "ui-li-has-alt") {
split = made[0];
} else {
target.appendChild(made[0]);
}
}
}
}
}
// list item spec // list item spec
item = factory.element({ item = factory.element({
...@@ -1869,7 +1850,7 @@ ...@@ -1869,7 +1850,7 @@
"className": divider ? ("ui-li-divider ui-bar-" + theme) : " " + "className": divider ? ("ui-li-divider ui-bar-" + theme) : " " +
(i === 0 ? " ui-first-child " : (i === 0 ? " ui-first-child " :
((i === config.length - 1) ? ((i === config.length - 1) ?
" ui-last-child " : " ")) + class_string + " ui-last-child " : " ")) + content.pop() +
(static_item ? " ui-li-static ui-body-inherit " : " ") + (static_item ? " ui-li-static ui-body-inherit " : " ") +
(config.form_item ? "ui-field-contain " : " ") + (config.form_item ? "ui-field-contain " : " ") +
(config.reveal ? "ui-screen-hidden " : " ") (config.reveal ? "ui-screen-hidden " : " ")
...@@ -1882,8 +1863,10 @@ ...@@ -1882,8 +1863,10 @@
// assemble // assemble
item.appendChild(target); item.appendChild(target);
if (split) {
item.appendChild(split); // link-alt
if (!!content[1]) {
item.appendChild(content[1]);
} }
return { return {
...@@ -2371,18 +2354,54 @@ ...@@ -2371,18 +2354,54 @@
return breadcrumb; return breadcrumb;
}; };
/**
* Loop over object and generate content elements inside array
* @method generateContent
* @param {object} config Custom content config object
* @param {string} split Indicator whether to split content
* @return {array} [content fragment, split content, class_string]
**/
// TODO: evolve into something not requiring this and the next method...
factory.util.generateContent = function (config, split) {
var section, arr, len, k, block, content, class_string, fragment, appendix;
class_string = "";
fragment = document.createDocumentFragment();
for (section in config) {
if (config.hasOwnProperty(section)) {
arr = config[section];
if (typeof arr === "object" && arr !== null) {
len = arr.length;
for (k = 0; k < len; k += 1) {
block = arr[k];
content = factory.util.generateContentElement(block.type, block, config);
class_string += content[1];
if (content[1] === split) {
appendix = content[0];
} else {
fragment.appendChild(content[0]);
}
}
}
}
}
return [fragment, appendix, class_string];
};
/** /**
* central method to generate custom-type elements * central method to generate custom-type elements
* @method generateCustomElement * @method generateContentElement
* @param {string} type Type of custom element * @param {string} type Type of custom element
* @param {object} spec Configuration object * @param {object} spec Configuration object
* @param {object} config Parent element configuration properties * @param {object} config Parent element configuration properties
* @return {array} [element, parent_class] * @return {array} [element, parent_class]
**/ **/
// TODO: in case other elements also need parent_class, map here // TODO: class_string only works for listview, could be expanded
// TODO: spec.value contains record values, so make sure they are here // TODO: this is crap though....
factory.util.generateCustomElement = function (type, spec, config) { factory.util.generateContentElement = function (type, spec, config) {
var id, is_type, is_main, no_icon, input_dict, container; var id, is_type, is_main, no_icon, input_dict, container, is_text;
switch (type) { switch (type) {
...@@ -2436,7 +2455,7 @@ ...@@ -2436,7 +2455,7 @@
}), "ui-li-has-icon"]; }), "ui-li-has-icon"];
// main link, split button // main link, split button
// TODO: make icon generic! // TODO: make icon generic! what about util.class_string
case "link": case "link":
is_main = !!spec.is_main; is_main = !!spec.is_main;
no_icon = config.icon === null; no_icon = config.icon === null;
...@@ -2448,11 +2467,11 @@ ...@@ -2448,11 +2467,11 @@
(config.split_theme || config.theme || "inherit") + (config.split_theme || config.theme || "inherit") +
(no_icon ? " " : (is_main ? " ui-btn-icon-right ": (no_icon ? " " : (is_main ? " ui-btn-icon-right ":
" ui-btn-icon-" + (spec.iconpos || "notext")) + " ui-btn-icon-" + (spec.iconpos || "notext")) +
"ui-icon-" + (config.icon || spec.icon || "carat-r")) " ui-icon-" + (config.icon || spec.icon || "carat-r"))
}, },
"attributes": { "attributes": {
"title": spec.title || "", "title": spec.title || "",
"data-i18n": "[title]" + (spec.title_i18n || "") "data-i18n": "[title]" + (spec.title_i18n || "") + ";" + (spec.text_i18n || "")
}, },
"logic":{ "logic":{
"rel": spec.external ? "external" : null, "rel": spec.external ? "external" : null,
...@@ -2462,7 +2481,7 @@ ...@@ -2462,7 +2481,7 @@
}), "ui-li-has-alt"]; }), "ui-li-has-alt"];
// checkbox/radio // checkbox/radio
// TODO: fiddle in refrence here // TODO: reference??
case "check": case "check":
case "radio": case "radio":
// need to do this out here to account for action // need to do this out here to account for action
...@@ -2510,15 +2529,15 @@ ...@@ -2510,15 +2529,15 @@
return [factory.element(spec), ""]; return [factory.element(spec), ""];
} }
return [factory.element({ return [factory.element({
"type": spec.type, "type": spec.type || "span",
"direct": { "direct": {
"className": (spec.aside ? "ui-li-aside " : " ") + "className": (spec.aside ? "ui-li-aside " : " ") +
(spec.text_i18n ? "translate " : " ") + (spec.text_i18n ? "translate " : " ") +
(spec.class_list || "") (spec.class_list || "")
}, },
"logic": { "logic": {
"text": (spec.value || spec.text), "text": (spec.value || spec.title || spec.text),
"data-i18n": spec.text_i18n || null "data-i18n": spec.text_i18n || spec.title_i18n || null
} }
}), ""]; }), ""];
...@@ -2578,80 +2597,8 @@ ...@@ -2578,80 +2597,8 @@
}] }]
} }
}; };
default: alert("default needs noItems"); break; default: alert("placeholder for no items missing"); break;
}
/*
output = {"children": []};
data = content_dict || {};
switch (type) {
case "td": class_string = "ui-no-result"; break;
case "li": class_string = "ui-li ui-li-static ui-first-child ui-last-child " +
"ui-no-result ui-body-inherit";
break;
default: class_string = "responsive ui-content-element"; break;
};
// container
fragment = {
"type": type || "p",
"direct": {"className": class_string},
"attributes": {"colspan": count || null},
"children":[{
"type": "span",
"direct": {"className": "translate"},
"attributes": {"data-i18n": data.message_i18n || "validation_dict.no_items_found"},
"logic": {"text": data.message || "No items found."}
}]
};
// custom message (e.g. modernizr features)
if (data.dynamic) {
fragment.children.push({
"type": "span",
"logic": {"text": message}
});
} }
// action menu
if (data.children && data.children.length > 0) {
action_menu = {
"generate": "widget",
"type": "controlgroup",
"property_dict": {"direction": "horizontal"},
"children": []
};
for (i = 0; i < data.children.length; i += 1) {
button = data.children[i];
back = button.back;
action_menu.children.push({
"type": "a",
"direct": {
"href": back ? "#" : button.href,
"className": "ui-corner-all ui-btn ui-shadow ui-btn-inline " +
(back ? "ui-icon-chevron-sign-left ui-btn-icon-left " :
(button.icon ? "ui-icon-" + button.icon +
" ui-btn-icon-left " : " ")) + (button.class_list || "")
},
"attributes": {
"data-action": button.action || null,
"data-rel": back ? "back" : (button.rel || null),
"data-i18n": back ?
"global_dict.back" : button.text_i18n
},
"logic": {"text": back ? "Back" : button.text}
});
}
fragment.children.push(action_menu);
}
// table cells need a wrapping row
if (type === "td") {
return {"type": "tr", "children": [fragment]};
}*/
}; };
/* ********************************************************************** */ /* ********************************************************************** */
...@@ -3553,27 +3500,22 @@ ...@@ -3553,27 +3500,22 @@
**/ **/
// TODO: multiple header rows! // TODO: multiple header rows!
// TODO: action_menu input + form? // TODO: action_menu input + form?
// TODO: merge with list mapping
// TODO: how to handle translations of record texts? // TODO: how to handle translations of record texts?
// TODO: merge link building with listItem (allow custom core)
map.tableItem = function (item, wrapper, i) { map.tableItem = function (item, wrapper, i) {
var j, k, l, segment, map_section, section, row, cell, fragment, var j, k, segment, row, cell, id, quirk_dict, record, new_item;
base, quirk_dict, record, record_id, core, crop, re;
quirk_dict = wrapper.property_dict; quirk_dict = wrapper.property_dict;
record = item.doc; record = item.doc;
record_id = record[quirk_dict.link_identifier || "id"]; id = record[quirk_dict.link_identifier] || record["_id"] || item["_id"];
core = {"id": record_id || item["id"] || null}; new_item = {};
// link base // id
if (quirk_dict.link && !quirk_dict.link_source) { new_item.id = id;
fragment = quirk_dict.fragment_list;
if (fragment.length > 0) { // link
base = fragment.slice(0, (quirk_dict.layout_level || 0) + 1).join("/"); if (quirk_dict.link) {
} new_item.href = app.util.generateLink(quirk_dict, id);
core.href = record[quirk_dict.link_source] || new_item.external = quirk_dict.external;
("#" + (base || "") + "/" + window.encodeURIComponent(record_id));
core.external = quirk_dict.link_external || null;
} }
// loop schemes // loop schemes
...@@ -3581,14 +3523,13 @@ ...@@ -3581,14 +3523,13 @@
segment = item.scheme[j]; segment = item.scheme[j];
row = []; row = [];
// loop field_list = cells per row // loop field_list = cells
for (k = 0; k < segment.field_list.length; k += 1) { for (k = 0; k < segment.field_list.length; k += 1) {
cell = util.mergeObject(core, util.cloneObject(segment.field_list[k])); cell = util.mergeObject(new_item, util.cloneObject(segment.field_list[k]));
// custom header (!) cells have text/i18n defined // custom header (!) cells have text/i18n defined
// TODO: convert to input field here?
if (!cell.custom) { if (!cell.custom) {
cell.text = util.generateText(record[cell.field], cell, record) cell.text = util.generateText(record[field.value || field.field], cell, record);
cell.text_i18n = record.text_i18n || null; cell.text_i18n = record.text_i18n || null;
} }
row.push(cell); row.push(cell);
...@@ -3609,40 +3550,18 @@ ...@@ -3609,40 +3550,18 @@
* @param {integer} i Counter indicating current item * @param {integer} i Counter indicating current item
* @return {object} mapped object * @return {object} mapped object
**/ **/
// TODO: move radio/check into property_dict and on item level? // TODO: move radio/check into property_dict and item? or do same on tableItem
// TODO: not nice & find better handling for text elements and i18n tags // TODO: not nice & find better handling for text elements and i18n tags
// TODO: core? // NOTE: make sure there is no "id" flying through here!!! only _id
map.listItem = function (item, wrapper, i) { map.listItem = function (item, wrapper, i) {
var quirk_dict, level, core, new_item, section, pos, label, j, k, field, var quirk_dict, core, section, pos, label, j, k, field, setter,
record, property, source; record, property, source, new_item, id, key, obj, translation_fields;
translation_fields = "titletextlabel";
quirk_dict = wrapper.property_dict; quirk_dict = wrapper.property_dict;
record = item.doc; record = item.doc;
new_item = { id = record[quirk_dict.link_identifier] || record["_id"] || item["_id"];
"type": "item" new_item = {};
};
// link base
if (quirk_dict.link) {
label = true;
source = quirk_dict.link_source;
if (source) {
new_item.href = source;
} else {
level = quirk_dict.layout_level || 0;
core = quirk_dict.link_core || (quirk_dict.fragment_list ?
quirk_dict.fragment_list.slice(0, level + 1).join("/") : "");
// set
new_item.href = ("#" + core + "/" + window.encodeURIComponent(
record[quirk_dict.link_identifier || "_id"])
);
}
if (quirk_dict.link_external) {
new_item.external = true;
}
}
// radio // radio
if (quirk_dict.radio) { if (quirk_dict.radio) {
...@@ -3656,10 +3575,16 @@ ...@@ -3656,10 +3575,16 @@
new_item.right = [{"type": "check", "action": "check"}]; new_item.right = [{"type": "check", "action": "check"}];
} }
// add record id for radio/check/linking // link
// TODO: develop a clean way to use _id and id. this is bad! if (quirk_dict.link) {
label = true;
new_item.href = app.util.generateLink(quirk_dict, id);
new_item.external = quirk_dict.external;
}
// id
if (label) { if (label) {
new_item.id = record["id"] || record["_id"] || null; new_item.id = id;
} }
// loop scheme sections // loop scheme sections
...@@ -3671,14 +3596,17 @@ ...@@ -3671,14 +3596,17 @@
// loop scheme fields // loop scheme fields
for (k = 0; k < section.field_list.length; k += 1) { for (k = 0; k < section.field_list.length; k += 1) {
field = section.field_list[k]; field = section.field_list[k];
new_item[pos].push(util.mergeObject( obj = {};
field, key = field.value || field.field;
{
"value": util.generateText( if (translation_fields.indexOf(key) > -1) {
record[field.value || field.field], field, record setter = key;
) obj[setter + "_i18n"] = record[key + "_i18n"];
} } else {
)); setter = "value";
}
obj[setter] = util.generateText(record[key], field, record);
new_item[pos].push(util.mergeObject(field, obj));
} }
} }
...@@ -5320,69 +5248,6 @@ ...@@ -5320,69 +5248,6 @@
document.title = value; document.title = value;
}; };
/**
* Parse a clicked link to determine which page to load
* @method parseLink
* @param {string} url Url being navigated to
* @return {object} navigation object
**/
app.parseLink = function (url) {
var i, hash, path, clean_hash, backup, decode, mode, root;
hash = $.mobile.path.parseUrl(
url.replace($.mobile.dialogHashKey, "")
).hash.replace("#", "");
decode = /^[^\/]*%2[^\/]*$/.test(hash);
backup = 0;
// decode (allowing URI encoded identifiers)
if (decode) {
clean_hash = window.decodeURIComponent(hash);
} else {
clean_hash = hash;
}
if (clean_hash === "") {
root = util.getPage().getAttribute("data-url");
return {
"data_url": root,
"root": root
};
}
// check for mode
path = clean_hash.split("/");
// TODO: this should be generic and without a backup....
// TODO: REFACTOR!!!
for (i = 0; i < path.length; i += 1) {
switch (path[i]) {
case "new":
mode = "new";
backup = 1;
break;
case "add":
case "config":
case "scope":
case "ssl_on":
case "ssl_off":
case "ssl":
case "request":
case "installation":
mode = path[i];
break;
}
}
return {
"mode": mode,
"fragment_list": path,
"data_url": clean_hash,
"layout_level": path.length - 1 - backup,
"deeplink": true,
"root": path[0]
};
};
/** /**
* Parse a page for gadgets and run page setup * Parse a page for gadgets and run page setup
* @method parsePage * @method parsePage
...@@ -5419,7 +5284,7 @@ ...@@ -5419,7 +5284,7 @@
if (data && data.options.reverse) { if (data && data.options.reverse) {
raw_url = window.decodeURIComponent(raw_url); raw_url = window.decodeURIComponent(raw_url);
} }
config = app.parseLink(raw_url); config = app.util.parseLink(raw_url);
if (e) { if (e) {
page = util.getPage(raw_url.split("#").pop()); page = util.getPage(raw_url.split("#").pop());
...@@ -6767,6 +6632,91 @@ ...@@ -6767,6 +6632,91 @@
/* ********************************************************************** */ /* ********************************************************************** */
app.util = {}; app.util = {};
/**
* Parse a clicked link to determine which page to load
* @method parseLink
* @param {string} url Url being navigated to
* @return {object} navigation object
**/
app.util.parseLink = function (url) {
var i, hash, path, clean_hash, backup, decode, mode, root;
hash = $.mobile.path.parseUrl(
url.replace($.mobile.dialogHashKey, "")
).hash.replace("#", "");
decode = /^[^\/]*%2[^\/]*$/.test(hash);
backup = 0;
// decode (allowing URI encoded identifiers)
if (decode) {
clean_hash = window.decodeURIComponent(hash);
} else {
clean_hash = hash;
}
if (clean_hash === "") {
root = util.getPage().getAttribute("data-url");
return {
"data_url": root,
"root": root
};
}
// check for mode
path = clean_hash.split("/");
// TODO: this should be generic and without a backup....
// TODO: REFACTOR!!!
for (i = 0; i < path.length; i += 1) {
switch (path[i]) {
case "new":
mode = "new";
backup = 1;
break;
case "add":
case "config":
case "scope":
case "ssl_on":
case "ssl_off":
case "ssl":
case "request":
case "installation":
mode = path[i];
break;
}
}
return {
"mode": mode,
"fragment_list": path,
"data_url": clean_hash,
"layout_level": path.length - 1 - backup,
"deeplink": true,
"root": path[0]
};
};
/**
* Generate a link based on hierarchy and record
* @method generateLink
* @param {object} spec Object containing query/link related info
* @param {object} record Object containing data including link id
* @return {string} href
*/
app.util.generateLink = function (spec, id) {
var level, core;
if (spec.source) {
return spec.source;
}
level = spec.layout_level || 0;
core = spec.link_core || (spec.fragment_list ?
spec.fragment_list.slice(0, level + 1).join("/") : "");
return ("#" + core + "/" + window.encodeURIComponent(id)
);
};
/** /**
* Main error handler * Main error handler
* @method error * @method error
......
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