|
1 | 1 | library angular2.src.compiler.schema.dom_element_schema_registry; |
2 | 2 |
|
3 | 3 | import "package:angular2/src/core/di.dart" show Injectable; |
4 | | -import "package:angular2/src/facade/lang.dart" show isPresent; |
| 4 | +import "package:angular2/src/facade/lang.dart" show isPresent, isBlank; |
5 | 5 | import "package:angular2/src/facade/collection.dart" show StringMapWrapper; |
| 6 | +import "package:angular2/src/platform/dom/dom_adapter.dart" show DOM; |
| 7 | +import "package:angular2/src/compiler/html_tags.dart" show splitNsName; |
6 | 8 | import "element_schema_registry.dart" show ElementSchemaRegistry; |
7 | 9 |
|
8 | | -const EVENT = "event"; |
9 | | -const BOOLEAN = "boolean"; |
10 | | -const NUMBER = "number"; |
11 | | -const STRING = "string"; |
12 | | -const List<String> PROPERTIES = const [ |
13 | | - "*|className,id,innerHTML,*beforecopy,*beforecut,*beforepaste,*copy,*cut,*paste,*search,*selectstart,*webkitfullscreenchange,*webkitfullscreenerror,*wheel,outerHTML,#scrollLeft,#scrollTop", |
14 | | - "^*|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,#tabIndex,title,!translate", |
15 | | - "@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,#tabIndex", |
16 | | - "anchor|", |
17 | | - "area|alt,coords,hash,host,hostname,href,!noHref,password,pathname,ping,port,protocol,search,shape,target,username", |
18 | | - "media|*encrypted", |
19 | | - "audio^media|", |
20 | | - "br|clear", |
21 | | - "base|href,target", |
22 | | - "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", |
23 | | - "button|!autofocus,!disabled,formAction,formEnctype,formMethod,!formNoValidate,formTarget,name,type,value", |
24 | | - "canvas|#height,#width", |
25 | | - "content|select", |
26 | | - "dlist|", |
27 | | - "datalist|", |
28 | | - "details|!open", |
29 | | - "dialog|!open,returnValue", |
30 | | - "directory|", |
31 | | - "div|align", |
32 | | - "embed|align,height,name,src,type,width", |
33 | | - "fieldset|!disabled,name", |
34 | | - "font|color,face,size", |
35 | | - "form|acceptCharset,action,autocomplete,encoding,enctype,method,name,!noValidate,target", |
36 | | - "frame|frameBorder,longDesc,marginHeight,marginWidth,name,!noResize,scrolling,src", |
37 | | - "frameset|cols,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,rows", |
38 | | - "hr|align,color,!noShade,size,width", |
39 | | - "head|", |
40 | | - "heading|", |
41 | | - "html|version", |
42 | | - "iframe|align,!allowFullscreen,frameBorder,height,longDesc,marginHeight,marginWidth,name,scrolling,src,srcdoc,width", |
43 | | - "image|", |
44 | | - "input|accept,align,alt,autocapitalize,autocomplete,!autofocus,!checked,!defaultChecked,defaultValue,dirName,!disabled,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,#valueAsNumber,#width", |
45 | | - "keygen|!autofocus,challenge,!disabled,keytype,name", |
46 | | - "li|type,#value", |
47 | | - "label|htmlFor", |
48 | | - "legend|align", |
49 | | - "link|as,charset,!disabled,href,hreflang,integrity,media,rel,rev,target,type", |
50 | | - "map|name", |
51 | | - "marquee|behavior,bgColor,direction,height,#hspace,#loop,#scrollAmount,#scrollDelay,!trueSpeed,#vspace,width", |
52 | | - "menu|!compact", |
53 | | - "meta|content,httpEquiv,name,scheme", |
54 | | - "meter|#high,#low,#max,#min,#optimum,#value", |
55 | | - "mod|", |
56 | | - "olist|", |
57 | | - "object|align,archive,border,code,codeBase,codeType,data,!declare,height,#hspace,name,standby,type,useMap,#vspace,width", |
58 | | - "optgroup|!disabled,label", |
59 | | - "option|!defaultSelected,!disabled,label,!selected,text,value", |
60 | | - "output|defaultValue,name,value", |
61 | | - "paragraph|", |
62 | | - "param|name,type,value,valueType", |
63 | | - "picture|", |
64 | | - "pre|#width", |
65 | | - "progress|#max,#value", |
66 | | - "quote|", |
67 | | - "script|!async,charset,!defer,event,htmlFor,integrity,src,text,type", |
68 | | - "select|!autofocus,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value", |
69 | | - "shadow|", |
70 | | - "source|media,sizes,src,srcset,type", |
71 | | - "span|", |
72 | | - "style|!disabled,media,type", |
73 | | - "tablecaption|", |
74 | | - "tablecell|", |
75 | | - "tablecol|", |
76 | | - "table|align,bgColor,border,cellPadding,cellSpacing,frame,rules,summary,width", |
77 | | - "tablerow|", |
78 | | - "tablesection|", |
79 | | - "template|", |
80 | | - "textarea|autocapitalize,!autofocus,#cols,defaultValue,dirName,!disabled,#maxLength,#minLength,name,placeholder,!readOnly,!required,#rows,selectionDirection,#selectionEnd,#selectionStart,value,wrap", |
81 | | - "title|text", |
82 | | - "track|!default,kind,label,src,srclang", |
83 | | - "ulist|", |
84 | | - "unknown|", |
85 | | - "video^media|#height,poster,#width", |
86 | | - "@svg:graphics^@svg:|", |
87 | | - "@svg:a^@svg:graphics|", |
88 | | - "@svg:animation^@svg:|*begin,*end,*repeat", |
89 | | - "@svg:animate^@svg:animation|", |
90 | | - "@svg:animatemotion^@svg:animation|", |
91 | | - "@svg:animatetransform^@svg:animation|", |
92 | | - "@svg:geometry^@svg:graphics|", |
93 | | - "@svg:circle^@svg:geometry|", |
94 | | - "@svg:clippath^@svg:graphics|", |
95 | | - "@svg:componenttransferfunction^@svg:|", |
96 | | - "@svg:cursor^@svg:|", |
97 | | - "@svg:defs^@svg:graphics|", |
98 | | - "@svg:desc^@svg:|", |
99 | | - "@svg:discard^@svg:|", |
100 | | - "@svg:ellipse^@svg:geometry|", |
101 | | - "@svg:feblend^@svg:|", |
102 | | - "@svg:fecolormatrix^@svg:|", |
103 | | - "@svg:fecomponenttransfer^@svg:|", |
104 | | - "@svg:fecomposite^@svg:|", |
105 | | - "@svg:feconvolvematrix^@svg:|", |
106 | | - "@svg:fediffuselighting^@svg:|", |
107 | | - "@svg:fedisplacementmap^@svg:|", |
108 | | - "@svg:fedistantlight^@svg:|", |
109 | | - "@svg:fedropshadow^@svg:|", |
110 | | - "@svg:feflood^@svg:|", |
111 | | - "@svg:fefunca^@svg:componenttransferfunction|", |
112 | | - "@svg:fefuncb^@svg:componenttransferfunction|", |
113 | | - "@svg:fefuncg^@svg:componenttransferfunction|", |
114 | | - "@svg:fefuncr^@svg:componenttransferfunction|", |
115 | | - "@svg:fegaussianblur^@svg:|", |
116 | | - "@svg:feimage^@svg:|", |
117 | | - "@svg:femerge^@svg:|", |
118 | | - "@svg:femergenode^@svg:|", |
119 | | - "@svg:femorphology^@svg:|", |
120 | | - "@svg:feoffset^@svg:|", |
121 | | - "@svg:fepointlight^@svg:|", |
122 | | - "@svg:fespecularlighting^@svg:|", |
123 | | - "@svg:fespotlight^@svg:|", |
124 | | - "@svg:fetile^@svg:|", |
125 | | - "@svg:feturbulence^@svg:|", |
126 | | - "@svg:filter^@svg:|", |
127 | | - "@svg:foreignobject^@svg:graphics|", |
128 | | - "@svg:g^@svg:graphics|", |
129 | | - "@svg:gradient^@svg:|", |
130 | | - "@svg:image^@svg:graphics|", |
131 | | - "@svg:line^@svg:geometry|", |
132 | | - "@svg:lineargradient^@svg:gradient|", |
133 | | - "@svg:mpath^@svg:|", |
134 | | - "@svg:marker^@svg:|", |
135 | | - "@svg:mask^@svg:|", |
136 | | - "@svg:metadata^@svg:|", |
137 | | - "@svg:path^@svg:geometry|", |
138 | | - "@svg:pattern^@svg:|", |
139 | | - "@svg:polygon^@svg:geometry|", |
140 | | - "@svg:polyline^@svg:geometry|", |
141 | | - "@svg:radialgradient^@svg:gradient|", |
142 | | - "@svg:rect^@svg:geometry|", |
143 | | - "@svg:svg^@svg:graphics|#currentScale,#zoomAndPan", |
144 | | - "@svg:script^@svg:|type", |
145 | | - "@svg:set^@svg:animation|", |
146 | | - "@svg:stop^@svg:|", |
147 | | - "@svg:style^@svg:|!disabled,media,title,type", |
148 | | - "@svg:switch^@svg:graphics|", |
149 | | - "@svg:symbol^@svg:|", |
150 | | - "@svg:textcontent^@svg:graphics|", |
151 | | - "@svg:textpositioning^@svg:textcontent|", |
152 | | - "@svg:tspan^@svg:textpositioning|", |
153 | | - "@svg:text^@svg:textpositioning|", |
154 | | - "@svg:textpath^@svg:textcontent|", |
155 | | - "@svg:title^@svg:|", |
156 | | - "@svg:use^@svg:graphics|", |
157 | | - "@svg:view^@svg:|#zoomAndPan" |
158 | | -]; |
159 | | -const attrToPropMap = (const { |
160 | | - "class": "className", |
161 | | - "innerHtml": "innerHTML", |
162 | | - "readonly": "readOnly", |
163 | | - "tabindex": "tabIndex" |
164 | | -} as Map<String, String>); |
| 10 | +const NAMESPACE_URIS = const { |
| 11 | + "xlink": "http://www.w3.org/1999/xlink", |
| 12 | + "svg": "http://www.w3.org/2000/svg" |
| 13 | +}; |
165 | 14 |
|
166 | 15 | @Injectable() |
167 | | -class DomElementSchemaRegistry implements ElementSchemaRegistry { |
168 | | - var schema = ({} as Map<String, Map<String, String>>); |
169 | | - DomElementSchemaRegistry() { |
170 | | - PROPERTIES.forEach((encodedType) { |
171 | | - var parts = encodedType.split("|"); |
172 | | - var properties = parts[1].split(","); |
173 | | - var typeParts = (parts[0] + "^").split("^"); |
174 | | - var typeName = typeParts[0]; |
175 | | - var type = this.schema[typeName] = ({} as Map<String, String>); |
176 | | - var superType = this.schema[typeParts[1]]; |
177 | | - if (isPresent(superType)) { |
178 | | - StringMapWrapper.forEach(superType, (v, k) => type[k] = v); |
179 | | - } |
180 | | - properties.forEach((String property) { |
181 | | - if (property == "") {} else if (property.startsWith("*")) { |
182 | | - type[property.substring(1)] = EVENT; |
183 | | - } else if (property.startsWith("!")) { |
184 | | - type[property.substring(1)] = BOOLEAN; |
185 | | - } else if (property.startsWith("#")) { |
186 | | - type[property.substring(1)] = NUMBER; |
187 | | - } else { |
188 | | - type[property] = STRING; |
189 | | - } |
190 | | - }); |
191 | | - }); |
| 16 | +class DomElementSchemaRegistry extends ElementSchemaRegistry { |
| 17 | + var _protoElements = new Map<String, dynamic>(); |
| 18 | + dynamic _getProtoElement(String tagName) { |
| 19 | + var element = this._protoElements[tagName]; |
| 20 | + if (isBlank(element)) { |
| 21 | + var nsAndName = splitNsName(tagName); |
| 22 | + element = isPresent(nsAndName[0]) |
| 23 | + ? DOM.createElementNS(NAMESPACE_URIS[nsAndName[0]], nsAndName[1]) |
| 24 | + : DOM.createElement(nsAndName[1]); |
| 25 | + this._protoElements[tagName] = element; |
| 26 | + } |
| 27 | + return element; |
192 | 28 | } |
| 29 | + |
193 | 30 | bool hasProperty(String tagName, String propName) { |
194 | 31 | if (!identical(tagName.indexOf("-"), -1)) { |
195 | 32 | // can't tell now as we don't know which properties a custom element will get |
196 | 33 |
|
197 | 34 | // once it is instantiated |
198 | 35 | return true; |
199 | 36 | } else { |
200 | | - var elementProperties = this.schema[tagName.toLowerCase()]; |
201 | | - if (!isPresent(elementProperties)) { |
202 | | - elementProperties = this.schema["unknown"]; |
203 | | - } |
204 | | - return isPresent(elementProperties[propName]); |
| 37 | + var elm = this._getProtoElement(tagName); |
| 38 | + return DOM.hasProperty(elm, propName); |
205 | 39 | } |
206 | 40 | } |
207 | 41 |
|
208 | 42 | String getMappedPropName(String propName) { |
209 | | - var mappedPropName = StringMapWrapper.get(attrToPropMap, propName); |
| 43 | + var mappedPropName = StringMapWrapper.get(DOM.attrToPropMap, propName); |
210 | 44 | return isPresent(mappedPropName) ? mappedPropName : propName; |
211 | 45 | } |
212 | 46 | } |
0 commit comments