
committed by
Tobias Bosch

parent
52236bd765
commit
841f8789fd
435
modules/angular2/src/core/dom/abstract_html_adapter.dart
Normal file
435
modules/angular2/src/core/dom/abstract_html_adapter.dart
Normal file
@ -0,0 +1,435 @@
|
||||
library angular2.dom.abstractHtmlAdapter;
|
||||
|
||||
import 'package:html/parser.dart' as parser;
|
||||
import 'package:html/dom.dart';
|
||||
|
||||
import 'dom_adapter.dart';
|
||||
import 'emulated_css.dart';
|
||||
|
||||
abstract class AbstractHtml5LibAdapter implements DomAdapter {
|
||||
hasProperty(element, String name) {
|
||||
// This is needed for serverside compile to generate the right getters/setters.
|
||||
// TODO: change this once we have property schema support.
|
||||
// Attention: Keep this in sync with browser_adapter.dart!
|
||||
return true;
|
||||
}
|
||||
|
||||
void setProperty(Element element, String name, Object value) =>
|
||||
throw 'not implemented';
|
||||
|
||||
getProperty(Element element, String name) => throw 'not implemented';
|
||||
|
||||
invoke(Element element, String methodName, List args) =>
|
||||
throw 'not implemented';
|
||||
|
||||
@override
|
||||
final attrToPropMap = const {
|
||||
'innerHtml': 'innerHTML',
|
||||
'readonly': 'readOnly',
|
||||
'tabindex': 'tabIndex',
|
||||
};
|
||||
|
||||
set attrToPropMap(value) {
|
||||
throw 'readonly';
|
||||
}
|
||||
|
||||
@override
|
||||
getGlobalEventTarget(String target) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
getTitle() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
setTitle(String newTitle) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
String getEventKey(event) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
void replaceChild(el, newNode, oldNode) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
@override
|
||||
dynamic getBoundingClientRect(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
Element parse(String templateHtml) => parser.parse(templateHtml).firstChild;
|
||||
query(selector) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
querySelector(el, String selector) {
|
||||
return el.querySelector(selector);
|
||||
}
|
||||
|
||||
List querySelectorAll(el, String selector) {
|
||||
return el.querySelectorAll(selector);
|
||||
}
|
||||
|
||||
on(el, evt, listener) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
Function onAndCancel(el, evt, listener) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
dispatchEvent(el, evt) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
createMouseEvent(eventType) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
createEvent(eventType) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
preventDefault(evt) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
isPrevented(evt) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getInnerHTML(el) {
|
||||
return el.innerHtml;
|
||||
}
|
||||
|
||||
getOuterHTML(el) {
|
||||
return el.outerHtml;
|
||||
}
|
||||
|
||||
String nodeName(node) {
|
||||
switch (node.nodeType) {
|
||||
case Node.ELEMENT_NODE:
|
||||
return (node as Element).localName;
|
||||
case Node.TEXT_NODE:
|
||||
return '#text';
|
||||
default:
|
||||
throw 'not implemented for type ${node.nodeType}. '
|
||||
'See http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-1950641247'
|
||||
' for node types definitions.';
|
||||
}
|
||||
}
|
||||
|
||||
String nodeValue(node) => node.data;
|
||||
String type(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
content(node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
firstChild(el) => el is NodeList ? el.first : el.firstChild;
|
||||
|
||||
nextSibling(el) {
|
||||
final parentNode = el.parentNode;
|
||||
if (parentNode == null) return null;
|
||||
final siblings = parentNode.nodes;
|
||||
final index = siblings.indexOf(el);
|
||||
if (index < siblings.length - 1) {
|
||||
return siblings[index + 1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
parentElement(el) {
|
||||
return el.parent;
|
||||
}
|
||||
|
||||
List childNodes(el) => el.nodes;
|
||||
List childNodesAsList(el) => el.nodes;
|
||||
clearNodes(el) {
|
||||
el.nodes.forEach((e) => e.remove());
|
||||
}
|
||||
|
||||
appendChild(el, node) => el.append(node.remove());
|
||||
removeChild(el, node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
remove(el) => el.remove();
|
||||
insertBefore(el, node) {
|
||||
if (el.parent == null) throw '$el must have a parent';
|
||||
el.parent.insertBefore(node, el);
|
||||
}
|
||||
|
||||
insertAllBefore(el, nodes) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
insertAfter(el, node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
setInnerHTML(el, value) {
|
||||
el.innerHtml = value;
|
||||
}
|
||||
|
||||
getText(el) {
|
||||
return el.text;
|
||||
}
|
||||
|
||||
setText(el, String value) => el.text = value;
|
||||
|
||||
getValue(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
setValue(el, String value) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getChecked(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
setChecked(el, bool value) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
createComment(String text) => new Comment(text);
|
||||
createTemplate(String html) => createElement('template')..innerHtml = html;
|
||||
createElement(tagName, [doc]) {
|
||||
return new Element.tag(tagName);
|
||||
}
|
||||
|
||||
createTextNode(String text, [doc]) => new Text(text);
|
||||
|
||||
createScriptTag(String attrName, String attrValue, [doc]) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
createStyleElement(String css, [doc]) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
createShadowRoot(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getShadowRoot(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getHost(el) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
clone(node) => node.clone(true);
|
||||
getElementsByClassName(element, String name) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getElementsByTagName(element, String name) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
List classList(element) => element.classes.toList();
|
||||
|
||||
addClass(element, String classname) {
|
||||
element.classes.add(classname);
|
||||
}
|
||||
|
||||
removeClass(element, String classname) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
hasClass(element, String classname) => element.classes.contains(classname);
|
||||
|
||||
setStyle(element, String stylename, String stylevalue) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
removeStyle(element, String stylename) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getStyle(element, String stylename) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
String tagName(element) => element.localName;
|
||||
|
||||
attributeMap(element) {
|
||||
// `attributes` keys can be {@link AttributeName}s.
|
||||
var map = <String, String>{};
|
||||
element.attributes.forEach((key, value) {
|
||||
map['$key'] = value;
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
hasAttribute(element, String attribute) {
|
||||
// `attributes` keys can be {@link AttributeName}s.
|
||||
return element.attributes.keys.any((key) => '$key' == attribute);
|
||||
}
|
||||
|
||||
getAttribute(element, String attribute) {
|
||||
// `attributes` keys can be {@link AttributeName}s.
|
||||
var key = element.attributes.keys.firstWhere((key) => '$key' == attribute,
|
||||
orElse: () {});
|
||||
return element.attributes[key];
|
||||
}
|
||||
|
||||
setAttribute(element, String name, String value) {
|
||||
element.attributes[name] = value;
|
||||
}
|
||||
|
||||
removeAttribute(element, String attribute) {
|
||||
element.attributes.remove(attribute);
|
||||
}
|
||||
|
||||
templateAwareRoot(el) => el;
|
||||
|
||||
createHtmlDocument() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
defaultDoc() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
bool elementMatches(n, String selector) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
bool isTemplateElement(Element el) {
|
||||
return el != null && el.localName.toLowerCase() == 'template';
|
||||
}
|
||||
|
||||
bool isTextNode(node) => node.nodeType == Node.TEXT_NODE;
|
||||
bool isCommentNode(node) => node.nodeType == Node.COMMENT_NODE;
|
||||
|
||||
bool isElementNode(node) => node.nodeType == Node.ELEMENT_NODE;
|
||||
|
||||
bool hasShadowRoot(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
bool isShadowRoot(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
importIntoDoc(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
adoptNode(node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
bool isPageRule(rule) => (rule.type == 6);
|
||||
|
||||
bool isStyleRule(rule) => (rule.type == 1);
|
||||
|
||||
bool isMediaRule(rule) => (rule.type == 4);
|
||||
|
||||
bool isKeyframesRule(rule) => (rule.type == 7);
|
||||
|
||||
String getHref(element) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
void resolveAndSetHref(element, baseUrl, href) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
List cssToRules(String css) {
|
||||
return parseAndEmulateCssRules(css);
|
||||
}
|
||||
|
||||
List getDistributedNodes(Node) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
bool supportsDOMEvents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supportsNativeShadowDOM() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool supportsUnprefixedCssAnimation() {
|
||||
// Currently during code transformation we do not know what
|
||||
// browsers we are targetting. To play it safe, we assume
|
||||
// unprefixed animations are not supported.
|
||||
return false;
|
||||
}
|
||||
|
||||
getHistory() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getLocation() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getBaseHref() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
resetBaseElement() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
String getUserAgent() {
|
||||
return 'Angular 2 Dart Transformer';
|
||||
}
|
||||
|
||||
void setData(Element element, String name, String value) {
|
||||
this.setAttribute(element, 'data-${name}', value);
|
||||
}
|
||||
|
||||
getComputedStyle(element) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
String getData(Element element, String name) {
|
||||
return this.getAttribute(element, 'data-${name}');
|
||||
}
|
||||
|
||||
// TODO(tbosch): move this into a separate environment class once we have it
|
||||
setGlobalVar(String name, value) {
|
||||
// noop on the server
|
||||
}
|
||||
|
||||
requestAnimationFrame(callback) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
cancelAnimationFrame(id) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
performanceNow() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getAnimationPrefix() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getTransitionEnd() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
supportsAnimation() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
}
|
102
modules/angular2/src/core/dom/emulated_css.dart
Normal file
102
modules/angular2/src/core/dom/emulated_css.dart
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Emulates browser CSS API.
|
||||
*
|
||||
* WARNING: this is a very incomplete emulation; it only has enough to support
|
||||
* Angular's CSS scoping (a.k.a. shimming).
|
||||
*/
|
||||
library angular2.dom.emulated_css;
|
||||
|
||||
import 'package:csslib/parser.dart' as cssp;
|
||||
import 'package:csslib/visitor.dart' as cssv;
|
||||
|
||||
/// Parses [css] string and emits the list of top-level CSS rules in it via
|
||||
/// data structures that mimick browser CSS APIs.
|
||||
List<EmulatedCssRule> parseAndEmulateCssRules(String css) {
|
||||
var stylesheet = cssp.parse(css);
|
||||
return emulateRules(stylesheet.topLevels);
|
||||
}
|
||||
|
||||
/// Converts `csslib` [rules] to their emulated counterparts.
|
||||
List<EmulatedCssRule> emulateRules(Iterable<cssv.TreeNode> rules) {
|
||||
return rules
|
||||
.map((cssv.TreeNode node) {
|
||||
if (node is cssv.RuleSet) {
|
||||
if (node.declarationGroup.span.text.isEmpty) {
|
||||
// Skip CSS matchers with no bodies
|
||||
return null;
|
||||
}
|
||||
return new EmulatedCssStyleRule(node);
|
||||
} else if (node is cssv.MediaDirective) {
|
||||
return new EmulatedCssMedialRule(node);
|
||||
}
|
||||
})
|
||||
.where((r) => r != null)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/// Emulates [CSSRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSRule)
|
||||
abstract class EmulatedCssRule {
|
||||
int type;
|
||||
String cssText;
|
||||
}
|
||||
|
||||
/// Emulates [CSSStyleRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule)
|
||||
class EmulatedCssStyleRule extends EmulatedCssRule {
|
||||
String selectorText;
|
||||
EmulatedCssStyleDeclaration style;
|
||||
|
||||
EmulatedCssStyleRule(cssv.RuleSet ruleSet) {
|
||||
final declarationText = new StringBuffer();
|
||||
ruleSet.declarationGroup.declarations.forEach((d) {
|
||||
if (d is! cssv.Declaration) {
|
||||
// Nested selectors not supported
|
||||
return;
|
||||
}
|
||||
// TODO: expression spans are currently broken in csslib; see:
|
||||
// https://github.com/dart-lang/csslib/pull/14
|
||||
var declarationSpan = d.span.text;
|
||||
var colonIdx = declarationSpan.indexOf(':');
|
||||
var expression = declarationSpan.substring(colonIdx + 1);
|
||||
declarationText.write('${d.property}: ${expression};');
|
||||
});
|
||||
|
||||
final style = new EmulatedCssStyleDeclaration()
|
||||
..cssText = declarationText.toString();
|
||||
|
||||
this
|
||||
..type = 1
|
||||
..cssText = ruleSet.span.text
|
||||
..selectorText = ruleSet.selectorGroup.span.text
|
||||
..style = style;
|
||||
}
|
||||
}
|
||||
|
||||
/// Emulates [CSSStyleDeclaration](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration)
|
||||
class EmulatedCssStyleDeclaration {
|
||||
final String content = '';
|
||||
String cssText;
|
||||
}
|
||||
|
||||
/// Emulates [CSSMediaRule](https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule)
|
||||
class EmulatedCssMedialRule extends EmulatedCssRule {
|
||||
List<EmulatedCssStyleRule> cssRules;
|
||||
EmulatedMediaList media;
|
||||
|
||||
EmulatedCssMedialRule(cssv.MediaDirective directive) {
|
||||
this
|
||||
..type = 4
|
||||
..media = new EmulatedMediaList(directive)
|
||||
..cssText = directive.span.text
|
||||
..cssRules = emulateRules(directive.rulesets);
|
||||
}
|
||||
}
|
||||
|
||||
/// Emulates [MediaList](https://developer.mozilla.org/en-US/docs/Web/API/MediaList)
|
||||
class EmulatedMediaList {
|
||||
String mediaText;
|
||||
|
||||
EmulatedMediaList(cssv.MediaDirective directive) {
|
||||
this.mediaText = directive.mediaQueries
|
||||
.map((q) => q.span.text).join(' and ');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user