11import { Injectable } from 'angular2/src/core/di' ;
2- import { isPresent , CONST_EXPR } from 'angular2/src/facade/lang' ;
2+ import { isPresent , isBlank , CONST_EXPR } from 'angular2/src/facade/lang' ;
33import { StringMapWrapper } from 'angular2/src/facade/collection' ;
4- import { ElementSchemaRegistry } from './element_schema_registry' ;
5-
6- const EVENT = 'event' ;
7- const BOOLEAN = 'boolean' ;
8- const NUMBER = 'number' ;
9- const STRING = 'string' ;
10- const OBJECT = 'object' ;
11-
12- /**
13- * This array represents the DOM schema. It encodes inheritance, properties, and events.
14- *
15- * ## Overview
16- *
17- * Each line represents one kind of element. The `element_inheritance` and properties are joined
18- * using `element_inheritance|preperties` syntax.
19- *
20- * ## Element Inheritance
21- *
22- * The `element_inheritance` can be further subdivided as `element1,element2,...^parentElement`.
23- * Here the individual elements are separated by `,` (commas). Every element in the list
24- * has identical properties.
25- *
26- * An `element` may inherit additional properties from `parentElement` If no `^parentElement` is
27- * specified then `""` (blank) element is assumed.
28- *
29- * NOTE: The blank element inherits from root `*` element, the super element of all elements.
30- *
31- * NOTE an element prefix such as `@svg:` has no special meaning to the schema.
32- *
33- * ## Properties
34- *
35- * Each element has a set of properties separated by `,` (commas). Each property can be prefixed
36- * by a special character designating its type:
37- *
38- * - (no prefix): property is a string.
39- * - `*`: property represents an event.
40- * - `!`: property is a boolean.
41- * - `#`: property is a number.
42- * - `%`: property is an object.
43- *
44- * ## Query
45- *
46- * The class creates an internal squas representaino which allows to easily answer the query of
47- * if a given property exist on a given element.
48- *
49- * NOTE: We don't yet support querying for types or events.
50- * NOTE: This schema is auto extracted from `schema_extractor.ts` located in the test folder.
51- */
52- const SCHEMA : string [ ] =
53- CONST_EXPR ( [
54- '*|%classList,className,id,innerHTML,*beforecopy,*beforecut,*beforepaste,*copy,*cut,*paste,*search,*selectstart,*webkitfullscreenchange,*webkitfullscreenerror,*wheel,outerHTML,#scrollLeft,#scrollTop' ,
55- '^*|accessKey,contentEditable,dir,!draggable,!hidden,innerText,lang,*abort,*autocomplete,*autocompleteerror,*beforecopy,*beforecut,*beforepaste,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*copy,*cuechange,*cut,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*message,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*mozfullscreenchange,*mozfullscreenerror,*mozpointerlockchange,*mozpointerlockerror,*paste,*pause,*play,*playing,*progress,*ratechange,*reset,*resize,*scroll,*search,*seeked,*seeking,*select,*selectstart,*show,*stalled,*submit,*suspend,*timeupdate,*toggle,*volumechange,*waiting,*webglcontextcreationerror,*webglcontextlost,*webglcontextrestored,*webkitfullscreenchange,*webkitfullscreenerror,*wheel,outerText,!spellcheck,%style,#tabIndex,title,!translate' ,
56- 'media|!autoplay,!controls,%crossOrigin,#currentTime,!defaultMuted,#defaultPlaybackRate,!disableRemotePlayback,!loop,!muted,*encrypted,#playbackRate,preload,src,#volume' ,
57- '@svg:^*|*abort,*autocomplete,*autocompleteerror,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*cuechange,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*pause,*play,*playing,*progress,*ratechange,*reset,*resize,*scroll,*seeked,*seeking,*select,*show,*stalled,*submit,*suspend,*timeupdate,*toggle,*volumechange,*waiting,%style,#tabIndex' ,
58- '@svg:graphics^@svg:|' ,
59- '@svg:animation^@svg:|*begin,*end,*repeat' ,
60- '@svg:geometry^@svg:|' ,
61- '@svg:componentTransferFunction^@svg:|' ,
62- '@svg:gradient^@svg:|' ,
63- '@svg:textContent^@svg:graphics|' ,
64- '@svg:textPositioning^@svg:textContent|' ,
65- 'a|charset,coords,download,hash,host,hostname,href,hreflang,name,password,pathname,ping,port,protocol,rel,rev,search,shape,target,text,type,username' ,
66- 'area|alt,coords,hash,host,hostname,href,!noHref,password,pathname,ping,port,protocol,search,shape,target,username' ,
67- 'audio^media|' ,
68- 'br|clear' ,
69- 'base|href,target' ,
70- 'body|aLink,background,bgColor,link,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,text,vLink' ,
71- 'button|!autofocus,!disabled,formAction,formEnctype,formMethod,!formNoValidate,formTarget,name,type,value' ,
72- 'canvas|#height,#width' ,
73- 'content|select' ,
74- 'dl|!compact' ,
75- 'datalist|' ,
76- 'details|!open' ,
77- 'dialog|!open,returnValue' ,
78- 'dir|!compact' ,
79- 'div|align' ,
80- 'embed|align,height,name,src,type,width' ,
81- 'fieldset|!disabled,name' ,
82- 'font|color,face,size' ,
83- 'form|acceptCharset,action,autocomplete,encoding,enctype,method,name,!noValidate,target' ,
84- 'frame|frameBorder,longDesc,marginHeight,marginWidth,name,!noResize,scrolling,src' ,
85- 'frameset|cols,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,rows' ,
86- 'hr|align,color,!noShade,size,width' ,
87- 'head|' ,
88- 'h1,h2,h3,h4,h5,h6|align' ,
89- 'html|version' ,
90- 'iframe|align,!allowFullscreen,frameBorder,height,longDesc,marginHeight,marginWidth,name,%sandbox,scrolling,src,srcdoc,width' ,
91- 'img|align,alt,border,%crossOrigin,#height,#hspace,!isMap,longDesc,lowsrc,name,sizes,src,srcset,useMap,#vspace,#width' ,
92- 'input|accept,align,alt,autocapitalize,autocomplete,!autofocus,!checked,!defaultChecked,defaultValue,dirName,!disabled,%files,formAction,formEnctype,formMethod,!formNoValidate,formTarget,#height,!incremental,!indeterminate,max,#maxLength,min,#minLength,!multiple,name,pattern,placeholder,!readOnly,!required,selectionDirection,#selectionEnd,#selectionStart,#size,src,step,type,useMap,value,%valueAsDate,#valueAsNumber,#width' ,
93- 'keygen|!autofocus,challenge,!disabled,keytype,name' ,
94- 'li|type,#value' ,
95- 'label|htmlFor' ,
96- 'legend|align' ,
97- 'link|as,charset,%crossOrigin,!disabled,href,hreflang,integrity,media,rel,%relList,rev,%sizes,target,type' ,
98- 'map|name' ,
99- 'marquee|behavior,bgColor,direction,height,#hspace,#loop,#scrollAmount,#scrollDelay,!trueSpeed,#vspace,width' ,
100- 'menu|!compact' ,
101- 'meta|content,httpEquiv,name,scheme' ,
102- 'meter|#high,#low,#max,#min,#optimum,#value' ,
103- 'ins,del|cite,dateTime' ,
104- 'ol|!compact,!reversed,#start,type' ,
105- 'object|align,archive,border,code,codeBase,codeType,data,!declare,height,#hspace,name,standby,type,useMap,#vspace,width' ,
106- 'optgroup|!disabled,label' ,
107- 'option|!defaultSelected,!disabled,label,!selected,text,value' ,
108- 'output|defaultValue,%htmlFor,name,value' ,
109- 'p|align' ,
110- 'param|name,type,value,valueType' ,
111- 'picture|' ,
112- 'pre|#width' ,
113- 'progress|#max,#value' ,
114- 'q,blockquote,cite|' ,
115- 'script|!async,charset,%crossOrigin,!defer,event,htmlFor,integrity,src,text,type' ,
116- 'select|!autofocus,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value' ,
117- 'shadow|' ,
118- 'source|media,sizes,src,srcset,type' ,
119- 'span|' ,
120- 'style|!disabled,media,type' ,
121- 'caption|align' ,
122- 'th,td|abbr,align,axis,bgColor,ch,chOff,#colSpan,headers,height,!noWrap,#rowSpan,scope,vAlign,width' ,
123- 'col,colgroup|align,ch,chOff,#span,vAlign,width' ,
124- 'table|align,bgColor,border,%caption,cellPadding,cellSpacing,frame,rules,summary,%tFoot,%tHead,width' ,
125- 'tr|align,bgColor,ch,chOff,vAlign' ,
126- 'tfoot,thead,tbody|align,ch,chOff,vAlign' ,
127- 'template|' ,
128- 'textarea|autocapitalize,!autofocus,#cols,defaultValue,dirName,!disabled,#maxLength,#minLength,name,placeholder,!readOnly,!required,#rows,selectionDirection,#selectionEnd,#selectionStart,value,wrap' ,
129- 'title|text' ,
130- 'track|!default,kind,label,src,srclang' ,
131- 'ul|!compact,type' ,
132- 'unknown|' ,
133- 'video^media|#height,poster,#width' ,
134- '@svg:a^@svg:graphics|' ,
135- '@svg:animate^@svg:animation|' ,
136- '@svg:animateMotion^@svg:animation|' ,
137- '@svg:animateTransform^@svg:animation|' ,
138- '@svg:circle^@svg:geometry|' ,
139- '@svg:clipPath^@svg:graphics|' ,
140- '@svg:cursor^@svg:|' ,
141- '@svg:defs^@svg:graphics|' ,
142- '@svg:desc^@svg:|' ,
143- '@svg:discard^@svg:|' ,
144- '@svg:ellipse^@svg:geometry|' ,
145- '@svg:feBlend^@svg:|' ,
146- '@svg:feColorMatrix^@svg:|' ,
147- '@svg:feComponentTransfer^@svg:|' ,
148- '@svg:feComposite^@svg:|' ,
149- '@svg:feConvolveMatrix^@svg:|' ,
150- '@svg:feDiffuseLighting^@svg:|' ,
151- '@svg:feDisplacementMap^@svg:|' ,
152- '@svg:feDistantLight^@svg:|' ,
153- '@svg:feDropShadow^@svg:|' ,
154- '@svg:feFlood^@svg:|' ,
155- '@svg:feFuncA^@svg:componentTransferFunction|' ,
156- '@svg:feFuncB^@svg:componentTransferFunction|' ,
157- '@svg:feFuncG^@svg:componentTransferFunction|' ,
158- '@svg:feFuncR^@svg:componentTransferFunction|' ,
159- '@svg:feGaussianBlur^@svg:|' ,
160- '@svg:feImage^@svg:|' ,
161- '@svg:feMerge^@svg:|' ,
162- '@svg:feMergeNode^@svg:|' ,
163- '@svg:feMorphology^@svg:|' ,
164- '@svg:feOffset^@svg:|' ,
165- '@svg:fePointLight^@svg:|' ,
166- '@svg:feSpecularLighting^@svg:|' ,
167- '@svg:feSpotLight^@svg:|' ,
168- '@svg:feTile^@svg:|' ,
169- '@svg:feTurbulence^@svg:|' ,
170- '@svg:filter^@svg:|' ,
171- '@svg:foreignObject^@svg:graphics|' ,
172- '@svg:g^@svg:graphics|' ,
173- '@svg:image^@svg:graphics|' ,
174- '@svg:line^@svg:geometry|' ,
175- '@svg:linearGradient^@svg:gradient|' ,
176- '@svg:mpath^@svg:|' ,
177- '@svg:marker^@svg:|' ,
178- '@svg:mask^@svg:|' ,
179- '@svg:metadata^@svg:|' ,
180- '@svg:path^@svg:geometry|' ,
181- '@svg:pattern^@svg:|' ,
182- '@svg:polygon^@svg:geometry|' ,
183- '@svg:polyline^@svg:geometry|' ,
184- '@svg:radialGradient^@svg:gradient|' ,
185- '@svg:rect^@svg:geometry|' ,
186- '@svg:svg^@svg:graphics|#currentScale,#zoomAndPan' ,
187- '@svg:script^@svg:|type' ,
188- '@svg:set^@svg:animation|' ,
189- '@svg:stop^@svg:|' ,
190- '@svg:style^@svg:|!disabled,media,title,type' ,
191- '@svg:switch^@svg:graphics|' ,
192- '@svg:symbol^@svg:|' ,
193- '@svg:tspan^@svg:textPositioning|' ,
194- '@svg:text^@svg:textPositioning|' ,
195- '@svg:textPath^@svg:textContent|' ,
196- '@svg:title^@svg:|' ,
197- '@svg:use^@svg:graphics|' ,
198- '@svg:view^@svg:|#zoomAndPan'
199- ] ) ;
4+ import { DOM } from 'angular2/src/platform/dom/dom_adapter' ;
5+ import { splitNsName } from 'angular2/src/compiler/html_tags' ;
2006
201- var attrToPropMap : { [ name : string ] : string } = < any > {
202- 'class' : 'className' ,
203- 'innerHtml' : 'innerHTML' ,
204- 'readonly' : 'readOnly' ,
205- 'tabindex' : 'tabIndex'
206- } ;
7+ import { ElementSchemaRegistry } from './element_schema_registry' ;
2078
9+ const NAMESPACE_URIS =
10+ CONST_EXPR ( { 'xlink' : 'http://www.w3.org/1999/xlink' , 'svg' : 'http://www.w3.org/2000/svg' } ) ;
20811
20912@Injectable ( )
210- export class DomElementSchemaRegistry implements ElementSchemaRegistry {
211- schema = < { [ element : string ] : { [ property : string ] : string } } > { } ;
212-
213- constructor ( ) {
214- SCHEMA . forEach ( encodedType => {
215- var parts = encodedType . split ( '|' ) ;
216- var properties = parts [ 1 ] . split ( ',' ) ;
217- var typeParts = ( parts [ 0 ] + '^' ) . split ( '^' ) ;
218- var typeName = typeParts [ 0 ] ;
219- var type = < { [ property : string ] : string } > { } ;
220- typeName . split ( ',' ) . forEach ( tag => this . schema [ tag ] = type ) ;
221- var superType = this . schema [ typeParts [ 1 ] ] ;
222- if ( isPresent ( superType ) ) {
223- StringMapWrapper . forEach ( superType , ( v , k ) => type [ k ] = v ) ;
224- }
225- properties . forEach ( ( property : string ) => {
226- if ( property == '' ) {
227- } else if ( property . startsWith ( '*' ) ) {
228- // We don't yet support events.
229- // type[property.substring(1)] = EVENT;
230- } else if ( property . startsWith ( '!' ) ) {
231- type [ property . substring ( 1 ) ] = BOOLEAN ;
232- } else if ( property . startsWith ( '#' ) ) {
233- type [ property . substring ( 1 ) ] = NUMBER ;
234- } else if ( property . startsWith ( '%' ) ) {
235- type [ property . substring ( 1 ) ] = OBJECT ;
236- } else {
237- type [ property ] = STRING ;
238- }
239- } ) ;
240- } ) ;
13+ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
14+ private _protoElements = new Map < string , Element > ( ) ;
15+
16+ private _getProtoElement ( tagName : string ) : Element {
17+ var element = this . _protoElements . get ( tagName ) ;
18+ if ( isBlank ( element ) ) {
19+ var nsAndName = splitNsName ( tagName ) ;
20+ element = isPresent ( nsAndName [ 0 ] ) ?
21+ DOM . createElementNS ( NAMESPACE_URIS [ nsAndName [ 0 ] ] , nsAndName [ 1 ] ) :
22+ DOM . createElement ( nsAndName [ 1 ] ) ;
23+ this . _protoElements . set ( tagName , element ) ;
24+ }
25+ return element ;
24126 }
24227
24328 hasProperty ( tagName : string , propName : string ) : boolean {
@@ -246,16 +31,13 @@ export class DomElementSchemaRegistry implements ElementSchemaRegistry {
24631 // once it is instantiated
24732 return true ;
24833 } else {
249- var elementProperties = this . schema [ tagName . toLowerCase ( ) ] ;
250- if ( ! isPresent ( elementProperties ) ) {
251- elementProperties = this . schema [ 'unknown' ] ;
252- }
253- return isPresent ( elementProperties [ propName ] ) ;
34+ var elm = this . _getProtoElement ( tagName ) ;
35+ return DOM . hasProperty ( elm , propName ) ;
25436 }
25537 }
25638
25739 getMappedPropName ( propName : string ) : string {
258- var mappedPropName = StringMapWrapper . get ( attrToPropMap , propName ) ;
40+ var mappedPropName = StringMapWrapper . get ( DOM . attrToPropMap , propName ) ;
25941 return isPresent ( mappedPropName ) ? mappedPropName : propName ;
26042 }
26143}
0 commit comments