tns-core-modules
Version:
Telerik NativeScript Core Modules
428 lines (427 loc) • 15.2 kB
JavaScript
var observable = require("ui/core/dependency-observable");
var trace = require("trace");
var styleProperty = require("ui/styling/style-property");
var types = require("utils/types");
var utils = require("utils/utils");
var ID_SPECIFICITY = 1000000;
var ATTR_SPECIFITY = 10000;
var CLASS_SPECIFICITY = 100;
var TYPE_SPECIFICITY = 1;
var CssSelector = (function () {
function CssSelector(expression, declarations) {
if (expression) {
var leftSquareBracketIndex = expression.indexOf(LSBRACKET);
if (leftSquareBracketIndex > 0) {
var paramsRegex = /\[\s*(.*)\s*\]/;
var attrParams = paramsRegex.exec(expression);
if (attrParams && attrParams.length > 1) {
this._attrExpression = attrParams[1].trim();
}
this._expression = expression.substr(0, leftSquareBracketIndex);
}
else {
this._expression = expression;
}
}
this._declarations = declarations;
}
Object.defineProperty(CssSelector.prototype, "expression", {
get: function () {
return this._expression;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CssSelector.prototype, "attrExpression", {
get: function () {
return this._attrExpression;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CssSelector.prototype, "declarations", {
get: function () {
return this._declarations;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CssSelector.prototype, "specificity", {
get: function () {
throw "Specificity property is abstract";
},
enumerable: true,
configurable: true
});
CssSelector.prototype.matches = function (view) {
return false;
};
CssSelector.prototype.apply = function (view) {
this.eachSetter(function (property, value) {
try {
view.style._setValue(property, value, observable.ValueSource.Css);
}
catch (ex) {
trace.write("Error setting property: " + property.name + " view: " + view + " value: " + value + " " + ex, trace.categories.Style, trace.messageType.error);
}
});
};
CssSelector.prototype.eachSetter = function (callback) {
for (var i = 0; i < this._declarations.length; i++) {
var declaration = this._declarations[i];
var name_1 = declaration.property;
var resolvedValue = declaration.value;
var property = styleProperty.getPropertyByCssName(name_1);
if (property) {
callback(property, resolvedValue);
}
else {
var pairs = styleProperty.getShorthandPairs(name_1, resolvedValue);
if (pairs) {
for (var j = 0; j < pairs.length; j++) {
var pair = pairs[j];
callback(pair.property, pair.value);
}
}
}
}
};
return CssSelector;
}());
exports.CssSelector = CssSelector;
var CssTypeSelector = (function (_super) {
__extends(CssTypeSelector, _super);
function CssTypeSelector() {
_super.apply(this, arguments);
}
Object.defineProperty(CssTypeSelector.prototype, "specificity", {
get: function () {
return TYPE_SPECIFICITY;
},
enumerable: true,
configurable: true
});
CssTypeSelector.prototype.matches = function (view) {
var result = matchesType(this.expression, view);
if (result && this.attrExpression) {
return matchesAttr(this.attrExpression, view);
}
return result;
};
return CssTypeSelector;
}(CssSelector));
function matchesType(expression, view) {
var exprArr = expression.split(".");
var exprTypeName = exprArr[0];
var exprClassName = exprArr[1];
var typeCheck = exprTypeName.toLowerCase() === view.typeName.toLowerCase() ||
exprTypeName.toLowerCase() === view.typeName.split(/(?=[A-Z])/).join("-").toLowerCase();
if (typeCheck) {
if (exprClassName) {
return view._cssClasses.some(function (cssClass, i, arr) { return cssClass === exprClassName; });
}
else {
return typeCheck;
}
}
else {
return false;
}
}
var CssIdSelector = (function (_super) {
__extends(CssIdSelector, _super);
function CssIdSelector() {
_super.apply(this, arguments);
}
Object.defineProperty(CssIdSelector.prototype, "specificity", {
get: function () {
return ID_SPECIFICITY;
},
enumerable: true,
configurable: true
});
CssIdSelector.prototype.matches = function (view) {
var result = this.expression === view.id;
if (result && this.attrExpression) {
return matchesAttr(this.attrExpression, view);
}
return result;
};
return CssIdSelector;
}(CssSelector));
var CssClassSelector = (function (_super) {
__extends(CssClassSelector, _super);
function CssClassSelector() {
_super.apply(this, arguments);
}
Object.defineProperty(CssClassSelector.prototype, "specificity", {
get: function () {
return CLASS_SPECIFICITY;
},
enumerable: true,
configurable: true
});
CssClassSelector.prototype.matches = function (view) {
var expectedClass = this.expression;
var result = view._cssClasses.some(function (cssClass, i, arr) { return cssClass === expectedClass; });
if (result && this.attrExpression) {
return matchesAttr(this.attrExpression, view);
}
return result;
};
return CssClassSelector;
}(CssSelector));
var CssCompositeSelector = (function (_super) {
__extends(CssCompositeSelector, _super);
function CssCompositeSelector(expr, declarations) {
_super.call(this, expr, declarations);
var expressions = this.splitExpression(expr);
var onlyParent = false;
this.parentCssSelectors = [];
for (var i = expressions.length - 1; i >= 0; i--) {
if (expressions[i].trim() === GTHAN) {
onlyParent = true;
continue;
}
this.parentCssSelectors.push({ selector: createSelector(expressions[i].trim(), null), onlyDirectParent: onlyParent });
onlyParent = false;
}
}
Object.defineProperty(CssCompositeSelector.prototype, "specificity", {
get: function () {
var result = 0;
for (var i = 0; i < this.parentCssSelectors.length; i++) {
result += this.parentCssSelectors[i].selector.specificity;
}
return result;
},
enumerable: true,
configurable: true
});
CssCompositeSelector.prototype.splitExpression = function (expression) {
var result = [];
var tempArr = [];
var validSpace = true;
for (var i = 0; i < expression.length; i++) {
if (expression[i] === LSBRACKET) {
validSpace = false;
}
if (expression[i] === RSBRACKET) {
validSpace = true;
}
if ((expression[i] === SPACE && validSpace) || (expression[i] === GTHAN)) {
if (tempArr.length > 0) {
result.push(tempArr.join(""));
tempArr = [];
}
if (expression[i] === GTHAN) {
result.push(GTHAN);
}
continue;
}
tempArr.push(expression[i]);
}
if (tempArr.length > 0) {
result.push(tempArr.join(""));
}
return result;
};
CssCompositeSelector.prototype.matches = function (view) {
var result = this.parentCssSelectors[0].selector.matches(view);
if (!result) {
return result;
}
var tempView = view.parent;
for (var i = 1; i < this.parentCssSelectors.length; i++) {
var parentCounter = 0;
while (tempView && parentCounter === 0) {
result = this.parentCssSelectors[i].selector.matches(tempView);
if (result) {
tempView = tempView.parent;
break;
}
if (this.parentCssSelectors[i].onlyDirectParent) {
parentCounter++;
}
tempView = tempView.parent;
}
if (!result) {
break;
}
}
return result;
};
return CssCompositeSelector;
}(CssSelector));
var CssAttrSelector = (function (_super) {
__extends(CssAttrSelector, _super);
function CssAttrSelector() {
_super.apply(this, arguments);
}
Object.defineProperty(CssAttrSelector.prototype, "specificity", {
get: function () {
return ATTR_SPECIFITY;
},
enumerable: true,
configurable: true
});
CssAttrSelector.prototype.matches = function (view) {
return matchesAttr(this.attrExpression, view);
};
return CssAttrSelector;
}(CssSelector));
function matchesAttr(attrExpression, view) {
var equalSignIndex = attrExpression.indexOf(EQUAL);
if (equalSignIndex > 0) {
var nameValueRegex = /(.*[^~|\^\$\*])[~|\^\$\*]?=(.*)/;
var nameValueRegexRes = nameValueRegex.exec(attrExpression);
var attrName = void 0;
var attrValue = void 0;
if (nameValueRegexRes && nameValueRegexRes.length > 2) {
attrName = nameValueRegexRes[1].trim();
attrValue = nameValueRegexRes[2].trim().replace(/^(["'])*(.*)\1$/, '$2');
}
var escapedAttrValue = utils.escapeRegexSymbols(attrValue);
var attrCheckRegex = void 0;
switch (attrExpression.charAt(equalSignIndex - 1)) {
case "~":
attrCheckRegex = new RegExp("(^|[^a-zA-Z-])" + escapedAttrValue + "([^a-zA-Z-]|$)");
break;
case "|":
attrCheckRegex = new RegExp("^" + escapedAttrValue + "\\b");
break;
case "^":
attrCheckRegex = new RegExp("^" + escapedAttrValue);
break;
case "$":
attrCheckRegex = new RegExp(escapedAttrValue + "$");
break;
case "*":
attrCheckRegex = new RegExp(escapedAttrValue);
break;
default:
attrCheckRegex = new RegExp("^" + escapedAttrValue + "$");
break;
}
return !types.isNullOrUndefined(view[attrName]) && attrCheckRegex.test(view[attrName] + "");
}
else {
return !types.isNullOrUndefined(view[attrExpression]);
}
}
var CssVisualStateSelector = (function (_super) {
__extends(CssVisualStateSelector, _super);
function CssVisualStateSelector(expression, declarations) {
_super.call(this, expression, declarations);
var args = expression.split(COLON);
this._key = args[0];
this._state = args[1];
if (this._key.charAt(0) === HASH) {
this._match = this._key.substring(1);
this._isById = true;
}
else if (this._key.charAt(0) === DOT) {
this._match = this._key.substring(1);
this._isByClass = true;
}
else if (this._key.charAt(0) === LSBRACKET) {
this._match = this._key;
this._isByAttr = true;
}
else if (this._key.length > 0) {
this._match = this._key;
this._isByType = true;
}
}
Object.defineProperty(CssVisualStateSelector.prototype, "specificity", {
get: function () {
return (this._isById ? ID_SPECIFICITY : 0) +
(this._isByAttr ? ATTR_SPECIFITY : 0) +
(this._isByClass ? CLASS_SPECIFICITY : 0) +
(this._isByType ? TYPE_SPECIFICITY : 0);
},
enumerable: true,
configurable: true
});
Object.defineProperty(CssVisualStateSelector.prototype, "key", {
get: function () {
return this._key;
},
enumerable: true,
configurable: true
});
Object.defineProperty(CssVisualStateSelector.prototype, "state", {
get: function () {
return this._state;
},
enumerable: true,
configurable: true
});
CssVisualStateSelector.prototype.matches = function (view) {
var matches = true;
if (this._isById) {
matches = this._match === view.id;
}
if (this._isByClass) {
var expectedClass = this._match;
matches = view._cssClasses.some(function (cssClass, i, arr) { return cssClass === expectedClass; });
}
if (this._isByType) {
matches = matchesType(this._match, view);
}
if (this._isByAttr) {
matches = matchesAttr(this._key, view);
}
return matches;
};
return CssVisualStateSelector;
}(CssSelector));
exports.CssVisualStateSelector = CssVisualStateSelector;
var HASH = "#";
var DOT = ".";
var COLON = ":";
var SPACE = " ";
var GTHAN = ">";
var LSBRACKET = "[";
var RSBRACKET = "]";
var EQUAL = "=";
function createSelector(expression, declarations) {
var goodExpr = expression.replace(/>/g, " > ").replace(/\s\s+/g, " ");
var spaceIndex = goodExpr.indexOf(SPACE);
if (spaceIndex >= 0) {
return new CssCompositeSelector(goodExpr, declarations);
}
var leftSquareBracketIndex = goodExpr.indexOf(LSBRACKET);
if (leftSquareBracketIndex === 0) {
return new CssAttrSelector(goodExpr, declarations);
}
var colonIndex = goodExpr.indexOf(COLON);
if (colonIndex >= 0) {
return new CssVisualStateSelector(goodExpr, declarations);
}
if (goodExpr.charAt(0) === HASH) {
return new CssIdSelector(goodExpr.substring(1), declarations);
}
if (goodExpr.charAt(0) === DOT) {
return new CssClassSelector(goodExpr.substring(1), declarations);
}
return new CssTypeSelector(goodExpr, declarations);
}
exports.createSelector = createSelector;
var InlineStyleSelector = (function (_super) {
__extends(InlineStyleSelector, _super);
function InlineStyleSelector(declarations) {
_super.call(this, undefined, declarations);
}
InlineStyleSelector.prototype.apply = function (view) {
this.eachSetter(function (property, value) {
view.style._setValue(property, value, observable.ValueSource.Local);
});
};
return InlineStyleSelector;
}(CssSelector));
function applyInlineSyle(view, declarations) {
var localStyleSelector = new InlineStyleSelector(declarations);
localStyleSelector.apply(view);
}
exports.applyInlineSyle = applyInlineSyle;