UNPKG

tns-core-modules

Version:

Telerik NativeScript Core Modules

221 lines (220 loc) • 8.71 kB
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;