tns-core-modules
Version:
Telerik NativeScript Core Modules
221 lines (220 loc) • 8.71 kB
JavaScript
var trace = require("trace");
var cssSelector = require("ui/styling/css-selector");
var cssParser = require("css");
var application = require("application");
var types;
function ensureTypes() {
if (!types) {
types = require("utils/types");
}
}
var utils;
function ensureUtils() {
if (!utils) {
utils = require("utils/utils");
}
}
var fs;
function ensureFS() {
if (!fs) {
fs = require("file-system");
}
}
var vs;
function ensureVisualState() {
if (!vs) {
vs = require("./visual-state");
}
}
var pattern = /('|")(.*?)\1/;
var StyleScope = (function () {
function StyleScope() {
this._statesByKey = {};
this._viewIdToKey = {};
}
Object.defineProperty(StyleScope.prototype, "css", {
get: function () {
return this._css;
},
set: function (value) {
this._css = value;
this._cssFileName = undefined;
this._cssSelectors = undefined;
this._reset();
},
enumerable: true,
configurable: true
});
StyleScope.prototype.addCss = function (cssString, cssFileName) {
this._css = this._css ? this._css + cssString : cssString;
this._cssFileName = cssFileName;
this._reset();
if (!this._cssSelectors) {
if (application.cssSelectorsCache) {
this._cssSelectors = StyleScope._joinCssSelectorsArrays([application.cssSelectorsCache]);
}
else {
this._cssSelectors = new Array();
}
}
var selectorsFromFile = StyleScope.createSelectorsFromCss(cssString, cssFileName);
this._cssSelectors = StyleScope._joinCssSelectorsArrays([this._cssSelectors, selectorsFromFile]);
};
StyleScope.createSelectorsFromCss = function (css, cssFileName) {
try {
var pageCssSyntaxTree = css ? cssParser.parse(css, { source: cssFileName }) : null;
var pageCssSelectors = new Array();
if (pageCssSyntaxTree) {
pageCssSelectors = StyleScope._joinCssSelectorsArrays([pageCssSelectors, StyleScope.createSelectorsFromImports(pageCssSyntaxTree)]);
pageCssSelectors = StyleScope._joinCssSelectorsArrays([pageCssSelectors, StyleScope.createSelectorsFromSyntaxTree(pageCssSyntaxTree)]);
}
return pageCssSelectors;
}
catch (e) {
trace.write("Css styling failed: " + e, trace.categories.Error, trace.messageType.error);
}
};
StyleScope.createSelectorsFromImports = function (tree) {
var selectors = new Array();
ensureTypes();
if (!types.isNullOrUndefined(tree)) {
var imports = tree["stylesheet"]["rules"].filter(function (r) { return r.type === "import"; });
for (var i = 0; i < imports.length; i++) {
var importItem = imports[i]["import"];
var match = importItem && importItem.match(pattern);
var url = match && match[2];
if (!types.isNullOrUndefined(url)) {
ensureUtils();
if (utils.isFileOrResourcePath(url)) {
ensureFS();
var fileName = types.isString(url) ? url.trim() : "";
if (fileName.indexOf("~/") === 0) {
fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", ""));
}
if (fs.File.exists(fileName)) {
var file = fs.File.fromPath(fileName);
var text = file.readTextSync();
if (text) {
selectors = StyleScope._joinCssSelectorsArrays([selectors, StyleScope.createSelectorsFromCss(text, fileName)]);
}
}
}
}
}
}
return selectors;
};
StyleScope.prototype.ensureSelectors = function () {
if (!this._cssSelectors && (this._css || application.cssSelectorsCache)) {
var applicationCssSelectors = application.cssSelectorsCache ? application.cssSelectorsCache : null;
var pageCssSelectors = StyleScope.createSelectorsFromCss(this._css, this._cssFileName);
this._cssSelectors = StyleScope._joinCssSelectorsArrays([applicationCssSelectors, pageCssSelectors]);
}
};
StyleScope._joinCssSelectorsArrays = function (arrays) {
var mergedResult = [];
var i;
for (i = 0; i < arrays.length; i++) {
if (arrays[i]) {
mergedResult.push.apply(mergedResult, arrays[i]);
}
}
mergedResult.sort(function (a, b) { return a.specificity - b.specificity; });
return mergedResult;
};
StyleScope.prototype.applySelectors = function (view) {
if (!this._cssSelectors) {
return;
}
view.style._beginUpdate();
var i, selector, matchedStateSelectors = new Array();
for (i = 0; i < this._cssSelectors.length; i++) {
selector = this._cssSelectors[i];
if (selector.matches(view)) {
if (selector instanceof cssSelector.CssVisualStateSelector) {
matchedStateSelectors.push(selector);
}
else {
selector.apply(view);
}
}
}
if (matchedStateSelectors.length > 0) {
var key = "";
matchedStateSelectors.forEach(function (s) { return key += s.key + "|"; });
this._viewIdToKey[view._domId] = key;
if (!this._statesByKey[key]) {
this._createVisualsStatesForSelectors(key, matchedStateSelectors);
}
}
view.style._endUpdate();
};
StyleScope.prototype.getVisualStates = function (view) {
var key = this._viewIdToKey[view._domId];
if (key === undefined) {
return undefined;
}
return this._statesByKey[key];
};
StyleScope.prototype._createVisualsStatesForSelectors = function (key, matchedStateSelectors) {
var i, allStates = {}, stateSelector;
this._statesByKey[key] = allStates;
ensureVisualState();
for (i = 0; i < matchedStateSelectors.length; i++) {
stateSelector = matchedStateSelectors[i];
var visualState = allStates[stateSelector.state];
if (!visualState) {
visualState = new vs.VisualState();
allStates[stateSelector.state] = visualState;
}
stateSelector.eachSetter(function (property, value) {
visualState.setters[property.name] = value;
});
}
};
StyleScope.createSelectorsFromSyntaxTree = function (ast) {
var result = [];
var rules = ast.stylesheet.rules;
var rule;
var i;
var j;
for (i = 0; i < rules.length; i++) {
rule = rules[i];
if (rule.type === "rule") {
var filteredDeclarations = [];
if (rule.declarations) {
for (j = 0; j < rule.declarations.length; j++) {
var declaration = rule.declarations[j];
if (declaration.type === "declaration") {
filteredDeclarations.push({
property: declaration.property.toLowerCase(),
value: declaration.value
});
}
}
}
for (j = 0; j < rule.selectors.length; j++) {
result.push(cssSelector.createSelector(rule.selectors[j], filteredDeclarations));
}
}
}
return result;
};
StyleScope.prototype._reset = function () {
this._statesByKey = {};
this._viewIdToKey = {};
};
return StyleScope;
}());
exports.StyleScope = StyleScope;
function applyInlineSyle(view, style) {
try {
var syntaxTree = cssParser.parse("local { " + style + " }", undefined);
var filteredDeclarations = syntaxTree.stylesheet.rules[0].declarations.filter(function (val, i, arr) { return val.type === "declaration"; });
cssSelector.applyInlineSyle(view, filteredDeclarations);
}
catch (ex) {
trace.write("Applying local style failed: " + ex, trace.categories.Error, trace.messageType.error);
}
}
exports.applyInlineSyle = applyInlineSyle;