UNPKG

20.8 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || function (d, b) {
3 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
4 function __() { this.constructor = d; }
5 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
6};
7var get_dom_1 = require('./get-dom');
8var core_1 = require('@angular/core');
9var platform_browser_1 = require('@angular/platform-browser');
10var helper_1 = require('./helper');
11var node_shared_styles_host_1 = require('./node-shared-styles-host');
12var NAMESPACE_URIS = {
13 'xlink': 'http://www.w3.org/1999/xlink',
14 'svg': 'http://www.w3.org/2000/svg',
15 'xhtml': 'http://www.w3.org/1999/xhtml'
16};
17var TEMPLATE_COMMENT_TEXT = 'template bindings={}';
18var TEMPLATE_BINDINGS_EXP = /^template bindings=(.*)$/;
19var NodeDomRootRenderer = (function () {
20 function NodeDomRootRenderer(document, eventManager, sharedStylesHost, _animationDriver) {
21 this.document = document;
22 this.eventManager = eventManager;
23 this.sharedStylesHost = sharedStylesHost;
24 this._animationDriver = _animationDriver;
25 this.registeredComponents = new Map();
26 }
27 NodeDomRootRenderer.prototype.renderComponent = function (componentProto) {
28 var renderer = this.registeredComponents.get(componentProto.id);
29 if (helper_1.isBlank(renderer)) {
30 renderer = new NodeDomRenderer(this, componentProto, this._animationDriver);
31 this.registeredComponents.set(componentProto.id, renderer);
32 }
33 return renderer;
34 };
35 NodeDomRootRenderer.decorators = [
36 { type: core_1.Injectable },
37 ];
38 NodeDomRootRenderer.ctorParameters = [
39 { type: undefined, decorators: [{ type: core_1.Inject, args: [platform_browser_1.DOCUMENT,] },] },
40 { type: platform_browser_1.EventManager, },
41 { type: node_shared_styles_host_1.NodeSharedStylesHost, },
42 { type: platform_browser_1.AnimationDriver, },
43 ];
44 return NodeDomRootRenderer;
45}());
46exports.NodeDomRootRenderer = NodeDomRootRenderer;
47exports.ATTRIBUTES = {
48 textarea: [
49 'autocapitalize',
50 'autocomplete',
51 'autofocus',
52 'cols',
53 'disabled',
54 'form',
55 'maxlength',
56 'minlength',
57 'name',
58 'placeholder',
59 'readonly',
60 'required',
61 'rows',
62 'selectionDirection',
63 'selectionEnd',
64 'selectionStart',
65 'spellcheck',
66 'wrap'
67 ],
68 script: [
69 'async',
70 'integrity',
71 'src',
72 'type',
73 'text',
74 'defer',
75 'crossorigin'
76 ],
77 button: [
78 'autofocus',
79 'autocomplete',
80 'disabled',
81 'form',
82 'formaction',
83 'formenctype',
84 'formmethod',
85 'formnovalidate',
86 'formtarget',
87 'name',
88 'type',
89 'value'
90 ],
91 fieldset: [
92 'disabled',
93 'form',
94 'name'
95 ],
96 a: [
97 'download',
98 'href',
99 'hreflang',
100 'ping',
101 'referrerpolicy',
102 'rel',
103 'target',
104 'type'
105 ],
106 img: [
107 'alt',
108 'crossorigin',
109 'height',
110 'ismap',
111 'longdesc',
112 'referrerpolicy',
113 'sizesHTML5',
114 'src',
115 'srcsetHTML5',
116 'width',
117 'usemap'
118 ],
119 input: [
120 'id',
121 'type',
122 'accept',
123 'mozactionhint',
124 'autocapitalize',
125 'autocomplete',
126 'autocorrect',
127 'autofocus',
128 'autosave',
129 'checked',
130 'disabled',
131 'form',
132 'formaction',
133 'formenctype',
134 'formmethod',
135 'formnovalidate',
136 'formtarget',
137 'height',
138 'incremental',
139 'inputmode',
140 'list',
141 'max',
142 'maxlength',
143 'min',
144 'minlength',
145 'multiple',
146 'name',
147 'pattern',
148 'placeholder',
149 'readonly',
150 'required',
151 'results',
152 'selectionDirection',
153 'size',
154 'spellcheck',
155 'src',
156 'step',
157 'tabindex',
158 'value',
159 'width',
160 'x-moz-errormessage'
161 ],
162 output: [
163 'for',
164 'form',
165 'name'
166 ],
167 progress: [
168 'max',
169 'value'
170 ],
171 label: [
172 'accesskey',
173 'for',
174 'form'
175 ],
176 option: [
177 'disabled',
178 'label',
179 'selected',
180 'value'
181 ],
182 select: [
183 'autofocus',
184 'disabled',
185 'multiple',
186 'form',
187 'multiple',
188 'name',
189 'required',
190 'size'
191 ],
192 optgroup: [
193 'disabled',
194 'label'
195 ],
196 form: [
197 'accept-charset',
198 'action',
199 'autocapitalize',
200 'autocomplete',
201 'enctype',
202 'method',
203 'name',
204 'novalidate',
205 'target'
206 ]
207};
208exports.IGNORE_ATTRIBUTES = {
209 'innerHTML': true,
210 'hidden': true
211};
212var DomRenderer = (function () {
213 function DomRenderer(_rootRenderer, componentProto, _animationDriver) {
214 this._rootRenderer = _rootRenderer;
215 this.componentProto = componentProto;
216 this._animationDriver = _animationDriver;
217 this._styles = _flattenStyles(componentProto.id, componentProto.styles, []);
218 if (componentProto.encapsulation !== core_1.ViewEncapsulation.Native) {
219 this._rootRenderer.sharedStylesHost.addStyles(this._styles);
220 }
221 if (this.componentProto.encapsulation === core_1.ViewEncapsulation.Emulated) {
222 this._contentAttr = _shimContentAttribute(componentProto.id);
223 this._hostAttr = _shimHostAttribute(componentProto.id);
224 }
225 else {
226 this._contentAttr = null;
227 this._hostAttr = null;
228 }
229 }
230 DomRenderer.prototype.selectRootElement = function (_selectorOrNode, _debugInfo) {
231 };
232 DomRenderer.prototype.createElement = function (parent, name, _debugInfo) {
233 var nsAndName = splitNamespace(name);
234 var el = helper_1.isPresent(nsAndName[0]) ?
235 get_dom_1.getDOM().createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) :
236 get_dom_1.getDOM().createElement(nsAndName[1]);
237 if (helper_1.isPresent(this._contentAttr)) {
238 get_dom_1.getDOM().setAttribute(el, this._contentAttr, '');
239 }
240 if (helper_1.isPresent(parent)) {
241 get_dom_1.getDOM().appendChild(parent, el);
242 }
243 return el;
244 };
245 DomRenderer.prototype.createViewRoot = function (hostElement) {
246 var nodesParent;
247 if (this.componentProto.encapsulation === core_1.ViewEncapsulation.Native) {
248 nodesParent = get_dom_1.getDOM().createShadowRoot(hostElement);
249 this._rootRenderer.sharedStylesHost.addHost(nodesParent);
250 for (var i = 0; i < this._styles.length; i++) {
251 get_dom_1.getDOM().appendChild(nodesParent, get_dom_1.getDOM().createStyleElement(this._styles[i]));
252 }
253 }
254 else {
255 if (helper_1.isPresent(this._hostAttr)) {
256 get_dom_1.getDOM().setAttribute(hostElement, this._hostAttr, '');
257 }
258 nodesParent = hostElement;
259 }
260 return nodesParent;
261 };
262 DomRenderer.prototype.createTemplateAnchor = function (parentElement, _debugInfo) {
263 var comment = get_dom_1.getDOM().createComment(TEMPLATE_COMMENT_TEXT);
264 if (helper_1.isPresent(parentElement)) {
265 get_dom_1.getDOM().appendChild(parentElement, comment);
266 }
267 return comment;
268 };
269 DomRenderer.prototype.createText = function (parentElement, value, _debugInfo) {
270 var node = get_dom_1.getDOM().createTextNode(value);
271 if (helper_1.isPresent(parentElement)) {
272 get_dom_1.getDOM().appendChild(parentElement, node);
273 }
274 return node;
275 };
276 DomRenderer.prototype.projectNodes = function (parentElement, nodes) {
277 if (helper_1.isBlank(parentElement)) {
278 return;
279 }
280 appendNodes(parentElement, nodes);
281 };
282 DomRenderer.prototype.attachViewAfter = function (node, viewRootNodes) {
283 moveNodesAfterSibling(node, viewRootNodes);
284 };
285 DomRenderer.prototype.detachView = function (viewRootNodes) {
286 for (var i = 0; i < viewRootNodes.length; i++) {
287 get_dom_1.getDOM().remove(viewRootNodes[i]);
288 }
289 };
290 DomRenderer.prototype.destroyView = function (hostElement, _viewAllNodes) {
291 if (this.componentProto.encapsulation === core_1.ViewEncapsulation.Native && helper_1.isPresent(hostElement)) {
292 this._rootRenderer.sharedStylesHost.removeHost(get_dom_1.getDOM().getShadowRoot(hostElement));
293 }
294 };
295 DomRenderer.prototype.listen = function (renderElement, name, callback) {
296 return this._rootRenderer.eventManager.addEventListener(renderElement, name, decoratePreventDefault(callback));
297 };
298 DomRenderer.prototype.listenGlobal = function (target, name, callback) {
299 return this._rootRenderer.eventManager.addGlobalEventListener(target, name, decoratePreventDefault(callback));
300 };
301 DomRenderer.prototype.setElementProperty = function (renderElement, propertyName, propertyValue) {
302 get_dom_1.getDOM().setProperty(renderElement, propertyName, propertyValue);
303 };
304 DomRenderer.prototype.setElementAttribute = function (renderElement, attributeName, attributeValue) {
305 var attrNs;
306 var nsAndName = splitNamespace(attributeName);
307 if (helper_1.isPresent(nsAndName[0])) {
308 attributeName = nsAndName[0] + ':' + nsAndName[1];
309 attrNs = NAMESPACE_URIS[nsAndName[0]];
310 }
311 if (helper_1.isPresent(attributeValue)) {
312 if (helper_1.isPresent(attrNs)) {
313 get_dom_1.getDOM().setAttributeNS(renderElement, attrNs, attributeName, attributeValue);
314 }
315 else {
316 get_dom_1.getDOM().setAttribute(renderElement, attributeName, attributeValue);
317 }
318 }
319 else {
320 if (helper_1.isPresent(attrNs)) {
321 get_dom_1.getDOM().removeAttributeNS(renderElement, attrNs, nsAndName[1]);
322 }
323 else {
324 get_dom_1.getDOM().removeAttribute(renderElement, attributeName);
325 }
326 }
327 };
328 DomRenderer.prototype.setBindingDebugInfo = function (renderElement, propertyName, propertyValue) {
329 var dashCasedPropertyName = helper_1.camelCaseToDashCase(propertyName);
330 if (get_dom_1.getDOM().isCommentNode(renderElement)) {
331 var existingBindings = get_dom_1.getDOM().getText(renderElement)
332 .replace(/\n/g, '')
333 .match(TEMPLATE_BINDINGS_EXP);
334 var parsedBindings = JSON.parse(existingBindings[1]);
335 parsedBindings[dashCasedPropertyName] = propertyValue;
336 get_dom_1.getDOM().setText(renderElement, TEMPLATE_COMMENT_TEXT.replace('{}', JSON.stringify(parsedBindings)));
337 }
338 else {
339 this.setElementAttribute(renderElement, propertyName, propertyValue);
340 }
341 };
342 DomRenderer.prototype.setElementClass = function (renderElement, className, isAdd) {
343 if (isAdd) {
344 get_dom_1.getDOM().addClass(renderElement, className);
345 }
346 else {
347 get_dom_1.getDOM().removeClass(renderElement, className);
348 }
349 };
350 DomRenderer.prototype.setElementStyle = function (renderElement, styleName, styleValue) {
351 if (helper_1.isPresent(styleValue)) {
352 get_dom_1.getDOM().setStyle(renderElement, styleName, helper_1.stringify(styleValue));
353 }
354 else {
355 get_dom_1.getDOM().removeStyle(renderElement, styleName);
356 }
357 };
358 DomRenderer.prototype.invokeElementMethod = function (renderElement, methodName, args) {
359 get_dom_1.getDOM().invoke(renderElement, methodName, args);
360 };
361 DomRenderer.prototype.setText = function (renderNode, text) {
362 get_dom_1.getDOM().setText(renderNode, text);
363 };
364 DomRenderer.prototype.animate = function (element, startingStyles, keyframes, duration, delay, easing) {
365 return this._animationDriver.animate(element, startingStyles, keyframes, duration, delay, easing);
366 };
367 return DomRenderer;
368}());
369exports.DomRenderer = DomRenderer;
370var NodeDomRenderer = (function (_super) {
371 __extends(NodeDomRenderer, _super);
372 function NodeDomRenderer(_rootRenderer, _componentProto, _animationDriver) {
373 if (_componentProto.encapsulation === core_1.ViewEncapsulation.Native) {
374 _componentProto.encapsulation = core_1.ViewEncapsulation.Emulated;
375 }
376 _super.call(this, _rootRenderer, _componentProto, _animationDriver);
377 this.__rootRenderer = _rootRenderer;
378 }
379 NodeDomRenderer.prototype.selectRootElement = function (selectorOrNode, _debugInfo) {
380 var el;
381 if (typeof selectorOrNode === 'string') {
382 el = get_dom_1.getDOM().querySelector(this.__rootRenderer.document, selectorOrNode);
383 if (helper_1.isBlank(el)) {
384 throw new Error("The selector \"" + selectorOrNode + "\" did not match any elements");
385 }
386 }
387 else {
388 el = selectorOrNode;
389 }
390 get_dom_1.getDOM().clearNodes(el);
391 return el;
392 };
393 NodeDomRenderer.prototype._isObject = function (val) {
394 if (val === null) {
395 return false;
396 }
397 return ((typeof val === 'function') || (typeof val === 'object'));
398 };
399 NodeDomRenderer.prototype.setElementProperty = function (renderElement, propertyName, propertyValue) {
400 if (this._isObject(propertyValue)) {
401 propertyValue = JSON.stringify(propertyValue);
402 }
403 else if (typeof propertyValue === 'number') {
404 propertyValue.toString();
405 }
406 if (propertyValue === null || propertyValue === undefined) {
407 propertyValue = false;
408 if (propertyName === 'innerHTML') {
409 propertyValue = '';
410 }
411 }
412 if (propertyName === 'innerHTML') {
413 return _super.prototype.setElementProperty.call(this, renderElement, propertyName, propertyValue);
414 }
415 if ((propertyName === 'autofocus' || propertyName === 'spellcheck') && propertyValue === false) {
416 return;
417 }
418 var setProp = _super.prototype.setElementProperty.call(this, renderElement, propertyName, propertyValue);
419 if (exports.IGNORE_ATTRIBUTES[propertyName]) {
420 return setProp;
421 }
422 var el = get_dom_1.getDOM().nodeName(renderElement);
423 var attrList = exports.ATTRIBUTES[el];
424 if (attrList) {
425 var booleanAttr = helper_1.listContains(attrList, propertyName);
426 if (booleanAttr) {
427 if (propertyName === 'autocomplete') {
428 return this._setOnOffAttribute(renderElement, propertyName, propertyValue);
429 }
430 else if (propertyName === 'checked') {
431 return this._setCheckedAttribute(renderElement, propertyName, propertyValue);
432 }
433 else if (propertyName === 'disabled') {
434 return this._setDisabledAttribute(renderElement, propertyName, propertyValue);
435 }
436 else {
437 return this._setBooleanAttribute(renderElement, propertyName, propertyValue);
438 }
439 }
440 }
441 if (typeof propertyValue === 'string') {
442 return _super.prototype.setElementAttribute.call(this, renderElement, propertyName, propertyValue);
443 }
444 };
445 NodeDomRenderer.prototype.setElementStyle = function (renderElement, styleName, styleValue) {
446 var styleNameCased = helper_1.cssHyphenate(styleName);
447 return _super.prototype.setElementStyle.call(this, renderElement, styleNameCased, styleValue);
448 };
449 NodeDomRenderer.prototype.invokeElementMethod = function (renderElement, methodName, args) {
450 if (methodName === 'focus') {
451 if (get_dom_1.getDOM().nodeName(renderElement) === 'input') {
452 return _super.prototype.setElementAttribute.call(this, renderElement, 'autofocus', '');
453 }
454 }
455 return _super.prototype.invokeElementMethod.call(this, location, methodName, args);
456 };
457 NodeDomRenderer.prototype._setDisabledAttribute = function (renderElement, _propertyName, propertyValue) {
458 if (helper_1.isPresent(propertyValue)) {
459 if (propertyValue === true || propertyValue.toString() !== 'false') {
460 return _super.prototype.setElementAttribute.call(this, renderElement, 'disabled', 'disabled');
461 }
462 }
463 };
464 NodeDomRenderer.prototype._setCheckedAttribute = function (renderElement, _propertyName, propertyValue) {
465 if (helper_1.isPresent(propertyValue)) {
466 if (propertyValue === true) {
467 return _super.prototype.setElementAttribute.call(this, renderElement, propertyValue, 'checked');
468 }
469 else if (propertyValue === false) {
470 return _super.prototype.setElementAttribute.call(this, renderElement, propertyValue, '');
471 }
472 }
473 };
474 NodeDomRenderer.prototype._setOnOffAttribute = function (renderElement, propertyName, propertyValue) {
475 if (helper_1.isPresent(propertyValue)) {
476 if (propertyValue === true) {
477 return _super.prototype.setElementAttribute.call(this, renderElement, propertyValue, 'on');
478 }
479 else if (propertyValue === false) {
480 return _super.prototype.setElementAttribute.call(this, renderElement, propertyValue, 'off');
481 }
482 }
483 return _super.prototype.setElementAttribute.call(this, renderElement, propertyName, String(propertyValue));
484 };
485 NodeDomRenderer.prototype._setBooleanAttribute = function (renderElement, propertyName, propertyValue) {
486 if (helper_1.isPresent(propertyValue) && propertyValue !== false) {
487 if (propertyValue === true) {
488 return _super.prototype.setElementAttribute.call(this, renderElement, propertyName, '');
489 }
490 else {
491 return _super.prototype.setElementAttribute.call(this, renderElement, propertyName, String(propertyValue));
492 }
493 }
494 return _super.prototype.setElementAttribute.call(this, renderElement, propertyName, String(propertyValue));
495 };
496 return NodeDomRenderer;
497}(DomRenderer));
498exports.NodeDomRenderer = NodeDomRenderer;
499function moveNodesAfterSibling(sibling, nodes) {
500 var parent = get_dom_1.getDOM().parentElement(sibling);
501 if (nodes.length > 0 && helper_1.isPresent(parent)) {
502 var nextSibling = get_dom_1.getDOM().nextSibling(sibling);
503 if (helper_1.isPresent(nextSibling)) {
504 for (var i = 0; i < nodes.length; i++) {
505 get_dom_1.getDOM().insertBefore(nextSibling, nodes[i]);
506 }
507 }
508 else {
509 for (var i = 0; i < nodes.length; i++) {
510 get_dom_1.getDOM().appendChild(parent, nodes[i]);
511 }
512 }
513 }
514}
515function appendNodes(parent, nodes) {
516 for (var i = 0; i < nodes.length; i++) {
517 get_dom_1.getDOM().appendChild(parent, nodes[i]);
518 }
519}
520function decoratePreventDefault(eventHandler) {
521 return function (event) {
522 var allowDefaultBehavior = eventHandler(event);
523 if (allowDefaultBehavior === false) {
524 get_dom_1.getDOM().preventDefault(event);
525 }
526 };
527}
528var COMPONENT_REGEX = /%COMP%/g;
529exports.COMPONENT_VARIABLE = '%COMP%';
530exports.HOST_ATTR = "_nghost-" + exports.COMPONENT_VARIABLE;
531exports.CONTENT_ATTR = "_ngcontent-" + exports.COMPONENT_VARIABLE;
532function _shimContentAttribute(componentShortId) {
533 return exports.CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId);
534}
535function _shimHostAttribute(componentShortId) {
536 return exports.HOST_ATTR.replace(COMPONENT_REGEX, componentShortId);
537}
538function _flattenStyles(compId, styles, target) {
539 for (var i = 0; i < styles.length; i++) {
540 var style = styles[i];
541 if (Array.isArray(style)) {
542 _flattenStyles(compId, style, target);
543 }
544 else {
545 style = style.replace(COMPONENT_REGEX, compId);
546 target.push(style);
547 }
548 }
549 return target;
550}
551var NS_PREFIX_RE = /^:([^:]+):(.+)$/;
552function splitNamespace(name) {
553 if (name[0] !== ':') {
554 return [null, name];
555 }
556 var match = name.match(NS_PREFIX_RE);
557 return [match[1], match[2]];
558}
559//# sourceMappingURL=node-renderer.js.map
\No newline at end of file