Commit 9eb2e5dd authored by Boris Kocherov's avatar Boris Kocherov

inital add, based on work vincent.bechu@nexedi.com

parents
{
"name": "erp5_officejs_fs2erp5_gadget",
"scopes": [
{
"prefix": "fs2erp5",
"paths": [
""
]
}
]
}
\ No newline at end of file
---
---
CACHE MANIFEST
CACHE:
{% assign s_files = site.static_files | where_exp: "file", "file.exclude != true" %}{% for file in s_files %}{{ file.path | remove_first: "/"}}
{% endfor %}
\ No newline at end of file
/**********************************************
* Colors
**********************************************/
/**********************************************
* Fonts (font-family)
**********************************************/
/**********************************************
* Shared
**********************************************/
/**********************************************
* http://meyerweb.com/eric/tools/css/reset/
* v2.0 | 20110126
* License: none (public domain)
**********************************************/
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/**********************************************
* Default
**********************************************/
@font-face {
font-family: 'FontAwesome';
src: url('font-awesome/font-awesome-webfont.eot?v=4.6.3');
src: url('font-awesome/font-awesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'), url('font-awesome/font-awesome-webfont.woff2?v=4.6.3') format('woff2'), url('font-awesome/font-awesome-webfont.woff?v=4.6.3') format('woff'), url('font-awesome/font-awesome-webfont.ttf?v=4.6.3') format('truetype'), url('font-awesome/font-awesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');
font-weight: normal;
font-style: normal;
}
html {
height: 100%;
width: 100%;
display: block;
background-color: #FFFFFF;
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
height: 100%;
width: 100%;
display: block;
color: #1F1F1F;
word-wrap: break-word;
}
body,
button,
input,
textarea,
select {
font-family: 'Open Sans', Helvetica, Arial, sans-serif;
font-size: 12pt;
padding: 0;
margin: 0;
font-weight: 400;
line-height: 1.5;
}
/**********************************************
* Inline elements
**********************************************/
strong {
font-weight: bold;
}
i,
cite,
em,
var,
address,
dfn {
font-style: italic;
}
strong,
b {
font-weight: bold;
}
u,
ins {
text-decoration: underline;
}
s,
strike,
del {
text-decoration: line-through;
}
sup {
vertical-align: super;
font-size: smaller;
}
sub {
vertical-align: sub;
font-size: smaller;
}
small {
font-size: smaller;
}
tt,
code,
kbd,
samp {
font-family: "Courier New", Courier, monospace;
}
q {
display: inline;
quotes: initial;
}
q:before {
content: open-quote;
}
q:after {
content: close-quote;
}
mark {
color: #22CC22;
}
/**********************************************
* Link
**********************************************/
a {
color: #2FA2E4;
text-decoration: none;
}
a[href=""] {
color: #1F1F1F;
}
a:hover {
text-decoration: underline;
}
a:focus {
outline-offset: -2px;
outline: 2px solid #3388cc;
}
@media not screen and (max-width: 85em) {
a[accesskey]:after {
content: " [" attr(accesskey) "] ";
}
}
/**********************************************
* Preformatted
**********************************************/
pre,
xmp,
plaintext,
listing {
display: block;
white-space: pre-wrap;
}
/**********************************************
* hr
**********************************************/
hr {
display: block;
border-style: inset;
border-width: 1px;
border-color: #FF6600;
}
/**********************************************
* Text fields
**********************************************/
label {
display: block;
}
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]),
textarea,
select {
width: 100%;
padding: 3pt;
background-color: #FFFFFF;
color: #1F1F1F;
border: 1px solid rgba(0, 0, 0, 0.3);
border-radius: 0.325em;
transition: border 0.2s ease-out, box-shadow 0.2s ease-out;
}
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):active,
textarea:active,
select:active,
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):focus,
textarea:focus,
select:focus {
outline: none;
}
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):focus,
textarea:focus,
select:focus {
border: 1px solid #3388cc;
box-shadow: 0 0 12pt #3388cc;
}
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid,
textarea:invalid,
select:invalid {
border: 1px solid #FF6600;
}
input:not([type=submit]):not([type=file]):not([type=checkbox]):not([type=radio]):not([type=color]):invalid:focus,
textarea:invalid:focus,
select:invalid:focus {
box-shadow: 0 0 12pt #FF6600;
}
select {
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: none;
background-color: #FFFFFF;
padding-right: 24pt;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50px' height='50px'><polyline fill-opacity='0.5' points='46.139,15.518 25.166,36.49 4.193,15.519'/></svg>") right no-repeat;
background-position: right 6pt top 50%;
background-size: 12pt 12pt;
}
select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
textarea {
word-wrap: break-word;
white-space: normal;
vertical-align: top;
transition: height 0.2s ease-out;
}
@media not screen and (min-width: 45em) {
textarea {
height: 4em;
}
textarea:focus {
height: 20em;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (max-width: 85em) {
textarea {
min-height: 10em;
}
}
::-webkit-input-placeholder {
color: #575757;
}
:-moz-placeholder {
/* Firefox 18- */
color: #575757;
}
::-moz-placeholder {
/* Firefox 19+ */
color: #575757;
}
:-ms-input-placeholder {
color: #575757;
}
input[type=submit],
button {
margin: 0;
padding: 0;
border: none;
background: transparent;
color: #1F1F1F;
/*
// XXX TODO
// transition: background-color 0.2s ease-out;
&:hover, &:focus {
outline: none;
}
&:active {
// box-shadow: inset 0 0 0 5px darken(@colorblocklinkbackground, 10%);
background-color: darken(@colorblocklinkbackground, 20%);
}
*/
cursor: pointer;
}
input[type=submit]::-moz-focus-inner,
button::-moz-focus-inner {
border: 0px;
padding: 0px;
}
input[type=submit]:hover,
button:hover,
input[type=submit]:focus,
button:focus {
outline: none;
}
/**********************************************
* Media
**********************************************/
img,
iframe,
video,
svg {
max-width: 100%;
}
svg polyline {
stroke: #1F1F1F;
fill: none;
}
svg text {
stroke: #1F1F1F;
fill: #1F1F1F;
}
iframe {
width: 100%;
height: 80vh;
background-color: #FFFFFF;
}
img {
image-orientation: from-image;
}
/**********************************************
* Gadget: panel
**********************************************/
div[data-gadget-scope='panel'] {
background-color: #444444;
color: #FFFFFF;
width: 180pt;
min-height: 100%;
max-height: 100%;
overflow-y: auto;
position: fixed;
top: 0;
left: 0;
display: block;
z-index: 2000;
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='panel'] {
box-shadow: 5px 0 5px rgba(0, 0, 0, 0.15);
}
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='panel'] {
left: -186pt;
transition: transform 200ms ease-out;
transform: translate3d(0, 0, 0);
}
div[data-gadget-scope='panel'].visible {
transform: translate3d(186pt, 0, 0);
}
}
div[data-gadget-scope='panel'] div[data-role="header"] {
display: flex;
justify-content: flex-start;
}
div[data-gadget-scope='panel'] div[data-role="header"] .panel_img {
text-align: center;
flex: 1;
height: 30pt;
}
div[data-gadget-scope='panel'] div[data-role="header"] button,
div[data-gadget-scope='panel'] div[data-role="header"] a {
width: 3em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
background-color: #444444;
display: block;
line-height: 30pt;
color: #FFFFFF;
}
div[data-gadget-scope='panel'] div[data-role="header"] button::before,
div[data-gadget-scope='panel'] div[data-role="header"] a::before {
float: left;
text-indent: 0;
margin-left: 12pt;
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='panel'] div[data-role="header"] button[data-i18n="Close"],
div[data-gadget-scope='panel'] div[data-role="header"] a[data-i18n="Close"] {
display: none;
}
}
div[data-gadget-scope='panel'] div[data-gadget-scope='erp5_searchfield'] {
padding: 3pt 12pt;
}
div[data-gadget-scope='panel'] div[data-gadget-scope='erp5_searchfield'] button {
color: #FFFFFF;
}
div[data-gadget-scope='panel'] div[data-gadget-scope='erp5_searchfield'] input[type="search"] {
color: #FFFFFF !important;
background-color: #777777 !important;
}
div[data-gadget-scope='panel'] img {
text-align: left;
height: 100%;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] {
padding: 3pt;
padding-left: 12pt;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] label,
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] span,
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] input {
cursor: pointer;
}
div[data-gadget-scope='panel'] div[data-gadget-scope="erp5_checkbox"] span {
width: 24pt;
display: inline-block;
}
div[data-gadget-scope='panel'] ul:first-child {
margin-top: 30pt;
}
div[data-gadget-scope='panel'] ul li a {
color: #FFFFFF;
display: block;
padding: 3pt;
padding-left: 12pt;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
div[data-gadget-scope='panel'] ul li a:hover,
div[data-gadget-scope='panel'] ul li a:active {
background-color: #2b2b2b;
}
div[data-gadget-scope='panel'] ul li a::before {
width: 24pt;
}
div[data-gadget-scope='panel'] dl {
background-color: #777777;
color: #1F1F1F;
transform-origin: 50% 0;
transform: scaleY(0);
transition: transform 0.2s ease-out;
}
div[data-gadget-scope='panel'] dl:not(:empty) {
transform: scaleY(1);
}
div[data-gadget-scope='panel'] dl dt {
padding: 3pt;
padding-left: 12pt;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
div[data-gadget-scope='panel'] dl dt::before {
width: 24pt;
}
div[data-gadget-scope='panel'] dl dd a {
color: #FFFFFF;
display: block;
padding: 3pt;
padding-left: 12pt;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding-left: 36pt;
}
div[data-gadget-scope='panel'] dl dd a:hover,
div[data-gadget-scope='panel'] dl dd a:active {
background-color: #2b2b2b;
}
div[data-gadget-scope='panel'] dl dd a::before {
width: 24pt;
}
/**********************************************
* Gadget: editor panel
**********************************************/
div[data-gadget-scope='editor_panel'] {
background-color: #FFFFFF;
width: 180pt;
min-height: 100%;
max-height: 100%;
overflow-y: auto;
position: fixed;
top: 0;
display: block;
z-index: 3000;
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='editor_panel'] {
left: -186pt;
transition: transform 200ms ease-out;
transform: translate3d(0, 0, 0);
box-shadow: 5px 0 5px rgba(0, 0, 0, 0.15);
}
div[data-gadget-scope='editor_panel'].visible {
transform: translate3d(186pt, 0, 0);
}
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='editor_panel'] {
right: -186pt;
transition: transform 200ms ease-out;
transform: translate3d(0, 0, 0);
box-shadow: -5px 0 5px rgba(0, 0, 0, 0.15);
}
div[data-gadget-scope='editor_panel'].visible {
transform: translate3d(-186pt, 0, 0);
}
}
div[data-gadget-scope='editor_panel'] div[data-role="header"] {
display: flex;
justify-content: space-between;
flex-direction: row-reverse;
}
div[data-gadget-scope='editor_panel'] div[data-role="header"] h1 {
text-align: left;
line-height: 30pt;
max-height: 30pt;
}
div[data-gadget-scope='editor_panel'] div[data-role="header"] button,
div[data-gadget-scope='editor_panel'] div[data-role="header"] a {
width: 3em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
display: block;
line-height: 30pt;
}
div[data-gadget-scope='editor_panel'] div[data-role="header"] button::before,
div[data-gadget-scope='editor_panel'] div[data-role="header"] a::before {
float: left;
text-indent: 0;
margin-left: 12pt;
}
div[data-gadget-scope='editor_panel'] section {
padding: 12pt;
}
div[data-gadget-scope='editor_panel'] section fieldset > div {
display: inline-block;
}
div[data-gadget-scope='editor_panel'] section fieldset label {
display: inline-block;
text-align: center;
}
div[data-gadget-scope='editor_panel'] section fieldset input[type="radio"] {
display: inline-block;
}
div[data-gadget-scope='editor_panel'] section .filter_item_container > div,
div[data-gadget-scope='editor_panel'] section .sort_item_container > div {
display: flex;
align-items: flex-start;
padding: 6pt 0;
}
div[data-gadget-scope='editor_panel'] section .filter_item_container > div .filter_item,
div[data-gadget-scope='editor_panel'] section .sort_item_container > div .filter_item,
div[data-gadget-scope='editor_panel'] section .filter_item_container > div .sort_item,
div[data-gadget-scope='editor_panel'] section .sort_item_container > div .sort_item {
flex: 1;
}
div[data-gadget-scope='editor_panel'] section button {
padding: 3pt 6pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
margin-right: 6pt;
width: 2em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
}
div[data-gadget-scope='editor_panel'] section button:last-of-type {
margin-right: 0;
}
div[data-gadget-scope='editor_panel'] section button::before {
margin-right: 6pt;
float: left;
text-indent: 0;
}
/**********************************************
* Gadget: header
**********************************************/
div[data-gadget-scope='header'] .ui-header {
position: fixed;
z-index: 1000;
text-align: center;
display: flex;
flex-flow: row wrap;
width: 100%;
color: #FFFFFF;
background-color: #0E81C2;
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header {
margin-left: 180pt;
}
}
div[data-gadget-scope='header'] .ui-header button,
div[data-gadget-scope='header'] .ui-header a {
color: #FFFFFF;
transition: background-color 0.2s ease-out;
}
div[data-gadget-scope='header'] .ui-header button:hover,
div[data-gadget-scope='header'] .ui-header a:hover,
div[data-gadget-scope='header'] .ui-header button:active,
div[data-gadget-scope='header'] .ui-header a:active {
background-color: #0e90d8;
}
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a {
display: block;
transition: background-color 0.2s ease-out;
line-height: 30pt;
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a {
background-color: #0E81C2;
}
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a {
background-color: #085078;
}
}
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button:hover,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a:hover,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button:active,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a:active {
background-color: #0e90d8;
}
@media only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a {
width: 8em;
}
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a {
width: 3em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button::before,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a::before {
width: 1em;
margin-right: 6pt;
text-align: center;
}
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button::before,
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a::before {
float: left;
text-indent: 0;
margin-left: 12pt;
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls button[name="panel"],
div[data-gadget-scope='header'] .ui-header .ui-controlgroup-controls a[name="panel"] {
display: none;
}
}
div[data-gadget-scope='header'] .ui-header > .ui-btn-left button,
div[data-gadget-scope='header'] .ui-header > .ui-btn-left a {
border-right: 1px solid rgba(255, 255, 255, 0.55);
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header > .ui-btn-right button,
div[data-gadget-scope='header'] .ui-header > .ui-btn-right a {
border-left: 1px solid rgba(255, 255, 255, 0.55);
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header > .ui-btn-right button,
div[data-gadget-scope='header'] .ui-header > .ui-btn-right a {
padding-left: 24pt;
padding-right: 24pt;
min-width: 5em;
}
}
div[data-gadget-scope='header'] .ui-header h1 {
text-align: left;
line-height: 30pt;
flex: 1;
background-color: #085078;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header h1 {
flex: 1 100%;
}
}
div[data-gadget-scope='header'] .ui-header h1 > span {
padding-left: 42pt;
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header h1 > span {
padding-left: 30pt;
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header h1 > span {
padding-left: 24pt;
}
}
div[data-gadget-scope='header'] .ui-header h1 a {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
div[data-gadget-scope='header'] .ui-header h1 a::before {
display: inline-block;
width: 42pt;
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header h1 a::before {
text-align: center;
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header h1 a::before {
padding-left: 24pt;
}
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header h1 a::before {
width: 30pt;
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-subheader {
text-align: left;
flex: 1;
}
}
@media not screen and (min-width: 45em), only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header .ui-subheader {
flex: 1 100%;
}
}
div[data-gadget-scope='header'] .ui-header ul {
display: flex;
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header ul li {
flex: 1;
border-left: 1px solid rgba(0, 0, 0, 0.55);
}
div[data-gadget-scope='header'] .ui-header ul li:first-child {
border-left: none;
}
div[data-gadget-scope='header'] .ui-header ul li a {
display: block;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header ul li a {
padding-top: 3pt;
padding-bottom: 3pt;
white-space: nowrap;
overflow: hidden;
}
div[data-gadget-scope='header'] .ui-header ul li a::before {
font-size: 1.2em;
display: block;
}
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='header'] .ui-header ul li a {
text-align: center;
vertical-align: middle;
font-size: 1.5em;
padding-top: 6pt;
padding-bottom: 6pt;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
}
div[data-gadget-scope='header'] .ui-header ul li a::before {
float: left;
text-indent: 0;
width: 100%;
}
}
@media not screen and (max-width: 85em) {
div[data-gadget-scope='header'] .ui-header ul li a {
display: block;
padding-left: 24pt;
padding-right: 24pt;
min-width: 5em;
line-height: 30pt;
white-space: nowrap;
overflow: hidden;
}
div[data-gadget-scope='header'] .ui-header ul li a::before {
display: none;
}
}
/**********************************************
* Gadget: main
**********************************************/
.gadget-content {
padding: 24pt;
padding-top: 66pt;
/*
@media @smartphone {
.ui-field-contain {
// padding: 0.8em 0;
// make sure there is a bottom border
// XXX TODO: border should be visible only if not input
// XXX How to not show it on last field?
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}
}
*/
/* form validation (assuming label>span is used) */
}
.gadget-content div[data-gadget-scope='m'] {
animation: fadein 0.2s ease-out;
}
.gadget-content input[type='submit'] {
padding: 6pt;
margin-top: 30pt;
margin-right: 12pt;
background-color: #FF6600;
color: #FFFFFF;
border-radius: 0.325em;
border-width: 1px;
border-style: solid;
min-width: 8em;
}
.gadget-content input[type='submit']:hover,
.gadget-content input[type='submit']:focus {
background-color: #ff8533;
}
.gadget-content input[type='submit']:active {
background-color: #ffa366;
}
@media not screen and (max-width: 85em) {
.gadget-content {
margin-left: 180pt;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em) {
.gadget-content {
padding-top: 7em;
}
}
@media not screen and (min-width: 45em) {
.gadget-content {
padding: 6pt;
padding-top: 6em;
}
}
.gadget-content .ui-field-contain {
padding: 6pt 0;
}
.gadget-content .ui-field-contain div {
width: 100%;
}
.gadget-content .ui-content-header-plain {
font-size: 150%;
}
.gadget-content ul.document-listview:not(:last-of-type) {
margin-bottom: 12pt;
}
.gadget-content ul.document-listview:first-child {
margin-top: 6pt;
}
.gadget-content ul.document-listview li {
border-color: rgba(0, 0, 0, 0.3);
border-width: 1px;
border-style: solid;
border-bottom-style: none;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
}
.gadget-content ul.document-listview li:not(.ui-li-has-count) a:after {
font-family: FontAwesome;
content: "\f0da";
text-align: right;
float: right;
position: absolute;
right: 12pt;
}
.gadget-content ul.document-listview li a {
display: block;
position: relative;
padding: 6pt 12pt;
padding-right: 24pt;
color: #222222;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.gadget-content ul.document-listview li a:hover,
.gadget-content ul.document-listview li a:active {
background-color: #e0e0e0;
}
.gadget-content ul.document-listview li:first-child {
border-top-left-radius: 0.325em;
border-top-right-radius: 0.325em;
}
.gadget-content ul.document-listview li:last-child {
border-bottom-left-radius: 0.325em;
border-bottom-right-radius: 0.325em;
border-bottom-style: solid;
}
.gadget-content ul.document-listview li .ui-li-count {
float: right;
padding: 0 6pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
position: absolute;
right: 6pt;
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (max-width: 85em) {
.gadget-content .left,
.gadget-content .right {
vertical-align: top;
display: inline-block;
width: 50%;
}
.gadget-content .right {
padding-left: 24pt;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (max-width: 85em) {
.gadget-content .ui-field-contain {
display: flex;
}
.gadget-content .ui-field-contain > label {
flex: 1;
color: #777777;
}
.gadget-content .ui-field-contain > label + div {
flex: 3;
}
}
@media only screen and (min-width: 45em) and (max-width: 85em), not screen and (max-width: 85em) {
.gadget-content .center .ui-field-contain > label + div {
flex: 7;
}
}
.gadget-content form label {
position: relative;
}
.gadget-content form label span span {
animation: fadein 0.2s ease-out;
}
@media not screen and (max-width: 85em), only screen and (min-width: 45em) and (max-width: 85em) {
.gadget-content form label span span {
background-color: #FF6600;
color: #f8fff3;
left: 110%;
position: absolute;
bottom: 130%;
white-space: pre;
padding: 6pt;
border-radius: 0.325em;
width: auto;
z-index: 1001;
}
.gadget-content form label span span:before {
position: absolute;
top: 100%;
left: 2em;
display: inline-block;
border-right: 6pt solid transparent;
border-top: 6pt solid #FF6600;
border-left: 6pt solid transparent;
content: '';
}
}
@media not screen and (min-width: 45em) {
.gadget-content form label span span {
margin-left: 6pt;
color: #FF6600;
}
}
/**********************************************
* Gadget: relation field
**********************************************/
.relation-input {
display: flex;
}
.relation-input a {
width: 24pt;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
display: block;
padding-top: 3pt;
padding-bottom: 3pt;
}
.relation-input a::before {
float: left;
text-indent: 0;
margin-left: 6pt;
}
.relation-input div {
position: relative;
}
.relation-input ul {
position: absolute;
display: block;
width: 100%;
z-index: 501;
}
.relation-input ul li {
cursor: pointer;
background-color: #444444;
color: #FFFFFF;
padding: 3pt;
padding-left: 6pt;
display: block;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.relation-input ul li::before {
padding-right: 6pt;
}
.relation-input ul li:hover,
.relation-input ul li:active {
background-color: #2b2b2b;
}
/**********************************************
* Gadget: datetime field
**********************************************/
.datetimefield {
display: flex;
}
.datetimefield div[data-gadget-scope=INPUT] {
flex: 2;
}
.datetimefield div[data-gadget-scope=SELECT] {
flex: 1;
}
/**********************************************
* Gadget: float/integer field
**********************************************/
.floatfield p,
.integerfield p,
.floatfield input,
.integerfield input {
text-align: right;
}
/**********************************************
* Listbox
**********************************************/
div[data-gadget-scope='erp5_searchfield'] {
padding-top: 6pt;
}
div[data-gadget-scope='erp5_searchfield'] .ui-input-text {
display: flex;
}
div[data-gadget-scope='erp5_searchfield'] .ui-input-text div[data-gadget-scope='input'] {
width: 100%;
}
div[data-gadget-scope='erp5_searchfield'] button {
padding: 3pt;
}
.document_table .ui-table-header {
display: flex;
padding-bottom: 6pt;
}
@media not screen and (min-width: 45em) {
.document_table .ui-table-header {
border-bottom: 2px solid rgba(0, 0, 0, 0.14902);
}
}
.document_table .ui-table-header h1 {
color: #777777;
flex: 2;
align-self: flex-end;
}
.document_table .ui-table-header button {
padding: 3pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
margin-right: 6pt;
}
.document_table .ui-table-header button:last-of-type {
margin-right: 0;
}
@media not screen and (min-width: 45em) {
.document_table .ui-table-header button {
width: 2em;
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
}
}
.document_table .ui-table-header button::before {
margin-right: 6pt;
}
@media not screen and (min-width: 45em) {
.document_table .ui-table-header button::before {
float: left;
text-indent: 0;
}
}
.document_table table {
width: 100%;
text-align: left;
}
.document_table table th,
.document_table table td {
vertical-align: middle;
}
.document_table table thead {
background-color: #0E81C2;
color: #FFFFFF;
}
.document_table table thead tr th {
padding: 6pt 3pt;
}
@media not screen and (min-width: 45em) {
.document_table table thead {
display: none;
}
}
.document_table table a {
color: #1F1F1F;
}
.document_table table tbody {
animation: fadein 0.2s ease-out;
}
.document_table table tbody tr:nth-child(even) {
background-color: #f2f2f2;
}
.document_table table tbody tr:hover,
.document_table table tbody tr:active {
background-color: #e0e0e0;
}
@media not screen and (max-width: 85em), only screen and (min-width: 45em) and (max-width: 85em) {
.document_table table tbody a {
display: block;
padding: 3pt;
}
}
@media not screen and (min-width: 45em) {
.document_table table tbody tr {
display: block;
overflow: hidden;
width: 100%;
height: 4em;
position: relative;
}
.document_table table tbody tr td,
.document_table table tbody tr th {
display: inline-block;
}
.document_table table tbody tr td:first-child,
.document_table table tbody tr th:first-child {
display: inline-block;
width: 100%;
}
.document_table table tbody tr td:first-child a,
.document_table table tbody tr th:first-child a {
position: absolute;
width: 100%;
top: 0;
bottom: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.document_table table tbody tr td:first-child a:after,
.document_table table tbody tr th:first-child a:after {
font-family: FontAwesome;
content: "\f0da";
font-size: 1.25em;
position: absolute;
right: 6pt;
top: 50%;
margin-top: -0.75em;
background-color: #FFFFFF;
border-radius: 0.5em;
width: 1em;
text-align: center;
line-height: 1em;
}
.document_table table tbody tr td:first-child ~ th,
.document_table table tbody tr th:first-child ~ th,
.document_table table tbody tr td:first-child ~ td,
.document_table table tbody tr th:first-child ~ td {
font-size: 0.8em;
}
.document_table table tbody tr td:first-child ~ th a,
.document_table table tbody tr th:first-child ~ th a,
.document_table table tbody tr td:first-child ~ td a,
.document_table table tbody tr th:first-child ~ td a {
pointer-events: none;
}
.document_table table tbody tr td:first-child ~ th:not(:last-child) a:not(:empty):after,
.document_table table tbody tr th:first-child ~ th:not(:last-child) a:not(:empty):after,
.document_table table tbody tr td:first-child ~ td:not(:last-child) a:not(:empty):after,
.document_table table tbody tr th:first-child ~ td:not(:last-child) a:not(:empty):after {
content: " ~ ";
}
}
.document_table table tfoot .ui-controlgroup-controls {
display: flex;
padding-top: 6pt;
border-top: 2px solid rgba(0, 0, 0, 0.14902);
}
.document_table table tfoot .ui-controlgroup-controls span {
opacity: .3;
flex: 2;
text-align: right;
}
.document_table table tfoot .ui-controlgroup-controls a {
padding: 6pt;
border: 1px solid rgba(0, 0, 0, 0.14);
border-radius: 0.325em;
margin-right: 6pt;
}
.document_table table tfoot .ui-controlgroup-controls a:last-of-type {
margin-right: 0;
}
.document_table table tfoot .ui-controlgroup-controls a:hover,
.document_table table tfoot .ui-controlgroup-controls a:active {
background-color: #e0e0e0;
}
@media not screen and (min-width: 45em) {
.document_table table tfoot .ui-controlgroup-controls a {
overflow: hidden;
text-indent: -9999px;
white-space: nowrap;
}
}
.document_table table tfoot .ui-controlgroup-controls a::before {
margin-right: 6pt;
}
@media not screen and (min-width: 45em) {
.document_table table tfoot .ui-controlgroup-controls a::before {
float: left;
text-indent: 6pt;
}
}
/**********************************************
* Notification
**********************************************/
div[data-gadget-scope='notification'] {
position: fixed;
z-index: 99999;
bottom: 12pt;
right: -192pt;
transition: transform 200ms ease-out;
transform: translate3d(0, 0, 0);
}
div[data-gadget-scope='notification'].visible {
transform: translate3d(-216pt, 0, 0);
}
@media not screen and (min-width: 45em) {
div[data-gadget-scope='notification'].visible {
transform: translate3d(-198pt, 0, 0);
}
}
div[data-gadget-scope='notification'] button {
text-align: left;
width: 180pt;
padding: 12pt;
background-color: #FF6600;
color: #f8fff3;
border-radius: 0.325em;
}
/**********************************************
* JQM
**********************************************/
.ui-disabled {
opacity: .3;
cursor: default;
pointer-events: none;
}
.ui-screen-hidden {
display: none;
}
/**********************************************
* First loader
**********************************************/
.first-loader {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 300%;
}
/**********************************************
* Keyframes
**********************************************/
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/**********************************************
* Class
**********************************************/
.content-iframe-maximize {
position: fixed;
}
@media not screen and (max-width: 85em) {
.content-iframe-maximize {
left: 180pt;
top: 60pt;
}
.content-iframe-maximize iframe {
width: calc(100vw - 180pt );
height: calc(100vh - 60pt );
}
}
@media only screen and (min-width: 45em) and (max-width: 85em) {
.content-iframe-maximize {
left: 0;
top: 73pt;
}
.content-iframe-maximize iframe {
height: calc(100vh - 73pt );
}
}
@media not screen and (min-width: 45em) {
.content-iframe-maximize {
left: 0;
top: 67pt;
}
.content-iframe-maximize iframe {
height: calc(100vh - 67pt );
}
}
/**********************************************
* Icons
**********************************************/
.ui-btn-icon-top::before,
.ui-btn-icon-left::before,
.ui-btn-icon-right::before,
.ui-icon::before,
.ui-btn-icon-notext::before {
font-family: FontAwesome;
display: inline-block;
content: "";
}
.ui-icon-warning {
background-color: #FF6600 !important;
}
.ui-icon-warning::before {
content: "\f071";
}
.ui-icon-spinner {
opacity: 1;
}
.ui-icon-spinner::before {
content: "\f110";
animation: spin .5s infinite linear;
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.ui-icon-glass::before {
content: "\f000";
}
.ui-icon-music::before {
content: "\f001";
}
.ui-icon-search::before {
content: "\f002";
}
.ui-icon-envelope-o::before {
content: "\f003";
}
.ui-icon-heart::before {
content: "\f004";
}
.ui-icon-star::before {
content: "\f005";
}
.ui-icon-star-o::before {
content: "\f006";
}
.ui-icon-user::before {
content: "\f007";
}
.ui-icon-film::before {
content: "\f008";
}
.ui-icon-th-large::before {
content: "\f009";
}
.ui-icon-th::before {
content: "\f00a";
}
.ui-icon-th-list::before {
content: "\f00b";
}
.ui-icon-check::before {
content: "\f00c";
}
.ui-icon-times::before,
.ui-icon-delete::before {
content: "\f00d";
}
.ui-icon-search-plus::before {
content: "\f00e";
}
.ui-icon-search-minus::before {
content: "\f010";
}
.ui-icon-power-off::before {
content: "\f011";
}
.ui-icon-signal::before {
content: "\f012";
}
.ui-icon-gear::before,
.ui-icon-cog::before {
content: "\f013";
}
.ui-icon-trash-o::before {
content: "\f014";
}
.ui-icon-home::before {
content: "\f015";
}
.ui-icon-file-o::before {
content: "\f016";
}
.ui-icon-clock-o::before {
content: "\f017";
}
.ui-icon-road::before {
content: "\f018";
}
.ui-icon-download::before {
content: "\f019";
}
.ui-icon-arrow-circle-o-down::before {
content: "\f01a";
}
.ui-icon-arrow-circle-o-up::before {
content: "\f01b";
}
.ui-icon-inbox::before {
content: "\f01c";
}
.ui-icon-play-circle-o::before {
content: "\f01d";
}
.ui-icon-rotate-right::before,
.ui-icon-repeat::before {
content: "\f01e";
}
.ui-icon-refresh::before {
content: "\f021";
}
.ui-icon-list-alt::before {
content: "\f022";
}
.ui-icon-lock::before {
content: "\f023";
}
.ui-icon-flag::before {
content: "\f024";
}
.ui-icon-headphones::before {
content: "\f025";
}
.ui-icon-volume-off::before {
content: "\f026";
}
.ui-icon-volume-down::before {
content: "\f027";
}
.ui-icon-volume-up::before {
content: "\f028";
}
.ui-icon-qrcode::before {
content: "\f029";
}
.ui-icon-barcode::before {
content: "\f02a";
}
.ui-icon-tag::before {
content: "\f02b";
}
.ui-icon-tags::before {
content: "\f02c";
}
.ui-icon-book::before {
content: "\f02d";
}
.ui-icon-bookmark::before {
content: "\f02e";
}
.ui-icon-print::before {
content: "\f02f";
}
.ui-icon-camera::before {
content: "\f030";
}
.ui-icon-font::before {
content: "\f031";
}
.ui-icon-bold::before {
content: "\f032";
}
.ui-icon-italic::before {
content: "\f033";
}
.ui-icon-text-height::before {
content: "\f034";
}
.ui-icon-text-width::before {
content: "\f035";
}
.ui-icon-align-left::before {
content: "\f036";
}
.ui-icon-align-center::before {
content: "\f037";
}
.ui-icon-align-right::before {
content: "\f038";
}
.ui-icon-align-justify::before {
content: "\f039";
}
.ui-icon-list::before {
content: "\f03a";
}
.ui-icon-dedent::before,
.ui-icon-outdent::before {
content: "\f03b";
}
.ui-icon-indent::before {
content: "\f03c";
}
.ui-icon-video-camera::before {
content: "\f03d";
}
.ui-icon-photo::before,
.ui-icon-image::before,
.ui-icon-picture-o::before {
content: "\f03e";
}
.ui-icon-pencil::before {
content: "\f040";
}
.ui-icon-map-marker::before {
content: "\f041";
}
.ui-icon-adjust::before {
content: "\f042";
}
.ui-icon-tint::before {
content: "\f043";
}
.ui-icon-edit::before,
.ui-icon-pencil-square-o::before {
content: "\f044";
}
.ui-icon-share-square-o::before {
content: "\f045";
}
.ui-icon-check-square-o::before,
.ui-icon-checkbox-on::before,
.ui-checkbox-on::before {
content: "\f046";
}
.ui-icon-arrows::before {
content: "\f047";
}
.ui-icon-step-backward::before {
content: "\f048";
}
.ui-icon-fast-backward::before {
content: "\f049";
}
.ui-icon-backward::before {
content: "\f04a";
}
.ui-icon-play::before {
content: "\f04b";
}
.ui-icon-pause::before {
content: "\f04c";
}
.ui-icon-stop::before {
content: "\f04d";
}
.ui-icon-forward::before {
content: "\f04e";
}
.ui-icon-fast-forward::before {
content: "\f050";
}
.ui-icon-step-forward::before {
content: "\f051";
}
.ui-icon-eject::before {
content: "\f052";
}
.ui-icon-chevron-left::before {
content: "\f053";
}
.ui-icon-chevron-right::before {
content: "\f054";
}
.ui-icon-plus-circle::before {
content: "\f055";
}
.ui-icon-minus-circle::before {
content: "\f056";
}
.ui-icon-times-circle::before {
content: "\f057";
}
.ui-icon-check-circle::before {
content: "\f058";
}
.ui-icon-question-circle::before {
content: "\f059";
}
.ui-icon-info-circle::before {
content: "\f05a";
}
.ui-icon-crosshairs::before {
content: "\f05b";
}
.ui-icon-times-circle-o::before {
content: "\f05c";
}
.ui-icon-check-circle-o::before,
.ui-icon-radio-off::before,
.ui-radio-on::before {
content: "\f05d";
}
.ui-icon-ban::before {
content: "\f05e";
}
.ui-icon-arrow-left::before {
content: "\f060";
}
.ui-icon-arrow-right::before {
content: "\f061";
}
.ui-icon-arrow-up::before {
content: "\f062";
}
.ui-icon-arrow-down::before {
content: "\f063";
}
.ui-icon-mail-forward::before,
.ui-icon-share::before {
content: "\f064";
}
.ui-icon-expand::before {
content: "\f065";
}
.ui-icon-compress::before {
content: "\f066";
}
.ui-icon-plus::before {
content: "\f067";
}
.ui-icon-minus::before {
content: "\f068";
}
.ui-icon-asterisk::before {
content: "\f069";
}
.ui-icon-exclamation-circle::before {
content: "\f06a";
}
.ui-icon-gift::before {
content: "\f06b";
}
.ui-icon-leaf::before {
content: "\f06c";
}
.ui-icon-fire::before {
content: "\f06d";
}
.ui-icon-eye::before {
content: "\f06e";
}
.ui-icon-eye-slash::before {
content: "\f070";
}
.ui-icon-exclamation-triangle::before {
content: "\f071";
}
.ui-icon-plane::before {
content: "\f072";
}
.ui-icon-calendar::before {
content: "\f073";
}
.ui-icon-random::before {
content: "\f074";
}
.ui-icon-comment::before {
content: "\f075";
}
.ui-icon-magnet::before {
content: "\f076";
}
.ui-icon-chevron-up::before {
content: "\f077";
}
.ui-icon-chevron-down::before {
content: "\f078";
}
.ui-icon-retweet::before {
content: "\f079";
}
.ui-icon-shopping-cart::before {
content: "\f07a";
}
.ui-icon-folder::before {
content: "\f07b";
}
.ui-icon-folder-open::before {
content: "\f07c";
}
.ui-icon-arrows-v::before {
content: "\f07d";
}
.ui-icon-arrows-h::before {
content: "\f07e";
}
.ui-icon-bar-chart-o::before {
content: "\f080";
}
.ui-icon-twitter-square::before {
content: "\f081";
}
.ui-icon-facebook-square::before {
content: "\f082";
}
.ui-icon-camera-retro::before {
content: "\f083";
}
.ui-icon-key::before {
content: "\f084";
}
.ui-icon-gears::before,
.ui-icon-cogs::before {
content: "\f085";
}
.ui-icon-comments::before {
content: "\f086";
}
.ui-icon-thumbs-o-up::before {
content: "\f087";
}
.ui-icon-thumbs-o-down::before {
content: "\f088";
}
.ui-icon-star-half::before {
content: "\f089";
}
.ui-icon-heart-o::before {
content: "\f08a";
}
.ui-icon-sign-out::before {
content: "\f08b";
}
.ui-icon-linkedin-square::before {
content: "\f08c";
}
.ui-icon-thumb-tack::before {
content: "\f08d";
}
.ui-icon-external-link::before {
content: "\f08e";
}
.ui-icon-sign-in::before {
content: "\f090";
}
.ui-icon-trophy::before {
content: "\f091";
}
.ui-icon-github-square::before {
content: "\f092";
}
.ui-icon-upload::before {
content: "\f093";
}
.ui-icon-lemon-o::before {
content: "\f094";
}
.ui-icon-phone::before {
content: "\f095";
}
.ui-icon-square-o::before,
.ui-icon-checkbox-off::before,
.ui-checkbox-off::before {
content: "\f096";
}
.ui-icon-bookmark-o::before {
content: "\f097";
}
.ui-icon-phone-square::before {
content: "\f098";
}
.ui-icon-twitter::before {
content: "\f099";
}
.ui-icon-facebook::before {
content: "\f09a";
}
.ui-icon-github::before {
content: "\f09b";
}
.ui-icon-unlock::before {
content: "\f09c";
}
.ui-icon-credit-card::before {
content: "\f09d";
}
.ui-icon-rss::before {
content: "\f09e";
}
.ui-icon-hdd-o::before {
content: "\f0a0";
}
.ui-icon-bullhorn::before {
content: "\f0a1";
}
.ui-icon-bell::before {
content: "\f0f3";
}
.ui-icon-certificate::before {
content: "\f0a3";
}
.ui-icon-hand-o-right::before {
content: "\f0a4";
}
.ui-icon-hand-o-left::before {
content: "\f0a5";
}
.ui-icon-hand-o-up::before {
content: "\f0a6";
}
.ui-icon-hand-o-down::before {
content: "\f0a7";
}
.ui-icon-arrow-circle-left::before {
content: "\f0a8";
}
.ui-icon-arrow-circle-right::before {
content: "\f0a9";
}
.ui-icon-arrow-circle-up::before {
content: "\f0aa";
}
.ui-icon-arrow-circle-down::before {
content: "\f0ab";
}
.ui-icon-globe::before {
content: "\f0ac";
}
.ui-icon-wrench::before {
content: "\f0ad";
}
.ui-icon-tasks::before {
content: "\f0ae";
}
.ui-icon-filter::before {
content: "\f0b0";
}
.ui-icon-briefcase::before {
content: "\f0b1";
}
.ui-icon-arrows-alt::before {
content: "\f0b2";
}
.ui-icon-group::before,
.ui-icon-users::before {
content: "\f0c0";
}
.ui-icon-chain::before,
.ui-icon-link::before {
content: "\f0c1";
}
.ui-icon-cloud::before {
content: "\f0c2";
}
.ui-icon-flask::before {
content: "\f0c3";
}
.ui-icon-cut::before,
.ui-icon-scissors::before {
content: "\f0c4";
}
.ui-icon-copy::before,
.ui-icon-files-o::before {
content: "\f0c5";
}
.ui-icon-paperclip::before {
content: "\f0c6";
}
.ui-icon-save::before,
.ui-icon-floppy-o::before {
content: "\f0c7";
}
.ui-icon-square::before {
content: "\f0c8";
}
.ui-icon-navicon::before,
.ui-icon-reorder::before,
.ui-icon-bars::before {
content: "\f0c9";
}
.ui-icon-list-ul::before {
content: "\f0ca";
}
.ui-icon-list-ol::before {
content: "\f0cb";
}
.ui-icon-strikethrough::before {
content: "\f0cc";
}
.ui-icon-underline::before {
content: "\f0cd";
}
.ui-icon-table::before {
content: "\f0ce";
}
.ui-icon-magic::before {
content: "\f0d0";
}
.ui-icon-truck::before {
content: "\f0d1";
}
.ui-icon-pinterest::before {
content: "\f0d2";
}
.ui-icon-pinterest-square::before {
content: "\f0d3";
}
.ui-icon-google-plus-square::before {
content: "\f0d4";
}
.ui-icon-google-plus::before {
content: "\f0d5";
}
.ui-icon-money::before {
content: "\f0d6";
}
.ui-icon-caret-down::before,
.ui-icon-carat-d::before {
content: "\f0d7";
}
.ui-icon-caret-up::before,
hmtl .ui-icon-carat-u::before {
content: "\f0d8";
}
.ui-icon-caret-left::before,
.ui-icon-carat-l::before {
content: "\f0d9";
}
.ui-icon-caret-right::before,
.ui-icon-carat-r::before {
content: "\f0da";
}
.ui-icon-columns::before {
content: "\f0db";
}
.ui-icon-unsorted::before,
.ui-icon-sort::before {
content: "\f0dc";
}
.ui-icon-sort-down::before,
.ui-icon-sort-desc::before {
content: "\f0dd";
}
.ui-icon-sort-up::before,
.ui-icon-sort-asc::before {
content: "\f0de";
}
.ui-icon-envelope::before {
content: "\f0e0";
}
.ui-icon-linkedin::before {
content: "\f0e1";
}
.ui-icon-rotate-left::before,
.ui-icon-undo::before {
content: "\f0e2";
}
.ui-icon-legal::before,
.ui-icon-gavel::before {
content: "\f0e3";
}
.ui-icon-dashboard::before,
.ui-icon-tachometer::before {
content: "\f0e4";
}
.ui-icon-comment-o::before {
content: "\f0e5";
}
.ui-icon-comments-o::before {
content: "\f0e6";
}
.ui-icon-flash::before,
.ui-icon-bolt::before {
content: "\f0e7";
}
.ui-icon-sitemap::before {
content: "\f0e8";
}
.ui-icon-umbrella::before {
content: "\f0e9";
}
.ui-icon-paste::before,
.ui-icon-clipboard::before {
content: "\f0ea";
}
.ui-icon-lightbulb-o::before {
content: "\f0eb";
}
.ui-icon-exchange::before {
content: "\f0ec";
}
.ui-icon-cloud-download::before {
content: "\f0ed";
}
.ui-icon-cloud-upload::before {
content: "\f0ee";
}
.ui-icon-user-md::before {
content: "\f0f0";
}
.ui-icon-stethoscope::before {
content: "\f0f1";
}
.ui-icon-suitcase::before {
content: "\f0f2";
}
.ui-icon-bell-o::before {
content: "\f0a2";
}
.ui-icon-coffee::before {
content: "\f0f4";
}
.ui-icon-cutlery::before {
content: "\f0f5";
}
.ui-icon-file-text-o::before {
content: "\f0f6";
}
.ui-icon-building-o::before {
content: "\f0f7";
}
.ui-icon-hospital-o::before {
content: "\f0f8";
}
.ui-icon-ambulance::before {
content: "\f0f9";
}
.ui-icon-medkit::before {
content: "\f0fa";
}
.ui-icon-fighter-jet::before {
content: "\f0fb";
}
.ui-icon-beer::before {
content: "\f0fc";
}
.ui-icon-h-square::before {
content: "\f0fd";
}
.ui-icon-plus-square::before {
content: "\f0fe";
}
.ui-icon-angle-double-left::before {
content: "\f100";
}
.ui-icon-angle-double-right::before {
content: "\f101";
}
.ui-icon-angle-double-up::before {
content: "\f102";
}
.ui-icon-angle-double-down::before {
content: "\f103";
}
.ui-icon-angle-left::before {
content: "\f104";
}
.ui-icon-angle-right::before {
content: "\f105";
}
.ui-icon-angle-up::before {
content: "\f106";
}
.ui-icon-angle-down::before {
content: "\f107";
}
.ui-icon-desktop::before {
content: "\f108";
}
.ui-icon-laptop::before {
content: "\f109";
}
.ui-icon-tablet::before {
content: "\f10a";
}
.ui-icon-mobile-phone::before,
.ui-icon-mobile::before {
content: "\f10b";
}
.ui-icon-circle-o::before,
.ui-radio-off::before {
content: "\f10c";
}
.ui-icon-quote-left::before {
content: "\f10d";
}
.ui-icon-quote-right::before {
content: "\f10e";
}
.ui-icon-circle::before {
content: "\f111";
}
.ui-icon-mail-reply::before,
.ui-icon-reply::before {
content: "\f112";
}
.ui-icon-github-alt::before {
content: "\f113";
}
.ui-icon-folder-o::before {
content: "\f114";
}
.ui-icon-folder-open-o::before {
content: "\f115";
}
.ui-icon-smile-o::before {
content: "\f118";
}
.ui-icon-frown-o::before {
content: "\f119";
}
.ui-icon-meh-o::before {
content: "\f11a";
}
.ui-icon-gamepad::before {
content: "\f11b";
}
.ui-icon-keyboard-o::before {
content: "\f11c";
}
.ui-icon-flag-o::before {
content: "\f11d";
}
.ui-icon-flag-checkered::before {
content: "\f11e";
}
.ui-icon-terminal::before {
content: "\f120";
}
.ui-icon-code::before {
content: "\f121";
}
.ui-icon-mail-reply-all::before,
.ui-icon-reply-all::before {
content: "\f122";
}
.ui-icon-star-half-empty::before,
.ui-icon-star-half-full::before,
.ui-icon-star-half-o::before {
content: "\f123";
}
.ui-icon-location-arrow::before {
content: "\f124";
}
.ui-icon-crop::before {
content: "\f125";
}
.ui-icon-code-fork::before {
content: "\f126";
}
.ui-icon-unlink::before,
.ui-icon-chain-broken::before {
content: "\f127";
}
.ui-icon-question::before {
content: "\f128";
}
.ui-icon-info::before {
content: "\f129";
}
.ui-icon-exclamation::before {
content: "\f12a";
}
.ui-icon-superscript::before {
content: "\f12b";
}
.ui-icon-subscript::before {
content: "\f12c";
}
.ui-icon-eraser::before {
content: "\f12d";
}
.ui-icon-puzzle-piece::before {
content: "\f12e";
}
.ui-icon-microphone::before {
content: "\f130";
}
.ui-icon-microphone-slash::before {
content: "\f131";
}
.ui-icon-shield::before {
content: "\f132";
}
.ui-icon-calendar-o::before {
content: "\f133";
}
.ui-icon-fire-extinguisher::before {
content: "\f134";
}
.ui-icon-rocket::before {
content: "\f135";
}
.ui-icon-maxcdn::before {
content: "\f136";
}
.ui-icon-chevron-circle-left::before {
content: "\f137";
}
.ui-icon-chevron-circle-right::before {
content: "\f138";
}
.ui-icon-chevron-circle-up::before {
content: "\f139";
}
.ui-icon-chevron-circle-down::before {
content: "\f13a";
}
.ui-icon-html5::before {
content: "\f13b";
}
.ui-icon-css3::before {
content: "\f13c";
}
.ui-icon-anchor::before {
content: "\f13d";
}
.ui-icon-unlock-alt::before {
content: "\f13e";
}
.ui-icon-bullseye::before {
content: "\f140";
}
.ui-icon-ellipsis-h::before {
content: "\f141";
}
.ui-icon-ellipsis-v::before {
content: "\f142";
}
.ui-icon-rss-square::before {
content: "\f143";
}
.ui-icon-play-circle::before {
content: "\f144";
}
.ui-icon-ticket::before {
content: "\f145";
}
.ui-icon-minus-square::before {
content: "\f146";
}
.ui-icon-minus-square-o::before {
content: "\f147";
}
.ui-icon-level-up::before {
content: "\f148";
}
.ui-icon-level-down::before {
content: "\f149";
}
.ui-icon-check-square::before {
content: "\f14a";
}
.ui-icon-pencil-square::before {
content: "\f14b";
}
.ui-icon-external-link-square::before {
content: "\f14c";
}
.ui-icon-share-square::before {
content: "\f14d";
}
.ui-icon-compass::before {
content: "\f14e";
}
.ui-icon-toggle-down::before,
.ui-icon-caret-square-o-down::before {
content: "\f150";
}
.ui-icon-toggle-up::before,
.ui-icon-caret-square-o-up::before {
content: "\f151";
}
.ui-icon-toggle-right::before,
.ui-icon-caret-square-o-right::before {
content: "\f152";
}
.ui-icon-euro::before,
.ui-icon-eur::before {
content: "\f153";
}
.ui-icon-gbp::before {
content: "\f154";
}
.ui-icon-dollar::before,
.ui-icon-usd::before {
content: "\f155";
}
.ui-icon-rupee::before,
.ui-icon-inr::before {
content: "\f156";
}
.ui-icon-cny::before,
.ui-icon-rmb::before,
.ui-icon-yen::before,
.ui-icon-jpy::before {
content: "\f157";
}
.ui-icon-ruble::before,
.ui-icon-rouble::before,
.ui-icon-rub::before {
content: "\f158";
}
.ui-icon-won::before,
.ui-icon-krw::before {
content: "\f159";
}
.ui-icon-bitcoin::before,
.ui-icon-btc::before {
content: "\f15a";
}
.ui-icon-file::before {
content: "\f15b";
}
.ui-icon-file-text::before {
content: "\f15c";
}
.ui-icon-sort-alpha-asc::before {
content: "\f15d";
}
.ui-icon-sort-alpha-desc::before {
content: "\f15e";
}
.ui-icon-sort-amount-asc::before {
content: "\f160";
}
.ui-icon-sort-amount-desc::before {
content: "\f161";
}
.ui-icon-sort-numeric-asc::before {
content: "\f162";
}
.ui-icon-sort-numeric-desc::before {
content: "\f163";
}
.ui-icon-thumbs-up::before {
content: "\f164";
}
.ui-icon-thumbs-down::before {
content: "\f165";
}
.ui-icon-youtube-square::before {
content: "\f166";
}
.ui-icon-youtube::before {
content: "\f167";
}
.ui-icon-xing::before {
content: "\f168";
}
.ui-icon-xing-square::before {
content: "\f169";
}
.ui-icon-youtube-play::before {
content: "\f16a";
}
.ui-icon-dropbox::before {
content: "\f16b";
}
.ui-icon-stack-overflow::before {
content: "\f16c";
}
.ui-icon-instagram::before {
content: "\f16d";
}
.ui-icon-flickr::before {
content: "\f16e";
}
.ui-icon-adn::before {
content: "\f170";
}
.ui-icon-bitbucket::before {
content: "\f171";
}
.ui-icon-bitbucket-square::before {
content: "\f172";
}
.ui-icon-tumblr::before {
content: "\f173";
}
.ui-icon-tumblr-square::before {
content: "\f174";
}
.ui-icon-long-arrow-down::before {
content: "\f175";
}
.ui-icon-long-arrow-up::before {
content: "\f176";
}
.ui-icon-long-arrow-left::before {
content: "\f177";
}
.ui-icon-long-arrow-right::before {
content: "\f178";
}
.ui-icon-apple::before {
content: "\f179";
}
.ui-icon-windows::before {
content: "\f17a";
}
.ui-icon-android::before {
content: "\f17b";
}
.ui-icon-linux::before {
content: "\f17c";
}
.ui-icon-dribbble::before {
content: "\f17d";
}
.ui-icon-skype::before {
content: "\f17e";
}
.ui-icon-foursquare::before {
content: "\f180";
}
.ui-icon-trello::before {
content: "\f181";
}
.ui-icon-female::before {
content: "\f182";
}
.ui-icon-male::before {
content: "\f183";
}
.ui-icon-gittip::before {
content: "\f184";
}
.ui-icon-sun-o::before {
content: "\f185";
}
.ui-icon-moon-o::before {
content: "\f186";
}
.ui-icon-archive::before {
content: "\f187";
}
.ui-icon-bug::before {
content: "\f188";
}
.ui-icon-vk::before {
content: "\f189";
}
.ui-icon-weibo::before {
content: "\f18a";
}
.ui-icon-renren::before {
content: "\f18b";
}
.ui-icon-pagelines::before {
content: "\f18c";
}
.ui-icon-stack-exchange::before {
content: "\f18d";
}
.ui-icon-arrow-circle-o-right::before {
content: "\f18e";
}
.ui-icon-arrow-circle-o-left::before {
content: "\f190";
}
.ui-icon-toggle-left::before,
.ui-icon-caret-square-o-left::before {
content: "\f191";
}
.ui-icon-dot-circle-o::before {
content: "\f192";
}
.ui-icon-wheelchair::before {
content: "\f193";
}
.ui-icon-vimeo-square::before {
content: "\f194";
}
.ui-icon-turkish-lira::before,
.ui-icon-try::before {
content: "\f195";
}
.ui-icon-plus-square-o::before {
content: "\f196";
}
.ui-icon-space-shuttle::before {
content: "\f197";
}
.ui-icon-slack::before {
content: "\f198";
}
.ui-icon-envelope-square::before {
content: "\f199";
}
.ui-icon-wordpress::before {
content: "\f19a";
}
.ui-icon-openid::before {
content: "\f19b";
}
.ui-icon-institution::before,
.ui-icon-bank::before,
.ui-icon-university::before {
content: "\f19c";
}
.ui-icon-mortar-board::before,
.ui-icon-graduation-cap::before {
content: "\f19d";
}
.ui-icon-yahoo::before {
content: "\f19e";
}
.ui-icon-google::before {
content: "\f1a0";
}
.ui-icon-reddit::before {
content: "\f1a1";
}
.ui-icon-reddit-square::before {
content: "\f1a2";
}
.ui-icon-stumbleupon-circle::before {
content: "\f1a3";
}
.ui-icon-stumbleupon::before {
content: "\f1a4";
}
.ui-icon-delicious::before {
content: "\f1a5";
}
.ui-icon-digg::before {
content: "\f1a6";
}
.ui-icon-pied-piper-square::before,
.ui-icon-pied-piper::before {
content: "\f1a7";
}
.ui-icon-pied-piper-alt::before {
content: "\f1a8";
}
.ui-icon-drupal::before {
content: "\f1a9";
}
.ui-icon-joomla::before {
content: "\f1aa";
}
.ui-icon-language::before {
content: "\f1ab";
}
.ui-icon-fax::before {
content: "\f1ac";
}
.ui-icon-building::before {
content: "\f1ad";
}
.ui-icon-child::before {
content: "\f1ae";
}
.ui-icon-paw::before {
content: "\f1b0";
}
.ui-icon-spoon::before {
content: "\f1b1";
}
.ui-icon-cube::before {
content: "\f1b2";
}
.ui-icon-cubes::before {
content: "\f1b3";
}
.ui-icon-behance::before {
content: "\f1b4";
}
.ui-icon-behance-square::before {
content: "\f1b5";
}
.ui-icon-steam::before {
content: "\f1b6";
}
.ui-icon-steam-square::before {
content: "\f1b7";
}
.ui-icon-recycle::before {
content: "\f1b8";
}
.ui-icon-automobile::before,
.ui-icon-car::before {
content: "\f1b9";
}
.ui-icon-cab::before,
.ui-icon-taxi::before {
content: "\f1ba";
}
.ui-icon-tree::before {
content: "\f1bb";
}
.ui-icon-spotify::before {
content: "\f1bc";
}
.ui-icon-deviantart::before {
content: "\f1bd";
}
.ui-icon-soundcloud::before {
content: "\f1be";
}
.ui-icon-database::before {
content: "\f1c0";
}
.ui-icon-file-pdf-o::before {
content: "\f1c1";
}
.ui-icon-file-word-o::before {
content: "\f1c2";
}
.ui-icon-file-excel-o::before {
content: "\f1c3";
}
.ui-icon-file-powerpoint-o::before {
content: "\f1c4";
}
.ui-icon-file-photo-o::before,
.ui-icon-file-picture-o::before,
.ui-icon-file-image-o::before {
content: "\f1c5";
}
.ui-icon-file-zip-o::before,
.ui-icon-file-archive-o::before {
content: "\f1c6";
}
.ui-icon-file-sound-o::before,
.ui-icon-file-audio-o::before {
content: "\f1c7";
}
.ui-icon-file-movie-o::before,
.ui-icon-file-video-o::before {
content: "\f1c8";
}
.ui-icon-file-code-o::before {
content: "\f1c9";
}
.ui-icon-vine::before {
content: "\f1ca";
}
.ui-icon-codepen::before {
content: "\f1cb";
}
.ui-icon-jsfiddle::before {
content: "\f1cc";
}
.ui-icon-life-bouy::before,
.ui-icon-life-saver::before,
.ui-icon-support::before,
.ui-icon-life-ring::before {
content: "\f1cd";
}
.ui-icon-circle-o-notch::before {
content: "\f1ce";
}
.ui-icon-ra::before,
.ui-icon-rebel::before {
content: "\f1d0";
}
.ui-icon-ge::before,
.ui-icon-empire::before {
content: "\f1d1";
}
.ui-icon-git-square::before {
content: "\f1d2";
}
.ui-icon-git::before {
content: "\f1d3";
}
.ui-icon-hacker-news::before {
content: "\f1d4";
}
.ui-icon-tencent-weibo::before {
content: "\f1d5";
}
.ui-icon-qq::before {
content: "\f1d6";
}
.ui-icon-wechat::before,
.ui-icon-weixin::before {
content: "\f1d7";
}
.ui-icon-send::before,
.ui-icon-paper-plane::before {
content: "\f1d8";
}
.ui-icon-send-o::before,
.ui-icon-paper-plane-o::before {
content: "\f1d9";
}
.ui-icon-history::before {
content: "\f1da";
}
.ui-icon-circle-thin::before {
content: "\f1db";
}
.ui-icon-header::before {
content: "\f1dc";
}
.ui-icon-paragraph::before {
content: "\f1dd";
}
.ui-icon-sliders::before {
content: "\f1de";
}
.ui-icon-share-alt::before {
content: "\f1e0";
}
.ui-icon-share-alt-square::before {
content: "\f1e1";
}
.ui-icon-bomb::before {
content: "\f1e2";
}
/*global window, RSVP, FileReader */
/*jslint indent: 2, maxerr: 3, unparam: true */
(function (window, RSVP, FileReader) {
"use strict";
window.loopEventListener = function (target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
};
window.promiseEventListener = function (target, type, useCapture) {
//////////////////////////
// Resolve the promise as soon as the event is triggered
// eventListener is removed when promise is cancelled/resolved/rejected
//////////////////////////
var handle_event_callback;
function canceller() {
target.removeEventListener(type, handle_event_callback, useCapture);
}
function resolver(resolve) {
handle_event_callback = function (evt) {
canceller();
evt.stopPropagation();
evt.preventDefault();
resolve(evt);
return false;
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(resolver, canceller);
};
window.promiseReadAsText = function (file) {
return new RSVP.Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function (evt) {
resolve(evt.target.result);
};
reader.onerror = function (evt) {
reject(evt);
};
reader.readAsText(file);
});
};
window.promiseDoWhile = function (loopFunction, input) {
// calls loopFunction(input) until it returns a non positive value
// this queue is to protect the inner loop queue from the
// `promiseDoWhile` caller, avoiding it to enqueue the inner
// loop queue.
return new RSVP.Queue()
.push(function () {
// here is the inner loop queue
var loop_queue = new RSVP.Queue();
function iterate(previous_iteration_result) {
if (!previous_iteration_result) {
return input;
}
loop_queue.push(iterate);
return loopFunction(input);
}
return loop_queue
.push(function () {
return loopFunction(input);
})
.push(iterate);
});
};
}(window, RSVP, FileReader));
\ No newline at end of file
/*globals window, RSVP, rJS, loopEventListener, URL, document
FileReader, console, navigator, jIO */
/*jslint indent: 2, nomen: true, maxlen: 80*/
(function (window, navigator, RSVP, rJS, jIO, URL) {
"use strict";
var origin_url = (window.location.origin + window.location.pathname)
.replace("officejs_fs2erp5_gadget/", "");
// application_list = [
// "officejs_fs2erp5_gadget",
//
// ];
function exportZip(gadget, event) {
var j,
zip_name,
// i = 0,
form_result = {},
len = event.target.length,
app_url;
for (j = 0; j < len; j += 1) {
form_result[event.target[j].name] = event.target[j].value;
}
app_url = origin_url + form_result.web_site + '/';
// len = 0;
zip_name = form_result.filename;
// function fill(zip_file) {
// if (i < len) {
// var sub_app = app.sub_gadget[i];
// return gadget.fillZip({
// cache: "erp5_/index.appcache",
// site_url: origin_url + app.url,
// zip_file: zip_file,
// prefix: sub_app + "/",
// take_installer: false
// })
// .push(function (zip_file) {
// i += 1;
// return fill(zip_file);
// });
// }
// return zip_file;
// }
//
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
type: "GET",
dataType: "json",
url: app_url + "erp5_/erp5.json"
});
})
.push(function (response) {
gadget.props.erp5_options = response.target.response;
})
.push(function () {
return gadget.fillZip({
cache: "erp5_/index.appcache",
site_url: app_url,
take_installer: false
});
})
// .push(function (zip_file) {
// return fill(zip_file);
// })
.push(function (zip_file) {
var element = gadget.props.element,
a = document.createElement("a"),
url = URL.createObjectURL(zip_file),
default_name = gadget.props.erp5_options.name
.replace(' ', '_');
element.appendChild(a);
a.style = "display: none";
a.href = url;
a.download = zip_name ? zip_name : default_name + ".zip";
a.click();
element.removeChild(a);
URL.revokeObjectURL(url);
});
}
rJS(window)
.ready(function (g) {
g.props = {};
return g.getElement()
.push(function (element) {
g.props.element = element;
});
})
.declareMethod("fillZip", function (options) {
var gadget = this,
file_storage = jIO.createJIO({
type: "replicate",
conflict_handling: 2,
check_remote_attachment_creation: true,
check_local_creation: false,
check_local_modification: false,
check_local_deletion: false,
check_remote_deletion: false,
check_remote_modification: false,
remote_sub_storage: {
type: "fs2erp5",
document: options.site_url,
sub_storage: {
type: "appcache",
take_installer: options.take_installer,
manifest: options.cache,
origin_url: options.site_url,
prefix: options.prefix || ""
}
},
signature_sub_storage: {
type: "query",
sub_storage: {
type: "memory"
}
},
local_sub_storage: {
type: "zipfile",
file: options.zip_file
}
});
return file_storage.repair()
.push(function () {
return file_storage.getAttachment('/', '/');
});
})
/////////////////////////////////////////
// Form submit
/////////////////////////////////////////
.declareService(function () {
var gadget = this;
return new RSVP.Queue()
.push(function () {
return loopEventListener(
gadget.props.element.querySelector('form.export-form'),
'submit',
true,
function (event) {
return exportZip(gadget, event);
}
);
});
});
}(window, navigator, RSVP, rJS, jIO, URL));
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Erp5 bt export gadget</title>
<link rel="stylesheet" href="gadget_erp5_nojqm.css">
<script src="rsvp.js"></script>
<script src="renderjs.js"></script>
<script src="jiodev.js"></script>
<script src="gadget_global.js"></script>
<script src="gadget_officejs_page_export2erp5.js"></script>
<script src="zipfilestorage-with-jszip.js"></script>
<script src="jio_fs2erp5storage.js"></script>
<script src="jio_appcachestorage.js"></script>
</head>
<body>
<article class="ui-content ui-body-c">
<section class="ui-content-header-plain">
<h3 class="ui-content-title ui-body-c">
<span class="ui-icon ui-icon-custom ui-icon-database">&nbsp;</span>
Export
</h3>
</section>
<section class="ui-body-c ui-content-section">
<form class="export-form">
<div class="ui-form">
<div class="ui-field-contain">
<label data-i18n="Site:">Site:</label>
<select name="web_site">
<option>officejs_fs2erp5_gadget</option>
<option>web-apps</option>
<option>sdkjs</option>
</select>
</div>
</div>
<div class="ui-form">
<div class="ui-field-contain">
<label data-i18n="File Name:">File Name:</label>
<input name="filename"/>
</div>
</div>
<div class="select-storage ui-controlgroup ui-controlgroup-horizontal">
<div class="ui-grid-b ui-responsive">
<div class="ui-block-a"></div>
<div class="ui-block-b"></div>
<div class="ui-block-c">
<button type="submit" data-i18n="Export" class="ui-btn-btn-right">Export</button>
</div>
</div>
</div>
</form>
</section>
</article>
<div id="global_setting_gadget" style="display: none;"></div>
</body>
</html>
\ No newline at end of file
/*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO, RSVP, window, console, Blob */
(function (window, jIO, RSVP, console, Blob) {
"use strict";
function AppCacheStorage(spec) {
this._manifest = spec.manifest;
this._take_installer = spec.take_installer || false;
this._origin_url = spec.origin_url !== undefined ? spec.origin_url :
(window.location.origin + window.location.pathname +
(window.location.pathname.endsWith('/') ? '' : '/') +
((spec.version !== undefined) ?
(spec.version + (spec.version.endsWith('/') ? '' : '/')) : ""));
this._prefix = spec.prefix || "";
this._relative_url_list = ["/", this._prefix + spec.manifest];
if (this._take_installer) {
this._relative_url_list = [
this._prefix || "/",
this._prefix + "development/" + spec.manifest,
this._prefix + "development/",
this._prefix + "gadget_officejs_bootloader.js",
this._prefix + "gadget_officejs_bootloader.appcache",
this._prefix + "gadget_officejs_bootloader_presentation.html",
this._prefix + "gadget_officejs_bootloader_presentation.js",
this._prefix + "gadget_officejs_bootloader_presentation.css",
this._prefix + "gadget_officejs_bootloader_serviceworker.js",
this._prefix + "gadget_erp5_nojqm.css",
this._prefix + "jio_appcachestorage.js"
];
}
}
AppCacheStorage.prototype.get = function (id) {
return {};
};
AppCacheStorage.prototype.hasCapacity = function (name) {
return (name === "list");
};
AppCacheStorage.prototype.getAttachment = function (doc_id, attachment_id) {
var storage = this, url = attachment_id;
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
type: "GET",
url: ((url.startsWith("http") || url.startsWith("//")) ?
url : storage._origin_url) + url,
dataType: "blob"
});
})
.push(function (result) {
return result.target.response;
});
};
AppCacheStorage.prototype.allAttachments = function (url) {
var result = {}, i, len = this._relative_url_list.length;
for (i = 0; i < len; i += 1) {
result[this._relative_url_list[i]] = {};
}
return result;
};
AppCacheStorage.prototype.buildQuery = function (options) {
return [{id: "/", doc: {}, value: {}}];
};
AppCacheStorage.prototype.repair = function () {
var storage = this,
prefix = storage._prefix +
(storage._take_installer ? "development/" : "");
return new RSVP.Queue()
.push(function () {
return jIO.util.ajax({
type: "GET",
url: storage._origin_url + storage._prefix + storage._manifest
});
})
.push(function (response) {
var text = response.target.responseText,
relative_url_list = text.split('\r\n'),
i,
take = false;
if (relative_url_list.length === 1) {
relative_url_list = text.split('\n');
}
if (relative_url_list.length === 1) {
relative_url_list = text.split('\r');
}
for (i = 0; i < relative_url_list.length; i += 1) {
if (relative_url_list[i].indexOf("NETWORK:") >= 0) {
take = false;
}
if (take &&
relative_url_list[i] !== "" &&
relative_url_list[i].charAt(0) !== '#' &&
relative_url_list[i].charAt(0) !== ' ') {
relative_url_list[i].replace("\r", "");
storage._relative_url_list.push(prefix + relative_url_list[i]);
}
if (relative_url_list[i].indexOf("CACHE:") >= 0) {
take = true;
}
}
});
};
jIO.addStorage('appcache', AppCacheStorage);
}(window, jIO, RSVP, console, Blob));
\ No newline at end of file
/*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO, RSVP, window, console, Blob */
(function (window, jIO, RSVP, console, Blob) {
"use strict";
function Fs2Erp5Storage(spec) {
this._document = spec.document;
this._sub_storage = jIO.createJIO(spec.sub_storage);
this._id_dict = {};
this._paths = {};
}
Fs2Erp5Storage.prototype.get = function (url) {
return {};
};
Fs2Erp5Storage.prototype.hasCapacity = function (name) {
return (name === "list");
};
Fs2Erp5Storage.prototype.getAttachment = function (doc_id, attachment_id) {
// doc_id + ((attachment_id === "index.html") ?
// (doc_id.endsWith("imagelib/") ? "index.html" : "") : attachment_id)
return this._sub_storage.getAttachment(
this._document, this._id_dict[doc_id][attachment_id]
);
};
Fs2Erp5Storage.prototype.allAttachments = function (doc_id) {
return this._id_dict[doc_id] || {};
};
Fs2Erp5Storage.prototype.buildQuery = function (options) {
var id, result = [], context = this;
for (id in context._id_dict) {
if (context._id_dict.hasOwnProperty(id)) {
result.push({id: id});
}
}
return result;
};
Fs2Erp5Storage.prototype.repair = function () {
// Transform id attachment ( file path ) to id list / attachments
var context = this;
return context._sub_storage.repair()
.push(function () {
return jIO.util.ajax({
type: "GET",
dataType: "json",
url: context._document + "erp5_/erp5.json"
});
})
.push(function (response) {
var scopes, i, x, scope;
context._options = response.target.response;
scopes = context._options.scopes;
for (i = 0; i < scopes.length; i += 1) {
scope = scopes[i];
for (x = 0; x < scope.paths.length; x += 1) {
context._paths[scope.paths[x]] = scope;
}
}
})
.push(function () {
return context._sub_storage.allAttachments(context._document);
})
.push(function (result) {
var id, path, last_index, filename, filename_xml, ext, new_id, i;
for (id in result) {
if (result.hasOwnProperty(id) && !id.startsWith("http")) {
last_index = id.lastIndexOf("/") + 1;
if (last_index === id.length) {
path = id || "/";
filename = "index.html";
} else {
path = id.substring(0, last_index);
filename = id.substring(last_index);
}
new_id = path + filename;
ext = filename.substring(filename.lastIndexOf('.') + 1);
switch (ext) {
case "js":
path = "/PathTemplateItem/web_page_module/";
break;
case "ttf":
path = "/PathTemplateItem/document_module/";
ext = "bin";
break;
default:
continue;
}
for (i in context._paths) {
if (new_id.startsWith(i)) {
if (context._paths[i].prefix) {
new_id = context._paths[i].prefix + "/" + new_id;
}
}
}
filename = new_id.split("/").join("_").split(".").join("_") + '.' + ext;
filename_xml = new_id.split("/").join("_").split(".").join("_") + '.xml';
if (!context._id_dict.hasOwnProperty(path)) {
context._id_dict[path] = {};
}
context._id_dict[path][filename] = id;
context._id_dict[path][filename_xml] = id;
}
}
});
};
jIO.addStorage('fs2erp5', Fs2Erp5Storage);
}(window, jIO, RSVP, console, Blob));
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* js_channel is a very lightweight abstraction on top of
* postMessage which defines message formats and semantics
* to support interactions more rich than just message passing
* js_channel supports:
* + query/response - traditional rpc
* + query/update/response - incremental async return of results
* to a query
* + notifications - fire and forget
* + error handling
*
* js_channel is based heavily on json-rpc, but is focused at the
* problem of inter-iframe RPC.
*
* Message types:
* There are 5 types of messages that can flow over this channel,
* and you may determine what type of message an object is by
* examining its parameters:
* 1. Requests
* + integer id
* + string method
* + (optional) any params
* 2. Callback Invocations (or just "Callbacks")
* + integer id
* + string callback
* + (optional) params
* 3. Error Responses (or just "Errors)
* + integer id
* + string error
* + (optional) string message
* 4. Responses
* + integer id
* + (optional) any result
* 5. Notifications
* + string method
* + (optional) any params
*/
;var Channel = (function() {
"use strict";
// current transaction id, start out at a random *odd* number between 1 and a million
// There is one current transaction counter id per page, and it's shared between
// channel instances. That means of all messages posted from a single javascript
// evaluation context, we'll never have two with the same id.
var s_curTranId = Math.floor(Math.random()*1000001);
// no two bound channels in the same javascript evaluation context may have the same origin, scope, and window.
// futher if two bound channels have the same window and scope, they may not have *overlapping* origins
// (either one or both support '*'). This restriction allows a single onMessage handler to efficiently
// route messages based on origin and scope. The s_boundChans maps origins to scopes, to message
// handlers. Request and Notification messages are routed using this table.
// Finally, channels are inserted into this table when built, and removed when destroyed.
var s_boundChans = { };
// add a channel to s_boundChans, throwing if a dup exists
function s_addBoundChan(win, origin, scope, handler) {
function hasWin(arr) {
for (var i = 0; i < arr.length; i++) if (arr[i].win === win) return true;
return false;
}
// does she exist?
var exists = false;
if (origin === '*') {
// we must check all other origins, sadly.
for (var k in s_boundChans) {
if (!s_boundChans.hasOwnProperty(k)) continue;
if (k === '*') continue;
if (typeof s_boundChans[k][scope] === 'object') {
exists = hasWin(s_boundChans[k][scope]);
if (exists) break;
}
}
} else {
// we must check only '*'
if ((s_boundChans['*'] && s_boundChans['*'][scope])) {
exists = hasWin(s_boundChans['*'][scope]);
}
if (!exists && s_boundChans[origin] && s_boundChans[origin][scope])
{
exists = hasWin(s_boundChans[origin][scope]);
}
}
if (exists) throw "A channel is already bound to the same window which overlaps with origin '"+ origin +"' and has scope '"+scope+"'";
if (typeof s_boundChans[origin] != 'object') s_boundChans[origin] = { };
if (typeof s_boundChans[origin][scope] != 'object') s_boundChans[origin][scope] = [ ];
s_boundChans[origin][scope].push({win: win, handler: handler});
}
function s_removeBoundChan(win, origin, scope) {
var arr = s_boundChans[origin][scope];
for (var i = 0; i < arr.length; i++) {
if (arr[i].win === win) {
arr.splice(i,1);
}
}
if (s_boundChans[origin][scope].length === 0) {
delete s_boundChans[origin][scope];
}
}
function s_isArray(obj) {
if (Array.isArray) return Array.isArray(obj);
else {
return (obj.constructor.toString().indexOf("Array") != -1);
}
}
// No two outstanding outbound messages may have the same id, period. Given that, a single table
// mapping "transaction ids" to message handlers, allows efficient routing of Callback, Error, and
// Response messages. Entries are added to this table when requests are sent, and removed when
// responses are received.
var s_transIds = { };
// class singleton onMessage handler
// this function is registered once and all incoming messages route through here. This
// arrangement allows certain efficiencies, message data is only parsed once and dispatch
// is more efficient, especially for large numbers of simultaneous channels.
var s_onMessage = function(e) {
try {
var m = JSON.parse(e.data);
if (typeof m !== 'object' || m === null) throw "malformed";
} catch(e) {
// just ignore any posted messages that do not consist of valid JSON
return;
}
var w = e.source;
var o = e.origin;
var s, i, meth;
if (typeof m.method === 'string') {
var ar = m.method.split('::');
if (ar.length == 2) {
s = ar[0];
meth = ar[1];
} else {
meth = m.method;
}
}
if (typeof m.id !== 'undefined') i = m.id;
// w is message source window
// o is message origin
// m is parsed message
// s is message scope
// i is message id (or undefined)
// meth is unscoped method name
// ^^ based on these factors we can route the message
// if it has a method it's either a notification or a request,
// route using s_boundChans
if (typeof meth === 'string') {
var delivered = false;
if (s_boundChans[o] && s_boundChans[o][s]) {
for (var j = 0; j < s_boundChans[o][s].length; j++) {
if (s_boundChans[o][s][j].win === w) {
s_boundChans[o][s][j].handler(o, meth, m);
delivered = true;
break;
}
}
}
if (!delivered && s_boundChans['*'] && s_boundChans['*'][s]) {
for (var j = 0; j < s_boundChans['*'][s].length; j++) {
if (s_boundChans['*'][s][j].win === w) {
s_boundChans['*'][s][j].handler(o, meth, m);
break;
}
}
}
}
// otherwise it must have an id (or be poorly formed
else if (typeof i != 'undefined') {
if (s_transIds[i]) s_transIds[i](o, meth, m);
}
};
// Setup postMessage event listeners
if (window.addEventListener) window.addEventListener('message', s_onMessage, false);
else if(window.attachEvent) window.attachEvent('onmessage', s_onMessage);
/* a messaging channel is constructed from a window and an origin.
* the channel will assert that all messages received over the
* channel match the origin
*
* Arguments to Channel.build(cfg):
*
* cfg.window - the remote window with which we'll communicate
* cfg.origin - the expected origin of the remote window, may be '*'
* which matches any origin
* cfg.scope - the 'scope' of messages. a scope string that is
* prepended to message names. local and remote endpoints
* of a single channel must agree upon scope. Scope may
* not contain double colons ('::').
* cfg.debugOutput - A boolean value. If true and window.console.log is
* a function, then debug strings will be emitted to that
* function.
* cfg.debugOutput - A boolean value. If true and window.console.log is
* a function, then debug strings will be emitted to that
* function.
* cfg.postMessageObserver - A function that will be passed two arguments,
* an origin and a message. It will be passed these immediately
* before messages are posted.
* cfg.gotMessageObserver - A function that will be passed two arguments,
* an origin and a message. It will be passed these arguments
* immediately after they pass scope and origin checks, but before
* they are processed.
* cfg.onReady - A function that will be invoked when a channel becomes "ready",
* this occurs once both sides of the channel have been
* instantiated and an application level handshake is exchanged.
* the onReady function will be passed a single argument which is
* the channel object that was returned from build().
*/
return {
build: function(cfg) {
var debug = function(m) {
if (cfg.debugOutput && window.console && window.console.log) {
// try to stringify, if it doesn't work we'll let javascript's built in toString do its magic
try { if (typeof m !== 'string') m = JSON.stringify(m); } catch(e) { }
console.log("["+chanId+"] " + m);
}
};
/* browser capabilities check */
if (!window.postMessage) throw("jschannel cannot run this browser, no postMessage");
if (!window.JSON || !window.JSON.stringify || ! window.JSON.parse) {
throw("jschannel cannot run this browser, no JSON parsing/serialization");
}
/* basic argument validation */
if (typeof cfg != 'object') throw("Channel build invoked without a proper object argument");
if (!cfg.window || !cfg.window.postMessage) throw("Channel.build() called without a valid window argument");
/* we'd have to do a little more work to be able to run multiple channels that intercommunicate the same
* window... Not sure if we care to support that */
if (window === cfg.window) throw("target window is same as present window -- not allowed");
// let's require that the client specify an origin. if we just assume '*' we'll be
// propagating unsafe practices. that would be lame.
var validOrigin = false;
if (typeof cfg.origin === 'string') {
var oMatch;
if (cfg.origin === "*") validOrigin = true;
// allow valid domains under http and https. Also, trim paths off otherwise valid origins.
else if (null !== (oMatch = cfg.origin.match(/^https?:\/\/(?:[-a-zA-Z0-9_\.])+(?::\d+)?/))) {
cfg.origin = oMatch[0].toLowerCase();
validOrigin = true;
}
}
if (!validOrigin) throw ("Channel.build() called with an invalid origin");
if (typeof cfg.scope !== 'undefined') {
if (typeof cfg.scope !== 'string') throw 'scope, when specified, must be a string';
if (cfg.scope.split('::').length > 1) throw "scope may not contain double colons: '::'";
}
/* private variables */
// generate a random and psuedo unique id for this channel
var chanId = (function () {
var text = "";
var alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for(var i=0; i < 5; i++) text += alpha.charAt(Math.floor(Math.random() * alpha.length));
return text;
})();
// registrations: mapping method names to call objects
var regTbl = { };
// current oustanding sent requests
var outTbl = { };
// current oustanding received requests
var inTbl = { };
// are we ready yet? when false we will block outbound messages.
var ready = false;
var pendingQueue = [ ];
var createTransaction = function(id,origin,callbacks) {
var shouldDelayReturn = false;
var completed = false;
return {
origin: origin,
invoke: function(cbName, v) {
// verify in table
if (!inTbl[id]) throw "attempting to invoke a callback of a nonexistent transaction: " + id;
// verify that the callback name is valid
var valid = false;
for (var i = 0; i < callbacks.length; i++) if (cbName === callbacks[i]) { valid = true; break; }
if (!valid) throw "request supports no such callback '" + cbName + "'";
// send callback invocation
postMessage({ id: id, callback: cbName, params: v});
},
error: function(error, message) {
completed = true;
// verify in table
if (!inTbl[id]) throw "error called for nonexistent message: " + id;
// remove transaction from table
delete inTbl[id];
// send error
postMessage({ id: id, error: error, message: message });
},
complete: function(v) {
completed = true;
// verify in table
if (!inTbl[id]) throw "complete called for nonexistent message: " + id;
// remove transaction from table
delete inTbl[id];
// send complete
postMessage({ id: id, result: v });
},
delayReturn: function(delay) {
if (typeof delay === 'boolean') {
shouldDelayReturn = (delay === true);
}
return shouldDelayReturn;
},
completed: function() {
return completed;
}
};
};
var setTransactionTimeout = function(transId, timeout, method) {
return window.setTimeout(function() {
if (outTbl[transId]) {
// XXX: what if client code raises an exception here?
var msg = "timeout (" + timeout + "ms) exceeded on method '" + method + "'";
(1,outTbl[transId].error)("timeout_error", msg);
delete outTbl[transId];
delete s_transIds[transId];
}
}, timeout);
};
var onMessage = function(origin, method, m) {
// if an observer was specified at allocation time, invoke it
if (typeof cfg.gotMessageObserver === 'function') {
// pass observer a clone of the object so that our
// manipulations are not visible (i.e. method unscoping).
// This is not particularly efficient, but then we expect
// that message observers are primarily for debugging anyway.
try {
cfg.gotMessageObserver(origin, m);
} catch (e) {
debug("gotMessageObserver() raised an exception: " + e.toString());
}
}
// now, what type of message is this?
if (m.id && method) {
// a request! do we have a registered handler for this request?
if (regTbl[method]) {
var trans = createTransaction(m.id, origin, m.callbacks ? m.callbacks : [ ]);
inTbl[m.id] = { };
try {
// callback handling. we'll magically create functions inside the parameter list for each
// callback
if (m.callbacks && s_isArray(m.callbacks) && m.callbacks.length > 0) {
for (var i = 0; i < m.callbacks.length; i++) {
var path = m.callbacks[i];
var obj = m.params;
var pathItems = path.split('/');
for (var j = 0; j < pathItems.length - 1; j++) {
var cp = pathItems[j];
if (typeof obj[cp] !== 'object') obj[cp] = { };
obj = obj[cp];
}
obj[pathItems[pathItems.length - 1]] = (function() {
var cbName = path;
return function(params) {
return trans.invoke(cbName, params);
};
})();
}
}
var resp = regTbl[method](trans, m.params);
if (!trans.delayReturn() && !trans.completed()) trans.complete(resp);
} catch(e) {
// automagic handling of exceptions:
var error = "runtime_error";
var message = null;
// * if it's a string then it gets an error code of 'runtime_error' and string is the message
if (typeof e === 'string') {
message = e;
} else if (typeof e === 'object') {
// either an array or an object
// * if it's an array of length two, then array[0] is the code, array[1] is the error message
if (e && s_isArray(e) && e.length == 2) {
error = e[0];
message = e[1];
}
// * if it's an object then we'll look form error and message parameters
else if (typeof e.error === 'string') {
error = e.error;
if (!e.message) message = "";
else if (typeof e.message === 'string') message = e.message;
else e = e.message; // let the stringify/toString message give us a reasonable verbose error string
}
}
// message is *still* null, let's try harder
if (message === null) {
try {
message = JSON.stringify(e);
/* On MSIE8, this can result in 'out of memory', which
* leaves message undefined. */
if (typeof(message) == 'undefined')
message = e.toString();
} catch (e2) {
message = e.toString();
}
}
trans.error(error,message);
}
}
} else if (m.id && m.callback) {
if (!outTbl[m.id] ||!outTbl[m.id].callbacks || !outTbl[m.id].callbacks[m.callback])
{
debug("ignoring invalid callback, id:"+m.id+ " (" + m.callback +")");
} else {
// XXX: what if client code raises an exception here?
outTbl[m.id].callbacks[m.callback](m.params);
}
} else if (m.id) {
if (!outTbl[m.id]) {
debug("ignoring invalid response: " + m.id);
} else {
// XXX: what if client code raises an exception here?
if (m.error) {
(1,outTbl[m.id].error)(m.error, m.message);
} else {
if (m.result !== undefined) (1,outTbl[m.id].success)(m.result);
else (1,outTbl[m.id].success)();
}
delete outTbl[m.id];
delete s_transIds[m.id];
}
} else if (method) {
// tis a notification.
if (regTbl[method]) {
// yep, there's a handler for that.
// transaction has only origin for notifications.
regTbl[method]({ origin: origin }, m.params);
// if the client throws, we'll just let it bubble out
// what can we do? Also, here we'll ignore return values
}
}
};
// now register our bound channel for msg routing
s_addBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === 'string') ? cfg.scope : ''), onMessage);
// scope method names based on cfg.scope specified when the Channel was instantiated
var scopeMethod = function(m) {
if (typeof cfg.scope === 'string' && cfg.scope.length) m = [cfg.scope, m].join("::");
return m;
};
// a small wrapper around postmessage whose primary function is to handle the
// case that clients start sending messages before the other end is "ready"
var postMessage = function(msg, force) {
if (!msg) throw "postMessage called with null message";
// delay posting if we're not ready yet.
var verb = (ready ? "post " : "queue ");
debug(verb + " message: " + JSON.stringify(msg));
if (!force && !ready) {
pendingQueue.push(msg);
} else {
if (typeof cfg.postMessageObserver === 'function') {
try {
cfg.postMessageObserver(cfg.origin, msg);
} catch (e) {
debug("postMessageObserver() raised an exception: " + e.toString());
}
}
cfg.window.postMessage(JSON.stringify(msg), cfg.origin);
}
};
var onReady = function(trans, type) {
debug('ready msg received');
if (ready) throw "received ready message while in ready state. help!";
if (type === 'ping') {
chanId += '-R';
} else {
chanId += '-L';
}
obj.unbind('__ready'); // now this handler isn't needed any more.
ready = true;
debug('ready msg accepted.');
if (type === 'ping') {
obj.notify({ method: '__ready', params: 'pong' });
}
// flush queue
while (pendingQueue.length) {
postMessage(pendingQueue.pop());
}
// invoke onReady observer if provided
if (typeof cfg.onReady === 'function') cfg.onReady(obj);
};
var obj = {
// tries to unbind a bound message handler. returns false if not possible
unbind: function (method) {
if (regTbl[method]) {
if (!(delete regTbl[method])) throw ("can't delete method: " + method);
return true;
}
return false;
},
bind: function (method, cb) {
if (!method || typeof method !== 'string') throw "'method' argument to bind must be string";
if (!cb || typeof cb !== 'function') throw "callback missing from bind params";
if (regTbl[method]) throw "method '"+method+"' is already bound!";
regTbl[method] = cb;
return this;
},
call: function(m) {
if (!m) throw 'missing arguments to call function';
if (!m.method || typeof m.method !== 'string') throw "'method' argument to call must be string";
if (!m.success || typeof m.success !== 'function') throw "'success' callback missing from call";
// now it's time to support the 'callback' feature of jschannel. We'll traverse the argument
// object and pick out all of the functions that were passed as arguments.
var callbacks = { };
var callbackNames = [ ];
var pruneFunctions = function (path, obj) {
if (typeof obj === 'object') {
for (var k in obj) {
if (!obj.hasOwnProperty(k)) continue;
var np = path + (path.length ? '/' : '') + k;
if (typeof obj[k] === 'function') {
callbacks[np] = obj[k];
callbackNames.push(np);
delete obj[k];
} else if (typeof obj[k] === 'object') {
pruneFunctions(np, obj[k]);
}
}
}
};
pruneFunctions("", m.params);
// build a 'request' message and send it
var msg = { id: s_curTranId, method: scopeMethod(m.method), params: m.params };
if (callbackNames.length) msg.callbacks = callbackNames;
if (m.timeout)
// XXX: This function returns a timeout ID, but we don't do anything with it.
// We might want to keep track of it so we can cancel it using clearTimeout()
// when the transaction completes.
setTransactionTimeout(s_curTranId, m.timeout, scopeMethod(m.method));
// insert into the transaction table
outTbl[s_curTranId] = { callbacks: callbacks, error: m.error, success: m.success };
s_transIds[s_curTranId] = onMessage;
// increment current id
s_curTranId++;
postMessage(msg);
},
notify: function(m) {
if (!m) throw 'missing arguments to notify function';
if (!m.method || typeof m.method !== 'string') throw "'method' argument to notify must be string";
// no need to go into any transaction table
postMessage({ method: scopeMethod(m.method), params: m.params });
},
destroy: function () {
s_removeBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === 'string') ? cfg.scope : ''));
if (window.removeEventListener) window.removeEventListener('message', onMessage, false);
else if(window.detachEvent) window.detachEvent('onmessage', onMessage);
ready = false;
regTbl = { };
inTbl = { };
outTbl = { };
cfg.origin = null;
pendingQueue = [ ];
debug("channel destroyed");
chanId = "";
}
};
obj.bind('__ready', onReady);
setTimeout(function() {
postMessage({ method: scopeMethod('__ready'), params: "ping" }, true);
}, 0);
return obj;
}
};
})();
;/*
* DOMParser HTML extension
* 2012-09-04
*
* By Eli Grey, http://eligrey.com
* Public domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/
/*! @source https://gist.github.com/1129031 */
(function (DOMParser) {
"use strict";
var DOMParser_proto = DOMParser.prototype,
real_parseFromString = DOMParser_proto.parseFromString;
// Firefox/Opera/IE throw errors on unsupported types
try {
// WebKit returns null on unsupported types
if ((new DOMParser()).parseFromString("", "text/html")) {
// text/html parsing is natively supported
return;
}
} catch (ignore) {}
DOMParser_proto.parseFromString = function (markup, type) {
var result, doc, doc_elt, first_elt;
if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
doc = document.implementation.createHTMLDocument("");
doc_elt = doc.documentElement;
doc_elt.innerHTML = markup;
first_elt = doc_elt.firstElementChild;
if (doc_elt.childElementCount === 1
&& first_elt.localName.toLowerCase() === "html") {
doc.replaceChild(first_elt, doc_elt);
}
result = doc;
} else {
result = real_parseFromString.apply(this, arguments);
}
return result;
};
}(DOMParser));
;// IE does not support have Document.prototype.contains.
if (typeof document.contains !== 'function') {
Document.prototype.contains = function(node) {
if (node === this || node.parentNode === this)
return true;
return this.documentElement.contains(node);
}
}
;/*! RenderJs */
/*jslint nomen: true*/
/*
* renderJs - Generic Gadget library renderer.
* http://www.renderjs.org/documentation
*/
(function (document, window, RSVP, DOMParser, Channel, MutationObserver,
Node, FileReader, Blob, navigator, Event, URL) {
"use strict";
function readBlobAsDataURL(blob) {
var fr = new FileReader();
return new RSVP.Promise(function (resolve, reject) {
fr.addEventListener("load", function (evt) {
resolve(evt.target.result);
});
fr.addEventListener("error", reject);
fr.readAsDataURL(blob);
}, function () {
fr.abort();
});
}
function loopEventListener(target, type, useCapture, callback,
prevent_default) {
//////////////////////////
// Infinite event listener (promise is never resolved)
// eventListener is removed when promise is cancelled/rejected
//////////////////////////
var handle_event_callback,
callback_promise;
if (prevent_default === undefined) {
prevent_default = true;
}
function cancelResolver() {
if ((callback_promise !== undefined) &&
(typeof callback_promise.cancel === "function")) {
callback_promise.cancel();
}
}
function canceller() {
if (handle_event_callback !== undefined) {
target.removeEventListener(type, handle_event_callback, useCapture);
}
cancelResolver();
}
function itsANonResolvableTrap(resolve, reject) {
var result;
handle_event_callback = function (evt) {
if (prevent_default) {
evt.stopPropagation();
evt.preventDefault();
}
cancelResolver();
try {
result = callback(evt);
} catch (e) {
result = RSVP.reject(e);
}
callback_promise = result;
new RSVP.Queue()
.push(function () {
return result;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
canceller();
reject(error);
}
});
};
target.addEventListener(type, handle_event_callback, useCapture);
}
return new RSVP.Promise(itsANonResolvableTrap, canceller);
}
function ajax(url) {
var xhr;
function resolver(resolve, reject) {
function handler() {
try {
if (xhr.readyState === 0) {
// UNSENT
reject(xhr);
} else if (xhr.readyState === 4) {
// DONE
if ((xhr.status < 200) || (xhr.status >= 300) ||
(!/^text\/html[;]?/.test(
xhr.getResponseHeader("Content-Type") || ""
))) {
reject(xhr);
} else {
resolve(xhr);
}
}
} catch (e) {
reject(e);
}
}
xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = handler;
xhr.setRequestHeader('Accept', 'text/html');
xhr.withCredentials = true;
xhr.send();
}
function canceller() {
if ((xhr !== undefined) && (xhr.readyState !== xhr.DONE)) {
xhr.abort();
}
}
return new RSVP.Promise(resolver, canceller);
}
var gadget_model_defer_dict = {},
javascript_registration_dict = {},
stylesheet_registration_dict = {},
gadget_loading_klass_list = [],
loading_klass_promise,
renderJS,
Monitor,
scope_increment = 0,
isAbsoluteOrDataURL = new RegExp('^(?:[a-z]+:)?//|data:', 'i'),
is_page_unloaded = false,
error_list = [];
window.addEventListener('error', function (error) {
error_list.push(error);
});
window.addEventListener('beforeunload', function () {
// XXX If another listener cancel the page unload,
// it will not restore renderJS crash report
is_page_unloaded = true;
});
/////////////////////////////////////////////////////////////////
// Helper functions
/////////////////////////////////////////////////////////////////
function removeHash(url) {
var index = url.indexOf('#');
if (index > 0) {
url = url.substring(0, index);
}
return url;
}
function letsCrash(e) {
var i,
body,
container,
paragraph,
link,
error;
if (is_page_unloaded) {
/*global console*/
console.info('-- Error dropped, as page is unloaded');
console.info(e);
return;
}
error_list.push(e);
// Add error handling stack
error_list.push(new Error('stopping renderJS'));
body = document.getElementsByTagName('body')[0];
while (body.firstChild) {
body.removeChild(body.firstChild);
}
container = document.createElement("section");
paragraph = document.createElement("h1");
paragraph.textContent = 'Unhandled Error';
container.appendChild(paragraph);
paragraph = document.createElement("p");
paragraph.textContent = 'Please report this error to the support team';
container.appendChild(paragraph);
paragraph = document.createElement("p");
paragraph.textContent = 'Location: ';
link = document.createElement("a");
link.href = link.textContent = window.location.toString();
paragraph.appendChild(link);
container.appendChild(paragraph);
paragraph = document.createElement("p");
paragraph.textContent = 'User-agent: ' + navigator.userAgent;
container.appendChild(paragraph);
paragraph = document.createElement("p");
paragraph.textContent = 'Date: ' + new Date(Date.now()).toISOString();
container.appendChild(paragraph);
body.appendChild(container);
for (i = 0; i < error_list.length; i += 1) {
error = error_list[i];
if (error instanceof Event) {
error = {
string: error.toString(),
message: error.message,
type: error.type,
target: error.target
};
if (error.target !== undefined) {
error_list.splice(i + 1, 0, error.target);
}
}
if (error instanceof XMLHttpRequest) {
error = {
message: error.toString(),
readyState: error.readyState,
status: error.status,
statusText: error.statusText,
response: error.response,
responseUrl: error.responseUrl,
response_headers: error.getAllResponseHeaders()
};
}
if (error.constructor === Array ||
error.constructor === String ||
error.constructor === Object) {
try {
error = JSON.stringify(error);
} catch (ignore) {
}
}
container = document.createElement("section");
paragraph = document.createElement("h2");
paragraph.textContent = error.message || error;
container.appendChild(paragraph);
if (error.fileName !== undefined) {
paragraph = document.createElement("p");
paragraph.textContent = 'File: ' +
error.fileName +
': ' + error.lineNumber;
container.appendChild(paragraph);
}
if (error.stack !== undefined) {
paragraph = document.createElement("pre");
paragraph.textContent = 'Stack: ' + error.stack;
container.appendChild(paragraph);
}
body.appendChild(container);
}
// XXX Do not crash the application if it fails
// Where to write the error?
/*global console*/
console.error(e.stack);
console.error(e);
}
/////////////////////////////////////////////////////////////////
// Service Monitor promise
/////////////////////////////////////////////////////////////////
function ResolvedMonitorError(message) {
this.name = "resolved";
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Default Message";
}
ResolvedMonitorError.prototype = new Error();
ResolvedMonitorError.prototype.constructor = ResolvedMonitorError;
Monitor = function () {
var monitor = this,
promise_list = [],
promise,
reject,
notify,
resolved;
if (!(this instanceof Monitor)) {
return new Monitor();
}
function canceller() {
var len = promise_list.length,
i;
for (i = 0; i < len; i += 1) {
promise_list[i].cancel();
}
// Clean it to speed up other canceller run
promise_list = [];
}
promise = new RSVP.Promise(function (done, fail, progress) {
reject = function (rejectedReason) {
if (resolved) {
return;
}
monitor.isRejected = true;
monitor.rejectedReason = rejectedReason;
resolved = true;
canceller();
return fail(rejectedReason);
};
notify = progress;
}, canceller);
monitor.cancel = function () {
if (resolved) {
return;
}
resolved = true;
promise.cancel();
promise.fail(function (rejectedReason) {
monitor.isRejected = true;
monitor.rejectedReason = rejectedReason;
});
};
monitor.then = function () {
return promise.then.apply(promise, arguments);
};
monitor.fail = function () {
return promise.fail.apply(promise, arguments);
};
monitor.monitor = function (promise_to_monitor) {
if (resolved) {
throw new ResolvedMonitorError();
}
var queue = new RSVP.Queue()
.push(function () {
return promise_to_monitor;
})
.push(function (fulfillmentValue) {
// Promise to monitor is fullfilled, remove it from the list
var len = promise_list.length,
sub_promise_to_monitor,
new_promise_list = [],
i;
for (i = 0; i < len; i += 1) {
sub_promise_to_monitor = promise_list[i];
if (!(sub_promise_to_monitor.isFulfilled ||
sub_promise_to_monitor.isRejected)) {
new_promise_list.push(sub_promise_to_monitor);
}
}
promise_list = new_promise_list;
}, function (rejectedReason) {
if (rejectedReason instanceof RSVP.CancellationError) {
if (!(promise_to_monitor.isFulfilled &&
promise_to_monitor.isRejected)) {
// The queue could be cancelled before the first push is run
promise_to_monitor.cancel();
}
}
reject(rejectedReason);
throw rejectedReason;
}, function (notificationValue) {
notify(notificationValue);
return notificationValue;
});
promise_list.push(queue);
return this;
};
};
Monitor.prototype = Object.create(RSVP.Promise.prototype);
Monitor.prototype.constructor = Monitor;
/////////////////////////////////////////////////////////////////
// RenderJSGadget
/////////////////////////////////////////////////////////////////
function RenderJSGadget() {
if (!(this instanceof RenderJSGadget)) {
return new RenderJSGadget();
}
}
RenderJSGadget.prototype.__title = "";
RenderJSGadget.prototype.__interface_list = [];
RenderJSGadget.prototype.__path = "";
RenderJSGadget.prototype.__html = "";
RenderJSGadget.prototype.__required_css_list = [];
RenderJSGadget.prototype.__required_js_list = [];
function createMonitor(g) {
if (g.__monitor !== undefined) {
g.__monitor.cancel();
}
g.__monitor = new Monitor();
g.__job_dict = {};
g.__job_list = [];
g.__job_triggered = false;
g.__monitor.fail(function (error) {
if (!(error instanceof RSVP.CancellationError)) {
return g.aq_reportServiceError(error);
}
}).fail(function (error) {
// Crash the application if the acquisition generates an error.
return letsCrash(error);
});
}
function clearGadgetInternalParameters() {
this.__sub_gadget_dict = {};
createMonitor(this);
}
function loadSubGadgetDOMDeclaration() {
var element_list = this.element.querySelectorAll('[data-gadget-url]'),
element,
promise_list = [],
scope,
url,
sandbox,
i,
context = this;
function prepareReportGadgetDeclarationError(scope) {
return function (error) {
var aq_dict = context.__acquired_method_dict || {},
method_name = 'reportGadgetDeclarationError';
if (aq_dict.hasOwnProperty(method_name)) {
return aq_dict[method_name].apply(context,
[arguments, scope]);
}
throw error;
};
}
for (i = 0; i < element_list.length; i += 1) {
element = element_list[i];
scope = element.getAttribute("data-gadget-scope");
url = element.getAttribute("data-gadget-url");
sandbox = element.getAttribute("data-gadget-sandbox");
if (url !== null) {
promise_list.push(
context.declareGadget(url, {
element: element,
scope: scope || undefined,
sandbox: sandbox || undefined
})
.push(undefined, prepareReportGadgetDeclarationError(scope))
);
}
}
return RSVP.all(promise_list);
}
RenderJSGadget.__ready_list = [clearGadgetInternalParameters,
loadSubGadgetDOMDeclaration];
RenderJSGadget.ready = function (callback) {
this.__ready_list.push(callback);
return this;
};
RenderJSGadget.setState = function (state_dict) {
var json_state = JSON.stringify(state_dict);
this.__ready_list.unshift(function () {
this.state = JSON.parse(json_state);
});
return this;
};
RenderJSGadget.onStateChange = function (callback) {
this.prototype.__state_change_callback = callback;
return this;
};
RenderJSGadget.__service_list = [];
RenderJSGadget.declareService = function (callback) {
this.__service_list.push(callback);
return this;
};
RenderJSGadget.onEvent = function (type, callback, use_capture,
prevent_default) {
this.__service_list.push(function () {
return loopEventListener(this.element, type, use_capture,
callback.bind(this), prevent_default);
});
return this;
};
function runJob(gadget, name, callback, argument_list) {
var job_promise = new RSVP.Queue()
.push(function () {
return callback.apply(gadget, argument_list);
});
if (gadget.__job_dict.hasOwnProperty(name)) {
gadget.__job_dict[name].cancel();
}
gadget.__job_dict[name] = job_promise;
gadget.__monitor.monitor(new RSVP.Queue()
.push(function () {
return job_promise;
})
.push(undefined, function (error) {
if (!(error instanceof RSVP.CancellationError)) {
throw error;
}
}));
}
function startService(gadget) {
gadget.__monitor.monitor(new RSVP.Queue()
.push(function () {
var i,
service_list = gadget.constructor.__service_list,
job_list = gadget.__job_list;
for (i = 0; i < service_list.length; i += 1) {
gadget.__monitor.monitor(service_list[i].apply(gadget));
}
for (i = 0; i < job_list.length; i += 1) {
runJob(gadget, job_list[i][0], job_list[i][1], job_list[i][2]);
}
gadget.__job_list = [];
gadget.__job_triggered = true;
})
);
}
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareJob
// gadget internal method, which trigger execution
// of a function inside a service
/////////////////////////////////////////////////////////////////
RenderJSGadget.declareJob = function (name, callback) {
this.prototype[name] = function () {
var context = this,
argument_list = arguments;
if (context.__job_triggered) {
runJob(context, name, callback, argument_list);
} else {
context.__job_list.push([name, callback, argument_list]);
}
};
// Allow chain
return this;
};
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareMethod
/////////////////////////////////////////////////////////////////
RenderJSGadget.declareMethod = function (name, callback) {
this.prototype[name] = function () {
var context = this,
argument_list = arguments;
return new RSVP.Queue()
.push(function () {
return callback.apply(context, argument_list);
});
};
// Allow chain
return this;
};
RenderJSGadget
.declareMethod('getInterfaceList', function () {
// Returns the list of gadget prototype
return this.__interface_list;
})
.declareMethod('getRequiredCSSList', function () {
// Returns a list of CSS required by the gadget
return this.__required_css_list;
})
.declareMethod('getRequiredJSList', function () {
// Returns a list of JS required by the gadget
return this.__required_js_list;
})
.declareMethod('getPath', function () {
// Returns the path of the code of a gadget
return this.__path;
})
.declareMethod('getTitle', function () {
// Returns the title of a gadget
return this.__title;
})
.declareMethod('getElement', function () {
// Returns the DOM Element of a gadget
// XXX Kept for compatibility. Use element property directly
if (this.element === undefined) {
throw new Error("No element defined");
}
return this.element;
})
.declareMethod('changeState', function (state_dict) {
var key,
modified = false,
previous_cancelled = this.hasOwnProperty('__modification_dict'),
modification_dict,
context = this;
if (previous_cancelled) {
modification_dict = this.__modification_dict;
modified = true;
} else {
modification_dict = {};
this.__modification_dict = modification_dict;
}
for (key in state_dict) {
if (state_dict.hasOwnProperty(key) &&
(state_dict[key] !== this.state[key])) {
this.state[key] = state_dict[key];
modification_dict[key] = state_dict[key];
modified = true;
}
}
if (modified && this.__state_change_callback !== undefined) {
return new RSVP.Queue()
.push(function () {
return context.__state_change_callback(modification_dict);
})
.push(function (result) {
delete context.__modification_dict;
return result;
});
}
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareAcquiredMethod
/////////////////////////////////////////////////////////////////
function acquire(child_gadget, method_name, argument_list) {
var gadget = this,
key,
gadget_scope;
for (key in gadget.__sub_gadget_dict) {
if (gadget.__sub_gadget_dict.hasOwnProperty(key)) {
if (gadget.__sub_gadget_dict[key] === child_gadget) {
gadget_scope = key;
}
}
}
return new RSVP.Queue()
.push(function () {
// Do not specify default __acquired_method_dict on prototype
// to prevent modifying this default value (with
// allowPublicAcquiredMethod for example)
var aq_dict = gadget.__acquired_method_dict || {};
if (aq_dict.hasOwnProperty(method_name)) {
return aq_dict[method_name].apply(gadget,
[argument_list, gadget_scope]);
}
throw new renderJS.AcquisitionError("aq_dynamic is not defined");
})
.push(undefined, function (error) {
if (error instanceof renderJS.AcquisitionError) {
return gadget.__aq_parent(method_name, argument_list);
}
throw error;
});
}
RenderJSGadget.declareAcquiredMethod =
function (name, method_name_to_acquire) {
this.prototype[name] = function () {
var argument_list = Array.prototype.slice.call(arguments, 0),
gadget = this;
return new RSVP.Queue()
.push(function () {
return gadget.__aq_parent(method_name_to_acquire, argument_list);
});
};
// Allow chain
return this;
};
RenderJSGadget.declareAcquiredMethod("aq_reportServiceError",
"reportServiceError");
RenderJSGadget.declareAcquiredMethod("aq_reportGadgetDeclarationError",
"reportGadgetDeclarationError");
/////////////////////////////////////////////////////////////////
// RenderJSGadget.allowPublicAcquisition
/////////////////////////////////////////////////////////////////
RenderJSGadget.allowPublicAcquisition =
function (method_name, callback) {
this.prototype.__acquired_method_dict[method_name] = callback;
// Allow chain
return this;
};
// Set aq_parent on gadget_instance which call acquire on parent_gadget
function setAqParent(gadget_instance, parent_gadget) {
gadget_instance.__aq_parent = function (method_name, argument_list) {
return acquire.apply(parent_gadget, [gadget_instance, method_name,
argument_list]);
};
}
/////////////////////////////////////////////////////////////////
// RenderJSEmbeddedGadget
/////////////////////////////////////////////////////////////////
// Class inheritance
function RenderJSEmbeddedGadget() {
if (!(this instanceof RenderJSEmbeddedGadget)) {
return new RenderJSEmbeddedGadget();
}
RenderJSGadget.call(this);
}
RenderJSEmbeddedGadget.__ready_list = RenderJSGadget.__ready_list.slice();
RenderJSEmbeddedGadget.__service_list =
RenderJSGadget.__service_list.slice();
RenderJSEmbeddedGadget.ready =
RenderJSGadget.ready;
RenderJSEmbeddedGadget.setState =
RenderJSGadget.setState;
RenderJSEmbeddedGadget.onStateChange =
RenderJSGadget.onStateChange;
RenderJSEmbeddedGadget.declareService =
RenderJSGadget.declareService;
RenderJSEmbeddedGadget.onEvent =
RenderJSGadget.onEvent;
RenderJSEmbeddedGadget.prototype = new RenderJSGadget();
RenderJSEmbeddedGadget.prototype.constructor = RenderJSEmbeddedGadget;
/////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget
/////////////////////////////////////////////////////////////////
function privateDeclarePublicGadget(url, options, parent_gadget) {
return new RSVP.Queue()
.push(function () {
return renderJS.declareGadgetKlass(url)
// gadget loading should not be interrupted
// if not, gadget's definition will not be complete
//.then will return another promise
//so loading_klass_promise can't be cancel
.then(function (result) {
return result;
});
})
// Get the gadget class and instanciate it
.push(function (Klass) {
if (options.element === undefined) {
options.element = document.createElement("div");
}
var i,
gadget_instance,
template_node_list = Klass.__template_element.body.childNodes,
fragment = document.createDocumentFragment();
gadget_instance = new Klass();
gadget_instance.element = options.element;
gadget_instance.state = {};
for (i = 0; i < template_node_list.length; i += 1) {
fragment.appendChild(
template_node_list[i].cloneNode(true)
);
}
gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget);
return gadget_instance;
});
}
/////////////////////////////////////////////////////////////////
// RenderJSIframeGadget
/////////////////////////////////////////////////////////////////
function RenderJSIframeGadget() {
if (!(this instanceof RenderJSIframeGadget)) {
return new RenderJSIframeGadget();
}
RenderJSGadget.call(this);
}
RenderJSIframeGadget.__ready_list = RenderJSGadget.__ready_list.slice();
RenderJSIframeGadget.ready =
RenderJSGadget.ready;
RenderJSIframeGadget.setState =
RenderJSGadget.setState;
RenderJSIframeGadget.onStateChange =
RenderJSGadget.onStateChange;
RenderJSIframeGadget.__service_list = RenderJSGadget.__service_list.slice();
RenderJSIframeGadget.declareService =
RenderJSGadget.declareService;
RenderJSIframeGadget.onEvent =
RenderJSGadget.onEvent;
RenderJSIframeGadget.prototype = new RenderJSGadget();
RenderJSIframeGadget.prototype.constructor = RenderJSIframeGadget;
/////////////////////////////////////////////////////////////////
// privateDeclareIframeGadget
/////////////////////////////////////////////////////////////////
function privateDeclareIframeGadget(url, options, parent_gadget) {
var gadget_instance,
iframe,
iframe_loading_deferred = RSVP.defer();
if (options.element === undefined) {
throw new Error("DOM element is required to create Iframe Gadget " +
url);
}
// Check if the element is attached to the DOM
if (!document.contains(options.element)) {
throw new Error("The parent element is not attached to the DOM for " +
url);
}
gadget_instance = new RenderJSIframeGadget();
setAqParent(gadget_instance, parent_gadget);
iframe = document.createElement("iframe");
iframe.addEventListener('error', function (error) {
iframe_loading_deferred.reject(error);
});
iframe.addEventListener('load', function () {
return RSVP.timeout(5000)
.fail(function () {
iframe_loading_deferred.reject(
new Error('Timeout while loading: ' + url)
);
});
});
// gadget_instance.element.setAttribute("seamless", "seamless");
iframe.setAttribute("src", url);
gadget_instance.__path = url;
gadget_instance.element = options.element;
gadget_instance.state = {};
// Attach it to the DOM
options.element.appendChild(iframe);
// XXX Manage unbind when deleting the gadget
// Create the communication channel with the iframe
gadget_instance.__chan = Channel.build({
window: iframe.contentWindow,
origin: "*",
scope: "renderJS"
});
// Create new method from the declareMethod call inside the iframe
gadget_instance.__chan.bind("declareMethod",
function (trans, method_name) {
gadget_instance[method_name] = function () {
var argument_list = arguments,
wait_promise = new RSVP.Promise(function (resolve, reject) {
gadget_instance.__chan.call({
method: "methodCall",
params: [
method_name,
Array.prototype.slice.call(argument_list, 0)],
success: function (s) {
resolve(s);
},
error: function (e) {
reject(e);
}
});
});
return new RSVP.Queue()
.push(function () {
return wait_promise;
});
};
return "OK";
});
// Wait for the iframe to be loaded before continuing
gadget_instance.__chan.bind("ready", function (trans) {
iframe_loading_deferred.resolve(gadget_instance);
return "OK";
});
gadget_instance.__chan.bind("failed", function (trans, params) {
iframe_loading_deferred.reject(params);
return "OK";
});
gadget_instance.__chan.bind("acquire", function (trans, params) {
gadget_instance.__aq_parent.apply(gadget_instance, params)
.then(function (g) {
trans.complete(g);
}).fail(function (e) {
trans.error(e.toString());
});
trans.delayReturn(true);
});
return iframe_loading_deferred.promise;
}
/////////////////////////////////////////////////////////////////
// privateDeclareDataUrlGadget
/////////////////////////////////////////////////////////////////
function privateDeclareDataUrlGadget(url, options, parent_gadget) {
return new RSVP.Queue()
.push(function () {
return ajax(url);
})
.push(function (xhr) {
// Insert a "base" element, in order to resolve all relative links
// which could get broken with a data url
var doc = (new DOMParser()).parseFromString(xhr.responseText,
'text/html'),
base = doc.createElement('base'),
blob;
base.href = url;
doc.head.insertBefore(base, doc.head.firstChild);
blob = new Blob([doc.documentElement.outerHTML],
{type: "text/html;charset=UTF-8"});
return readBlobAsDataURL(blob);
})
.push(function (data_url) {
return privateDeclareIframeGadget(data_url, options, parent_gadget);
});
}
/////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget
/////////////////////////////////////////////////////////////////
RenderJSGadget
.declareMethod('declareGadget', function (url, options) {
var parent_gadget = this;
if (options === undefined) {
options = {};
}
if (options.sandbox === undefined) {
options.sandbox = "public";
}
// transform url to absolute url if it is relative
url = renderJS.getAbsoluteURL(url, this.__path);
return new RSVP.Queue()
.push(function () {
var method;
if (options.sandbox === "public") {
method = privateDeclarePublicGadget;
} else if (options.sandbox === "iframe") {
method = privateDeclareIframeGadget;
} else if (options.sandbox === "dataurl") {
method = privateDeclareDataUrlGadget;
} else {
throw new Error("Unsupported sandbox options '" +
options.sandbox + "'");
}
return method(url, options, parent_gadget);
})
// Set the HTML context
.push(function (gadget_instance) {
var i,
scope,
queue = new RSVP.Queue();
// Trigger calling of all ready callback
function ready_wrapper() {
return gadget_instance;
}
function ready_executable_wrapper(fct) {
return function () {
return fct.call(gadget_instance, gadget_instance);
};
}
for (i = 0; i < gadget_instance.constructor.__ready_list.length;
i += 1) {
// Put a timeout?
queue.push(ready_executable_wrapper(
gadget_instance.constructor.__ready_list[i]
));
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
}
// Store local reference to the gadget instance
scope = options.scope;
if (scope === undefined) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
}
}
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
gadget_instance.element.setAttribute("data-gadget-scope",
scope);
// Put some attribute to ease page layout comprehension
gadget_instance.element.setAttribute("data-gadget-url", url);
gadget_instance.element.setAttribute("data-gadget-sandbox",
options.sandbox);
gadget_instance.element._gadget = gadget_instance;
if (document.contains(gadget_instance.element)) {
// Put a timeout
queue.push(startService);
}
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
return queue;
});
})
.declareMethod('getDeclaredGadget', function (gadget_scope) {
if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {
throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
}
return this.__sub_gadget_dict[gadget_scope];
})
.declareMethod('dropGadget', function (gadget_scope) {
if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {
throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
}
// http://perfectionkills.com/understanding-delete/
delete this.__sub_gadget_dict[gadget_scope];
});
/////////////////////////////////////////////////////////////////
// renderJS selector
/////////////////////////////////////////////////////////////////
renderJS = function (selector) {
var result;
if (selector === window) {
// window is the 'this' value when loading a javascript file
// In this case, use the current loading gadget constructor
result = gadget_loading_klass_list[0];
}
if (result === undefined) {
throw new Error("Unknown selector '" + selector + "'");
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.AcquisitionError
/////////////////////////////////////////////////////////////////
renderJS.AcquisitionError = function (message) {
this.name = "AcquisitionError";
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Acquisition failed";
};
renderJS.AcquisitionError.prototype = new Error();
renderJS.AcquisitionError.prototype.constructor =
renderJS.AcquisitionError;
/////////////////////////////////////////////////////////////////
// renderJS.getAbsoluteURL
/////////////////////////////////////////////////////////////////
renderJS.getAbsoluteURL = function (url, base_url) {
if (base_url && url) {
return new URL(url, base_url).href;
}
return url;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareJS
/////////////////////////////////////////////////////////////////
renderJS.declareJS = function (url, container, pop) {
// https://www.html5rocks.com/en/tutorials/speed/script-loading/
// Prevent infinite recursion if loading render.js
// more than once
var result;
if (javascript_registration_dict.hasOwnProperty(url)) {
result = RSVP.resolve();
} else {
javascript_registration_dict[url] = null;
result = new RSVP.Promise(function (resolve, reject) {
var newScript;
newScript = document.createElement('script');
newScript.async = false;
newScript.type = 'text/javascript';
newScript.onload = function () {
if (pop === true) {
// Drop the current loading klass info used by selector
gadget_loading_klass_list.shift();
}
resolve();
};
newScript.onerror = function (e) {
if (pop === true) {
// Drop the current loading klass info used by selector
gadget_loading_klass_list.shift();
}
reject(e);
};
newScript.src = url;
container.appendChild(newScript);
});
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareCSS
/////////////////////////////////////////////////////////////////
renderJS.declareCSS = function (url, container) {
// https://github.com/furf/jquery-getCSS/blob/master/jquery.getCSS.js
// No way to cleanly check if a css has been loaded
// So, always resolve the promise...
// http://requirejs.org/docs/faq-advanced.html#css
var result;
if (stylesheet_registration_dict.hasOwnProperty(url)) {
result = RSVP.resolve();
} else {
result = new RSVP.Promise(function (resolve, reject) {
var link;
link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = url;
link.onload = function () {
stylesheet_registration_dict[url] = null;
resolve();
};
link.onerror = function (e) {
reject(e);
};
container.appendChild(link);
});
}
return result;
};
/////////////////////////////////////////////////////////////////
// renderJS.declareGadgetKlass
/////////////////////////////////////////////////////////////////
function parse(xhr, url) {
var tmp_constructor,
key,
parsed_html;
// Class inheritance
tmp_constructor = function () {
RenderJSGadget.call(this);
};
tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();
tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();
tmp_constructor.declareMethod =
RenderJSGadget.declareMethod;
tmp_constructor.declareJob =
RenderJSGadget.declareJob;
tmp_constructor.declareAcquiredMethod =
RenderJSGadget.declareAcquiredMethod;
tmp_constructor.allowPublicAcquisition =
RenderJSGadget.allowPublicAcquisition;
tmp_constructor.ready =
RenderJSGadget.ready;
tmp_constructor.setState =
RenderJSGadget.setState;
tmp_constructor.onStateChange =
RenderJSGadget.onStateChange;
tmp_constructor.declareService =
RenderJSGadget.declareService;
tmp_constructor.onEvent =
RenderJSGadget.onEvent;
tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.__path = url;
tmp_constructor.prototype.__acquired_method_dict = {};
// https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest
// https://developer.mozilla.org/en-US/docs/Web/API/DOMParser
// https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM
tmp_constructor.__template_element =
(new DOMParser()).parseFromString(xhr.responseText, "text/html");
parsed_html = renderJS.parseGadgetHTMLDocument(
tmp_constructor.__template_element,
url
);
for (key in parsed_html) {
if (parsed_html.hasOwnProperty(key)) {
tmp_constructor.prototype['__' + key] = parsed_html[key];
}
}
return tmp_constructor;
}
renderJS.declareGadgetKlass = function (url) {
if (gadget_model_defer_dict.hasOwnProperty(url)) {
// Return klass object if it already exists
return gadget_model_defer_dict[url].promise;
}
var tmp_constructor,
defer = RSVP.defer();
gadget_model_defer_dict[url] = defer;
// Change the global variable to update the loading queue
loading_klass_promise = defer.promise;
// Fetch the HTML page and parse it
return new RSVP.Queue()
.push(function () {
return ajax(url);
})
.push(function (result) {
tmp_constructor = parse(result, url);
var fragment = document.createDocumentFragment(),
promise_list = [],
i,
js_list = tmp_constructor.prototype.__required_js_list,
css_list = tmp_constructor.prototype.__required_css_list;
// Load JS
if (js_list.length) {
gadget_loading_klass_list.push(tmp_constructor);
for (i = 0; i < js_list.length - 1; i += 1) {
promise_list.push(renderJS.declareJS(js_list[i], fragment));
}
promise_list.push(renderJS.declareJS(js_list[i], fragment, true));
}
// Load CSS
for (i = 0; i < css_list.length; i += 1) {
promise_list.push(renderJS.declareCSS(css_list[i], fragment));
}
document.head.appendChild(fragment);
return RSVP.all(promise_list);
})
.push(function () {
defer.resolve(tmp_constructor);
return tmp_constructor;
})
.push(undefined, function (e) {
// Drop the current loading klass info used by selector
// even in case of error
defer.reject(e);
throw e;
});
};
/////////////////////////////////////////////////////////////////
// renderJS.clearGadgetKlassList
/////////////////////////////////////////////////////////////////
// For test purpose only
renderJS.clearGadgetKlassList = function () {
gadget_model_defer_dict = {};
javascript_registration_dict = {};
stylesheet_registration_dict = {};
};
/////////////////////////////////////////////////////////////////
// renderJS.parseGadgetHTMLDocument
/////////////////////////////////////////////////////////////////
renderJS.parseGadgetHTMLDocument = function (document_element, url) {
var settings = {
title: "",
interface_list: [],
required_css_list: [],
required_js_list: []
},
i,
element;
if (!url || !isAbsoluteOrDataURL.test(url)) {
throw new Error("The url should be absolute: " + url);
}
if (document_element.nodeType === 9) {
settings.title = document_element.title;
if (document_element.head !== null) {
for (i = 0; i < document_element.head.children.length; i += 1) {
element = document_element.head.children[i];
if (element.href !== null) {
// XXX Manage relative URL during extraction of URLs
// element.href returns absolute URL in firefox but "" in chrome;
if (element.rel === "stylesheet") {
settings.required_css_list.push(
renderJS.getAbsoluteURL(element.getAttribute("href"), url)
);
} else if (element.nodeName === "SCRIPT" &&
(element.type === "text/javascript" ||
!element.type)) {
settings.required_js_list.push(
renderJS.getAbsoluteURL(element.getAttribute("src"), url)
);
} else if (element.rel ===
"http://www.renderjs.org/rel/interface") {
settings.interface_list.push(
renderJS.getAbsoluteURL(element.getAttribute("href"), url)
);
}
}
}
}
} else {
throw new Error("The first parameter should be an HTMLDocument");
}
return settings;
};
/////////////////////////////////////////////////////////////////
// global
/////////////////////////////////////////////////////////////////
window.rJS = window.renderJS = renderJS;
window.__RenderJSGadget = RenderJSGadget;
window.__RenderJSEmbeddedGadget = RenderJSEmbeddedGadget;
window.__RenderJSIframeGadget = RenderJSIframeGadget;
///////////////////////////////////////////////////
// Bootstrap process. Register the self gadget.
///////////////////////////////////////////////////
function bootstrap() {
var url = removeHash(window.location.href),
TmpConstructor,
root_gadget,
loading_gadget_promise = new RSVP.Queue(),
declare_method_count = 0,
embedded_channel,
notifyReady,
notifyDeclareMethod,
gadget_ready = false,
iframe_top_gadget,
last_acquisition_gadget,
declare_method_list_waiting = [],
gadget_failed = false,
gadget_error,
connection_ready = false;
// Create the gadget class for the current url
if (gadget_model_defer_dict.hasOwnProperty(url)) {
throw new Error("bootstrap should not be called twice");
}
loading_klass_promise = new RSVP.Promise(function (resolve, reject) {
last_acquisition_gadget = new RenderJSGadget();
last_acquisition_gadget.__acquired_method_dict = {
reportServiceError: function (param_list) {
letsCrash(param_list[0]);
}
};
// Stop acquisition on the last acquisition gadget
// Do not put this on the klass, as their could be multiple instances
last_acquisition_gadget.__aq_parent = function (method_name) {
throw new renderJS.AcquisitionError(
"No gadget provides " + method_name
);
};
//we need to determine tmp_constructor's value before exit bootstrap
//because of function : renderJS
//but since the channel checking is async,
//we can't use code structure like:
// if channel communication is ok
// tmp_constructor = RenderJSGadget
// else
// tmp_constructor = RenderJSEmbeddedGadget
if (window.self === window.top) {
// XXX Copy/Paste from declareGadgetKlass
TmpConstructor = function () {
RenderJSGadget.call(this);
};
TmpConstructor.declareMethod = RenderJSGadget.declareMethod;
TmpConstructor.declareJob = RenderJSGadget.declareJob;
TmpConstructor.declareAcquiredMethod =
RenderJSGadget.declareAcquiredMethod;
TmpConstructor.allowPublicAcquisition =
RenderJSGadget.allowPublicAcquisition;
TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice();
TmpConstructor.ready = RenderJSGadget.ready;
TmpConstructor.setState = RenderJSGadget.setState;
TmpConstructor.onStateChange = RenderJSGadget.onStateChange;
TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
TmpConstructor.declareService =
RenderJSGadget.declareService;
TmpConstructor.onEvent =
RenderJSGadget.onEvent;
TmpConstructor.prototype = new RenderJSGadget();
TmpConstructor.prototype.constructor = TmpConstructor;
TmpConstructor.prototype.__path = url;
gadget_model_defer_dict[url] = {
promise: RSVP.resolve(TmpConstructor)
};
// Create the root gadget instance and put it in the loading stack
root_gadget = new TmpConstructor();
setAqParent(root_gadget, last_acquisition_gadget);
} else {
// Create the root gadget instance and put it in the loading stack
TmpConstructor = RenderJSEmbeddedGadget;
TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice();
TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
TmpConstructor.prototype.__path = url;
root_gadget = new RenderJSEmbeddedGadget();
setAqParent(root_gadget, last_acquisition_gadget);
// Create the communication channel
embedded_channel = Channel.build({
window: window.parent,
origin: "*",
scope: "renderJS",
onReady: function () {
var k;
iframe_top_gadget = false;
//Default: Define __aq_parent to inform parent window
root_gadget.__aq_parent =
TmpConstructor.prototype.__aq_parent = function (method_name,
argument_list, time_out) {
return new RSVP.Promise(function (resolve, reject) {
embedded_channel.call({
method: "acquire",
params: [
method_name,
argument_list
],
success: function (s) {
resolve(s);
},
error: function (e) {
reject(e);
},
timeout: time_out
});
});
};
// Channel is ready, so now declare Function
notifyDeclareMethod = function (name) {
declare_method_count += 1;
embedded_channel.call({
method: "declareMethod",
params: name,
success: function () {
declare_method_count -= 1;
notifyReady();
},
error: function () {
declare_method_count -= 1;
}
});
};
for (k = 0; k < declare_method_list_waiting.length; k += 1) {
notifyDeclareMethod(declare_method_list_waiting[k]);
}
declare_method_list_waiting = [];
// If Gadget Failed Notify Parent
if (gadget_failed) {
embedded_channel.notify({
method: "failed",
params: gadget_error
});
return;
}
connection_ready = true;
notifyReady();
//the channel is ok
//so bind calls to renderJS method on the instance
embedded_channel.bind("methodCall", function (trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1])
.then(function (g) {
trans.complete(g);
}).fail(function (e) {
trans.error(e.toString());
});
trans.delayReturn(true);
});
}
});
// Notify parent about gadget instanciation
notifyReady = function () {
if ((declare_method_count === 0) && (gadget_ready === true)) {
embedded_channel.notify({method: "ready"});
}
};
// Inform parent gadget about declareMethod calls here.
notifyDeclareMethod = function (name) {
declare_method_list_waiting.push(name);
};
notifyDeclareMethod("getInterfaceList");
notifyDeclareMethod("getRequiredCSSList");
notifyDeclareMethod("getRequiredJSList");
notifyDeclareMethod("getPath");
notifyDeclareMethod("getTitle");
// Surcharge declareMethod to inform parent window
TmpConstructor.declareMethod = function (name, callback) {
var result = RenderJSGadget.declareMethod.apply(
this,
[name, callback]
);
notifyDeclareMethod(name);
return result;
};
TmpConstructor.declareService =
RenderJSGadget.declareService;
TmpConstructor.declareJob =
RenderJSGadget.declareJob;
TmpConstructor.onEvent =
RenderJSGadget.onEvent;
TmpConstructor.declareAcquiredMethod =
RenderJSGadget.declareAcquiredMethod;
TmpConstructor.allowPublicAcquisition =
RenderJSGadget.allowPublicAcquisition;
iframe_top_gadget = true;
}
TmpConstructor.prototype.__acquired_method_dict = {};
gadget_loading_klass_list.push(TmpConstructor);
function init() {
// XXX HTML properties can only be set when the DOM is fully loaded
var settings = renderJS.parseGadgetHTMLDocument(document, url),
j,
key,
fragment = document.createDocumentFragment();
for (key in settings) {
if (settings.hasOwnProperty(key)) {
TmpConstructor.prototype['__' + key] = settings[key];
}
}
TmpConstructor.__template_element = document.createElement("div");
root_gadget.element = document.body;
root_gadget.state = {};
for (j = 0; j < root_gadget.element.childNodes.length; j += 1) {
fragment.appendChild(
root_gadget.element.childNodes[j].cloneNode(true)
);
}
TmpConstructor.__template_element.appendChild(fragment);
RSVP.all([root_gadget.getRequiredJSList(),
root_gadget.getRequiredCSSList()])
.then(function (all_list) {
var i,
js_list = all_list[0],
css_list = all_list[1];
for (i = 0; i < js_list.length; i += 1) {
javascript_registration_dict[js_list[i]] = null;
}
for (i = 0; i < css_list.length; i += 1) {
stylesheet_registration_dict[css_list[i]] = null;
}
gadget_loading_klass_list.shift();
}).then(function () {
// select the target node
var target = document.querySelector('body'),
// create an observer instance
observer = new MutationObserver(function (mutations) {
var i, k, len, len2, node, added_list;
mutations.forEach(function (mutation) {
if (mutation.type === 'childList') {
len = mutation.removedNodes.length;
for (i = 0; i < len; i += 1) {
node = mutation.removedNodes[i];
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.hasAttribute("data-gadget-url") &&
(node._gadget !== undefined)) {
createMonitor(node._gadget);
}
added_list =
node.querySelectorAll("[data-gadget-url]");
len2 = added_list.length;
for (k = 0; k < len2; k += 1) {
node = added_list[k];
if (node._gadget !== undefined) {
createMonitor(node._gadget);
}
}
}
}
len = mutation.addedNodes.length;
for (i = 0; i < len; i += 1) {
node = mutation.addedNodes[i];
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.hasAttribute("data-gadget-url") &&
(node._gadget !== undefined)) {
if (document.contains(node)) {
startService(node._gadget);
}
}
added_list =
node.querySelectorAll("[data-gadget-url]");
len2 = added_list.length;
for (k = 0; k < len2; k += 1) {
node = added_list[k];
if (document.contains(node)) {
if (node._gadget !== undefined) {
startService(node._gadget);
}
}
}
}
}
}
});
}),
// configuration of the observer:
config = {
childList: true,
subtree: true,
attributes: false,
characterData: false
};
// pass in the target node, as well as the observer options
observer.observe(target, config);
return root_gadget;
}).then(resolve, function (e) {
reject(e);
console.error(e);
throw e;
});
}
document.addEventListener('DOMContentLoaded', init, false);
});
loading_gadget_promise
.push(function () {
return loading_klass_promise;
})
.push(function (root_gadget) {
var i;
function ready_wrapper() {
return root_gadget;
}
function ready_executable_wrapper(fct) {
return function (g) {
return fct.call(g, g);
};
}
TmpConstructor.ready(function () {
return startService(this);
});
loading_gadget_promise.push(ready_wrapper);
for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) {
// Put a timeout?
loading_gadget_promise
.push(ready_executable_wrapper(TmpConstructor.__ready_list[i]))
// Always return the gadget instance after ready function
.push(ready_wrapper);
}
});
if (window.self === window.top) {
loading_gadget_promise
.fail(function (e) {
letsCrash(e);
throw e;
});
} else {
// Inform parent window that gadget is correctly loaded
loading_gadget_promise
.then(function () {
gadget_ready = true;
if (connection_ready) {
notifyReady();
}
})
.fail(function (e) {
//top gadget in iframe
if (iframe_top_gadget) {
gadget_failed = true;
gadget_error = e.toString();
letsCrash(e);
} else {
embedded_channel.notify({method: "failed", params: e.toString()});
}
throw e;
});
}
}
bootstrap();
}(document, window, RSVP, DOMParser, Channel, MutationObserver, Node,
FileReader, Blob, navigator, Event, URL));
\ No newline at end of file
(function(globals) {
var define, requireModule;
(function() {
var registry = {}, seen = {};
define = function(name, deps, callback) {
registry[name] = { deps: deps, callback: callback };
};
requireModule = function(name) {
if (seen[name]) { return seen[name]; }
seen[name] = {};
var mod = registry[name];
if (!mod) {
throw new Error("Module '" + name + "' not found.");
}
var deps = mod.deps,
callback = mod.callback,
reified = [],
exports;
for (var i=0, l=deps.length; i<l; i++) {
if (deps[i] === 'exports') {
reified.push(exports = {});
} else {
reified.push(requireModule(deps[i]));
}
}
var value = callback.apply(this, reified);
return seen[name] = exports || value;
};
})();
define("rsvp/all",
["rsvp/promise","exports"],
function(__dependency1__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
/* global toString */
function promiseAtLeast(expected_count, promises) {
if (Object.prototype.toString.call(promises) !== "[object Array]") {
throw new TypeError('You must pass an array to all.');
}
function canceller() {
var promise;
for (var i = 0; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function' &&
typeof promise.cancel === 'function') {
promise.cancel();
}
}
}
return new Promise(function(resolve, reject, notify) {
var results = [], remaining = promises.length,
promise, remaining_count = promises.length - expected_count;
if (remaining === 0) {
if (expected_count === 1) {
resolve();
} else {
resolve([]);
}
}
function resolver(index) {
return function(value) {
resolveAll(index, value);
};
}
function resolveAll(index, value) {
results[index] = value;
if (--remaining === remaining_count) {
if (remaining_count === 0) {
resolve(results);
} else {
resolve(value);
canceller();
}
}
}
function notifier(index) {
return function(value) {
notify({"index": index, "value": value});
};
}
function cancelAll(rejectionValue) {
reject(rejectionValue);
canceller();
}
for (var i = 0; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolver(i), cancelAll, notifier(i));
} else {
resolveAll(i, promise);
}
}
}, canceller
);
}
function all(promises) {
return promiseAtLeast(promises.length, promises);
}
function any(promises) {
return promiseAtLeast(1, promises);
}
__exports__.all = all;
__exports__.any = any;
});
define("rsvp/async",
["exports"],
function(__exports__) {
"use strict";
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var async;
var local = (typeof global !== 'undefined') ? global : this;
function checkNativePromise() {
if (typeof Promise === "function" &&
typeof Promise.resolve === "function") {
try {
/* global Promise */
var promise = new Promise(function(){});
if ({}.toString.call(promise) === "[object Promise]") {
return true;
}
} catch (e) {}
}
return false;
}
function useNativePromise() {
var nativePromise = Promise.resolve();
return function(callback, arg) {
nativePromise.then(function () {
callback(arg);
});
};
}
// old node
function useNextTick() {
return function(callback, arg) {
process.nextTick(function() {
callback(arg);
});
};
}
// node >= 0.10.x
function useSetImmediate() {
return function(callback, arg) {
/* global setImmediate */
setImmediate(function(){
callback(arg);
});
};
}
function useMutationObserver() {
var queue = [];
var observer = new BrowserMutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], arg= tuple[1];
callback(arg);
});
});
var element = document.createElement('div');
observer.observe(element, { attributes: true });
// Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661
window.addEventListener('unload', function(){
observer.disconnect();
observer = null;
}, false);
return function(callback, arg) {
queue.push([callback, arg]);
element.setAttribute('drainQueue', 'drainQueue');
};
}
function useSetTimeout() {
return function(callback, arg) {
local.setTimeout(function() {
callback(arg);
}, 1);
};
}
if (typeof setImmediate === 'function') {
async = useSetImmediate();
} else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
async = useNextTick();
} else if (BrowserMutationObserver) {
async = useMutationObserver();
} else if (checkNativePromise()) {
async = useNativePromise();
} else {
async = useSetTimeout();
}
__exports__.async = async;
});
define("rsvp/cancellation_error",
["exports"],
function(__exports__) {
"use strict";
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
function CancellationError(message) {
this.name = "cancel";
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Default Message";
}
CancellationError.prototype = new Error();
CancellationError.prototype.constructor = CancellationError;
__exports__.CancellationError = CancellationError;
});
define("rsvp/config",
["rsvp/async","exports"],
function(__dependency1__, __exports__) {
"use strict";
var async = __dependency1__.async;
var config = {};
config.async = async;
__exports__.config = config;
});
define("rsvp/defer",
["rsvp/promise","exports"],
function(__dependency1__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
function defer() {
var deferred = {
// pre-allocate shape
resolve: undefined,
reject: undefined,
promise: undefined
};
deferred.promise = new Promise(function(resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
__exports__.defer = defer;
});
define("rsvp/events",
["exports"],
function(__exports__) {
"use strict";
var Event = function(type, options) {
this.type = type;
for (var option in options) {
if (!options.hasOwnProperty(option)) { continue; }
this[option] = options[option];
}
};
var indexOf = function(callbacks, callback) {
for (var i=0, l=callbacks.length; i<l; i++) {
if (callbacks[i][0] === callback) { return i; }
}
return -1;
};
var callbacksFor = function(object) {
var callbacks = object._promiseCallbacks;
if (!callbacks) {
callbacks = object._promiseCallbacks = {};
}
return callbacks;
};
var EventTarget = {
mixin: function(object) {
object.on = this.on;
object.off = this.off;
object.trigger = this.trigger;
return object;
},
on: function(eventNames, callback, binding) {
var allCallbacks = callbacksFor(this), callbacks, eventName;
eventNames = eventNames.split(/\s+/);
binding = binding || this;
while (eventName = eventNames.shift()) {
callbacks = allCallbacks[eventName];
if (!callbacks) {
callbacks = allCallbacks[eventName] = [];
}
if (indexOf(callbacks, callback) === -1) {
callbacks.push([callback, binding]);
}
}
},
off: function(eventNames, callback) {
var allCallbacks = callbacksFor(this), callbacks, eventName, index;
eventNames = eventNames.split(/\s+/);
while (eventName = eventNames.shift()) {
if (!callback) {
allCallbacks[eventName] = [];
continue;
}
callbacks = allCallbacks[eventName];
index = indexOf(callbacks, callback);
if (index !== -1) { callbacks.splice(index, 1); }
}
},
trigger: function(eventName, options) {
var allCallbacks = callbacksFor(this),
callbacks, callbackTuple, callback, binding, event;
if (callbacks = allCallbacks[eventName]) {
// Don't cache the callbacks.length since it may grow
for (var i=0; i<callbacks.length; i++) {
callbackTuple = callbacks[i];
callback = callbackTuple[0];
binding = callbackTuple[1];
if (typeof options !== 'object') {
options = { detail: options };
}
event = new Event(eventName, options);
callback.call(binding, event);
}
}
}
};
__exports__.EventTarget = EventTarget;
});
define("rsvp/hash",
["rsvp/defer","exports"],
function(__dependency1__, __exports__) {
"use strict";
var defer = __dependency1__.defer;
function size(object) {
var s = 0;
for (var prop in object) {
s++;
}
return s;
}
function hash(promises) {
var results = {}, deferred = defer(), remaining = size(promises);
if (remaining === 0) {
deferred.resolve({});
}
var resolver = function(prop) {
return function(value) {
resolveAll(prop, value);
};
};
var resolveAll = function(prop, value) {
results[prop] = value;
if (--remaining === 0) {
deferred.resolve(results);
}
};
var rejectAll = function(error) {
deferred.reject(error);
};
for (var prop in promises) {
if (promises[prop] && typeof promises[prop].then === 'function') {
promises[prop].then(resolver(prop), rejectAll);
} else {
resolveAll(prop, promises[prop]);
}
}
return deferred.promise;
}
__exports__.hash = hash;
});
define("rsvp/node",
["rsvp/promise","rsvp/all","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
var all = __dependency2__.all;
function makeNodeCallbackFor(resolve, reject) {
return function (error, value) {
if (error) {
reject(error);
} else if (arguments.length > 2) {
resolve(Array.prototype.slice.call(arguments, 1));
} else {
resolve(value);
}
};
}
function denodeify(nodeFunc) {
return function() {
var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
var thisArg = this;
var promise = new Promise(function(nodeResolve, nodeReject) {
resolve = nodeResolve;
reject = nodeReject;
});
all(nodeArgs).then(function(nodeArgs) {
nodeArgs.push(makeNodeCallbackFor(resolve, reject));
try {
nodeFunc.apply(thisArg, nodeArgs);
} catch(e) {
reject(e);
}
});
return promise;
};
}
__exports__.denodeify = denodeify;
});
define("rsvp/promise",
["rsvp/config","rsvp/events","rsvp/cancellation_error","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
"use strict";
var config = __dependency1__.config;
var EventTarget = __dependency2__.EventTarget;
var CancellationError = __dependency3__.CancellationError;
function objectOrFunction(x) {
return isFunction(x) || (typeof x === "object" && x !== null);
}
function isFunction(x){
return typeof x === "function";
}
var Promise = function(resolver, canceller) {
var promise = this,
resolved = false;
if (typeof resolver !== 'function') {
throw new TypeError('You must pass a resolver function as the sole argument to the promise constructor');
}
if ((canceller !== undefined) && (typeof canceller !== 'function')) {
throw new TypeError('You can only pass a canceller function' +
' as the second argument to the promise constructor');
}
if (!(promise instanceof Promise)) {
return new Promise(resolver, canceller);
}
var resolvePromise = function(value) {
if (resolved) { return; }
resolved = true;
resolve(promise, value);
};
var rejectPromise = function(value) {
if (resolved) { return; }
resolved = true;
reject(promise, value);
};
var notifyPromise = function(value) {
if (resolved) { return; }
notify(promise, value);
};
this.on('promise:failed', function(event) {
this.trigger('error', { detail: event.detail });
}, this);
this.on('error', onerror);
this.cancel = function () {
// For now, simply reject the promise and does not propagate the cancel
// to parent or children
if (resolved) { return; }
if (canceller !== undefined) {
try {
canceller();
} catch (e) {
rejectPromise(e);
return;
}
}
// Trigger cancel?
rejectPromise(new CancellationError());
};
try {
resolver(resolvePromise, rejectPromise, notifyPromise);
} catch(e) {
rejectPromise(e);
}
};
function onerror(event) {
if (config.onerror) {
config.onerror(event.detail);
}
}
var invokeCallback = function(type, promise, callback, event) {
var hasCallback = isFunction(callback),
value, error, succeeded, failed;
if (promise.isFulfilled) { return; }
if (promise.isRejected) { return; }
if (hasCallback) {
try {
value = callback(event.detail);
succeeded = true;
} catch(e) {
failed = true;
error = e;
}
} else {
value = event.detail;
succeeded = true;
}
if (handleThenable(promise, value)) {
return;
} else if (hasCallback && succeeded) {
resolve(promise, value);
} else if (failed) {
reject(promise, error);
} else if (type === 'resolve') {
resolve(promise, value);
} else if (type === 'reject') {
reject(promise, value);
}
};
var invokeNotifyCallback = function(promise, callback, event) {
var value;
if (typeof callback === 'function') {
try {
value = callback(event.detail);
} catch (e) {
// stop propagating
return;
}
notify(promise, value);
} else {
notify(promise, event.detail);
}
};
Promise.prototype = {
constructor: Promise,
isRejected: undefined,
isFulfilled: undefined,
rejectedReason: undefined,
fulfillmentValue: undefined,
then: function(done, fail, progress) {
this.off('error', onerror);
var thenPromise = new this.constructor(function() {},
function () {
thenPromise.trigger('promise:cancelled', {});
});
if (this.isFulfilled) {
config.async(function(promise) {
invokeCallback('resolve', thenPromise, done, { detail: promise.fulfillmentValue });
}, this);
}
if (this.isRejected) {
config.async(function(promise) {
invokeCallback('reject', thenPromise, fail, { detail: promise.rejectedReason });
}, this);
}
this.on('promise:resolved', function(event) {
invokeCallback('resolve', thenPromise, done, event);
});
this.on('promise:failed', function(event) {
invokeCallback('reject', thenPromise, fail, event);
});
this.on('promise:notified', function (event) {
invokeNotifyCallback(thenPromise, progress, event);
});
return thenPromise;
},
fail: function(fail) {
return this.then(null, fail);
},
always: function(fail) {
return this.then(fail, fail);
}
};
EventTarget.mixin(Promise.prototype);
function resolve(promise, value) {
if (promise === value) {
fulfill(promise, value);
} else if (!handleThenable(promise, value)) {
fulfill(promise, value);
}
}
function handleThenable(promise, value) {
var then = null,
resolved;
try {
if (promise === value) {
throw new TypeError("A promises callback cannot return that same promise.");
}
if (objectOrFunction(value)) {
then = value.then;
if (isFunction(then)) {
if (isFunction(value.on)) {
value.on('promise:notified', function (event) {
notify(promise, event.detail);
});
}
promise.on('promise:cancelled', function(event) {
if (isFunction(value.cancel)) {
value.cancel();
}
});
then.call(value, function(val) {
if (resolved) { return true; }
resolved = true;
if (value !== val) {
resolve(promise, val);
} else {
fulfill(promise, val);
}
}, function(val) {
if (resolved) { return true; }
resolved = true;
reject(promise, val);
});
return true;
}
}
} catch (error) {
reject(promise, error);
return true;
}
return false;
}
function fulfill(promise, value) {
config.async(function() {
if (promise.isFulfilled) { return; }
if (promise.isRejected) { return; }
promise.trigger('promise:resolved', { detail: value });
promise.isFulfilled = true;
promise.fulfillmentValue = value;
});
}
function reject(promise, value) {
config.async(function() {
if (promise.isFulfilled) { return; }
if (promise.isRejected) { return; }
promise.trigger('promise:failed', { detail: value });
promise.isRejected = true;
promise.rejectedReason = value;
});
}
function notify(promise, value) {
config.async(function() {
promise.trigger('promise:notified', { detail: value });
});
}
__exports__.Promise = Promise;
});
define("rsvp/queue",
["rsvp/promise","rsvp/resolve","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
var resolve = __dependency2__.resolve;
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
function ResolvedQueueError(message) {
this.name = "resolved";
if ((message !== undefined) && (typeof message !== "string")) {
throw new TypeError('You must pass a string.');
}
this.message = message || "Default Message";
}
ResolvedQueueError.prototype = new Error();
ResolvedQueueError.prototype.constructor = ResolvedQueueError;
var Queue = function() {
var queue = this,
promise_list = [],
promise,
fulfill,
reject,
notify,
resolved;
if (!(this instanceof Queue)) {
return new Queue();
}
function canceller() {
for (var i = 0; i < 2; i++) {
promise_list[i].cancel();
}
}
promise = new Promise(function(done, fail, progress) {
fulfill = function (fulfillmentValue) {
if (resolved) {return;}
queue.isFulfilled = true;
queue.fulfillmentValue = fulfillmentValue;
resolved = true;
return done(fulfillmentValue);
};
reject = function (rejectedReason) {
if (resolved) {return;}
queue.isRejected = true;
queue.rejectedReason = rejectedReason ;
resolved = true;
return fail(rejectedReason);
};
notify = progress;
}, canceller);
promise_list.push(resolve());
promise_list.push(promise_list[0].then(function () {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
fulfill();
}
}));
queue.cancel = function () {
if (resolved) {return;}
resolved = true;
promise.cancel();
promise.fail(function (rejectedReason) {
queue.isRejected = true;
queue.rejectedReason = rejectedReason;
});
};
queue.then = function () {
return promise.then.apply(promise, arguments);
};
queue.push = function(done, fail, progress) {
var last_promise = promise_list[promise_list.length - 1],
next_promise;
if (resolved) {
throw new ResolvedQueueError();
}
next_promise = last_promise.then(done, fail, progress);
promise_list.push(next_promise);
// Handle pop
last_promise = next_promise.then(function (fulfillmentValue) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
fulfill(fulfillmentValue);
} else {
return fulfillmentValue;
}
}, function (rejectedReason) {
promise_list.splice(0, 2);
if (promise_list.length === 0) {
reject(rejectedReason);
} else {
throw rejectedReason;
}
}, function (notificationValue) {
if (promise_list[promise_list.length - 1] === last_promise) {
notify(notificationValue);
}
return notificationValue;
});
promise_list.push(last_promise);
return this;
};
};
Queue.prototype = Object.create(Promise.prototype);
Queue.prototype.constructor = Queue;
__exports__.Queue = Queue;
__exports__.ResolvedQueueError = ResolvedQueueError;
});
define("rsvp/reject",
["rsvp/promise","exports"],
function(__dependency1__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
function reject(reason) {
return new Promise(function (resolve, reject) {
reject(reason);
});
}
__exports__.reject = reject;
});
define("rsvp/resolve",
["rsvp/promise","exports"],
function(__dependency1__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
function resolve(thenable) {
return new Promise(function(resolve, reject) {
if (typeof thenable === "object" && thenable !== null) {
var then = thenable.then;
if ((then !== undefined) && (typeof then === "function")) {
return then.apply(thenable, [resolve, reject]);
}
}
return resolve(thenable);
}, function () {
if ((thenable !== undefined) && (thenable.cancel !== undefined)) {
thenable.cancel();
}
});
}
__exports__.resolve = resolve;
});
define("rsvp/rethrow",
["exports"],
function(__exports__) {
"use strict";
var local = (typeof global === "undefined") ? this : global;
function rethrow(reason) {
local.setTimeout(function() {
throw reason;
});
throw reason;
}
__exports__.rethrow = rethrow;
});
define("rsvp/timeout",
["rsvp/promise","exports"],
function(__dependency1__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
function promiseSetTimeout(millisecond, should_reject, message) {
var timeout_id;
function resolver(resolve, reject) {
timeout_id = setTimeout(function () {
if (should_reject) {
reject(message);
} else {
resolve(message);
}
}, millisecond);
}
function canceller() {
clearTimeout(timeout_id);
}
return new Promise(resolver, canceller);
}
function delay(millisecond, message) {
return promiseSetTimeout(millisecond, false, message);
}
function timeout(millisecond) {
return promiseSetTimeout(millisecond, true,
"Timed out after " + millisecond + " ms");
}
Promise.prototype.delay = function(millisecond) {
return this.then(function (fulfillmentValue) {
return delay(millisecond, fulfillmentValue);
});
};
__exports__.delay = delay;
__exports__.timeout = timeout;
});
define("rsvp",
["rsvp/events","rsvp/cancellation_error","rsvp/promise","rsvp/node","rsvp/all","rsvp/queue","rsvp/timeout","rsvp/hash","rsvp/rethrow","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __exports__) {
"use strict";
var EventTarget = __dependency1__.EventTarget;
var CancellationError = __dependency2__.CancellationError;
var Promise = __dependency3__.Promise;
var denodeify = __dependency4__.denodeify;
var all = __dependency5__.all;
var any = __dependency5__.any;
var Queue = __dependency6__.Queue;
var ResolvedQueueError = __dependency6__.ResolvedQueueError;
var delay = __dependency7__.delay;
var timeout = __dependency7__.timeout;
var hash = __dependency8__.hash;
var rethrow = __dependency9__.rethrow;
var defer = __dependency10__.defer;
var config = __dependency11__.config;
var resolve = __dependency12__.resolve;
var reject = __dependency13__.reject;
function configure(name, value) {
config[name] = value;
}
__exports__.CancellationError = CancellationError;
__exports__.Promise = Promise;
__exports__.EventTarget = EventTarget;
__exports__.all = all;
__exports__.any = any;
__exports__.Queue = Queue;
__exports__.ResolvedQueueError = ResolvedQueueError;
__exports__.delay = delay;
__exports__.timeout = timeout;
__exports__.hash = hash;
__exports__.rethrow = rethrow;
__exports__.defer = defer;
__exports__.denodeify = denodeify;
__exports__.configure = configure;
__exports__.resolve = resolve;
__exports__.reject = reject;
});
window.RSVP = requireModule("rsvp");
})(window);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
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