Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
E
ecommerce-ui
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
ecommerce-ui
Commits
a64ca636
Commit
a64ca636
authored
Apr 30, 2014
by
Sven Franck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
app: updated to latest generator
parent
b6a3bf4a
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1079 additions
and
525 deletions
+1079
-525
js/erp5_loader.js
js/erp5_loader.js
+1079
-525
No files found.
js/erp5_loader.js
View file @
a64ca636
...
...
@@ -77,6 +77,7 @@
case
"
type
"
:
case
"
rel
"
:
case
"
alt
"
:
case
"
src
"
:
case
"
readonly
"
:
case
"
size
"
:
case
"
colspan
"
:
...
...
@@ -178,7 +179,7 @@
theme
,
icon_string
,
input_type
,
need_text_node
,
container_class_list
,
label_class_list
,
index
,
disabled
,
active
,
text
,
addLabel
,
readonly
,
mask_set
,
mask
,
star
,
hidden_field
,
icon
,
no_validate
,
has_opts
,
push_label
,
no_text
;
push_label
,
no_text
,
label_set
;
// exit early with a span tag
// TODO: make this with label et al
...
...
@@ -216,6 +217,7 @@
// add missing logic
spec
.
logic
=
spec
.
logic
||
{};
spec
.
attributes
=
spec
.
attributes
||
{};
// enhanced!
spec
.
attributes
[
"
data-enhanced
"
]
=
true
;
...
...
@@ -269,7 +271,7 @@
// optionally wrap input in a div-fieldcontain
// NOTE: route is for custom HTML elements... service_instance_status
if
(
!
spec
.
logic
.
route
&&
(
spec
.
logic
.
wrap
!==
true
||
hidden_field
)
)
{
if
(
!
spec
.
logic
.
route
&&
(
spec
.
logic
.
wrap
!==
true
&&
spec
.
wrap
!==
true
)
||
hidden_field
)
{
wrapper
=
document
.
createDocumentFragment
();
}
else
{
wrapper
=
factory
.
element
({
...
...
@@ -304,7 +306,7 @@
}
// label position (before/after element) and class string
container_class_list
=
""
;
container_class_list
=
spec
.
logic
.
wrapper_class_list
||
""
;
label_class_list
=
""
;
// TODO: no, no only because of custom elements having to go through here
...
...
@@ -349,9 +351,9 @@
case
"
submit
"
:
case
"
reset
"
:
if
(
icon
)
{
icon_string
=
factory
.
util
.
classes
(
spec
,
icon
);
icon_string
=
factory
.
util
.
classes
(
spec
,
icon
,
true
);
}
container_class_list
=
"
ui-btn ui-input-btn
"
+
icon_string
;
container_class_list
+
=
"
ui-btn ui-input-btn
"
+
icon_string
;
need_text_node
=
true
;
no_validate
=
true
;
break
;
...
...
@@ -363,8 +365,8 @@
text
=
"
search
"
;
}
// disable IOS auto functionality (WARNING: fails W3C validation)
spec
.
attributes
.
autocapitalize
=
"
none
"
;
spec
.
attributes
.
autocorrect
=
"
none
"
;
//
spec.attributes.autocapitalize = "none";
//
spec.attributes.autocorrect = "none";
container_class_list
=
"
ui-input-
"
+
text
;
}
...
...
@@ -384,6 +386,7 @@
disabled
+
readonly
+
(
action
||
""
)
+
(
clear
||
""
)
+
(
theme
?
(
"
ui-bar-
"
+
theme
+
"
"
)
:
"
ui-body-inherit
"
);
}
// NOTE: time to make elements - needs shuffling to fit all variants
// container
...
...
@@ -437,12 +440,14 @@
// This saves doing "invalid" handler with javascript
if
(
spec
.
logic
.
add_label
!==
false
&&
((
need_text_node
===
undefined
&&
(
push_label
||
!
label_inside
)
&&
!
hidden_field
)
||
spec
.
logic
.
route
))
{
label_set
=
true
;
label_target
.
appendChild
(
addLabel
(
spec
,
label_class_list
));
}
// add <span> which contains JQM current select
if
(
element_reverse
)
{
element_target
.
appendChild
(
factory
.
element
({
"
type
"
:
"
span
"
}));
element_target
.
appendChild
(
factory
.
element
({
"
type
"
:
"
span
"
}));
}
else
{
element_target
=
container
;
}
...
...
@@ -456,18 +461,18 @@
element_target
.
appendChild
(
factory
.
element
(
spec
));
// checkbox radio need label after input
if
(
label_inside
)
{
if
(
label_inside
&&
!
label_set
)
{
label_target
.
appendChild
(
addLabel
(
spec
,
label_class_list
));
}
// add invalid validation messages
// TODO: "wrong" is wrong
// TODO: "wrong" is wrong - but don't put any text references here
// all text references should be somewhere in config!
if
(
!
no_validate
&&
!
spec
.
logic
.
route
)
{
element_target
.
appendChild
(
factory
.
element
({
"
type
"
:
"
span
"
,
"
direct
"
:
{
"
className
"
:
"
ui-invalid-label
"
},
"
attributes
"
:
{},
"
logic
"
:
{
"
text
"
:
"
wrong
"
}
"
direct
"
:
{
"
className
"
:
"
ui-invalid-label translate
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
validation_dict.required_field
"
}
}));
}
...
...
@@ -522,7 +527,6 @@
}
else
{
wrapper
=
container
;
}
return
wrapper
;
};
...
...
@@ -539,7 +543,8 @@
* "title": "",
* "title_i18n": null,
* "theme": null,
* "fix": true,
* "fix_footer": null,
* "fix_header": null
* "create": null (added automatically)
* "data_url": null (added automatically)
* "fragment_list": [] (added automatically)
...
...
@@ -559,14 +564,13 @@
// new page
if
(
container
===
null
||
spec
.
create
===
true
)
{
container
=
factory
.
element
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
ui-page
"
+
(
"
ui-page-theme-
"
+
spec
.
theme
||
""
)
+
"
"
+
((
spec
.
fix
&&
spec
.
fix
===
false
)
?
""
:
"
ui-page-header-fixed ui-page-footer-fixed
"
)
spec
.
theme
||
""
)
+
"
"
+
(
spec
.
fix_header
?
"
ui-page-header-fixed
"
:
"
"
)
+
(
spec
.
fix_footer
?
"
ui-page-footer-fixed
"
:
"
"
)
},
"
attributes
"
:
{
"
data-role
"
:
"
page
"
,
...
...
@@ -774,7 +778,8 @@
(
collapsed
?
"
"
:
"
ui-collapsible-heading-collapsed
"
)
},
"
logic
"
:
{
"
role
"
:
spec
.
form
?
"
heading
"
:
null
//pfff (WARNING: fails W3C validation)
//"role": spec.form ? "heading" : null
}
});
...
...
@@ -868,6 +873,8 @@
* @param {object} spec JSON configuration
* @return {object} object including fragment, child-selector, placeholder
*/
// TODO: too complicated and too much custom stuff passed back
// This cannot be so difficult...
factory
.
widget
.
header
=
function
(
spec
)
{
var
container
,
id
,
target
,
set_img
,
img
;
...
...
@@ -877,11 +884,11 @@
img
=
spec
.
image
||
{};
// button group wrappers and title (inserted before last wrapper!)
target
=
function
(
spec
)
{
target
=
function
(
new_
spec
)
{
var
position
,
drop_content
,
fragment
,
count
,
config
;
count
=
spec
.
j
;
config
=
spec
.
config
;
count
=
new_
spec
.
j
;
config
=
new_
spec
.
config
;
fragment
=
document
.
createDocumentFragment
();
position
=
(
config
.
section_list
||
[
"
first
"
,
"
last
"
])[
count
];
drop_content
=
config
.
add_content
===
0
?
0
:
1
;
...
...
@@ -903,7 +910,8 @@
"
direct
"
:
{
"
className
"
:
"
translate ui-title
"
},
"
attributes
"
:
{
"
data-i18n
"
:
config
.
title_i18n
||
""
,
"
role
"
:
"
heading
"
,
// WARNING Fails W3C
//"role": "heading",
"
aria-level
"
:
"
1
"
},
"
logic
"
:
{
"
text
"
:
config
.
title
||
"
\
u00A0
"
}
...
...
@@ -926,7 +934,7 @@
"
direct
"
:
{
"
id
"
:
id
,
"
className
"
:
(
spec
.
class_list
||
"
"
)
+
(
spec
.
fixed
?
"
ui-header-fixed
"
:
"
"
)
+
"
bar ui-header foo
"
+
(
spec
.
fixed
?
"
ui-header-fixed
"
:
"
"
)
+
"
ui-header
"
+
"
slidedown ui-bar-
"
+
(
spec
.
theme
||
"
inherit
"
)
},
"
attributes
"
:
{
...
...
@@ -943,9 +951,10 @@
return
{
"
fragment
"
:
container
,
"
child_selector
"
:
container
.
querySelector
(
"
#
"
+
id
),
"
child_selector
"
:
container
.
querySelector
(
"
#
"
+
id
)
||
container
,
"
target
"
:
target
,
"
target_selector
"
:
"
last
"
,
// TODO: remove this...
"
spec
"
:
{
"
img
"
:
!!
set_img
,
"
src
"
:
img
.
src
,
...
...
@@ -969,6 +978,7 @@
* "property_dict": {
* "id": null,
* "class_list": null,
* "mini": null
* "theme": null,
* "direction": "horizontal",
* "label": {
...
...
@@ -993,6 +1003,7 @@
direction
=
spec
.
direction
||
"
vertical
"
;
// NOTE: will only be used for dynamic element creation
// TODO: what does this do here?
generator
=
function
(
generator_spec
)
{
var
element
=
generator_spec
.
item
;
// TODO: no!
...
...
@@ -1009,6 +1020,7 @@
// controlgroup label
if
(
spec
.
label
)
{
// TODO: how to get required on the legend? or off?
// NOTE: this will always wrap controlgroups!!!
i18n
=
spec
.
label
.
title_i18n
||
spec
.
label
.
text_i18n
;
contain
=
factory
.
element
({
...
...
@@ -1021,14 +1033,17 @@
});
label
=
factory
.
element
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
ui-controlgroup-label
"
},
"
attributes
"
:
{
"
role
"
:
"
heading
"
}
"
direct
"
:
{
"
className
"
:
"
ui-controlgroup-label
"
}
//,
//"attributes": {"role": "heading"}
});
label
.
appendChild
(
factory
.
element
({
"
type
"
:
"
legend
"
,
"
logic
"
:
{
"
text
"
:
spec
.
label
.
text
,
"
data-i18n
"
:
i18n
?
(
spec
.
label
.
text_i18n
)
:
null
"
direct
"
:
{
"
className
"
:
"
translate required_label
"
},
"
attributes
"
:
{
"
data-i18n
"
:
spec
.
label
.
text_i18n
}
}));
contain
.
appendChild
(
label
);
...
...
@@ -1039,14 +1054,13 @@
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
ui-corner-all ui-controlgroup
"
+
(
spec
.
class_list
||
""
)
+
"
ui-controlgroup-
"
+
direction
(
spec
.
class_list
||
""
)
+
"
ui-controlgroup-
"
+
direction
+
(
spec
.
mini
?
"
ui-mini
"
:
""
)
},
"
attributes
"
:
{
"
data-role
"
:
"
controlgroup
"
,
"
data-enhanced
"
:
"
true
"
,
"
data-type
"
:
direction
},
"
logic
"
:
{
"
id
"
:
spec
.
id
||
null
}
"
logic
"
:
{
"
id
"
:
spec
.
id
||
null
,
"
data-persist
"
:
spec
.
persist
||
null
}
});
// controls
...
...
@@ -1266,9 +1280,7 @@
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
navbar ui-navbar
"
+
(
spec
.
class_list
||
""
)},
"
attributes
"
:
{
"
data-role
"
:
"
navbar
"
,
"
role
"
:
"
navigation
"
,
"
data-enhanced
"
:
"
true
"
},
"
logic
"
:
{
"
data-reference
"
:
spec
.
reference
||
null
}
});
...
...
@@ -1308,13 +1320,12 @@
pass
=
function
(
container
)
{
return
{
"
fragment
"
:
container
,
"
child_selector
"
:
container
.
firstElementChild
||
container
,
"
child_selector
"
:
container
.
querySelector
(
"
div
"
)
||
container
,
"
add_on_dom
"
:
spec
.
target
===
"
document
"
};
};
container
=
document
.
createDocumentFragment
();
slot
=
spec
.
slot
;
switch
(
spec
.
wrap
)
{
case
"
fragment
"
:
...
...
@@ -1323,6 +1334,7 @@
class_list
=
spec
.
class_list
;
break
;
default
:
slot
=
spec
.
slot
;
class_list
=
(
slot
?
""
:
"
ui-controlbar
"
)
+
(
spec
.
class_list
||
""
);
break
;
}
...
...
@@ -1332,8 +1344,8 @@
"
direct
"
:
{
"
className
"
:
class_list
},
"
attributes
"
:
{},
"
logic
"
:
{
"
data-persist
"
:
spec
.
persist
||
null
,
"
data-wrap
"
:
slot
?
null
:
true
,
"
data-slot
"
:
slot
?
true
:
null
,
"
data-slot-id
"
:
slot
||
null
,
...
...
@@ -1474,21 +1486,28 @@
container
=
document
.
createDocumentFragment
();
form_id
=
"
form_
"
+
util
.
uuid
();
item_id
=
spec
.
data
?
(
spec
.
data
.
_id
||
undefined
)
:
undefined
;
form
=
factory
.
element
({
"
type
"
:
"
form
"
,
"
direct
"
:
{
"
id
"
:
form_id
,
"
method
"
:
"
POST
"
,
"
action
"
:
"
#
"
,
"
className
"
:
(
spec
.
class_list
||
""
)
},
"
attributes
"
:
{
"
data-ajax
"
:
false
,
"
autocomplete
"
:
"
off
"
},
"
logic
"
:
{
"
data-reference
"
:
spec
.
reference
||
null
,
"
data-depend
"
:
spec
.
depend
||
null
,
"
data-reset
"
:
spec
.
reset
||
null
}
});
if
(
spec
.
update
)
{
form
=
document
.
createDocumentFragment
();
}
else
{
form
=
factory
.
element
({
"
type
"
:
"
form
"
,
"
direct
"
:
{
"
id
"
:
form_id
,
"
method
"
:
"
POST
"
,
"
action
"
:
"
#
"
,
"
className
"
:
(
spec
.
class_list
||
""
)
},
"
attributes
"
:
{
"
data-ajax
"
:
false
,
"
autocomplete
"
:
"
off
"
,
"
data-widget
"
:
"
form
"
},
"
logic
"
:
{
"
data-reference
"
:
spec
.
reference
||
null
,
"
data-map
"
:
spec
.
map_children
||
null
}
});
}
// NOTE: needed to differentiate between PUT/POST
// TODO: block_identifier is only used for release_install, find better!
...
...
@@ -1639,7 +1658,10 @@
if
(
has_link
)
{
target
=
factory
.
element
({
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
ui-link ui-carousel-selector
"
}
"
direct
"
:
{
"
href
"
:
has_link
,
"
className
"
:
"
ui-link ui-carousel-selector
"
}
});
}
else
{
target
=
item
;
...
...
@@ -1685,13 +1707,13 @@
"
direct
"
:
{
"
role
"
:
"
carousel
"
,
"
className
"
:
(
spec
.
class_list
||
empty_string
)
+
"
ui-carousel
"
+
(
is_thumb
?
"
ui-carousel-thumbnails
"
:
"
ui-carousel-bullets
"
+
(
is_thumb
?
"
ui-carousel-thumbnails
"
:
"
ui-carousel-bullets
"
+
((
has_handles
?
"
ui-carousel-handles
"
:
empty_string
)
+
(
spec
.
shadow
?
"
ui-shadow
"
:
empty_string
)
+
(
spec
.
captions
?
"
ui-carousel-captions
"
:
empty_string
)
+
(
spec
.
inset
?
"
ui-carousel-inset
"
:
empty_string
)
+
(
spec
.
corners
?
"
ui-corner-all
"
:
empty_string
)))
+
(
"
ui-body-
"
+
(
spec
.
theme
||
"
inherit
"
))
(
"
ui-body-
"
+
(
spec
.
theme
||
"
inherit
"
))
},
"
attributes
"
:
{
"
data-enhanced
"
:
true
,
...
...
@@ -1820,6 +1842,7 @@
*/
// TODO: add collapsible support if needed
// TODO: dividers? will not be in spec, so can only be listview option!
// TODO: find better way to set mapper/widget
factory
.
widget
.
listview
=
function
(
spec
)
{
var
fragment
,
has_filter
,
generator
;
...
...
@@ -1836,6 +1859,9 @@
theme
=
config
.
divider_theme
||
config
.
theme
||
"
inherit
"
;
// autodividers (TODO: does this work? NO!!! do with i!)
// NOTE: it should also work without enhancing the widget, because
// the list items are re-generated on refresh, so autodividers can be
// aswell
if
(
config
.
autodividers
)
{
auto
=
element
.
text
[
0
].
text
.
slice
(
0
,
1
).
toUpperCase
();
if
(
last
!==
auto
)
{
...
...
@@ -1846,7 +1872,7 @@
"
className
"
:
"
ui-li-divider ui-bar-
"
+
theme
+
(
count
===
0
?
"
ui-first-child
"
:
((
count
===
config
.
length
-
1
)
?
"
ui-last-child
"
:
""
))
"
ui-last-child
"
:
""
))
+
(
element
.
class_list
||
""
)
},
"
attributes
"
:
{},
"
logic
"
:
{
"
text
"
:
auto
}
...
...
@@ -1881,11 +1907,8 @@
"
ui-last-child
"
:
"
"
))
+
content
.
pop
()
+
(
static_item
?
"
ui-li-static ui-body-inherit
"
:
"
"
)
+
(
config
.
form_item
?
"
ui-field-contain
"
:
"
"
)
+
(
config
.
reveal
?
"
ui-screen-hidden
"
:
"
"
)
},
"
logic
"
:
{
"
data-role
"
:
divider
?
"
divider
"
:
null
,
"
role
"
:
divider
?
"
heading
"
:
null
(
config
.
reveal
?
"
ui-screen-hidden
"
:
"
"
)
+
(
element
.
class_list
||
""
)
}
});
...
...
@@ -1909,25 +1932,17 @@
// search filter
if
(
spec
.
update
!==
true
)
{
// NOTE: if input provided, the filter is already there!
if
(
spec
.
filter
&&
spec
.
input
===
undefined
)
{
has_filter
=
true
;
fragment
.
appendChild
(
factory
.
widget
.
formElement
({
"
type
"
:
"
input
"
,
"
direct
"
:
{
"
id
"
:
"
filter_
"
+
(
spec
.
id
||
"
items
"
),
"
className
"
:
"
action
"
},
"
attributes
"
:
{
"
data-action
"
:
"
search
"
,
"
data-enhanced
"
:
true
,
"
data-i18n
"
:
""
,
"
placeholder
"
:
"
Search
"
,
"
data-icon
"
:
"
search
"
},
"
logic
"
:
{
"
clear
"
:
"
true
"
}
}));
// THIS MAKES B
if
(
spec
.
filter
&&
!
spec
.
input
)
{
has_filter
=
true
;
fragment
.
appendChild
(
factory
.
widget
.
formElement
(
factory
.
util
.
searchBarTemplate
({
"
search_id
"
:
spec
.
id
||
"
search
"
,
"
text
"
:
spec
.
text
||
""
,
"
text_i18n
"
:
spec
.
text_i18n
||
null
})
));
}
fragment
.
appendChild
(
factory
.
element
({
...
...
@@ -1937,29 +1952,26 @@
(
spec
.
inset
?
"
ui-listview-inset ui-corner-all ui-shadow
"
:
""
)
},
"
attributes
"
:
{
"
data-role
"
:
"
listview
"
,
"
data-enhanced
"
:
true
},
"
attributes
"
:
{
// NOTE: on updates, we need wrapper with generator and mapper???
"
data-widget
"
:
"
listview
"
},
"
logic
"
:
{
"
id
"
:
spec
.
id
||
null
,
"
data-update
"
:
spec
.
dynamic
?
true
:
null
,
// NOTE: on updates, we need wrapper with generator...
"
data-widget
"
:
"
listview
"
,
"
data-reference
"
:
spec
.
reference
||
null
,
"
data-filter
"
:
spec
.
filter
||
null
,
"
data-input
"
:
spec
.
input
||
null
,
"
data-filter-theme
"
:
spec
.
filter_theme
||
null
,
"
data-filter-placeholder
"
:
spec
.
placeholder
||
null
,
"
data-divider-theme
"
:
spec
.
divider_theme
||
null
"
data-map
"
:
spec
.
map_children
||
null
}
}));
}
return
{
"
fragment
"
:
fragment
,
"
child_selector
"
:
spec
.
update
!==
true
?
fragment
[
has_filter
?
"
last
"
:
"
first
"
+
"
ElementChild
"
]
:
fragment
,
"
child_selector
"
:
spec
.
update
!==
true
?
fragment
.
querySelector
(
"
ul
"
)
:
fragment
,
"
child_constructor
"
:
generator
,
"
child_mapper
"
:
spec
.
map_children
,
"
base
"
:
"
li
"
"
base
"
:
"
li
"
,
"
foo
"
:
"
listview
"
};
};
...
...
@@ -2030,8 +2042,7 @@
*/
// TODO: pre-enhance!
factory
.
widget
.
table
=
function
(
spec
)
{
var
fragment
,
container
,
generator
,
counter
,
target
,
section
,
i
,
tag
,
image
;
var
fragment
,
container
,
generator
,
counter
,
section
,
i
,
tag
,
image
;
counter
=
function
(
scheme
)
{
var
m
,
field
,
k
;
...
...
@@ -2053,13 +2064,6 @@
return
config
.
text
;
};
target
=
function
()
{
return
factory
.
widget
.
controlbar
({
"
wrap
"
:
"
section
"
,
"
class_list
"
:
"
span_2
"
});
};
generator
=
function
(
generator_spec
)
{
var
quirk_dict
,
row
,
temp
,
cell
,
j
,
field
,
link
,
logic
,
faux_id
,
attributes
,
property
,
snippet
,
title
,
k
,
button
,
group
,
dict
,
set
,
...
...
@@ -2284,9 +2288,12 @@
case
"
header
"
:
tag
=
factory
.
element
({
"
type
"
:
"
thead
"
});
tag
.
appendChild
(
generator
(
section
.
field_list
,
{
"
wrap
"
:
true
,
"
property_dict
"
:
spec
generator
({
"
item
"
:
section
.
field_list
,
"
wrapper
"
:
{
"
property_dict
"
:
spec
,
"
wrap
"
:
true
}
}).
content
);
container
.
appendChild
(
tag
);
...
...
@@ -2297,22 +2304,21 @@
"
attributes
"
:
{
"
data-update
"
:
"
true
"
,
"
data-widget
"
:
"
table
"
}
},
"
logic
"
:
{
"
data-map
"
:
spec
.
map_children
||
null
}
}));
break
;
}
}
fragment
.
appendChild
(
container
);
}
return
{
"
fragment
"
:
fragment
,
"
child_selector
"
:
fragment
.
querySelector
(
"
tbody
"
),
"
child_constructor
"
:
generator
,
"
child_mapper
"
:
spec
.
map_children
,
"
base
"
:
"
tr
"
,
"
count
"
:
counter
,
"
target
"
:
target
"
count
"
:
counter
};
};
...
...
@@ -2404,9 +2410,9 @@
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
)
{
for
(
k
=
0
,
len
=
arr
.
length
;
k
<
len
;
k
+=
1
)
{
block
=
arr
[
k
];
content
=
factory
.
util
.
generateContentElement
(
block
.
type
,
...
...
@@ -2424,6 +2430,7 @@
}
}
}
// TODO: return an object...
return
[
fragment
,
appendix
,
class_string
];
};
...
...
@@ -2478,7 +2485,7 @@
return
[
factory
.
element
({
"
type
"
:
"
img
"
,
"
direct
"
:
{
"
src
"
:
(
spec
.
src
||
spec
.
value
),
"
alt
"
:
(
spec
.
alt
||
""
)}
}),
"
ui-li-has-thumb
"
];
}),
"
ui-li-has-thumb
"
];
// custom icon > left
case
"
icon
"
:
...
...
@@ -2486,10 +2493,10 @@
"
type
"
:
"
span
"
,
"
direct
"
:
{
"
className
"
:
"
ui-li-icon ui-li-icon-custom ui-icon-
"
+
spec
.
icon
+
"
ui-icon
"
(
spec
.
icon
||
spec
.
value
)
+
"
ui-icon
"
},
"
logic
"
:
{
"
text
"
:
"
\
u00A0
"
}
}),
"
ui-li-has-icon
"
];
}),
"
ui-li-has-icon
"
];
// main link, split button
// TODO: make icon generic! what about util.class_string
...
...
@@ -2668,18 +2675,22 @@
* util.classes
* @param {object} element Configuration
* @param {string} default_icon Icon to pass as default
* @param {string} pass Allow to pass through manually (input-wrapper eg)
* @return {string} finished class string
**/
factory
.
util
.
classes
=
function
(
element
,
default_icon
)
{
factory
.
util
.
classes
=
function
(
element
,
default_icon
,
pass
)
{
var
def
,
string
,
iconpos
,
icon
;
string
=
""
;
// NOTE: we only set on <a>
if
(
element
.
type
===
"
a
"
)
{
// NOTE: we only set on <a>
NOT on INPUTs, because they are wrappped!
if
(
element
.
type
===
"
a
"
||
pass
)
{
icon
=
(
element
.
attributes
||
{})[
"
data-icon
"
]
||
default_icon
;
// because of custom a in service_instance_status!
if
(
!
element
.
logic
.
plain_link
)
{
// because of custom a in service_instance_status
// NOTE: input buttons may need icons, but not ui-btn ui-shadow
// TODO: this has nothing to do here!!!
if
(
!
(
element
.
logic
||
{}).
plain_link
)
{
string
+=
"
ui-btn ui-shadow
"
;
}
if
(
icon
)
{
...
...
@@ -2695,38 +2706,52 @@
return
string
;
};
/** Generate a
seach bar (controlbar)
/** Generate a
configuration object for a search input
* @method searchBar
* @param {object} spec
Pagination
configuration
* @return {object} finished
config object
* @param {object} spec
Search bar
configuration
* @return {object} finished
search bar config
**/
factory
.
util
.
searchBar
=
function
(
spec
)
{
var
i
,
element_list
,
search_id
,
props
,
class_list
;
search_id
=
"
search_
"
+
util
.
uuid
();
class_list
=
spec
.
class_list
||
""
;
props
=
spec
.
slot
?
{
"
slot
"
:
spec
.
slot
}
:
{};
element_list
=
[{
factory
.
util
.
searchBarTemplate
=
function
(
spec
)
{
return
{
"
type
"
:
"
input
"
,
"
direct
"
:
{
"
id
"
:
search_id
,
"
className
"
:
"
translate
"
},
"
direct
"
:
{
"
id
"
:
s
pec
.
s
earch_id
,
"
className
"
:
"
translate
"
},
"
attributes
"
:
{
"
data-action
"
:
"
search
"
,
"
data-enhanced
"
:
"
true
"
,
"
data-i18n
"
:
"
[placeholder]
"
+
spec
.
text_i18n
,
"
placeholder
"
:
spec
.
text
,
"
data-icon
"
:
"
search
"
,
"
data-action-btn
"
:
"
true
"
,
"
data-type
"
:
"
search
"
,
"
type
"
:
"
search
"
},
"
logic
"
:
{
"
clear
"
:
"
true
"
,
"
action
"
:
"
search
"
}
}];
"
logic
"
:
{
"
clear
"
:
"
true
"
,
"
action
"
:
"
search
"
,
"
data-i18n
"
:
spec
.
text_i18n
?
(
"
[placeholder]
"
+
spec
.
text_i18n
)
:
null
}
};
};
for
(
i
=
0
;
i
<
spec
.
info_list
.
length
;
i
+=
1
)
{
/** Generate a seach bar (controlbar)
* @method searchBar
* @param {object} spec Pagination configuration
* @return {object} finished config object
**/
factory
.
util
.
searchBar
=
function
(
spec
)
{
var
i
,
element_list
,
search_id
,
props
,
class_list
,
spec_list
;
search_id
=
spec
.
search_id
=
"
search_
"
+
util
.
uuid
();
props
=
spec
.
slot
?
{
"
slot
"
:
spec
.
slot
}
:
{};
props
.
class_list
=
spec
.
class_list
||
""
;
element_list
=
[
factory
.
util
.
searchBarTemplate
(
spec
)];
spec_list
=
spec
.
info_list
||
[];
for
(
i
=
0
;
i
<
spec_list
.
length
;
i
+=
1
)
{
element_list
.
push
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
info
"
},
"
attributes
"
:
{
"
data-info
"
:
spec
.
info
_list
[
i
]}
"
attributes
"
:
{
"
data-info
"
:
spec_list
[
i
]}
});
}
...
...
@@ -2734,7 +2759,6 @@
"
config
"
:
{
"
generate
"
:
"
widget
"
,
"
type
"
:
"
controlbar
"
,
"
class_list
"
:
class_list
,
"
property_dict
"
:
props
,
"
children
"
:
element_list
},
...
...
@@ -2743,19 +2767,21 @@
};
/** Generate a pagination toolbar (controlbar)
* @method paginat
e
* @method paginat
ionBar
* @param {object} spec Pagination configuration
* @return {object} finished config object
**/
// TODO: make this a real widget with methods!
factory
.
util
.
paginationBar
=
function
(
spec
)
{
var
n
,
option
,
props
,
option_list
,
c
lass_list
,
config
;
var
n
,
option
,
props
,
option_list
,
c
onfig
,
len
,
opts
,
pointer
;
option_list
=
[{
"
value
"
:
""
,
"
text
"
:
""
,
"
text_i18n
"
:
""
}];
opts
=
spec
.
option_list
||
[];
props
=
spec
.
slot
?
{
"
slot
"
:
spec
.
slot
}
:
{};
class_list
=
spec
.
class_list
||
""
;
props
.
class_list
=
spec
.
class_list
||
""
;
for
(
n
=
0
;
n
<
spec
.
option_list
.
length
;
n
+=
1
)
{
option
=
spec
.
option_list
[
n
];
for
(
n
=
0
,
len
=
opts
.
length
;
n
<
len
;
n
+=
1
)
{
option
=
opts
[
n
];
option_list
.
push
({
"
value
"
:
option
.
value
,
"
text
"
:
option
.
text
,
...
...
@@ -2766,58 +2792,75 @@
config
=
{
"
generate
"
:
"
widget
"
,
"
type
"
:
"
controlbar
"
,
"
class_list
"
:
class_list
,
"
property_dict
"
:
props
,
"
children
"
:
[{
"
generate
"
:
"
widget
"
,
"
type
"
:
"
controlgroup
"
,
"
property_dict
"
:
{
"
direction
"
:
"
horizontal
"
},
"
children
"
:
[{
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.first
"
,
"
data-action
"
:
"
first
"
,
"
data-icon
"
:
"
step-backward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
First
"
}
},
{
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.previous
"
,
"
data-action
"
:
"
prev
"
,
"
data-icon
"
:
"
backward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
Previous
"
}
},
{
"
type
"
:
"
select
"
,
"
direct
"
:
{
"
id
"
:
"
select_
"
+
util
.
uuid
(),
"
className
"
:
"
action
"
},
"
attributes
"
:
{
"
data-icon
"
:
"
bars
"
,
"
data-action
"
:
"
limit
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
options
"
:
option_list
}
},
{
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.next
"
,
"
data-action
"
:
"
next
"
,
"
data-icon
"
:
"
forward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
Next
"
}
}]
"
children
"
:
[]
}]
};
pointer
=
config
.
children
[
0
].
children
;
// first
if
(
!
spec
.
single
)
{
config
.
children
[
0
].
property_dict
.
class_list
=
"
ui-pagination-single
"
;
pointer
.
push
({
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.first
"
,
"
data-action
"
:
"
first
"
,
"
data-icon
"
:
"
step-backward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
First
"
}
});
}
// always add previous
pointer
.
push
({
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.previous
"
,
"
data-action
"
:
"
prev
"
,
"
data-icon
"
:
"
backward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
Previous
"
}
});
// select
if
(
len
>
0
)
{
pointer
.
push
({
"
type
"
:
"
select
"
,
"
direct
"
:
{
"
id
"
:
"
select_
"
+
util
.
uuid
(),
"
className
"
:
"
action
"
},
"
attributes
"
:
{
"
data-icon
"
:
"
bars
"
,
"
data-action
"
:
"
limit
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
options
"
:
option_list
}
});
}
// always add next
pointer
.
push
({
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
"
data-i18n
"
:
"
global_dict.next
"
,
"
data-action
"
:
"
next
"
,
"
data-icon
"
:
"
forward
"
,
"
data-iconpos
"
:
"
notext
"
},
"
logic
"
:
{
"
text
"
:
"
Next
"
}
});
// only add last button, if total is available
if
(
!
app
.
storage_dict
.
property_dict
.
skip_total_records
)
{
config
.
children
[
0
].
children
.
push
({
if
(
!
app
.
storage_dict
.
property_dict
.
skip_total_records
&&
!
spec
.
single
)
{
pointer
.
push
({
"
type
"
:
"
a
"
,
"
direct
"
:
{
"
className
"
:
"
action
"
,
"
href
"
:
"
#
"
},
"
attributes
"
:
{
...
...
@@ -2950,6 +2993,115 @@
factory
.
util
.
setDynamicPointer
(
obj
,
"
ui_panel_sales
"
);
},
/**
* POST an object
* @method new
* @param {object} obj Action Object
**/
"
new
"
:
function
(
obj
)
{
storage
.
write
(
obj
)
.
then
(
function
(
response
)
{
app
.
util
.
loader
(
""
,
"
status_dict.saved
"
,
"
check
"
);
app
.
navigate
(
obj
,
response
);
})
.
fail
(
function
(
error
)
{
switch
(
error
.
status
)
{
case
408
:
app
.
util
.
loader
(
""
,
"
status_dict.timeout
"
,
"
clock-o
"
);
break
;
case
400
:
app
.
util
.
loader
(
""
,
"
validation_dict.general
"
,
"
ban
"
);
break
;
default
:
app
.
util
.
loader
(
""
,
"
status_dict.error
"
,
"
ban
"
);
break
;
}
});
},
/**
* GET an object
* @method get
* @param {object} obj Action Object
**/
"
get
"
:
function
(
obj
)
{
storage
.
fetch
(
obj
);
},
/**
* PUT an object
* @method update
* @param {object} obj Action Object
**/
"
update
"
:
function
(
obj
)
{
storage
.
write
(
obj
)
.
then
(
function
(
response
)
{
app
.
util
.
loader
(
""
,
"
status_dict.saved
"
,
"
check
"
);
app
.
navigate
(
obj
,
response
);
})
.
fail
(
function
(
error
)
{
switch
(
error
.
status
)
{
case
408
:
app
.
util
.
loader
(
""
,
"
status_dict.timeout
"
,
"
clock-o
"
);
break
;
case
400
:
app
.
util
.
loader
(
""
,
"
validation_dict.general
"
,
"
ban
"
);
break
;
default
:
app
.
util
.
loader
(
""
,
"
status_dict.error
"
,
"
ban
"
);
break
;
}
});
},
/**
* Same as put but since there is no time to make dyno interaction, we cheat!
* @method update
* @param {object} obj Action Object
**/
"
update_custom
"
:
function
(
obj
)
{
storage
.
write
(
obj
)
.
then
(
function
(
response
)
{
var
i
,
len
,
dyno_list
,
dyno
,
promise_list
,
dump
;
// clear active page, because we need to reload
dump
=
document
.
querySelector
(
"
div.ui-content
"
);
util
.
deleteChildren
(
dump
);
// refresh dynos that are left!
dyno_list
=
document
.
querySelectorAll
(
"
div.dyno
"
);
// set first page to reload and clean it up!
delete
app
.
deeplink_flag
;
promise_list
=
[];
for
(
i
=
0
,
len
=
dyno_list
.
length
;
i
<
len
;
i
+=
1
)
{
dyno
=
dyno_list
[
i
];
// update gadgets
promise_list
[
i
]
=
app
.
content
.
set
(
{
"
portal_type_source
"
:
dyno
.
state
.
type
,
"
portal_type_title
"
:
dyno
.
state
.
title
,
"
property_dict
"
:
util
.
mergeObject
(
{
"
dynamic
"
:
true
},
dyno
.
state
.
dyno_dict
),
"
scheme
"
:
dyno
.
state
.
scheme
},
{
"
reference
"
:
dyno
.
id
,
"
href
"
:
dyno
.
state
.
href
,
"
fragment_list
"
:
dyno
.
state
.
fragment_list
,
"
layout_level
"
:
dyno
.
state
.
layout_level
},
false
)
.
fail
(
app
.
util
.
error
);
}
return
RSVP
.
all
(
promise_list
)
.
then
(
function
(
response_list
)
{
app
.
util
.
loader
(
""
,
"
status_dict.saved
"
,
"
check
"
);
//app.navigate(obj, response);
})
.
fail
(
app
.
util
.
error
);
})
.
then
(
app
.
setPageBindings
)
.
fail
(
function
(
error
)
{
switch
(
error
.
status
)
{
case
408
:
app
.
util
.
loader
(
""
,
"
status_dict.timeout
"
,
"
clock-o
"
);
break
;
case
400
:
app
.
util
.
loader
(
""
,
"
validation_dict.general
"
,
"
ban
"
);
break
;
default
:
app
.
util
.
loader
(
""
,
"
status_dict.error
"
,
"
ban
"
);
break
;
}
});
},
/**
* Look up single value from dict
* @method translateLookup
...
...
@@ -2972,14 +3124,14 @@
* @param {object} nodeList Nodelist to translate
* @param {boolean} single Single element
**/
// TODO:
no solution yet for selectMenu-refesh and input (submit/reset/btn)
// TODO:
don't call this so often on init
"
translateNodeList
"
:
function
(
nodeList
,
single
)
{
var
i
,
l
,
element
,
lookup
,
targets
,
target
,
route_text
,
elements
;
var
i
,
l
,
element
,
lookup
,
targets
,
target
,
route_text
,
elements
,
len
;
elements
=
single
?
[
nodeList
]
:
nodeList
.
querySelectorAll
(
"
.translate
"
);
if
(
i18n
)
{
for
(
i
=
0
;
i
<
elements
.
length
;
i
+=
1
)
{
for
(
i
=
0
,
len
=
elements
.
length
;
i
<
len
;
i
+=
1
)
{
element
=
elements
[
i
];
lookup
=
element
.
getAttribute
(
"
data-i18n
"
);
...
...
@@ -3025,14 +3177,19 @@
break
;
default
:
// NOTE: empty - setting .translate on a wrapper will empty it
while
(
element
.
hasChildNodes
())
{
element
.
removeChild
(
element
.
firstChild
);
}
util
.
deleteChildren
(
element
);
element
.
appendChild
(
document
.
createTextNode
(
i18n
.
t
(
target
[
0
])));
break
;
}
}
}
// handle select > span!
if
(
element
.
tagName
===
"
OPTION
"
)
{
if
(
element
.
selected
&&
element
.
parentNode
.
previousSibling
)
{
element
.
parentNode
.
previousSibling
.
textContent
=
element
.
textContent
;
}
}
}
}
else
{
app
.
util
.
error
(
"
Translate NodeList - i18n not defined
"
);
...
...
@@ -3056,8 +3213,8 @@
current_language
=
$
.
i18n
.
lng
(),
shortcut
=
function
(
language
)
{
switch
(
language
)
{
case
"
zh-CN
"
:
return
"
flag-
cn
"
;
case
"
fr-FR
"
:
return
"
flag-
fr
"
;
case
"
en-EN
"
:
return
"
flag-en
"
;
}
...
...
@@ -3092,42 +3249,6 @@
}
},
/**
* Show jumps popup
* @method jump
* @param {object} obj Action Object
**/
"
browse
"
:
function
(
obj
)
{
factory
.
util
.
setDynamicPointer
(
obj
,
"
browse
"
);
},
/**
* Show task popup
* @method tasks
* @param {object} obj Action Object
**/
"
tasks
"
:
function
(
obj
)
{
factory
.
util
.
setDynamicPointer
(
obj
,
"
tasks
"
);
},
/**
* Show application popup
* @method login
* @param {object} obj Action Object
**/
"
login
"
:
function
(
obj
)
{
factory
.
util
.
setDynamicPointer
(
obj
,
"
login
"
);
},
/**
* Show export popup
* @method export
* @param {object} obj Action Object
**/
"
export
"
:
function
(
obj
)
{
factory
.
util
.
setDynamicPointer
(
obj
,
"
export
"
);
},
/**
* Generic pagination method changing number of records displayed
* @method limit
...
...
@@ -3309,9 +3430,19 @@
})
.
fail
(
app
.
util
.
error
);
}
return
RSVP
.
resolve
(
wrapper
.
child_constructor
(
element
,
wrapper
,
i
));
return
RSVP
.
resolve
(
wrapper
.
child_constructor
({
"
item
"
:
element
,
"
wrapper
"
:
wrapper
,
"
count
"
:
i
}));
}
// NOTE: when loading content via href, element is set to undefined
// TODO: Why? ^^^^^^
// NOTE: fetch subordinate fields
if
(
element
&&
element
.
needs_subordination
)
{
return
app
.
util
.
setSubordinate
(
element
,
wrapper
);
}
return
RSVP
.
resolve
(
element
||
wrapper
.
inherit
);
};
...
...
@@ -3327,12 +3458,14 @@
// TODO: multiple header rows!
// TODO: action_menu input + form?
// TODO: how to handle translations of record texts?
// TODO: subordinate handling
// TODO: pick translations from field_dict for header!
map
.
tableItem
=
function
(
spec
)
{
var
j
,
k
,
segment
,
row
,
cell
,
id
,
quirk_dict
,
record
,
new_item
,
item
;
quirk_dict
=
spec
.
parent
.
property_dict
;
quirk_dict
=
spec
.
wrapper
.
property_dict
;
item
=
spec
.
item
;
record
=
item
.
doc
;
record
=
item
.
doc
||
{}
;
id
=
record
[
quirk_dict
.
link_identifier
]
||
record
.
_id
||
item
.
_id
;
new_item
=
{};
...
...
@@ -3384,17 +3517,20 @@
**/
// 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: subordinated fields should have links, not id only!!!
// NOTE: make sure there is no "id" flying through here!!! only _id
map
.
listItem
=
function
(
spec
)
{
var
quirk_dict
,
section
,
pos
,
label
,
j
,
k
,
field
,
setter
,
record
,
new_item
,
id
,
key
,
obj
,
translation_fields
,
item
;
var
quirk_dict
,
section
,
label
,
j
,
k
,
field
,
setter
,
record
,
new_item
,
id
,
key
,
translation_fields
,
item
,
relation
,
promise_list
,
pass
,
count
;
promise_list
=
[];
translation_fields
=
"
titletextlabel
"
;
quirk_dict
=
spec
.
wrapper
.
property_dict
;
item
=
spec
.
item
;
record
=
item
.
doc
;
id
=
record
[
quirk_dict
.
link_identifier
]
||
record
.
_id
||
item
.
_id
;
new_item
=
{};
count
=
0
;
// radio
if
(
quirk_dict
.
radio
)
{
...
...
@@ -3423,27 +3559,58 @@
// loop scheme sections
for
(
j
=
0
;
j
<
item
.
scheme
.
length
;
j
+=
1
)
{
section
=
item
.
scheme
[
j
];
pos
=
section
.
position
;
new_item
[
pos
]
=
new_item
[
pos
]
||
[];
// loop scheme fields
for
(
k
=
0
;
k
<
section
.
field_list
.
length
;
k
+=
1
)
{
field
=
section
.
field_list
[
k
];
obj
=
{};
key
=
field
.
value
||
field
.
field
;
key
=
field
.
value
||
field
.
field
||
""
;
relation
=
key
.
split
(
"
subordinate_
"
);
pass
=
{
"
record
"
:
record
,
"
position
"
:
section
.
position
,
"
key
"
:
key
,
"
field
"
:
field
,
"
text_element
"
:
translation_fields
.
indexOf
(
key
)
>
-
1
};
if
(
translation_fields
.
indexOf
(
key
)
>
-
1
)
{
setter
=
key
;
obj
[
setter
+
"
_i18n
"
]
=
record
[
key
+
"
_i18n
"
];
// fetch values of subordinate fields via query or flux/memory
if
(
relation
.
length
>
1
)
{
pass
.
relation
=
record
[
key
];
pass
.
subordinate
=
relation
[
1
];
promise_list
[
count
+
k
]
=
storage
.
subordinate
(
pass
);
}
else
{
setter
=
"
value
"
;
pass
.
value
=
util
.
generateText
(
record
[
key
],
field
,
record
);
promise_list
[
count
+
k
]
=
RSVP
.
resolve
(
pass
);
}
obj
[
setter
]
=
util
.
generateText
(
record
[
key
],
field
,
record
);
new_item
[
pos
].
push
(
util
.
mergeObject
(
field
,
obj
));
}
count
+=
k
;
}
return
RSVP
.
resolve
(
new_item
);
return
RSVP
.
all
(
promise_list
)
.
then
(
function
(
response_list
)
{
var
l
,
len
,
response
,
obj
,
setter
,
pos
;
for
(
l
=
0
,
len
=
response_list
.
length
;
l
<
len
;
l
+=
1
)
{
response
=
response_list
[
l
];
pos
=
response
.
position
;
obj
=
{};
new_item
[
pos
]
=
new_item
[
pos
]
||
[];
// text/label/... all stuff translateable
if
(
response
.
text_element
)
{
obj
[
response
.
key
+
"
_18n
"
]
=
record
[
response
.
key
+
"
_i18n
"
];
setter
=
key
;
}
else
{
setter
=
"
value
"
;
}
obj
[
setter
]
=
response
.
value
;
new_item
[
pos
].
push
(
util
.
mergeObject
(
response
.
field
,
obj
));
}
return
new_item
;
})
.
fail
(
app
.
util
.
error
);
};
/* ********************************************************************** */
...
...
@@ -3457,6 +3624,7 @@
**/
// TODO: should a span still have full structure (label/container)?
// TODO: should we wrap in span_12 here. why do we wrap at all, do with CSS
// TODO: subordinate value
map
.
formItem
=
function
(
spec
)
{
var
helper
,
getHelp
,
j
,
k
,
segment
,
section
,
field
,
setValue
,
root
,
veto
,
textarea_value
,
override_value
,
value
,
field_value
,
validation_list
,
...
...
@@ -3476,23 +3644,25 @@
// TODO: remove this crap or make it generic...
// set = setter_list ... JSLINT
setValue
=
function
(
setter
)
{
var
n
,
len
,
set_value
,
set_flux
,
set
,
val
,
set_reference
;
var
n
,
len
,
set_value
,
set_flux
,
set
,
val
,
set_reference
,
logic
,
selection
,
split
;
if
(
setter
.
logic
)
{
set_reference
=
setter
.
logic
.
setReference
;
set_value
=
setter
.
logic
.
setValue
;
val
=
setter
.
logic
.
lookupValue
;
set
=
setter
.
logic
.
setters
;
set_flux
=
setter
.
logic
.
setFlux
;
logic
=
setter
.
logic
;
if
(
logic
)
{
set_reference
=
logic
.
setReference
;
set_value
=
logic
.
setValue
;
val
=
logic
.
lookupValue
;
set
=
logic
.
setters
;
set_flux
=
logic
.
setFlux
;
if
(
set
)
{
len
=
set
.
length
;
for
(
n
=
0
;
n
<
len
;
n
+=
1
)
{
if
(
val
)
{
// FU§$%&/NG HAL
setter
.
logic
[
set
[
n
]]
=
item
.
doc
[
val
[
n
][
0
]][
val
[
n
][
1
]][
val
[
n
][
2
]];
// FU
Â
§$%&/NG HAL
logic
[
set
[
n
]]
=
item
.
doc
[
val
[
n
][
0
]][
val
[
n
][
1
]][
val
[
n
][
2
]];
}
else
{
setter
.
logic
[
set
[
n
]]
=
item
.
doc
[
set_value
];
logic
[
set
[
n
]]
=
item
.
doc
[
set_value
];
}
}
}
else
if
(
set_value
)
{
...
...
@@ -3510,7 +3680,7 @@
delete
flux
.
_temp
[
set_flux
];
}
else
{
// translation!?
setter
.
direct
.
value
=
setter
.
logic
.
noFlux
;
setter
.
direct
.
value
=
logic
.
noFlux
;
}
}
}
...
...
@@ -3522,15 +3692,24 @@
if
(
!!
item
.
direct
)
{
setValue
(
item
);
}
else
if
(
!!
item
.
generate
)
{
// we must declare wrap for non-form elements here, because they
//
NOTE:
we must declare wrap for non-form elements here, because they
// don't belong into any widget
// NOTE: persist if set!
container
=
getHelp
({
"
wrap
"
:
"
section
"
,
"
persist
"
:
item
.
property_dict
.
persist
,
"
class_list
"
:
"
span_
"
+
(
item
.
property_dict
.
wrap
||
1
)
});
container
.
children
.
push
(
item
);
}
else
{
helper
=
getHelp
({
"
wrap
"
:
"
fragment
"
});
// NOTE: since we are creating 2 levels in the DOM tree (fragment &
// sections), the normal inheritance will break, because a wrapper
// will be missing state. Therefore we add the state manually here,
// TODO: don't do 2 level stuff.... and complain later when debugging
helper
=
getHelp
({
"
wrap
"
:
"
fragment
"
,
"
state
"
:
spec
.
wrapper
.
property_dict
.
state
});
}
// nothing to do, pass back directly
...
...
@@ -3545,6 +3724,7 @@
for
(
j
=
0
;
j
<
item
.
scheme
.
length
;
j
+=
1
)
{
segment
=
item
.
scheme
[
j
];
field_list
=
[];
type
=
null
;
// loop scheme field_list
for
(
k
=
0
;
k
<
segment
.
field_list
.
length
;
k
+=
1
)
{
...
...
@@ -3568,6 +3748,7 @@
field
.
overrides
||
{},
{
"
properties
"
:
{},
"
widget
"
:
{}}
);
value
=
item
.
doc
[
field
.
setValue
||
field
.
field
];
// flag false/missing field_dict
...
...
@@ -3715,8 +3896,8 @@
pass
=
{
"
push
"
:
{
"
type
"
:
el
,
"
wrap
"
:
true
,
"
label
"
:
true
,
"
wrap
"
:
veto
.
wrap
||
true
,
"
label
"
:
veto
.
label
||
true
,
"
direct
"
:
{
"
id
"
:
item
.
reference
+
"
_
"
+
(
veto
.
widget
.
id
||
root
.
widget
.
id
),
...
...
@@ -3755,8 +3936,13 @@
};
}
// NOTE: we can't remove type from attributes, but must delete
// it if it's null, otherwise code is not valid (Opera chokes)
if
(
pass
.
push
.
attributes
.
type
===
null
)
{
delete
pass
.
push
.
attributes
.
type
;
}
// need to set position here to also include custom fields
pass
.
position
=
segment
.
position
===
"
center
"
?
2
:
1
;
pass
.
position
=
segment
.
position
===
"
center
"
?
1
:
2
;
// fetch dynamic options
if
(
fetch_items
===
null
)
{
...
...
@@ -3777,7 +3963,7 @@
loaded_options
=
answer
.
response
;
// need to handle multi radio/checkbox groups...
// need to handle multi radio/checkbox groups...
and selects????
if
(
loaded_options
)
{
push
=
answer
.
pass
.
push
;
...
...
@@ -3832,6 +4018,12 @@
clone
.
logic
.
label_i18n
=
clone_opt
.
text_i18n
;
clone
.
logic
.
value
=
clone_opt
.
value
;
clone
.
attributes
[
"
data-i18n
"
]
=
clone_opt
.
text_i18n
;
switch
(
p
)
{
case
0
:
clone
.
position
=
len
===
1
?
null
:
true
;
break
;
case
len
-
1
:
clone
.
position
=
false
;
break
;
}
group
.
children
.
push
(
clone
);
}
...
...
@@ -3845,6 +4037,8 @@
.
fail
(
app
.
util
.
error
);
}
// NOTE: must set property_dict on the controlbar in order to inherit
// dynamic data to the contained field elements
section_list
[
j
]
=
RSVP
.
all
(
field_list
)
.
then
(
function
(
field_response_list
)
{
section
=
getHelp
({
...
...
@@ -3864,6 +4058,7 @@
for
(
m
=
0
;
m
<
section_response_list
.
length
;
m
+=
1
)
{
helper
.
children
.
push
(
section_response_list
[
m
]);
}
return
RSVP
.
resolve
(
helper
);
})
.
fail
(
app
.
util
.
error
);
...
...
@@ -3876,49 +4071,86 @@
// generate storage object with placeholders
storage
=
{
"
obj
"
:
{},
"
empty_
obj
"
:
{},
"
arr
"
:
[],
"
span
"
:
document
.
createElement
(
"
span
"
)
};
/**
* Get a subordinate record and store in flux in case multiple properties
* of this object are requested
* @method subordinate
* @param {object} spec Current record
* @return {promise}
*/
storage
.
subordinate
=
function
(
spec
)
{
var
output
;
// fetch from cache or query
if
(
flux
.
active_record
[
spec
.
relation
])
{
output
=
flux
.
active_record
[
spec
.
relation
];
}
else
{
output
=
flux
.
active_record
[
spec
.
relation
]
=
storage
.
fetch
({
"
pass
"
:
spec
,
"
query
"
:
{
"
_id
"
:
spec
.
relation
}
});
}
return
output
.
then
(
function
(
answer
)
{
var
data
=
answer
.
response
.
data
;
// set subordinate value
if
(
data
.
total_rows
>
0
)
{
spec
.
value
=
data
.
rows
[
0
].
doc
[
spec
.
subordinate
]
}
// NOTE: delete here, otherwise impossible to track. This will still
// work cause subsequent requests will fire async and be set from flux
delete
flux
.
active_record
[
spec
.
relation
];
return
spec
;
}).
fail
(
app
.
util
.
error
);
};
/**
* Fetch data from storage = GET or ALLDOCS
* @method fetch
* @param {object} obj Action object
*/
// TODO: merge pass.x or pass.state.x
// TODO: set pointer directly inside data-action, remove pointer!
// TODO: state needs to have url_pointer set earlier, so
// there is no need to look it up in pass.config.property_dict...
// TODO: convert config/url_dict into state and save 50000 assignments
// TODO: set pointer directly inside data-action.... remove pointer!
// TODO: jump is bad, it is the lookup for the data to display. rename!
// TODO: the whole assignments are crap
// TODO: action_id > this should be triggered via form submit not links!!!
// TODO: does _id always include portal_type? if link, yes, else no.
storage
.
fetch
=
function
(
obj
)
{
var
pass
,
query
,
method
,
mapper
,
config
,
answer
,
lookup
,
pointer
,
action_id
,
quirk
;
var
pass
,
query
,
method
,
mapper
,
config
,
answer
,
lookup
,
pointer
,
empty
,
action_id
,
quirk
;
empty
=
storage
.
empty_obj
;
pass
=
obj
.
pass
;
quirk
=
obj
.
state
||
pass
.
config_dict
;
lookup
=
obj
.
state
||
quirk
.
property_dict
||
storage
.
obj
;
query
=
obj
.
query
||
lookup
.
query
||
storage
.
obj
;
pointer
=
(
lookup
.
url_pointer
||
storage
.
obj
).
jump
;
// TODO: action > id, this should be triggered via form submit not link!
action_id
=
((
obj
.
element
||
storage
.
obj
).
href
||
""
).
split
(
"
/
"
).
pop
();
quirk
=
obj
.
state
||
pass
.
config_dict
||
empty
;
lookup
=
obj
.
state
||
quirk
.
property_dict
||
empty
;
query
=
obj
.
query
||
lookup
.
query
||
empty
;
pointer
=
(
lookup
.
url_pointer
||
empty
).
jump
;
action_id
=
((
obj
.
element
||
empty
).
href
||
""
).
split
(
"
/
"
).
pop
();
if
(
action_id
)
{
pointer
=
undefined
;
query
=
{
"
_id
"
:
window
.
decodeURIComponent
(
action_id
)};
}
// F%&/() JSLINT...
// JSLINT my ...
// TODO: "hack" for forcing get into allDocs, don't overwrite criteria!
if
(
!!
pointer
)
{
// TODO: "hack" for forcing get into allDocs, don't overwrite criteria!
mapper
=
"
values
"
;
query
.
select_list
=
query
.
select_list
||
pass
.
data_dict
.
field_list
;
query
.
limit
=
query
.
limit
||
pass
.
config_dict
.
initial_query
.
limit
;
}
else
if
((
query
.
select_list
||
storage
.
arr
).
length
>
0
&&
!
query
.
include_docs
)
{
mapper
=
"
values
"
;
}
else
if
(
!!
query
.
_id
)
{
mapper
=
"
single_item
"
;
method
=
"
get
"
;
...
...
@@ -3971,11 +4203,11 @@
// TODO: storage.add included prefetch of field_items and validation
// TODO: storage.add deleted identifier if create_new was set
storage
.
write
=
function
(
obj
)
{
var
form
,
data
,
valid
,
prefix
,
config
,
method
,
action
,
pointer
;
var
form
,
data
,
valid
,
prefix
,
config
,
method
,
action
,
pointer
,
sample
;
form
=
obj
.
form
;
pointer
=
(
obj
.
element
||
storage
.
span
).
getAttribute
(
"
data-action
"
);
action
=
(
obj
.
state
.
url_pointer
||
storage
.
obj
)[
pointer
];
action
=
(
obj
.
state
.
url_pointer
||
storage
.
empty_
obj
)[
pointer
];
config
=
{};
prefix
=
obj
.
id
+
"
_
"
;
valid
=
obj
.
sample_store
||
storage
.
validate
(
form
);
...
...
@@ -3987,9 +4219,9 @@
config
.
_force_data
=
true
;
}
if
(
obj
.
sample_
data
.
_id
||
form
.
identifier
)
{
if
(
data
.
_id
||
form
.
identifier
)
{
// PUT > set id, method and view
data
.
_id
=
obj
.
sample_
data
.
_id
||
form
.
identifier
.
value
;
data
.
_id
=
data
.
_id
||
form
.
identifier
.
value
;
method
=
"
put
"
;
config
.
_view
=
obj
.
state
.
view
;
}
...
...
@@ -4365,6 +4597,7 @@
}
}
}
return
answer
||
response
;
};
...
...
@@ -4475,8 +4708,9 @@
/**
* @object flux Maintain flux in memory.
**/
// TODO: secure?
flux
=
{};
flux
=
{
"
active_record
"
:
{}
};
/* ====================================================================== */
/* APP */
...
...
@@ -4511,7 +4745,6 @@
id
=
answer
.
id
;
decode
=
/%
[
0-9a-f
]{2}
/i
.
test
(
id
);
goto_page
=
decode
?
id
:
window
.
encodeURIComponent
(
id
);
$
.
mobile
.
changePage
(
obj
.
state
.
callback
.
replace
(
"
__id__
"
,
goto_page
));
}
};
...
...
@@ -4535,7 +4768,14 @@
// update gadget
app
.
content
.
set
(
{},
{
"
portal_type_source
"
:
config
.
state
.
type
,
"
portal_type_title
"
:
config
.
state
.
title
,
"
property_dict
"
:
util
.
mergeObject
(
{
"
dynamic
"
:
true
},
config
.
state
.
dyno_dict
),
"
scheme
"
:
config
.
state
.
scheme
},
{
"
reference
"
:
config
.
id
,
"
href
"
:
config
.
state
.
href
,
...
...
@@ -4558,10 +4798,11 @@
*/
// TODO: overwrite direction on single state sorting
app
.
sort
=
function
(
config
,
direction
,
prev
,
next
,
single
)
{
var
i
,
in_array
,
sort_by
,
delay
;
var
i
,
in_array
,
sort_by
,
delay
,
state
;
// NOTE: if column title is not set, we might be sortling a list!
sort_by
=
config
.
element
.
getAttribute
(
"
data-column-title
"
);
state
=
config
.
state
;
if
(
sort_by
)
{
// sorting button update
...
...
@@ -4580,8 +4821,8 @@
util
.
clearTimer
();
// check if we are already sorting by this sort_by value
for
(
i
=
0
;
i
<
config
.
state
.
query
.
sort_on
.
length
;
i
+=
1
)
{
if
(
config
.
state
.
query
.
sort_on
[
i
][
0
]
===
sort_by
)
{
for
(
i
=
0
;
i
<
state
.
query
.
sort_on
.
length
;
i
+=
1
)
{
if
(
state
.
query
.
sort_on
[
i
][
0
]
===
sort_by
)
{
in_array
=
true
;
break
;
}
...
...
@@ -4593,9 +4834,9 @@
case
"
desc_abc
"
:
if
(
sort_by
)
{
if
(
in_array
===
undefined
)
{
config
.
state
.
query
.
sort_on
.
push
([
sort_by
,
"
descending
"
]);
state
.
query
.
sort_on
.
push
([
sort_by
,
"
descending
"
]);
}
else
{
config
.
state
.
query
.
sort_on
.
splice
(
i
,
1
)
state
.
query
.
sort_on
.
splice
(
i
,
1
)
.
push
([
sort_by
,
"
descending
"
]);
}
}
...
...
@@ -4604,9 +4845,9 @@
case
"
asc_abc
"
:
if
(
sort_by
)
{
if
(
in_array
===
undefined
)
{
config
.
state
.
query
.
sort_on
.
push
([
sort_by
,
"
ascending
"
]);
state
.
query
.
sort_on
.
push
([
sort_by
,
"
ascending
"
]);
}
else
{
config
.
state
.
query
.
sort_on
.
splice
(
i
,
1
)
state
.
query
.
sort_on
.
splice
(
i
,
1
)
.
push
([
sort_by
,
"
ascending
"
]);
}
}
...
...
@@ -4614,7 +4855,7 @@
default
:
// need to remove a column from sorting when set to undefined
if
(
sort_by
&&
in_array
)
{
config
.
state
.
query
.
sort_on
.
splice
(
i
,
1
);
state
.
query
.
sort_on
.
splice
(
i
,
1
);
}
break
;
}
...
...
@@ -4625,9 +4866,9 @@
{},
{
"
reference
"
:
config
.
id
,
"
href
"
:
config
.
state
.
href
,
"
fragment_list
"
:
config
.
state
.
fragment_list
,
"
layout_level
"
:
config
.
state
.
layout_level
"
href
"
:
state
.
href
,
"
fragment_list
"
:
state
.
fragment_list
,
"
layout_level
"
:
state
.
layout_level
},
false
)
...
...
@@ -4737,31 +4978,33 @@
* @param {string} value New limit when changing number of records
*/
app
.
paginate
=
function
(
config
,
type
,
value
)
{
var
start
,
records
,
total
;
var
start
,
records
,
total
,
state
,
current_limit
;
total
=
config
.
state
.
total
;
state
=
config
.
state
;
total
=
state
.
total
;
current_limit
=
state
.
query
.
limit
||
state
.
initial_query
.
limit
;
if
(
config
.
gadget
)
{
if
(
config
.
state
)
{
if
(
state
&&
current_limit
)
{
switch
(
type
)
{
case
"
first
"
:
start
=
0
;
records
=
c
onfig
.
state
.
query
.
limit
[
1
];
records
=
c
urrent_
limit
[
1
];
break
;
case
"
next
"
:
start
=
c
onfig
.
state
.
query
.
limit
[
0
]
+
config
.
state
.
query
.
limit
[
1
];
records
=
c
onfig
.
state
.
query
.
limit
[
1
];
start
=
c
urrent_limit
[
0
]
+
current_
limit
[
1
];
records
=
c
urrent_
limit
[
1
];
break
;
case
"
prev
"
:
start
=
c
onfig
.
state
.
query
.
limit
[
0
]
-
config
.
state
.
query
.
limit
[
1
];
records
=
c
onfig
.
state
.
query
.
limit
[
1
];
start
=
c
urrent_limit
[
0
]
-
current_
limit
[
1
];
records
=
c
urrent_
limit
[
1
];
break
;
case
"
last
"
:
start
=
total
-
c
onfig
.
state
.
query
.
limit
[
1
];
records
=
c
onfig
.
state
.
query
.
limit
[
1
];
start
=
total
-
c
urrent_
limit
[
1
];
records
=
c
urrent_
limit
[
1
];
break
;
case
"
limit
"
:
start
=
c
onfig
.
state
.
query
.
limit
[
0
];
start
=
c
urrent_
limit
[
0
];
records
=
parseInt
(
value
,
null
);
break
;
}
...
...
@@ -4771,37 +5014,35 @@
}
// set new limits
config
.
state
.
query
.
limit
=
[
start
,
records
];
state
.
query
.
limit
=
[
start
,
records
];
// reset selected
if
(
config
.
state
.
selected
)
{
config
.
state
.
selected
=
[];
if
(
state
.
selected
)
{
state
.
selected
=
[];
}
// update gadget
app
.
content
.
set
(
{
"
portal_type_source
"
:
config
.
state
.
type
,
"
portal_type_title
"
:
config
.
state
.
title
,
"
property_dict
"
:
util
.
mergeObject
({
"
dynamic
"
:
true
,
"
map_children
"
:
"
listItem
"
},
config
.
state
.
dyno_dict
),
"
scheme
"
:
config
.
state
.
scheme
"
portal_type_source
"
:
state
.
type
,
"
portal_type_title
"
:
state
.
title
,
"
property_dict
"
:
util
.
mergeObject
(
{
"
dynamic
"
:
true
},
state
.
dyno_dict
),
"
scheme
"
:
state
.
scheme
},
{
"
reference
"
:
config
.
id
,
"
href
"
:
config
.
state
.
href
,
"
fragment_list
"
:
config
.
state
.
fragment_list
,
"
layout_level
"
:
config
.
state
.
layout_level
"
href
"
:
state
.
href
,
"
fragment_list
"
:
state
.
fragment_list
,
"
layout_level
"
:
state
.
layout_level
},
false
)
.
fail
(
app
.
util
.
error
);
}
else
{
app
.
util
.
error
(
"
No state information stored for gadget
"
);
app
.
util
.
error
(
"
No state
/limit
information stored for gadget
"
);
}
}
else
{
app
.
util
.
error
(
"
Action is missing reference gadget
"
);
...
...
@@ -4829,11 +5070,12 @@
info
=
""
;
no_total
=
total
===
undefined
&&
app
.
storage_dict
.
property_dict
.
skip_total_records
;
generateInfo
=
function
(
text
,
text_i18n
)
{
return
factory
.
element
(
"
span
"
,
{
"
className
"
:
"
translate
"
},
{
"
data-i18n
"
:
"
global_dict.
info_dict.
"
+
text_i18n
},
{
"
data-i18n
"
:
"
global_dict.
"
+
text_i18n
},
{
"
text
"
:
text
}
);
};
...
...
@@ -4925,7 +5167,7 @@
}
// initial fill or update
if
(
slot
!==
undefined
)
{
if
(
!
slot
)
{
if
(
info_field
.
children
.
length
===
0
)
{
first
=
document
.
createTextNode
(
info
);
last
=
generateInfo
(
text_snippet
,
i18n_snippet
);
...
...
@@ -5017,6 +5259,10 @@
"
gadget
"
:
document
.
getElementById
(
id
)
};
if
(
response
.
gadget
===
null
)
{
return
response
;
}
has_form
=
response
.
gadget
.
getElementsByTagName
(
"
form
"
);
return
util
.
mergeObject
(
{
...
...
@@ -5040,9 +5286,11 @@
if
(
util
.
testForString
(
"
ui-header
"
,
header
.
className
))
{
title
=
header
.
getElementsByTagName
(
"
h1
"
)[
0
];
title
.
setAttribute
(
"
data-i18n
"
,
(
page_i18n
||
""
));
title
.
removeChild
(
title
.
childNodes
[
0
]);
title
.
appendChild
(
document
.
createTextNode
((
value
||
"
\
u00A0
"
)));
if
(
title
)
{
title
.
setAttribute
(
"
data-i18n
"
,
(
page_i18n
||
""
));
title
.
removeChild
(
title
.
childNodes
[
0
]);
title
.
appendChild
(
document
.
createTextNode
((
value
||
"
\
u00A0
"
)));
}
}
// also set document title
document
.
title
=
value
;
...
...
@@ -5055,16 +5303,27 @@
* @param {object} data Data passed along with this (JQM) event
*/
app
.
parsePage
=
function
(
e
,
data
)
{
var
page
,
base
,
config
,
raw_url
,
handle
,
clean_url
,
parsed_url
,
first
;
var
page
,
base
,
config
,
raw_url
,
handle
,
clean_url
,
parsed_url
,
first
,
skipper
,
base_page
;
if
(
data
)
{
// update page title on backwards transition to the first page (still
// is in DOM, so no new page created, so no title update...)
// TODO: not bulletproof i18n handling... we expect i18n to be defined
// TODO: blocker is not nice
if
(
typeof
data
.
toPage
===
"
object
"
)
{
base_page
=
data
.
toPage
[
0
];
if
(
$
.
mobile
.
firstPage
[
0
].
getAttribute
(
"
data-url
"
)
===
data
.
toPage
[
0
]
.
getAttribute
(
"
data-url
"
))
{
base_page
.
getAttribute
(
"
data-url
"
))
{
app
.
setPageTitle
(
"
global_dict.home
"
);
// NOTE: this will allow going back, but only if we are not
// coming from root
if
(
!
app
.
deeplink_flag
)
{
skipper
=
true
;
app
.
deeplink_flag
=
true
;
}
}
}
...
...
@@ -5075,25 +5334,35 @@
}
else
{
raw_url
=
data
.
toPage
;
}
}
else
{
raw_url
=
window
.
location
.
href
;
}
if
(
typeof
raw_url
===
"
string
"
)
{
// decode
if
(
data
&&
data
.
options
.
reverse
)
{
raw_url
=
window
.
decodeURIComponent
(
raw_url
);
}
config
=
app
.
util
.
parseLink
(
raw_url
);
// NOTE: if we start from home we must prevent reloading home
// because it will be kept in the DOM
if
(
!
config
.
deeplink
)
{
// we start from home, so we must not allow going back
// and reloading
app
.
deeplink_flag
=
true
;
}
if
(
e
)
{
page
=
util
.
getPage
(
raw_url
.
split
(
"
#
"
).
pop
());
base
=
page
?
page
.
getAttribute
(
"
data-external-page
"
)
:
null
;
first
=
$
.
mobile
.
firstPage
[
0
].
getAttribute
(
"
data-url
"
)
===
config
.
data_url
;
if
(
first
||
(
page
&&
base
)
||
raw_url
===
$
.
mobile
.
getDocumentUrl
()
||
data
.
options
.
role
===
"
popup
"
)
{
if
(
(
first
||
(
page
&&
base
)
||
raw_url
===
$
.
mobile
.
getDocumentUrl
()
||
data
.
options
.
role
===
"
popup
"
)
&&
!
skipper
)
{
// stop us, JQM can go
return
RSVP
.
resolve
(
undefined
);
}
...
...
@@ -5287,17 +5556,24 @@
// generateFormElement
$
(
form_element
).
validVal
({
validate
:
{
onKeyup
:
"
valid
"
,
onBlur
:
"
valid
"
"
validate
"
:
{
"
onKeyup
"
:
"
valid
"
,
"
onBlu
"
:
"
valid
"
},
"
fields
"
:
{
"
hidden
"
:
true
},
//customValidations: util.declareJS(),
form
:
{
onInvalid
:
function
()
{
"
form
"
:
{
"
onInvalid
"
:
function
()
{
util
.
return_out
();
}
}
});
}
else
{
// TODO: AAAARGH! so much jquery...
// TODO: AND IT DOES NOT WORK... §$%&/()=!
$
(
form_element
).
trigger
(
"
addField
"
,
$
(
form_element
).
find
(
"
.required
"
));
}
}
};
...
...
@@ -5561,13 +5837,14 @@
* Get the active JQM page in JavaScript-only
* @method getPage
* @param {string} url url of the page to fetch
* @param {string} straight If not set, we start searching from behind
* @return {string} id of active page
*/
util
.
getPage
=
function
(
url
)
{
var
i
,
kid
,
kids
=
document
.
body
.
children
;
util
.
getPage
=
function
(
url
,
straight
)
{
var
i
,
kid
,
len
,
kids
=
document
.
body
.
children
;
// reverse, because in JQM last page is the active page!
for
(
i
=
kids
.
length
-
1
;
i
>=
0
;
i
-=
1
)
{
for
(
len
=
kids
.
length
,
i
=
len
-
1
;
i
>=
0
;
i
-=
1
)
{
kid
=
kids
[
i
];
if
(
util
.
testForString
(
"
ui-page
"
,
kid
.
className
))
{
...
...
@@ -5579,6 +5856,17 @@
return
undefined
;
};
/**
* Remove all children of an element
* @method deleteChildren
* @param {object} el Element to remove children from
*/
util
.
deleteChildren
=
function
(
el
)
{
while
(
el
.
hasChildNodes
())
{
el
.
removeChild
(
el
.
lastChild
);
}
};
/**
* Reverse an array
* @method reverseArray
...
...
@@ -5633,6 +5921,22 @@
return
new
RegExp
(
"
(?:^|
\\
s)
"
+
className
+
"
(?!
\\
S)
"
,
"
g
"
);
};
// /**
// * Property to set whether classlist is supported
// * @property support_classList
// */
// // TODO: add to support module/Modernizr
// util.no_support_classList = document.documentElement.classList === undefined;
//
// util.testForString = util.no_support_classList ?
// function(el, clss) {
// return el.className && new RegExp("(^|\\s)" +
// clss + "(\\s|$)").test(el.className);
// } :
// function(el, clss) {
// return el.classList.contains(clss);
// };
/**
* Test for a class name
* @method testForString
...
...
@@ -5641,7 +5945,6 @@
* @param {boolean} nowrap Whether to wrap in space
* @return {boolean} result True/False
*/
// WARNING: requires IE8- requires shim
util
.
testForString
=
function
(
search_string
,
full_string
,
nowrap
)
{
var
s
=
nowrap
?
""
:
"
"
;
return
(
s
+
full_string
+
s
).
indexOf
(
s
+
search_string
+
s
)
>
-
1
;
...
...
@@ -5743,17 +6046,37 @@
* @return {object} field defintions and pass through
*/
app
.
content
.
fields
=
function
(
reply
)
{
var
pass
=
reply
.
pass
;
var
pass
=
reply
.
pass
,
query
,
crop
;
if
(
!
pass
.
skip
)
{
// (dynamic element) config_dict
// NOTE: so config_dict will always be present and we don't need to
// ever test for it again after here.... because if we fetch by URL
// whatever was fetched is here and if we just render it will be
// on content_dict.
pass
.
config_dict
=
util
.
parse
(
reply
.
response
)
||
pass
.
content_dict
;
delete
pass
.
no_config
;
// test for auth based access
pass
.
grant
=
true
;
// update initial query with urlQuery if one was passed
if
(
pass
.
url_dict
.
url_query
)
{
crop
=
pass
.
config_dict
.
property_dict
.
url_crop
;
query
=
util
.
mergeObject
(
pass
.
url_dict
.
url_query
,
pass
.
config_dict
.
initial_query
||
{}
);
// TODO: TOTALLY UGLY hack to allow 2 gadgets who require different urls
// to share... remove ASAP
if
(
crop
)
{
query
.
query
=
query
.
query
.
replace
(
crop
,
""
);
}
pass
.
config_dict
.
initial_query
=
query
;
}
// fetch field definitions - why make a query without fieldlist?
if
(
pass
.
grant
||
pass
.
mode
===
"
new
"
)
{
app
.
util
.
loader
(
""
,
"
status_dict.loading_config
"
);
...
...
@@ -5842,14 +6165,8 @@
return
RSVP
.
all
(
promise_list
)
.
then
(
function
(
response_list
)
{
if
(
!
response_list
[
0
])
{
app
.
util
.
loader
(
""
,
"
status_dict.internal_error
"
,
"
ban-circle
"
);
}
else
{
app
.
util
.
loader
(
""
,
"
status_dict.success
"
,
"
check
"
);
if
(
!
response_list
[
0
]
&&
promise_list
.
length
!==
0
)
{
app
.
util
.
loader
(
""
,
"
status_dict.internal_error
"
,
"
ban
"
);
}
// just return pass and continue
return
{
...
...
@@ -5888,7 +6205,7 @@
if
(
pass
.
create
===
false
)
{
pass
.
state
=
document
.
getElementById
(
pass
.
url_dict
.
reference
).
state
;
pass
.
store_limit
=
pass
.
state
.
query
.
limit
;
pass
.
state
.
query
.
l
f
imit
=
[];
pass
.
state
.
query
.
limit
=
[];
// create state object
}
else
{
...
...
@@ -5937,7 +6254,8 @@
pass
.
config_dict
.
skip_total_records
!==
true
)
&&
((
pass
.
grant
||
pass
.
url_dict
.
mode
===
"
new
"
)
&&
(
pass
.
state
&&
pass
.
state
.
query
.
_id
===
undefined
)
&&
pass
.
config_dict
.
initial_query
)
(
pass
.
config_dict
.
initial_query
||
pass
.
create
===
false
)
&&
!
pass
.
config_dict
.
property_dict
.
force_new
)
)
{
// reset limit from sampling [0,1] and store query
pass
.
state
.
query
.
limit
=
[];
...
...
@@ -5964,7 +6282,6 @@
var
pass
=
reply
.
pass
;
if
(
!
pass
.
skip
)
{
// set total rows
if
(
reply
.
response
)
{
pass
.
state
.
total
=
util
.
parse
(
reply
.
response
).
data
.
total_rows
;
...
...
@@ -6000,7 +6317,7 @@
}
// get items/item
if
(
pass
.
grant
&&
if
(
pass
.
grant
&&
!
pass
.
config_dict
.
property_dict
.
force_new
&&
(
pass
.
url_dict
.
mode
!==
"
new
"
||
!
pass
.
config_dict
.
initial_query
)
)
{
app
.
util
.
loader
(
""
,
"
status_dict.loading_set
"
);
...
...
@@ -6023,11 +6340,15 @@
* @return {object} response object/promise
**/
// TODO: refactor... appocalyptic
// TODO: determine what should be inherit and make inherit object, that
// will be passed down the rendering tree
app
.
content
.
make
=
function
(
reply
)
{
var
pass
,
method
,
type
,
kids
,
promise_list
,
route
,
search
,
search_id
,
kid
,
is_html
,
is_dynamic
,
is_id
,
i
,
j
,
last
,
search
,
search_id
,
kid
,
is_html
,
is_dynamic
,
is_id
,
i
,
j
,
k
,
last
,
encoded
,
wrapper
,
active
,
selector
,
update_target
,
target
,
widget
,
grant_child
,
quirk_dict
,
generator
,
pointer_results
,
data_total_rows
;
quirk_dict
,
generator
,
pointer_results
,
data_total_rows
,
is_parameter
,
param_len
,
parameter
,
no_item
,
dyno
,
container
,
has_props
,
widget_dyno
,
set_reference
;
pass
=
reply
.
pass
;
pass
.
config_dict
=
pass
.
config_dict
||
{};
...
...
@@ -6035,44 +6356,33 @@
method
=
factory
.
widget
[
type
]
||
undefined
;
promise_list
=
[];
// set results, here, so dynamic kids are correct!
if
(
pass
.
grant
&&
reply
.
response
)
{
pointer_results
=
util
.
parse
(
reply
.
response
);
// NOTE:
// set results here, so kids.length is available in wrapper generation.
// Also, if dynamic and no response (eg for "new" record, we set an empty
// placeholder here which will generate an empty form
if
(
!
pass
.
skip
)
{
pointer_results
=
util
.
parse
(
reply
.
response
)
||
{
"
data
"
:
{
"
total_rows
"
:
0
,
"
rows
"
:
[]}};
data_total_rows
=
pointer_results
.
data
.
total_rows
;
}
// kids (must be declared before wrapper, because some wrapper need length
if
(
pass
.
content_dict
.
view_dict
)
{
kids
=
pass
.
content_dict
.
view_dict
[
pass
.
url_dict
.
mode
||
"
default
"
];
kids
=
pass
.
content_dict
.
view_dict
[
pass
.
url_dict
.
mode
]
||
pass
.
content_dict
.
view_dict
[
"
default
"
];
}
else
{
kids
=
pass
.
content_dict
.
children
||
pass
.
config_dict
.
children
||
[];
}
// ============= TODO: improve property_dict generation ==============
// TODO: no all elements need them?
// wrapper object and properties
quirk_dict
=
util
.
mergeObject
(
(
pass
[
method
?
"
content_dict
"
:
"
config_dict
"
].
property_dict
),
{
"
create
"
:
pass
.
create
,
"
update
"
:
pass
.
create
===
false
?
true
:
null
,
"
total_rows
"
:
data_total_rows
,
"
length
"
:
kids
.
length
,
"
layout_level
"
:
pass
.
url_dict
.
layout_level
,
"
fragment_list
"
:
pass
.
url_dict
.
fragment_list
,
"
data_url
"
:
pass
.
url_dict
.
data_url
,
"
scheme
"
:
pass
.
config_dict
.
scheme
,
"
field_dict
"
:
(
pass
.
data_dict
||
{}).
field_dict
,
"
skip
"
:
pass
.
skip
}
);
// set generator
if
(
quirk_dict
.
skip
)
{
if
(
pass
.
skip
)
{
if
(
!
pass
.
content_dict
.
generate
)
{
route
=
type
;
// force custom elements into form layout...
// NOTE: only used in service_instance_status to make a link go
// through formElement, not sure this must be a viable option,
// maybe better with custom, question is were do wrapper, label
// come from.
if
(
pass
.
content_dict
.
logic
&&
pass
.
content_dict
.
logic
.
route
)
{
route
=
pass
.
content_dict
.
logic
.
route
;
}
...
...
@@ -6100,6 +6410,23 @@
}
}
// wrapper object and properties
quirk_dict
=
util
.
mergeObject
(
(
pass
[
method
?
"
content_dict
"
:
"
config_dict
"
].
property_dict
),
{
"
create
"
:
pass
.
create
,
"
update
"
:
pass
.
create
===
false
?
true
:
null
,
"
total_rows
"
:
data_total_rows
,
"
length
"
:
kids
.
length
,
"
layout_level
"
:
pass
.
url_dict
.
layout_level
,
"
fragment_list
"
:
pass
.
url_dict
.
fragment_list
,
"
data_url
"
:
pass
.
url_dict
.
data_url
,
"
scheme
"
:
pass
.
config_dict
.
scheme
,
"
field_dict
"
:
(
pass
.
data_dict
||
{}).
field_dict
,
"
skip
"
:
pass
.
skip
}
);
if
(
!
generator
)
{
if
(
method
)
{
generator
=
method
(
quirk_dict
);
...
...
@@ -6110,26 +6437,32 @@
// switch back
wrapper
=
generator
;
// make properties available to children in need
wrapper
.
property_dict
=
quirk_dict
;
// =============================
// no records returned, no_show set below on dyno
// TODO: find better way to set dynamic flag
if
(
quirk_dict
.
no_show
)
{
kids
.
push
(
factory
.
util
.
noItems
(
no_item
=
factory
.
util
.
noItems
(
quirk_dict
.
no_show
,
wrapper
.
base
,
wrapper
.
count
?
wrapper
.
count
(
quirk_dict
.
scheme
[
0
])
:
null
));
);
kids
=
util
.
inherit
(
no_item
,
{
"
scheme
"
:
quirk_dict
.
scheme
,
"
field_dict
"
:
quirk_dict
.
field_dict
}
);
}
// dynamic content
// TODO: 10 if-else...
if
(
!
pass
.
skip
)
{
// set empty "record" to allow generation of empty form
if
(
pass
.
url_dict
.
mode
===
"
new
"
)
{
pointer_results
=
{
"
data
"
:
{
"
total_rows
"
:
1
,
"
rows
"
:
[{
"
doc
"
:
{}}]}};
}
// =====================================================================
// NOTE: store state on wrapper property_dict to inherit!
wrapper
.
property_dict
.
state
=
pass
.
state
// =====================================================================
// inherit item id, so it's available in form as indentifier
if
(
pointer_results
.
data
.
total_rows
===
1
)
{
...
...
@@ -6137,72 +6470,108 @@
}
// no items, need no show! (default to empty {} if none provided
if
(
pointer_results
.
data
.
total_rows
===
0
)
{
quirk_dict
.
no_show
=
quirk_dict
.
no_items
||
{};
if
(
quirk_dict
.
allow_new
||
quirk_dict
.
force_new
)
{
// NOTE: on updates with force_new, reference must be passed to not
// have undefined form-id values
if
(
quirk_dict
.
update
)
{
set_reference
=
{
"
doc
"
:
{},
"
reference
"
:
pass
.
url_dict
.
reference
};
}
pointer_results
=
{
"
data
"
:
{
"
total_rows
"
:
1
,
"
rows
"
:
[
set_reference
||
{
"
doc
"
:
{}}]
}
};
}
else
{
quirk_dict
.
no_show
=
quirk_dict
.
no_items
||
{};
}
}
// set up fragment and child_selector
if
(
quirk_dict
.
update
!==
true
)
{
// set reference for children in need
quirk_dict
.
reference
=
"
dyno_
"
+
util
.
uuid
();
// setup fragment and child_selector
wrapper
.
fragment
.
appendChild
(
factory
.
element
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
id
"
:
quirk_dict
.
reference
,
"
className
"
:
"
dyno
"
if
(
!
quirk_dict
.
no_content
)
{
// set reference for children in need
quirk_dict
.
reference
=
"
dyno_
"
+
util
.
uuid
();
dyno
=
factory
.
element
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
id
"
:
quirk_dict
.
reference
,
"
className
"
:
"
dyno
"
}
});
// setup fragment and child_selector
if
(
quirk_dict
.
wrap_gadget
)
{
container
=
factory
.
element
({
"
type
"
:
"
div
"
,
"
direct
"
:
{
"
className
"
:
"
span_
"
+
quirk_dict
.
wrap_gadget
}
});
container
.
appendChild
(
dyno
);
}
}));
wrapper
.
child_selector
=
wrapper
.
fragment
.
querySelector
(
"
#
"
+
quirk_dict
.
reference
);
// add auto pagination bar
if
(
quirk_dict
.
pagination
)
{
kids
.
push
(
factory
.
util
.
paginationBar
(
quirk_dict
.
pagination
));
}
wrapper
.
fragment
.
appendChild
(
container
||
dyno
);
wrapper
.
child_selector
=
wrapper
.
fragment
.
querySelector
(
"
#
"
+
quirk_dict
.
reference
);
// add caption
if
(
quirk_dict
.
caption
)
{
kids
.
push
({
"
generate
"
:
"
widget
"
,
"
type
"
:
"
controlbar
"
,
"
property_dict
"
:
{
"
slot
"
:
quirk_dict
.
caption
.
slot
||
1
},
"
children
"
:
[{
"
type
"
:
"
p
"
,
"
direct
"
:
{
"
className
"
:
"
ui-table-caption translate
"
},
"
attributes
"
:
{
"
data-i18n
"
:
quirk_dict
.
caption
.
text_i18n
||
null
},
"
logic
"
:
{
"
text
"
:
quirk_dict
.
caption
.
text
}
}]
});
}
// add auto pagination bar
if
(
quirk_dict
.
pagination
)
{
kids
.
push
(
factory
.
util
.
paginationBar
(
quirk_dict
.
pagination
));
}
// add auto search bar
if
(
quirk_dict
.
search
)
{
search
=
factory
.
util
.
searchBar
(
quirk_dict
.
search
);
search_id
=
search
.
id
;
kids
.
unshift
(
search
.
config
);
}
// add caption
if
(
quirk_dict
.
caption
)
{
kids
.
push
({
"
generate
"
:
"
widget
"
,
"
type
"
:
"
controlbar
"
,
"
property_dict
"
:
{
"
slot
"
:
quirk_dict
.
caption
.
slot
||
1
},
"
children
"
:
[{
"
type
"
:
"
p
"
,
"
direct
"
:
{
"
className
"
:
"
ui-table-caption translate
"
},
"
attributes
"
:
{
"
data-i18n
"
:
quirk_dict
.
caption
.
text_i18n
||
null
},
"
logic
"
:
{
"
text
"
:
quirk_dict
.
caption
.
text
}
}]
});
}
// add popup (local/global)
switch
(
quirk_dict
.
need_popup
)
{
case
"
local
"
:
if
(
util
.
getPage
().
querySelectorAll
(
"
div.local_popup
"
)
===
null
)
{
target
.
appendChild
(
factory
.
widget
.
popup
({})
);
// add auto search bar
if
(
quirk_dict
.
search
)
{
search
=
factory
.
util
.
searchBar
(
quirk_dict
.
search
);
search_id
=
search
.
id
;
kids
.
unshift
(
search
.
config
);
}
break
;
case
"
global
"
:
if
(
document
.
getElementById
(
"
global_popup
"
)
===
null
)
{
document
.
documentElement
.
appendChild
(
factory
.
widget
.
popup
({}));
// add popup (local/global)
switch
(
quirk_dict
.
need_popup
)
{
case
"
local
"
:
if
(
util
.
getPage
().
querySelectorAll
(
"
div.local_popup
"
)
===
null
)
{
target
.
appendChild
(
factory
.
widget
.
popup
({}));
}
break
;
case
"
global
"
:
if
(
document
.
getElementById
(
"
global_popup
"
)
===
null
)
{
document
.
documentElement
.
appendChild
(
factory
.
widget
.
popup
({}));
}
break
;
}
break
;
}
}
else
{
widget
=
pass
.
state
.
gadget
.
querySelector
(
"
[data-update]
"
)
.
getAttribute
(
"
data-widget
"
);
// TODO: can this be done without storing on and querying DOM???!!!
// TODO: THIS MAKES ME INSANE... qsa || widget does not work!
widget
=
pass
.
state
.
gadget
;
widget_dyno
=
widget
.
querySelector
(
"
[data-update]
"
)
||
widget
.
getElementsByTagName
(
"
form
"
)[
0
];
wrapper
.
property_dict
.
map_children
=
widget_dyno
.
getAttribute
(
"
data-map
"
);
wrapper
=
util
.
mergeObject
(
factory
.
widget
[
widget
](
wrapper
.
property_dict
),
factory
.
widget
[
widget
_dyno
.
getAttribute
(
"
data-widget
"
)
](
wrapper
.
property_dict
),
wrapper
);
// add scheme and field_dict to list
kids
=
util
.
inherit
(
pointer_results
.
data
.
rows
,
...
...
@@ -6226,7 +6595,6 @@
is_dynamic
=
kid
.
property_dict
&&
kid
.
property_dict
.
dynamic
;
is_html
=
kid
.
direct
;
// inherit item id to child elements (see above)
if
(
is_id
)
{
if
(
is_html
&&
is_html
.
href
)
{
...
...
@@ -6246,34 +6614,44 @@
kid
.
property_dict
.
input
=
"
#
"
+
search_id
;
}
// inherit properties of parent (> dynamic!) and add data to kid
kid
.
property_dict
=
util
.
mergeObject
(
kid
.
property_dict
,
quirk_dict
);
kid
.
children
=
util
.
inherit
(
pointer_results
.
data
.
rows
.
concat
(
kid
.
children
||
[]),
{
"
scheme
"
:
quirk_dict
.
scheme
,
"
field_dict
"
:
quirk_dict
.
field_dict
}
);
}
// map on kid directly and inherit data down (only single items)
if
(
quirk_dict
.
direct_map
)
{
kid
.
property_dict
.
data
=
pointer_results
.
data
.
rows
[
0
];
// HACK for setParam in login window
if
(
kid
.
logic
&&
kid
.
logic
.
setParam
)
{
kid
.
direct
.
href
+=
kid
.
direct
.
href
.
indexOf
(
"
?
"
)
>
0
?
"
&
"
:
"
?
"
;
switch
(
kid
.
logic
.
setParam
[
1
])
{
case
"
location
"
:
target
=
window
.
location
.
origin
+
window
.
location
.
pathname
+
window
.
location
.
hash
.
split
(
"
?
"
)[
0
];
break
;
// NOTE: we may be setting on a wrapper!
}
else
{
kid
.
property_dict
=
util
.
mergeObject
(
kid
.
property_dict
,
quirk_dict
);
kid
.
children
=
util
.
inherit
(
pointer_results
.
data
.
rows
.
concat
(
kid
.
children
||
[]),
{
"
scheme
"
:
quirk_dict
.
scheme
,
"
field_dict
"
:
quirk_dict
.
field_dict
}
);
}
kid
.
direct
.
href
+=
window
.
encodeURIComponent
(
kid
.
logic
.
setParam
[
0
])
+
"
=
"
+
window
.
encodeURIComponent
(
target
);
}
// ===================================================================
is_parameter
=
(
kid
.
logic
||
{}).
setParam
;
has_props
=
kid
.
property_dict
;
// inherit dynamic state to all children with property_dict
if
(
has_props
&&
wrapper
.
property_dict
.
state
)
{
kid
.
property_dict
.
state
=
wrapper
.
property_dict
.
state
;
}
// set dynamic Param(s)
if
(
is_parameter
)
{
kid
=
app
.
util
.
setParam
(
kid
,
wrapper
);
}
// ===================================================================
if
(
quirk_dict
.
update
!==
true
||
is_dynamic
||
quirk_dict
.
dynamic
)
{
// for content loaded via href, generate URL dict and undefine kid
// TODO: make sure this works and does not inherit to regular widgets
if
(
wrapper
.
is_page
&&
kid
.
href
)
{
wrapper
.
inherit
=
{
"
href
"
:
kid
.
href
,
"
url_query
"
:
pass
.
url_dict
.
url_query
,
"
fragment_list
"
:
pass
.
url_dict
.
fragment_list
,
"
layout_level
"
:
pass
.
url_dict
.
layout_level
,
"
inherit
"
:
true
,
...
...
@@ -6315,12 +6693,13 @@
return
RSVP
.
all
(
promise_list
)
.
then
(
function
(
response_list
)
{
var
k
,
l
,
done_target
,
wrapper_selector
,
response
,
content
,
content_target
;
var
k
,
l
,
m
,
len
,
done_target
,
wrapper_selector
,
response
,
content
,
content_target
,
last_child
,
detach
,
child_list
;
for
(
k
=
0
,
l
=
response_list
.
length
;
k
<
l
;
k
+=
1
)
{
response
=
response_list
[
k
];
done_target
=
undefined
;
if
(
response
)
{
// generate target for and append response
// NOTE: wrapper.spec is used for header only.
...
...
@@ -6333,10 +6712,15 @@
"
len
"
:
kids
.
length
,
"
config
"
:
wrapper
.
spec
});
// NOTE: wrapper_selector will return a fragment (set to
// first/last-ElementChild or a DOM node
// NOTE: Opera/old IOS do not support first/lastELEMENTChild...
// must use first/lastChild instead
// TODO: can this be .... removed?
done_target
=
wrapper_selector
[
wrapper
.
target_selector
+
"
ElementChild
"
]
||
wrapper_selector
[
wrapper
.
target_selector
+
"
Child
"
]
||
wrapper_selector
;
done_target
.
appendChild
(
response
);
}
...
...
@@ -6381,21 +6765,39 @@
}
// only for dynamic content
if
(
!
pass
.
skip
)
{
// UPDATES
if
(
!
pass
.
skip
&&
!
quirk_dict
.
no_content
)
{
// UPDATES
- same %&/( as above
if
(
quirk_dict
.
update
)
{
selector
=
pass
.
state
.
gadget
;
update_target
=
selector
.
querySelector
(
"
[data-update]
"
);
// dump
while
(
update_target
.
hasChildNodes
())
{
update_target
.
removeChild
(
update_target
.
lastChild
);
update_target
=
widget
.
querySelector
(
"
[data-update]
"
)
||
widget
.
getElementsByTagName
(
"
form
"
)[
0
];
// TODO: generic method!
// TODO: or inherit reference to controlgroup without being child of form?
// rescue persistent elements from dump
detach
=
document
.
createDocumentFragment
();
child_list
=
update_target
.
children
;
for
(
m
=
0
,
len
=
child_list
.
length
;
m
<
len
;
m
+=
1
)
{
last_child
=
child_list
[
m
];
if
(
last_child
.
getAttribute
(
"
data-persist
"
))
{
detach
.
appendChild
(
last_child
.
cloneNode
(
true
));
}
}
//and add new dynamic content
//empty target, add new dynamic content and detached elements
util
.
deleteChildren
(
update_target
);
update_target
.
appendChild
(
wrapper
.
fragment
);
update_target
.
appendChild
(
detach
);
// CREATE
}
else
{
selector
=
wrapper
.
fragment
.
firstElementChild
||
wrapper
.
fragment
;
// TODO: find way to dig down into tree
if
(
util
.
testForString
(
"
dyno
"
,
selector
.
className
)
===
false
)
{
selector
=
selector
.
firstChild
;
}
pass
.
state
.
gadget
=
selector
;
}
...
...
@@ -6405,6 +6807,8 @@
}
// if a callback is provided, set it on state
// TODO: once containers work, submit_to should change the container
// vs the whole page?
if
(
pass
.
config_dict
.
property_dict
.
submit_to
)
{
pass
.
state
.
callback
=
pass
.
config_dict
.
property_dict
.
submit_to
;
}
...
...
@@ -6418,7 +6822,8 @@
app
.
setInfo
(
pass
.
create
?
wrapper
.
fragment
:
selector
,
pass
.
state
.
query
,
pass
.
state
.
total
pass
.
state
.
total
,
pass
.
state
.
selected
);
}
}
...
...
@@ -6450,10 +6855,6 @@
wrapper
.
fragment
.
appendChild
(
wrapper
.
placeholder
);
}
// we should have some wrapper to call enhanceWithin on
// TODO: only call on whatever we append!
$
(
document
).
enhanceWithin
();
// return fragment
return
RSVP
.
resolve
(
wrapper
.
fragment
||
undefined
);
})
...
...
@@ -6465,6 +6866,167 @@
/* ********************************************************************** */
app
.
util
=
{};
/** Fetch a subordinate record to set values of an object
* @method setSubordinate
* @method setParam
* @param {object} kid Element configuration object
* @param {object} wrapper Wrapping document
* @returns {object} kid
*/
// TODO: change setParams into scheme like structure to use same handler?
app
.
util
.
setSubordinate
=
function
(
element
,
wrapper
)
{
var
i
,
len
,
param_list
,
param
,
promise_list
,
field
,
pass
,
data
;
param_list
=
element
.
logic
.
setParam
;
promise_list
=
[];
data
=
wrapper
.
property_dict
.
data
;
// NOTE: data may be undefined - no records because of missing link
// NOTE: throw?
if
(
data
)
{
for
(
i
=
0
,
len
=
param_list
.
length
;
i
<
len
;
i
+=
1
)
{
param
=
param_list
[
i
];
// NOTE: all regular params should be deleted by now!
field
=
param
[
1
];
pass
=
{
"
field
"
:
field
,
"
relation
"
:
data
.
doc
[
field
],
"
subordinate
"
:
field
.
split
(
"
subordinate_
"
)[
1
]
};
promise_list
[
i
]
=
storage
.
subordinate
(
pass
);
}
}
return
RSVP
.
all
(
promise_list
)
.
then
(
function
(
response_list
)
{
var
j
,
k
,
res_len
,
response
,
param_len
,
out_param
,
val
;
// TODO: CUSTOM CODE, wrap in callback and make generic handler
for
(
j
=
0
,
res_len
=
response_list
.
length
;
j
<
res_len
;
j
+=
1
)
{
response
=
response_list
[
j
];
for
(
k
=
0
,
param_len
=
param_list
.
length
;
k
<
param_len
;
k
+=
1
)
{
out_param
=
param_list
[
k
];
if
(
response
.
field
===
out_param
[
1
])
{
val
=
out_param
[
0
];
element
.
logic
[
val
]
=
element
.
logic
[
val
]
||
""
;
element
.
logic
[
val
]
+=
response
.
value
;
}
}
}
return
element
;
})
.
fail
(
app
.
util
.
error
);
};
/** Set parameters on an object or flag object for subordination =
* fetch related record to get value
* @method setParam
* @param {object} kid Element configuration object
* @param {object} wrapper Wrapping document
* @returns {object} kid
*/
// TODO: clean up, no exceptions (location), clear key + val!
// TODO: make lookup parsing robust!
app
.
util
.
setParam
=
function
(
kid
,
wrapper
)
{
var
i
,
len
,
param_list
,
param
,
href
,
loc
,
splitter
,
key
,
val
,
lookup
,
new_val
;
param_list
=
kid
.
logic
.
setParam
;
for
(
i
=
0
,
len
=
param_list
.
length
;
i
<
len
;
i
+=
1
)
{
param
=
param_list
[
i
];
val
=
param
[
1
];
key
=
param
[
0
];
switch
(
val
)
{
// NOTE: hacked for oauth redirect url
// TODO: find way to include encoding when setting a href
case
"
location
"
:
href
=
kid
.
direct
.
href
;
splitter
=
href
.
indexOf
(
"
?
"
)
>
0
?
"
&
"
:
"
?
"
;
loc
=
window
.
location
;
kid
.
direct
.
href
+=
splitter
+
window
.
encodeURIComponent
(
key
)
+
"
=
"
+
window
.
encodeURIComponent
(
loc
.
origin
+
loc
.
pathname
+
loc
.
hash
.
split
(
"
?
"
)[
0
]
);
break
;
// set values or flag for subordination inside map.element
default
:
kid
.
logic
[
key
]
=
kid
.
logic
[
key
]
||
""
;
if
(
val
.
split
(
"
subordinate_
"
).
length
>
1
)
{
// NOTE: try to get value from state/URL before flagging
// NOTE: must check for equality, otherwise id foo > foofoo
// TODO: this is still super-not-robust... redo!
lookup
=
wrapper
.
property_dict
.
state
.
query
.
query
;
if
(
lookup
&&
lookup
.
indexOf
(
val
)
>
-
1
)
{
new_val
=
lookup
.
split
(
val
)[
1
].
split
(
"
+
"
)[
0
]
.
replace
(
"
:=
"
,
""
).
replace
(
"
)
"
,
""
);
if
(
kid
.
logic
[
key
]
!==
new_val
)
{
kid
.
logic
[
key
]
+=
new_val
;
}
}
else
{
kid
.
needs_subordination
=
true
;
}
}
else
{
kid
.
logic
[
key
]
+=
wrapper
.
property_dict
.
data
.
doc
[
val
];
delete
kid
.
logic
.
setParam
[
i
];
}
}
}
return
kid
;
};
/**
* Parse url query parameter into storage query object
* Expects the following URL format:
*
* #foo&
* query:id=bar+foo=baz&
* limit:start=0+items=5&
* sort:id=ascending+foo=descending&
* select:id+foo+baz+cous
*
* @method parseUrlQuery
* @param {string} str String to parse
* @returns {object} Query to run based on parameters
*/
app
.
util
.
parseQueryParameter
=
function
(
str
)
{
var
i
,
param_list
,
param_len
,
param
,
initial_query
,
indicator
,
value_list
;
param_list
=
str
.
split
(
"
&
"
);
initial_query
=
{};
for
(
i
=
0
,
param_len
=
param_list
.
length
;
i
<
param_len
;
i
+=
1
)
{
param
=
param_list
[
i
].
split
(
"
:
"
);
indicator
=
param
[
0
];
value_list
=
param
[
1
];
switch
(
indicator
)
{
case
"
query
"
:
initial_query
.
query
=
param
[
1
].
replace
(
"
=
"
,
"
:=
"
,
"
g
"
)
.
replace
(
"
+
"
,
"
AND
"
,
"
g
"
);
break
;
case
"
limit
"
:
// NOTE: Thanks Tristan!
initial_query
.
limit
=
param
[
1
].
split
(
"
+
"
)
.
map
(
function
(
part
)
{
return
part
.
split
(
"
=
"
)[
1
];
});
break
;
case
"
sort
"
:
initial_query
.
sort_on
=
param
[
1
].
split
(
"
+
"
).
map
(
function
(
part
)
{
var
s
=
part
.
split
(
"
=
"
);
return
[
s
[
0
],
s
[
1
]];
});
break
;
case
"
select
"
:
initial_query
.
select_list
=
param
[
1
].
replace
(
"
+
"
,
"
,
"
,
"
g
"
);
break
;
}
}
return
initial_query
;
};
/**
* Parse a clicked link to determine which page to load
* @method parseLink
...
...
@@ -6472,14 +7034,14 @@
* @return {object} navigation object
**/
app
.
util
.
parseLink
=
function
(
url
)
{
var
i
,
hash
,
path
,
clean_hash
,
backup
,
decode
,
mode
,
root
;
var
i
,
hash
,
path
,
clean_hash
,
decode
,
root
,
last
,
stripped
,
url_query
,
strip
;
hash
=
$
.
mobile
.
path
.
parseUrl
(
url
.
replace
(
$
.
mobile
.
dialogHashKey
,
""
)
).
hash
.
replace
(
"
#
"
,
""
);
// decode = /^[^\/]*%2[^\/]*$/.test(hash);
decode
=
/%
[
0-9a-f
]{2}
/i
.
test
(
hash
);
backup
=
0
;
// decode (allowing URI encoded identifiers)
if
(
decode
)
{
...
...
@@ -6488,7 +7050,15 @@
clean_hash
=
hash
;
}
if
(
clean_hash
===
""
)
{
// query parameters
strip
=
clean_hash
.
split
(
"
&
"
);
stripped
=
strip
[
0
];
if
(
strip
.
length
>
1
)
{
url_query
=
app
.
util
.
parseQueryParameter
(
strip
[
1
]);
}
if
(
stripped
===
""
)
{
root
=
util
.
getPage
().
getAttribute
(
"
data-url
"
);
return
{
"
data_url
"
:
root
,
...
...
@@ -6496,34 +7066,15 @@
};
}
// 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
;
}
}
path
=
stripped
.
split
(
"
/
"
);
last
=
path
.
length
-
1
;
return
{
"
mode
"
:
mode
,
"
mode
"
:
path
[
last
]
,
"
fragment_list
"
:
path
,
"
url_query
"
:
url_query
,
"
data_url
"
:
clean_hash
,
"
layout_level
"
:
path
.
length
-
1
-
backup
,
"
layout_level
"
:
last
,
"
deeplink
"
:
true
,
"
root
"
:
path
[
0
]
};
...
...
@@ -6537,7 +7088,9 @@
* @return {string} href
*/
app
.
util
.
generateLink
=
function
(
spec
,
id
)
{
var
level
,
core
,
separator
;
var
level
,
core
,
separator
,
empty_string
;
empty_string
=
""
;
// external link
if
(
spec
.
source
)
{
...
...
@@ -6545,15 +7098,15 @@
}
// link current segment parameter vs segment
if
(
spec
.
link_core
.
split
(
"
::
"
).
length
>
1
)
{
separator
=
""
;
if
(
(
spec
.
link_core
||
empty_string
).
split
(
"
%26
"
).
length
>
1
)
{
separator
=
empty_string
;
}
else
{
separator
=
"
/
"
;
}
level
=
spec
.
layout_level
||
0
;
core
=
spec
.
link_core
||
(
spec
.
fragment_list
?
spec
.
fragment_list
.
slice
(
0
,
level
+
1
).
join
(
"
/
"
)
:
""
);
spec
.
fragment_list
.
slice
(
0
,
level
+
1
).
join
(
"
/
"
)
:
empty_string
);
return
(
"
#
"
+
core
+
separator
+
window
.
encodeURIComponent
(
id
));
};
...
...
@@ -6643,24 +7196,26 @@
app
.
init
.
testSupport
=
function
(
property_list
)
{
var
j
,
no_support
,
fail
,
message
;
if
(
Modernizr
)
{
fail
=
""
;
for
(
j
=
0
;
j
<
property_list
.
length
;
j
+=
1
)
{
if
(
Modernizr
[
property_list
[
j
]]
===
false
)
{
no_support
=
true
;
fail
+=
property_list
[
j
]
+
"
|
"
;
if
(
property_list
.
length
>
0
)
{
if
(
Modernizr
)
{
fail
=
""
;
for
(
j
=
0
;
j
<
property_list
.
length
;
j
+=
1
)
{
if
(
Modernizr
[
property_list
[
j
]]
===
false
)
{
no_support
=
true
;
fail
+=
property_list
[
j
]
+
"
|
"
;
}
}
}
if
(
no_support
)
{
message
=
fail
.
splice
(
0
,
-
1
);
app
.
util
.
error
(
"
browser:
"
+
message
+
"
not supported
"
);
if
(
no_support
)
{
message
=
fail
.
splice
(
0
,
-
1
);
app
.
util
.
error
(
"
browser:
"
+
message
+
"
not supported
"
);
factory
.
util
.
noItems
({
"
message
"
:
message
});
return
false
;
factory
.
util
.
noItems
({
"
message
"
:
message
});
return
false
;
}
return
true
;
}
return
true
;
app
.
util
.
error
(
"
testSupport: Modernizr requested but undefined
"
)
;
}
app
.
util
.
error
(
"
testSupport: Modernizr requested but undefined
"
);
return
true
;
};
...
...
@@ -6670,11 +7225,6 @@
* @param {Object} spec The configuration for the module to load
* @param {Promise} The promise
*/
/**
* Generate storages if specified in storage recipe/definition
* @method setStorage
* @param {object} content_dict JSON configuration for storage
**/
app
.
init
.
config
=
function
(
content_dict
)
{
var
i
,
j
,
arr
,
promise_list
,
len
,
feature
,
feature_len
,
name
,
dict
,
set
,
type
,
nav
,
language
,
target
,
initializer
;
...
...
@@ -6866,6 +7416,10 @@
.
then
(
app
.
init
.
config
)
.
then
(
app
.
setGlobalBindings
)
.
then
(
app
.
parsePage
)
.
then
(
function
()
{
// need one call here to initialize whats on the first page
$
(
document
).
enhanceWithin
();
})
.
fail
(
app
.
util
.
error
);
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment