Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
R
renderjs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Romain Courteaud
renderjs
Commits
8c2ac0cc
Commit
8c2ac0cc
authored
Dec 06, 2016
by
Romain Courteaud
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow to load multiple gadget HTML definition in parallel.
Speed up loading the declarative sub gadget definition.
parent
4dc97e6d
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
169 additions
and
178 deletions
+169
-178
renderjs.js
renderjs.js
+169
-178
No files found.
renderjs.js
View file @
8c2ac0cc
...
...
@@ -122,7 +122,7 @@
return
new
RSVP
.
Promise
(
resolver
,
canceller
);
}
var
gadget_model_dict
=
{},
var
gadget_model_d
efer_d
ict
=
{},
javascript_registration_dict
=
{},
stylesheet_registration_dict
=
{},
gadget_loading_klass
,
...
...
@@ -714,20 +714,26 @@
// privateDeclarePublicGadget
/////////////////////////////////////////////////////////////////
function
privateDeclarePublicGadget
(
url
,
options
,
parent_gadget
)
{
var
gadget_instance
;
if
(
options
.
element
===
undefined
)
{
options
.
element
=
document
.
createElement
(
"
div
"
);
}
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
renderJS
.
declareGadgetKlass
(
url
);
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
;
gadget_loading_klass
=
Klass
;
gadget_instance
=
new
Klass
();
gadget_instance
.
element
=
options
.
element
;
gadget_instance
.
state
=
{};
...
...
@@ -737,29 +743,6 @@
);
}
setAqParent
(
gadget_instance
,
parent_gadget
);
// Load dependencies if needed
return
RSVP
.
all
([
gadget_instance
.
getRequiredJSList
(),
gadget_instance
.
getRequiredCSSList
()
]);
})
// Load all JS/CSS
.
push
(
function
(
all_list
)
{
var
fragment
=
document
.
createDocumentFragment
(),
promise_list
=
[],
i
;
// Load JS
for
(
i
=
0
;
i
<
all_list
[
0
].
length
;
i
+=
1
)
{
promise_list
.
push
(
renderJS
.
declareJS
(
all_list
[
0
][
i
],
fragment
));
}
// Load CSS
for
(
i
=
0
;
i
<
all_list
[
1
].
length
;
i
+=
1
)
{
promise_list
.
push
(
renderJS
.
declareCSS
(
all_list
[
1
][
i
],
fragment
));
}
document
.
head
.
appendChild
(
fragment
);
return
RSVP
.
all
(
promise_list
);
})
.
push
(
function
()
{
return
gadget_instance
;
});
}
...
...
@@ -918,10 +901,7 @@
/////////////////////////////////////////////////////////////////
RenderJSGadget
.
declareMethod
(
'
declareGadget
'
,
function
(
url
,
options
)
{
var
queue
,
parent_gadget
=
this
,
local_loading_klass_promise
,
previous_loading_klass_promise
=
loading_klass_promise
;
var
parent_gadget
=
this
;
if
(
options
===
undefined
)
{
options
=
{};
...
...
@@ -932,16 +912,8 @@
// transform url to absolute url if it is relative
url
=
renderJS
.
getAbsoluteURL
(
url
,
this
.
__path
);
// Change the global variable to update the loading queue
loading_klass_promise
=
new
RSVP
.
Queue
()
// Wait for previous gadget loading to finish first
.
push
(
function
()
{
return
previous_loading_klass_promise
;
})
.
push
(
undefined
,
function
()
{
// Forget previous declareGadget error
return
;
})
return
new
RSVP
.
Queue
()
.
push
(
function
()
{
var
method
;
if
(
options
.
sandbox
===
"
public
"
)
{
...
...
@@ -957,41 +929,17 @@
return
method
(
url
,
options
,
parent_gadget
);
})
// Set the HTML context
.
push
(
function
(
gadget_instance
)
{
// Drop the current loading klass info used by selector
gadget_loading_klass
=
undefined
;
return
gadget_instance
;
})
.
push
(
undefined
,
function
(
e
)
{
// Drop the current loading klass info used by selector
// even in case of error
gadget_loading_klass
=
undefined
;
throw
e
;
});
//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
local_loading_klass_promise
=
loading_klass_promise
.
then
(
function
(
gadget_instance
)
{
return
gadget_instance
;
});
queue
=
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
local_loading_klass_promise
;
})
// Set the HTML context
.
push
(
function
(
gadget_instance
)
{
var
i
,
scope
;
scope
,
queue
=
new
RSVP
.
Queue
();
// Trigger calling of all ready callback
function
ready_wrapper
()
{
return
gadget_instance
;
}
function
ready_executable_wrapper
(
fct
)
{
return
function
(
g
)
{
return
fct
.
call
(
g
,
g
);
return
function
()
{
return
fct
.
call
(
g
adget_instance
,
gadget_instance
);
};
}
for
(
i
=
0
;
i
<
gadget_instance
.
constructor
.
__ready_list
.
length
;
...
...
@@ -1031,9 +979,8 @@
// Always return the gadget instance after ready function
queue
.
push
(
ready_wrapper
);
return
gadget_instanc
e
;
return
queu
e
;
});
return
queue
;
})
.
declareMethod
(
'
getDeclaredGadget
'
,
function
(
gadget_scope
)
{
if
(
!
this
.
__sub_gadget_dict
.
hasOwnProperty
(
gadget_scope
))
{
...
...
@@ -1153,77 +1100,119 @@
/////////////////////////////////////////////////////////////////
// renderJS.declareGadgetKlass
/////////////////////////////////////////////////////////////////
renderJS
.
declareGadgetKlass
=
function
(
url
)
{
var
result
;
function
parse
(
xhr
)
{
var
tmp_constructor
,
key
,
parsed_html
;
if
(
!
gadget_model_dict
.
hasOwnProperty
(
url
))
{
// 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
];
}
}
gadget_model_dict
[
url
]
=
tmp_constructor
;
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
gadget_model_dict
[
url
];
}
return
tmp_constructor
;
}
if
(
gadget_model_dict
.
hasOwnProperty
(
url
))
{
renderJS
.
declareGadgetKlass
=
function
(
url
)
{
if
(
gadget_model_defer_dict
.
hasOwnProperty
(
url
))
{
// Return klass object if it already exists
result
=
RSVP
.
resolve
(
gadget_model_dict
[
url
]);
}
else
{
// Fetch the HTML page and parse it
result
=
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
ajax
(
url
);
})
.
push
(
function
(
xhr
)
{
return
parse
(
xhr
);
});
return
gadget_model_defer_dict
[
url
].
promise
;
}
return
result
;
var
tmp_constructor
,
defer
=
RSVP
.
defer
(),
previous_loading_klass_promise
=
loading_klass_promise
;
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
RSVP
.
all
([
ajax
(
url
),
// Wait for previous gadget loading to finish first
new
RSVP
.
Queue
()
.
push
(
function
()
{
return
previous_loading_klass_promise
;
})
.
push
(
undefined
,
function
()
{
// Forget previous declareGadget error
return
;
})
]);
})
.
push
(
function
(
result_list
)
{
tmp_constructor
=
parse
(
result_list
[
0
],
url
);
gadget_loading_klass
=
tmp_constructor
;
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
for
(
i
=
0
;
i
<
js_list
.
length
;
i
+=
1
)
{
promise_list
.
push
(
renderJS
.
declareJS
(
js_list
[
i
],
fragment
));
}
// 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
);
// Drop the current loading klass info used by selector
gadget_loading_klass
=
undefined
;
return
tmp_constructor
;
})
.
push
(
undefined
,
function
(
e
)
{
// Drop the current loading klass info used by selector
// even in case of error
defer
.
reject
(
e
);
gadget_loading_klass
=
undefined
;
throw
e
;
});
};
/////////////////////////////////////////////////////////////////
...
...
@@ -1231,7 +1220,7 @@
/////////////////////////////////////////////////////////////////
// For test purpose only
renderJS
.
clearGadgetKlassList
=
function
()
{
gadget_model_dict
=
{};
gadget_model_d
efer_d
ict
=
{};
javascript_registration_dict
=
{};
stylesheet_registration_dict
=
{};
};
...
...
@@ -1301,7 +1290,7 @@
function
bootstrap
()
{
var
url
=
removeHash
(
window
.
location
.
href
),
tmp_c
onstructor
,
TmpC
onstructor
,
root_gadget
,
loading_gadget_promise
=
new
RSVP
.
Queue
(),
declare_method_count
=
0
,
...
...
@@ -1317,7 +1306,7 @@
connection_ready
=
false
;
// Create the gadget class for the current url
if
(
gadget_model_dict
.
hasOwnProperty
(
url
))
{
if
(
gadget_model_d
efer_d
ict
.
hasOwnProperty
(
url
))
{
throw
new
Error
(
"
bootstrap should not be called twice
"
);
}
loading_klass_promise
=
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
...
...
@@ -1346,40 +1335,42 @@
// tmp_constructor = RenderJSEmbeddedGadget
if
(
window
.
self
===
window
.
top
)
{
// XXX Copy/Paste from declareGadgetKlass
tmp_c
onstructor
=
function
()
{
TmpC
onstructor
=
function
()
{
RenderJSGadget
.
call
(
this
);
};
tmp_c
onstructor
.
declareMethod
=
RenderJSGadget
.
declareMethod
;
tmp_c
onstructor
.
declareJob
=
RenderJSGadget
.
declareJob
;
tmp_c
onstructor
.
declareAcquiredMethod
=
TmpC
onstructor
.
declareMethod
=
RenderJSGadget
.
declareMethod
;
TmpC
onstructor
.
declareJob
=
RenderJSGadget
.
declareJob
;
TmpC
onstructor
.
declareAcquiredMethod
=
RenderJSGadget
.
declareAcquiredMethod
;
tmp_c
onstructor
.
allowPublicAcquisition
=
TmpC
onstructor
.
allowPublicAcquisition
=
RenderJSGadget
.
allowPublicAcquisition
;
tmp_c
onstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
tmp_c
onstructor
.
ready
=
RenderJSGadget
.
ready
;
tmp_c
onstructor
.
setState
=
RenderJSGadget
.
setState
;
tmp_c
onstructor
.
onStateChange
=
RenderJSGadget
.
onStateChange
;
tmp_c
onstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
tmp_c
onstructor
.
declareService
=
TmpC
onstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
TmpC
onstructor
.
ready
=
RenderJSGadget
.
ready
;
TmpC
onstructor
.
setState
=
RenderJSGadget
.
setState
;
TmpC
onstructor
.
onStateChange
=
RenderJSGadget
.
onStateChange
;
TmpC
onstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
TmpC
onstructor
.
declareService
=
RenderJSGadget
.
declareService
;
tmp_c
onstructor
.
onEvent
=
TmpC
onstructor
.
onEvent
=
RenderJSGadget
.
onEvent
;
tmp_constructor
.
prototype
=
new
RenderJSGadget
();
tmp_constructor
.
prototype
.
constructor
=
tmp_constructor
;
tmp_constructor
.
prototype
.
__path
=
url
;
gadget_model_dict
[
url
]
=
tmp_constructor
;
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
gadget_model_dict
[
url
]
();
root_gadget
=
new
TmpConstructor
();
setAqParent
(
root_gadget
,
last_acquisition_gadget
);
}
else
{
// Create the root gadget instance and put it in the loading stack
tmp_c
onstructor
=
RenderJSEmbeddedGadget
;
tmp_c
onstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
tmp_c
onstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
tmp_c
onstructor
.
prototype
.
__path
=
url
;
TmpC
onstructor
=
RenderJSEmbeddedGadget
;
TmpC
onstructor
.
__ready_list
=
RenderJSGadget
.
__ready_list
.
slice
();
TmpC
onstructor
.
__service_list
=
RenderJSGadget
.
__service_list
.
slice
();
TmpC
onstructor
.
prototype
.
__path
=
url
;
root_gadget
=
new
RenderJSEmbeddedGadget
();
setAqParent
(
root_gadget
,
last_acquisition_gadget
);
...
...
@@ -1393,7 +1384,7 @@
iframe_top_gadget
=
false
;
//Default: Define __aq_parent to inform parent window
root_gadget
.
__aq_parent
=
tmp_c
onstructor
.
prototype
.
__aq_parent
=
function
(
method_name
,
TmpC
onstructor
.
prototype
.
__aq_parent
=
function
(
method_name
,
argument_list
,
time_out
)
{
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
embedded_channel
.
call
({
...
...
@@ -1475,7 +1466,7 @@
notifyDeclareMethod
(
"
getTitle
"
);
// Surcharge declareMethod to inform parent window
tmp_c
onstructor
.
declareMethod
=
function
(
name
,
callback
)
{
TmpC
onstructor
.
declareMethod
=
function
(
name
,
callback
)
{
var
result
=
RenderJSGadget
.
declareMethod
.
apply
(
this
,
[
name
,
callback
]
...
...
@@ -1484,22 +1475,22 @@
return
result
;
};
tmp_c
onstructor
.
declareService
=
TmpC
onstructor
.
declareService
=
RenderJSGadget
.
declareService
;
tmp_c
onstructor
.
declareJob
=
TmpC
onstructor
.
declareJob
=
RenderJSGadget
.
declareJob
;
tmp_c
onstructor
.
onEvent
=
TmpC
onstructor
.
onEvent
=
RenderJSGadget
.
onEvent
;
tmp_c
onstructor
.
declareAcquiredMethod
=
TmpC
onstructor
.
declareAcquiredMethod
=
RenderJSGadget
.
declareAcquiredMethod
;
tmp_c
onstructor
.
allowPublicAcquisition
=
TmpC
onstructor
.
allowPublicAcquisition
=
RenderJSGadget
.
allowPublicAcquisition
;
iframe_top_gadget
=
true
;
}
tmp_c
onstructor
.
prototype
.
__acquired_method_dict
=
{};
gadget_loading_klass
=
tmp_c
onstructor
;
TmpC
onstructor
.
prototype
.
__acquired_method_dict
=
{};
gadget_loading_klass
=
TmpC
onstructor
;
function
init
()
{
// XXX HTML properties can only be set when the DOM is fully loaded
...
...
@@ -1508,14 +1499,14 @@
key
;
for
(
key
in
settings
)
{
if
(
settings
.
hasOwnProperty
(
key
))
{
tmp_c
onstructor
.
prototype
[
'
__
'
+
key
]
=
settings
[
key
];
TmpC
onstructor
.
prototype
[
'
__
'
+
key
]
=
settings
[
key
];
}
}
tmp_c
onstructor
.
__template_element
=
document
.
createElement
(
"
div
"
);
TmpC
onstructor
.
__template_element
=
document
.
createElement
(
"
div
"
);
root_gadget
.
element
=
document
.
body
;
root_gadget
.
state
=
{};
for
(
j
=
0
;
j
<
root_gadget
.
element
.
childNodes
.
length
;
j
+=
1
)
{
tmp_c
onstructor
.
__template_element
.
appendChild
(
TmpC
onstructor
.
__template_element
.
appendChild
(
root_gadget
.
element
.
childNodes
[
j
].
cloneNode
(
true
)
);
}
...
...
@@ -1625,15 +1616,15 @@
return
fct
.
call
(
g
,
g
);
};
}
tmp_c
onstructor
.
ready
(
function
(
g
)
{
TmpC
onstructor
.
ready
(
function
(
g
)
{
return
startService
(
g
);
});
loading_gadget_promise
.
push
(
ready_wrapper
);
for
(
i
=
0
;
i
<
tmp_c
onstructor
.
__ready_list
.
length
;
i
+=
1
)
{
for
(
i
=
0
;
i
<
TmpC
onstructor
.
__ready_list
.
length
;
i
+=
1
)
{
// Put a timeout?
loading_gadget_promise
.
push
(
ready_executable_wrapper
(
tmp_c
onstructor
.
__ready_list
[
i
]))
.
push
(
ready_executable_wrapper
(
TmpC
onstructor
.
__ready_list
[
i
]))
// Always return the gadget instance after ready function
.
push
(
ready_wrapper
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment