mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Added support for immediate widget initialization (versus waiting for DOM ready event)
Also, better support for initializing widgets in async fragments.
This commit is contained in:
parent
0279d17c46
commit
7c8c8a8f49
@ -6,9 +6,9 @@ var initWidgets = require('./init-widgets');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var inherit = require('raptor-util/inherit');
|
||||
|
||||
function WidgetsContext(context) {
|
||||
function WidgetsContext(out) {
|
||||
EventEmitter.call(this);
|
||||
this.context = context;
|
||||
this.out = out;
|
||||
this.widgets = [];
|
||||
this.widgetStack = [];
|
||||
}
|
||||
@ -54,7 +54,7 @@ WidgetsContext.prototype = {
|
||||
_this.widgets.push(widgetDef);
|
||||
}
|
||||
widgetStack.push(widgetDef);
|
||||
|
||||
|
||||
this.emit('beginWidget', widgetDef);
|
||||
|
||||
return widgetDef;
|
||||
@ -67,7 +67,7 @@ WidgetsContext.prototype = {
|
||||
this.widgetStack = [];
|
||||
},
|
||||
_nextWidgetId: function () {
|
||||
return 'w' + uniqueId(this.context);
|
||||
return 'w' + uniqueId(this.out);
|
||||
},
|
||||
initWidgets: function () {
|
||||
var widgetDefs = this.widgets;
|
||||
@ -81,11 +81,11 @@ WidgetsContext.prototype = {
|
||||
|
||||
inherit(WidgetsContext, EventEmitter);
|
||||
|
||||
WidgetsContext.getWidgetsContext = function (context) {
|
||||
var attributes = context.attributes;
|
||||
WidgetsContext.getWidgetsContext = function (out) {
|
||||
var global = out.global;
|
||||
|
||||
return attributes[WIDGET_CONTEXT_KEY] ||
|
||||
(attributes[WIDGET_CONTEXT_KEY] = new WidgetsContext(context));
|
||||
return global[WIDGET_CONTEXT_KEY] ||
|
||||
(global[WIDGET_CONTEXT_KEY] = new WidgetsContext(out));
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -304,21 +304,29 @@ exports.initClientRendered = function(widgetDefs) {
|
||||
* @param {boolean} If the
|
||||
*/
|
||||
exports.initServerRendered = function(scanDOM) {
|
||||
ready(function() {
|
||||
var idsEl = document.getElementById('rwidgets');
|
||||
if (!idsEl && !scanDOM) { // If there is no index and "scan DOM" is not set to true then do nothing
|
||||
return;
|
||||
function doInit() {
|
||||
var dataIds;
|
||||
|
||||
if (typeof scanDOM === 'string') {
|
||||
dataIds = scanDOM;
|
||||
scanDOM = false;
|
||||
} else {
|
||||
var idsEl = document.getElementById('rwidgets');
|
||||
if (!idsEl && !scanDOM) { // If there is no index and "scan DOM" is not set to true then do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure widgets are only initialized once by checking a flag
|
||||
if (document.rwidgetsInitialized === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set flag to avoid trying to do this multiple times
|
||||
document.rwidgetsInitialized = true;
|
||||
|
||||
dataIds = idsEl ? idsEl.getAttribute('data-ids') : null;
|
||||
}
|
||||
|
||||
// Make sure widgets are only initialized once by checking a flag
|
||||
if (document.rwidgetsInitialized === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set flag to avoid trying to do this multiple times
|
||||
document.rwidgetsInitialized = true;
|
||||
|
||||
var dataIds = idsEl ? idsEl.getAttribute('data-ids') : null;
|
||||
var initContext = new InitContext();
|
||||
if (dataIds == null || dataIds === '*') { // If the data-ids attribute is * then server is tell us we need to scan the DOM
|
||||
initAllWidgetsInDOM(initContext);
|
||||
@ -336,5 +344,13 @@ exports.initServerRendered = function(scanDOM) {
|
||||
initWidgetFromEl(el, initContext);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof scanDOM === 'string') {
|
||||
doInit();
|
||||
} else {
|
||||
ready(doInit);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
@ -60,4 +60,8 @@ raptorPubsub
|
||||
if (widgetsContext) {
|
||||
widgetsContext.initWidgets();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.$rwidgets = function(ids) {
|
||||
initWidgets.initServerRendered(ids);
|
||||
};
|
||||
@ -112,17 +112,19 @@ exports.attrs = function(widget) {
|
||||
return attrs;
|
||||
};
|
||||
|
||||
exports.writeInitWidgetsCode = function(widgetsContext, context, options) {
|
||||
exports.writeInitWidgetsCode = function(widgetsContext, out, options) {
|
||||
var clearWidgets = true;
|
||||
var scanDOM = false;
|
||||
var immediate = false;
|
||||
|
||||
if (options) {
|
||||
clearWidgets = options.clearWidgets !== false;
|
||||
scanDOM = options.scanDOM === true;
|
||||
immediate = options.immediate === true;
|
||||
}
|
||||
|
||||
if (scanDOM) {
|
||||
context.write(TAG_START + '*' + TAG_END);
|
||||
out.write(TAG_START + '*' + TAG_END);
|
||||
} else {
|
||||
var widgets = widgetsContext.getWidgets();
|
||||
|
||||
@ -134,12 +136,6 @@ exports.writeInitWidgetsCode = function(widgetsContext, context, options) {
|
||||
|
||||
var commaRequired = false;
|
||||
|
||||
var writeWidgets = function(widgets) {
|
||||
for (var i = 0, len = widgets.length; i < len; i++) {
|
||||
writeWidget(widgets[i]);
|
||||
}
|
||||
};
|
||||
|
||||
var writeWidget = function(widget) {
|
||||
|
||||
if (widget.children.length) {
|
||||
@ -156,9 +152,19 @@ exports.writeInitWidgetsCode = function(widgetsContext, context, options) {
|
||||
ids += widget.id;
|
||||
};
|
||||
|
||||
var writeWidgets = function(widgets) {
|
||||
for (var i = 0, len = widgets.length; i < len; i++) {
|
||||
writeWidget(widgets[i]);
|
||||
}
|
||||
};
|
||||
|
||||
writeWidgets(widgets);
|
||||
|
||||
context.write(TAG_START + ids + TAG_END);
|
||||
if (immediate) {
|
||||
out.write('<script type="text/javascript">$rwidgets("' + ids + '")</script>');
|
||||
} else {
|
||||
out.write(TAG_START + ids + TAG_END);
|
||||
}
|
||||
}
|
||||
|
||||
if (clearWidgets !== false) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
module.exports = function (context) {
|
||||
var attrs = context.attributes;
|
||||
if (!attrs._nextId) {
|
||||
attrs._nextId = 0;
|
||||
module.exports = function (out) {
|
||||
var global = out.global;
|
||||
if (!global._nextWidgetId) {
|
||||
global._nextWidgetId = 0;
|
||||
}
|
||||
return attrs._nextId++;
|
||||
return global._nextWidgetId++;
|
||||
};
|
||||
@ -38,14 +38,16 @@
|
||||
"renderer": "./taglib/init-widgets-tag.js",
|
||||
"attributes": {
|
||||
"function-name": "string",
|
||||
"include-script-tag": "boolean"
|
||||
"include-script-tag": "boolean",
|
||||
"immediate": "boolean"
|
||||
}
|
||||
},
|
||||
"init-widgets": {
|
||||
"renderer": "./taglib/init-widgets-tag.js",
|
||||
"attributes": {
|
||||
"function-name": "string",
|
||||
"include-script-tag": "boolean"
|
||||
"include-script-tag": "boolean",
|
||||
"immediate": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,32 @@
|
||||
var raptorWidgets = require('../');
|
||||
var markoWidgets = require('../');
|
||||
|
||||
module.exports = function render(input, context) {
|
||||
var widgetsContext = raptorWidgets.getWidgetsContext(context);
|
||||
module.exports = function render(input, out) {
|
||||
var widgetsContext = markoWidgets.getWidgetsContext(out);
|
||||
|
||||
if (context.featureLastFlush === false) {
|
||||
// If the rendering context doesn't support the ability to know when all of the asynchronous fragmnents
|
||||
var options = input.immediate ? {immediate: true} : null;
|
||||
|
||||
if (input.immediate === true) {
|
||||
out.on('asyncFragmentFinish', function(eventArgs) {
|
||||
var asyncFragmentOut = eventArgs.out;
|
||||
var widgetsContext = markoWidgets.getWidgetsContext(asyncFragmentOut);
|
||||
markoWidgets.writeInitWidgetsCode(widgetsContext, asyncFragmentOut, options);
|
||||
});
|
||||
}
|
||||
|
||||
if (out.featureLastFlush === false) {
|
||||
// If the rendering out doesn't support the ability to know when all of the asynchronous fragmnents
|
||||
// have completed then we won't be able to know which widgets were rendered so we will
|
||||
// need to scan the DOM to find the widgets
|
||||
raptorWidgets.writeInitWidgetsCode(widgetsContext, context, {scanDOM: true});
|
||||
markoWidgets.writeInitWidgetsCode(widgetsContext, out, {scanDOM: true});
|
||||
} else {
|
||||
var asyncContext = context.beginAsync({ last: true, timeout: -1 });
|
||||
context.once('last', function() {
|
||||
if (!widgetsContext.hasWidgets()) {
|
||||
return asyncContext.end();
|
||||
var asyncOut = out.beginAsync({ last: true, timeout: -1 });
|
||||
out.onLast(function(next) {
|
||||
if (widgetsContext.hasWidgets()) {
|
||||
markoWidgets.writeInitWidgetsCode(widgetsContext, asyncOut, options);
|
||||
}
|
||||
|
||||
raptorWidgets.writeInitWidgetsCode(widgetsContext, asyncContext);
|
||||
asyncContext.end();
|
||||
asyncOut.end();
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -4,16 +4,16 @@ var DUMMY_WIDGET_DEF = {
|
||||
elId: function () {
|
||||
}
|
||||
};
|
||||
module.exports = function render(input, context) {
|
||||
module.exports = function render(input, out) {
|
||||
var modulePath = input.module;
|
||||
var config = input.config || input._cfg;
|
||||
var widgetArgs = context.attributes.widgetArgs;
|
||||
var widgetArgs = out.global.widgetArgs;
|
||||
var id = input.id;
|
||||
var scope = input.scope || context.getAttribute('widget');
|
||||
var scope = input.scope || out.getAttribute('widget');
|
||||
var assignedId = input.assignedId;
|
||||
var events;
|
||||
if (widgetArgs) {
|
||||
delete context.attributes.widgetArgs;
|
||||
delete out.global.widgetArgs;
|
||||
scope = scope || widgetArgs.scope;
|
||||
assignedId = assignedId || widgetArgs.id;
|
||||
events = widgetArgs.events;
|
||||
@ -21,7 +21,7 @@ module.exports = function render(input, context) {
|
||||
if (!id && input.hasOwnProperty('id')) {
|
||||
throw new Error('Invalid widget ID for "' + modulePath + '"');
|
||||
}
|
||||
var widgetsContext = widgets.getWidgetsContext(context);
|
||||
var widgetsContext = widgets.getWidgetsContext(out);
|
||||
|
||||
if (modulePath) {
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user