marko/components/util-browser.js
2017-03-28 11:02:12 -06:00

136 lines
3.7 KiB
JavaScript

var markoGlobal = window.$MG || (window.$MG = {
uid: 0
});
var runtimeId = markoGlobal.uid++;
var componentLookup = {};
var defaultDocument = document;
var EMPTY_OBJECT = {};
function getComponentForEl(el, doc) {
if (el) {
var node = typeof el == 'string' ? (doc || defaultDocument).getElementById(el) : el;
if (node) {
var component = node._w;
while(component) {
var rootFor = component.$__rootFor;
if (rootFor) {
component = rootFor;
} else {
break;
}
}
return component;
}
}
}
var lifecycleEventMethods = {};
[
'create',
'render',
'update',
'mount',
'destroy',
].forEach(function(eventName) {
lifecycleEventMethods[eventName] = 'on' + eventName[0].toUpperCase() + eventName.substring(1);
});
/**
* This method handles invoking a component's event handler method
* (if present) while also emitting the event through
* the standard EventEmitter.prototype.emit method.
*
* Special events and their corresponding handler methods
* include the following:
*
* beforeDestroy --> onBeforeDestroy
* destroy --> onDestroy
* beforeUpdate --> onBeforeUpdate
* update --> onUpdate
* render --> onRender
*/
function emitLifecycleEvent(component, eventType, eventArg1, eventArg2) {
var listenerMethod = component[lifecycleEventMethods[eventType]];
if (listenerMethod !== undefined) {
listenerMethod.call(component, eventArg1, eventArg2);
}
component.emit(eventType, eventArg1, eventArg2);
}
function destroyComponentForEl(el) {
var componentToDestroy = el._w;
if (componentToDestroy) {
componentToDestroy.$__destroyShallow();
el._w = null;
while ((componentToDestroy = componentToDestroy.$__rootFor)) {
componentToDestroy.$__rootFor = null;
componentToDestroy.$__destroyShallow();
}
}
}
function destroyElRecursive(el) {
var curChild = el.firstChild;
while(curChild) {
if (curChild.nodeType === 1) {
destroyComponentForEl(curChild);
destroyElRecursive(curChild);
}
curChild = curChild.nextSibling;
}
}
function nextComponentId() {
// Each component will get an ID that is unique across all loaded
// marko runtimes. This allows multiple instances of marko to be
// loaded in the same window and they should all place nice
// together
return 'b' + ((markoGlobal.uid)++);
}
function getElementById(doc, id) {
return doc.getElementById(id);
}
function attachBubblingEvent(componentDef, handlerMethodName, extraArgs) {
if (handlerMethodName) {
var id = componentDef.id;
return extraArgs ?
[handlerMethodName, id, extraArgs] :
[handlerMethodName, id];
}
}
function getMarkoPropsFromEl(el) {
var virtualProps = el._vprops;
if (virtualProps === undefined) {
virtualProps = el.getAttribute('data-marko');
if (virtualProps) {
virtualProps = JSON.parse(virtualProps);
}
el._vprops = virtualProps = virtualProps || EMPTY_OBJECT;
}
return virtualProps;
}
exports.$__runtimeId = runtimeId;
exports.$__componentLookup = componentLookup;
exports.$__getComponentForEl = getComponentForEl;
exports.$__emitLifecycleEvent = emitLifecycleEvent;
exports.$__destroyComponentForEl = destroyComponentForEl;
exports.$__destroyElRecursive = destroyElRecursive;
exports.$__nextComponentId = nextComponentId;
exports.$__getElementById = getElementById;
exports.$__attachBubblingEvent = attachBubblingEvent;
exports.$__getMarkoPropsFromEl = getMarkoPropsFromEl;