2015-09-03 22:01:36 -07:00
|
|
|
import {Inject, Injectable, OpaqueToken} from 'angular2/src/core/di';
|
2015-08-28 14:39:34 -07:00
|
|
|
import {AnimationBuilder} from 'angular2/src/animate/animation_builder';
|
2015-11-17 15:24:36 -08:00
|
|
|
|
2015-11-02 08:39:14 -08:00
|
|
|
import {
|
|
|
|
isPresent,
|
|
|
|
isBlank,
|
|
|
|
RegExpWrapper,
|
|
|
|
CONST_EXPR,
|
|
|
|
stringify,
|
|
|
|
StringWrapper
|
|
|
|
} from 'angular2/src/facade/lang';
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-11-17 15:24:36 -08:00
|
|
|
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
2015-10-02 09:30:36 -07:00
|
|
|
import {DomSharedStylesHost} from './shared_styles_host';
|
2015-11-17 15:24:36 -08:00
|
|
|
import {WtfScopeFn, wtfLeave, wtfCreateScope} from 'angular2/src/core/profile/profile';
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-06-24 13:46:39 -07:00
|
|
|
import {
|
|
|
|
Renderer,
|
|
|
|
RenderProtoViewRef,
|
|
|
|
RenderViewRef,
|
|
|
|
RenderElementRef,
|
|
|
|
RenderFragmentRef,
|
2015-10-01 10:07:49 -07:00
|
|
|
RenderViewWithFragments,
|
|
|
|
RenderTemplateCmd,
|
2015-11-02 08:39:14 -08:00
|
|
|
RenderEventDispatcher,
|
2015-11-17 15:24:36 -08:00
|
|
|
RenderComponentTemplate,
|
|
|
|
EventManager
|
|
|
|
} from 'angular2/core';
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-08-20 15:11:12 -07:00
|
|
|
import {DOCUMENT} from './dom_tokens';
|
2015-11-17 15:24:36 -08:00
|
|
|
import {
|
|
|
|
createRenderView,
|
|
|
|
NodeFactory,
|
|
|
|
encapsulateStyles
|
|
|
|
} from 'angular2/src/core/render/view_factory';
|
|
|
|
import {
|
|
|
|
DefaultRenderView,
|
|
|
|
DefaultRenderFragmentRef,
|
|
|
|
DefaultProtoViewRef
|
|
|
|
} from 'angular2/src/core/render/view';
|
2015-10-01 10:07:49 -07:00
|
|
|
import {camelCaseToDashCase} from './util';
|
2015-11-02 08:39:14 -08:00
|
|
|
import {ViewEncapsulation} from 'angular2/src/core/metadata';
|
2015-06-14 16:42:26 -07:00
|
|
|
|
2015-11-17 15:24:36 -08:00
|
|
|
// TODO move it once DomAdapter is moved
|
2015-11-19 15:09:34 -08:00
|
|
|
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
2015-11-17 15:24:36 -08:00
|
|
|
|
2015-11-10 15:56:25 -08:00
|
|
|
const NAMESPACE_URIS =
|
|
|
|
CONST_EXPR({'xlink': 'http://www.w3.org/1999/xlink', 'svg': 'http://www.w3.org/2000/svg'});
|
2015-10-27 13:16:27 -07:00
|
|
|
|
2015-10-06 06:53:39 -07:00
|
|
|
export abstract class DomRenderer extends Renderer implements NodeFactory<Node> {
|
2015-11-02 08:39:14 -08:00
|
|
|
abstract registerComponentTemplate(template: RenderComponentTemplate);
|
2015-10-06 06:53:39 -07:00
|
|
|
|
2015-11-02 08:39:14 -08:00
|
|
|
abstract resolveComponentTemplate(templateId: string): RenderComponentTemplate;
|
2015-10-06 06:53:39 -07:00
|
|
|
|
2015-11-02 08:39:14 -08:00
|
|
|
abstract createProtoView(componentTemplateId: string,
|
|
|
|
cmds: RenderTemplateCmd[]): RenderProtoViewRef;
|
2015-10-06 06:53:39 -07:00
|
|
|
|
|
|
|
abstract createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
|
|
|
|
hostElementSelector: string): RenderViewWithFragments;
|
|
|
|
|
2015-10-28 08:59:19 +01:00
|
|
|
abstract createView(protoViewRef: RenderProtoViewRef,
|
|
|
|
fragmentCount: number): RenderViewWithFragments;
|
2015-10-06 06:53:39 -07:00
|
|
|
|
|
|
|
abstract destroyView(viewRef: RenderViewRef);
|
|
|
|
|
2015-10-09 14:53:04 -07:00
|
|
|
abstract createRootContentInsertionPoint();
|
|
|
|
|
2015-10-06 06:53:39 -07:00
|
|
|
getNativeElementSync(location: RenderElementRef): any {
|
|
|
|
return resolveInternalDomView(location.renderView).boundElements[location.boundElementIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
getRootNodes(fragment: RenderFragmentRef): Node[] { return resolveInternalDomFragment(fragment); }
|
|
|
|
|
|
|
|
attachFragmentAfterFragment(previousFragmentRef: RenderFragmentRef,
|
|
|
|
fragmentRef: RenderFragmentRef) {
|
|
|
|
var previousFragmentNodes = resolveInternalDomFragment(previousFragmentRef);
|
|
|
|
if (previousFragmentNodes.length > 0) {
|
|
|
|
var sibling = previousFragmentNodes[previousFragmentNodes.length - 1];
|
|
|
|
let nodes = resolveInternalDomFragment(fragmentRef);
|
|
|
|
moveNodesAfterSibling(sibling, nodes);
|
|
|
|
this.animateNodesEnter(nodes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Iterates through all nodes being added to the DOM and animates them if necessary
|
|
|
|
* @param nodes
|
|
|
|
*/
|
|
|
|
animateNodesEnter(nodes: Node[]) {
|
|
|
|
for (let i = 0; i < nodes.length; i++) this.animateNodeEnter(nodes[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Performs animations if necessary
|
|
|
|
* @param node
|
|
|
|
*/
|
|
|
|
abstract animateNodeEnter(node: Node);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If animations are necessary, performs animations then removes the element; otherwise, it just
|
|
|
|
* removes the element.
|
|
|
|
* @param node
|
|
|
|
*/
|
|
|
|
abstract animateNodeLeave(node: Node);
|
|
|
|
|
|
|
|
attachFragmentAfterElement(elementRef: RenderElementRef, fragmentRef: RenderFragmentRef) {
|
|
|
|
var parentView = resolveInternalDomView(elementRef.renderView);
|
|
|
|
var element = parentView.boundElements[elementRef.boundElementIndex];
|
|
|
|
var nodes = resolveInternalDomFragment(fragmentRef);
|
|
|
|
moveNodesAfterSibling(element, nodes);
|
|
|
|
this.animateNodesEnter(nodes);
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract detachFragment(fragmentRef: RenderFragmentRef);
|
|
|
|
|
|
|
|
hydrateView(viewRef: RenderViewRef) { resolveInternalDomView(viewRef).hydrate(); }
|
|
|
|
|
|
|
|
dehydrateView(viewRef: RenderViewRef) { resolveInternalDomView(viewRef).dehydrate(); }
|
|
|
|
|
2015-11-16 11:15:28 -08:00
|
|
|
createTemplateAnchor(attrNameAndValues: string[]): Node {
|
|
|
|
return this.createElement('script', attrNameAndValues);
|
|
|
|
}
|
2015-10-06 06:53:39 -07:00
|
|
|
abstract createElement(name: string, attrNameAndValues: string[]): Node;
|
|
|
|
abstract mergeElement(existing: Node, attrNameAndValues: string[]);
|
2015-11-02 08:39:14 -08:00
|
|
|
abstract createShadowRoot(host: Node, templateId: string): Node;
|
2015-10-06 06:53:39 -07:00
|
|
|
createText(value: string): Node { return DOM.createTextNode(isPresent(value) ? value : ''); }
|
|
|
|
appendChild(parent: Node, child: Node) { DOM.appendChild(parent, child); }
|
|
|
|
abstract on(element: Node, eventName: string, callback: Function);
|
|
|
|
abstract globalOn(target: string, eventName: string, callback: Function): Function;
|
|
|
|
|
|
|
|
setElementProperty(location: RenderElementRef, propertyName: string, propertyValue: any): void {
|
|
|
|
var view = resolveInternalDomView(location.renderView);
|
|
|
|
DOM.setProperty(<Element>view.boundElements[location.boundElementIndex], propertyName,
|
|
|
|
propertyValue);
|
|
|
|
}
|
|
|
|
|
2015-10-28 08:59:19 +01:00
|
|
|
setElementAttribute(location: RenderElementRef, attributeName: string,
|
|
|
|
attributeValue: string): void {
|
2015-10-06 06:53:39 -07:00
|
|
|
var view = resolveInternalDomView(location.renderView);
|
|
|
|
var element = view.boundElements[location.boundElementIndex];
|
|
|
|
var dashCasedAttributeName = camelCaseToDashCase(attributeName);
|
|
|
|
if (isPresent(attributeValue)) {
|
|
|
|
DOM.setAttribute(element, dashCasedAttributeName, stringify(attributeValue));
|
|
|
|
} else {
|
|
|
|
DOM.removeAttribute(element, dashCasedAttributeName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setElementClass(location: RenderElementRef, className: string, isAdd: boolean): void {
|
|
|
|
var view = resolveInternalDomView(location.renderView);
|
|
|
|
var element = view.boundElements[location.boundElementIndex];
|
|
|
|
if (isAdd) {
|
|
|
|
DOM.addClass(element, className);
|
|
|
|
} else {
|
|
|
|
DOM.removeClass(element, className);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setElementStyle(location: RenderElementRef, styleName: string, styleValue: string): void {
|
|
|
|
var view = resolveInternalDomView(location.renderView);
|
|
|
|
var element = view.boundElements[location.boundElementIndex];
|
|
|
|
var dashCasedStyleName = camelCaseToDashCase(styleName);
|
|
|
|
if (isPresent(styleValue)) {
|
|
|
|
DOM.setStyle(element, dashCasedStyleName, stringify(styleValue));
|
|
|
|
} else {
|
|
|
|
DOM.removeStyle(element, dashCasedStyleName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
invokeElementMethod(location: RenderElementRef, methodName: string, args: any[]): void {
|
|
|
|
var view = resolveInternalDomView(location.renderView);
|
|
|
|
var element = <Element>view.boundElements[location.boundElementIndex];
|
|
|
|
DOM.invoke(element, methodName, args);
|
|
|
|
}
|
|
|
|
|
|
|
|
setText(viewRef: RenderViewRef, textNodeIndex: number, text: string): void {
|
|
|
|
var view = resolveInternalDomView(viewRef);
|
|
|
|
DOM.setText(view.boundTextNodes[textNodeIndex], text);
|
|
|
|
}
|
|
|
|
|
|
|
|
setEventDispatcher(viewRef: RenderViewRef, dispatcher: RenderEventDispatcher): void {
|
|
|
|
resolveInternalDomView(viewRef).setEventDispatcher(dispatcher);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-06 10:49:42 -07:00
|
|
|
@Injectable()
|
2015-10-06 06:53:39 -07:00
|
|
|
export class DomRenderer_ extends DomRenderer {
|
2015-11-02 08:39:14 -08:00
|
|
|
private _componentTpls: Map<string, RenderComponentTemplate> =
|
|
|
|
new Map<string, RenderComponentTemplate>();
|
2015-10-01 10:07:49 -07:00
|
|
|
private _document;
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-07-31 10:58:24 -07:00
|
|
|
constructor(private _eventManager: EventManager,
|
2015-08-28 14:39:34 -07:00
|
|
|
private _domSharedStylesHost: DomSharedStylesHost, private _animate: AnimationBuilder,
|
2015-10-01 10:07:49 -07:00
|
|
|
@Inject(DOCUMENT) document) {
|
2015-10-06 06:53:39 -07:00
|
|
|
super();
|
2015-05-06 10:49:42 -07:00
|
|
|
this._document = document;
|
|
|
|
}
|
|
|
|
|
2015-11-02 08:39:14 -08:00
|
|
|
registerComponentTemplate(template: RenderComponentTemplate) {
|
|
|
|
this._componentTpls.set(template.id, template);
|
|
|
|
if (template.encapsulation !== ViewEncapsulation.Native) {
|
|
|
|
var encapsulatedStyles = encapsulateStyles(template);
|
|
|
|
this._domSharedStylesHost.addStyles(encapsulatedStyles);
|
2015-10-05 09:43:00 -07:00
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
}
|
|
|
|
|
2015-11-02 08:39:14 -08:00
|
|
|
createProtoView(componentTemplateId: string, cmds: RenderTemplateCmd[]): RenderProtoViewRef {
|
|
|
|
return new DefaultProtoViewRef(this._componentTpls.get(componentTemplateId), cmds);
|
|
|
|
}
|
|
|
|
|
|
|
|
resolveComponentTemplate(templateId: string): RenderComponentTemplate {
|
|
|
|
return this._componentTpls.get(templateId);
|
2015-10-01 10:07:49 -07:00
|
|
|
}
|
|
|
|
|
2015-10-09 17:21:25 -07:00
|
|
|
/** @internal */
|
2015-08-24 17:01:07 -07:00
|
|
|
_createRootHostViewScope: WtfScopeFn = wtfCreateScope('DomRenderer#createRootHostView()');
|
2015-06-24 13:46:39 -07:00
|
|
|
createRootHostView(hostProtoViewRef: RenderProtoViewRef, fragmentCount: number,
|
|
|
|
hostElementSelector: string): RenderViewWithFragments {
|
2015-08-24 17:01:07 -07:00
|
|
|
var s = this._createRootHostViewScope();
|
2015-05-15 09:55:43 -07:00
|
|
|
var element = DOM.querySelector(this._document, hostElementSelector);
|
2015-05-06 10:49:42 -07:00
|
|
|
if (isBlank(element)) {
|
2015-06-14 16:42:26 -07:00
|
|
|
wtfLeave(s);
|
2015-05-06 10:49:42 -07:00
|
|
|
throw new BaseException(`The selector "${hostElementSelector}" did not match any elements`);
|
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
return wtfLeave(s, this._createView(hostProtoViewRef, element));
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
|
|
|
|
2015-10-09 17:21:25 -07:00
|
|
|
/** @internal */
|
2015-08-24 17:01:07 -07:00
|
|
|
_createViewScope = wtfCreateScope('DomRenderer#createView()');
|
2015-06-24 13:46:39 -07:00
|
|
|
createView(protoViewRef: RenderProtoViewRef, fragmentCount: number): RenderViewWithFragments {
|
2015-08-24 17:01:07 -07:00
|
|
|
var s = this._createViewScope();
|
2015-10-01 10:07:49 -07:00
|
|
|
return wtfLeave(s, this._createView(protoViewRef, null));
|
|
|
|
}
|
|
|
|
|
|
|
|
private _createView(protoViewRef: RenderProtoViewRef,
|
|
|
|
inplaceElement: HTMLElement): RenderViewWithFragments {
|
2015-11-02 08:39:14 -08:00
|
|
|
var dpvr = <DefaultProtoViewRef>protoViewRef;
|
|
|
|
var view = createRenderView(dpvr.template, dpvr.cmds, inplaceElement, this);
|
2015-10-01 10:07:49 -07:00
|
|
|
var sdRoots = view.nativeShadowRoots;
|
|
|
|
for (var i = 0; i < sdRoots.length; i++) {
|
|
|
|
this._domSharedStylesHost.addHost(sdRoots[i]);
|
|
|
|
}
|
|
|
|
return new RenderViewWithFragments(view, view.fragments);
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
|
|
|
|
2015-06-24 13:46:39 -07:00
|
|
|
destroyView(viewRef: RenderViewRef) {
|
2015-10-01 10:07:49 -07:00
|
|
|
var view = <DefaultRenderView<Node>>viewRef;
|
|
|
|
var sdRoots = view.nativeShadowRoots;
|
|
|
|
for (var i = 0; i < sdRoots.length; i++) {
|
|
|
|
this._domSharedStylesHost.removeHost(sdRoots[i]);
|
2015-07-24 15:28:44 -07:00
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
|
|
|
|
2015-08-28 14:39:34 -07:00
|
|
|
animateNodeEnter(node: Node) {
|
|
|
|
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
|
|
|
|
DOM.addClass(node, 'ng-enter');
|
|
|
|
this._animate.css()
|
|
|
|
.addAnimationClass('ng-enter-active')
|
|
|
|
.start(<HTMLElement>node)
|
|
|
|
.onComplete(() => { DOM.removeClass(node, 'ng-enter'); });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
animateNodeLeave(node: Node) {
|
|
|
|
if (DOM.isElementNode(node) && DOM.hasClass(node, 'ng-animate')) {
|
|
|
|
DOM.addClass(node, 'ng-leave');
|
|
|
|
this._animate.css()
|
|
|
|
.addAnimationClass('ng-leave-active')
|
|
|
|
.start(<HTMLElement>node)
|
|
|
|
.onComplete(() => {
|
|
|
|
DOM.removeClass(node, 'ng-leave');
|
|
|
|
DOM.remove(node);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
DOM.remove(node);
|
2015-07-16 15:18:02 -07:00
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
|
|
|
|
2015-10-09 17:21:25 -07:00
|
|
|
/** @internal */
|
2015-08-24 17:01:07 -07:00
|
|
|
_detachFragmentScope = wtfCreateScope('DomRenderer#detachFragment()');
|
2015-06-24 13:46:39 -07:00
|
|
|
detachFragment(fragmentRef: RenderFragmentRef) {
|
2015-08-24 17:01:07 -07:00
|
|
|
var s = this._detachFragmentScope();
|
2015-06-24 13:46:39 -07:00
|
|
|
var fragmentNodes = resolveInternalDomFragment(fragmentRef);
|
|
|
|
for (var i = 0; i < fragmentNodes.length; i++) {
|
2015-08-28 14:39:34 -07:00
|
|
|
this.animateNodeLeave(fragmentNodes[i]);
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
2015-06-14 16:42:26 -07:00
|
|
|
wtfLeave(s);
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
createElement(name: string, attrNameAndValues: string[]): Node {
|
2015-11-10 15:56:25 -08:00
|
|
|
var nsAndName = splitNamespace(name);
|
|
|
|
var el = isPresent(nsAndName[0]) ?
|
|
|
|
DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
|
|
|
|
DOM.createElement(nsAndName[1]);
|
|
|
|
this._setAttributes(el, attrNameAndValues);
|
2015-10-01 10:07:49 -07:00
|
|
|
return el;
|
|
|
|
}
|
|
|
|
mergeElement(existing: Node, attrNameAndValues: string[]) {
|
|
|
|
DOM.clearNodes(existing);
|
2015-11-10 15:56:25 -08:00
|
|
|
this._setAttributes(existing, attrNameAndValues);
|
2015-10-01 10:07:49 -07:00
|
|
|
}
|
2015-11-10 15:56:25 -08:00
|
|
|
private _setAttributes(node: Node, attrNameAndValues: string[]) {
|
2015-10-01 10:07:49 -07:00
|
|
|
for (var attrIdx = 0; attrIdx < attrNameAndValues.length; attrIdx += 2) {
|
2015-11-10 15:56:25 -08:00
|
|
|
var attrNs;
|
2015-10-27 13:16:27 -07:00
|
|
|
var attrName = attrNameAndValues[attrIdx];
|
2015-11-10 15:56:25 -08:00
|
|
|
var nsAndName = splitNamespace(attrName);
|
|
|
|
if (isPresent(nsAndName[0])) {
|
|
|
|
attrName = nsAndName[0] + ':' + nsAndName[1];
|
|
|
|
attrNs = NAMESPACE_URIS[nsAndName[0]];
|
|
|
|
}
|
2015-10-27 13:16:27 -07:00
|
|
|
var attrValue = attrNameAndValues[attrIdx + 1];
|
|
|
|
if (isPresent(attrNs)) {
|
2015-11-10 15:56:25 -08:00
|
|
|
DOM.setAttributeNS(node, attrNs, attrName, attrValue);
|
2015-10-27 13:16:27 -07:00
|
|
|
} else {
|
2015-11-10 15:56:25 -08:00
|
|
|
DOM.setAttribute(node, nsAndName[1], attrValue);
|
2015-10-27 13:16:27 -07:00
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
}
|
2015-10-09 14:53:04 -07:00
|
|
|
createRootContentInsertionPoint(): Node {
|
|
|
|
return DOM.createComment('root-content-insertion-point');
|
|
|
|
}
|
2015-11-02 08:39:14 -08:00
|
|
|
createShadowRoot(host: Node, templateId: string): Node {
|
2015-10-05 09:43:00 -07:00
|
|
|
var sr = DOM.createShadowRoot(host);
|
2015-11-02 08:39:14 -08:00
|
|
|
var tpl = this._componentTpls.get(templateId);
|
|
|
|
for (var i = 0; i < tpl.styles.length; i++) {
|
|
|
|
DOM.appendChild(sr, DOM.createStyleElement(tpl.styles[i]));
|
2015-10-05 09:43:00 -07:00
|
|
|
}
|
|
|
|
return sr;
|
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
on(element: Node, eventName: string, callback: Function) {
|
|
|
|
this._eventManager.addEventListener(<HTMLElement>element, eventName,
|
|
|
|
decoratePreventDefault(callback));
|
|
|
|
}
|
|
|
|
globalOn(target: string, eventName: string, callback: Function): Function {
|
|
|
|
return this._eventManager.addGlobalEventListener(target, eventName,
|
|
|
|
decoratePreventDefault(callback));
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-10-01 10:07:49 -07:00
|
|
|
function resolveInternalDomView(viewRef: RenderViewRef): DefaultRenderView<Node> {
|
|
|
|
return <DefaultRenderView<Node>>viewRef;
|
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-10-01 10:07:49 -07:00
|
|
|
function resolveInternalDomFragment(fragmentRef: RenderFragmentRef): Node[] {
|
|
|
|
return (<DefaultRenderFragmentRef<Node>>fragmentRef).nodes;
|
2015-06-24 13:46:39 -07:00
|
|
|
}
|
2015-05-06 10:49:42 -07:00
|
|
|
|
2015-06-24 13:46:39 -07:00
|
|
|
function moveNodesAfterSibling(sibling, nodes) {
|
2015-07-16 15:18:02 -07:00
|
|
|
if (nodes.length > 0 && isPresent(DOM.parentElement(sibling))) {
|
2015-06-24 13:46:39 -07:00
|
|
|
for (var i = 0; i < nodes.length; i++) {
|
|
|
|
DOM.insertBefore(sibling, nodes[i]);
|
2015-05-06 10:49:42 -07:00
|
|
|
}
|
2015-10-01 10:07:49 -07:00
|
|
|
DOM.insertBefore(nodes[0], sibling);
|
2015-06-02 10:15:16 -07:00
|
|
|
}
|
2015-06-24 13:46:39 -07:00
|
|
|
}
|
2015-06-02 10:15:16 -07:00
|
|
|
|
2015-10-01 10:07:49 -07:00
|
|
|
function decoratePreventDefault(eventHandler: Function): Function {
|
|
|
|
return (event) => {
|
|
|
|
var allowDefaultBehavior = eventHandler(event);
|
|
|
|
if (!allowDefaultBehavior) {
|
|
|
|
// TODO(tbosch): move preventDefault into event plugins...
|
|
|
|
DOM.preventDefault(event);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2015-11-10 15:56:25 -08:00
|
|
|
|
|
|
|
var NS_PREFIX_RE = /^@([^:]+):(.+)/g;
|
|
|
|
|
|
|
|
function splitNamespace(name: string): string[] {
|
|
|
|
if (name[0] != '@') {
|
|
|
|
return [null, name];
|
|
|
|
}
|
|
|
|
let match = RegExpWrapper.firstMatch(NS_PREFIX_RE, name);
|
|
|
|
return [match[1], match[2]];
|
|
|
|
}
|