UNPKG

zpt

Version:

Zenon Page Templates - JS (ZPT-JS)

311 lines (238 loc) 7.58 kB
/* Class Scope */ "use strict"; var context = require( '../context.js' ); var utils = require( '../utils.js' ); var loadjs = require( 'loadjs' ); var Scope = function( _dictionary, _dictionaryExtension, addCommonVars, _folderDictionaries ) { this.dictionary = _dictionary || {}; this.dictionaryExtension = _dictionaryExtension || {}; this.vars = {}; this.changesStack = []; this.nocallVars = {}; this.folderDictionaries = _folderDictionaries || []; this.globalVarsExpressions = {}; if ( addCommonVars ){ this.setCommonVars(); } this.setMandatoryVars(); }; Scope.prototype.setMandatoryVars = function(){ // Register nothing var this.setVar( context.getConf().nothingVarName, context.getConf().nothingVarValue ); // Register default var this.setVar( context.getConf().defaultVarName, context.getConf().defaultVarValue ); }; Scope.prototype.setCommonVars = function(){ // Register window object if it exists if ( window ){ this.setVar( context.getConf().windowVarName, window ); } // Register context this.setVar( context.getConf().contextVarName, context ); }; Scope.prototype.startElement = function(){ var vars = { varsToUnset: [], varsToSet: {}, expressions: {}, impliedDeclaredVars: [] }; this.changesStack.push( vars ); return vars; }; Scope.prototype.currentVars = function(){ return this.changesStack[ this.changesStack.length - 1 ]; }; Scope.prototype.setVar = function( name, value ) { this.vars[ name ] = value; }; Scope.prototype.getWithoutEvaluating = function( name ) { var value; value = this.vars[ name ]; if ( value !== undefined ){ return value; } value = this.dictionaryExtension[ name ]; if ( value !== undefined ){ return value; } value = this.dictionary[ name ]; if ( value !== undefined ){ return value; } for ( var i = 0; i < this.folderDictionaries.length; ++i ){ value = this.folderDictionaries[ i ][ name ]; if ( value !== undefined ){ return value; } } return undefined; }; Scope.prototype.get = function( name ) { var value = this.getWithoutEvaluating( name ); if ( ! this.nocallVars[ name ] ){ return value; } return value && utils.isFunction( value.evaluate )? value.evaluate( this ): 'Error evaluating property "' + name + '": ' + value; }; Scope.prototype.unset = function( name ) { delete this.vars[ name ]; }; Scope.prototype.endElement = function ( ) { var vars = this.changesStack.pop(); var varsToUnset = vars.varsToUnset; var varsToSet = vars.varsToSet; for ( var i = 0; i < varsToUnset.length; ++i ){ this.unset( varsToUnset[ i ] ); } for ( var name in varsToSet ){ var value = varsToSet[ name ]; this.setVar( name, value ); } }; Scope.prototype.set = function ( name, value, isGlobal, nocall, _expression ) { var expression = _expression === undefined? null: _expression; if ( ! isGlobal ){ // Local vars var vars = this.currentVars(); var currentValue = this.getWithoutEvaluating( name ); if ( currentValue != null ){ vars.varsToSet[ name ] = currentValue; } else { vars.varsToUnset.push( name ); } vars.expressions[ name ] = expression; if ( this.isStrictMode() ){ vars.impliedDeclaredVars.push( name ); } } else { // Global vars this.globalVarsExpressions[ name ] = expression; } // Common to global and local vars this.setVar( name, value ); // Add to nocallVars if needed if ( nocall ){ this.nocallVars[ name ] = true; } }; Scope.prototype.loadFolderDictionariesAsync = function ( maxFolderDictionaries, location, callback ) { if ( ! maxFolderDictionaries ) { callback(); return; } var urlList = this.buildUrlListOfFolderDictionaries( maxFolderDictionaries, location ); this.loadFolderDictionary( maxFolderDictionaries, callback, urlList, 0 ); }; Scope.prototype.loadFolderDictionary = function ( maxFolderDictionaries, callback, urlList, i ) { var instance = this; var loadjsCallback = function( url, success ){ // Treat js file only if load is sucessfull if ( success && window.folderDictionary ){ instance.folderDictionaries.push( window.folderDictionary ); } // Run callback and return if the urlList is over if ( i === urlList.length){ callback(); return; } // Continue, the urlList is not over instance.loadFolderDictionary( maxFolderDictionaries, callback, urlList, i ); }; var url = urlList[ i++ ]; loadjs( url, { success: function() { loadjsCallback( url, true ); }, error: function() { loadjsCallback( url, false ); } } ); }; Scope.prototype.buildUrlListOfFolderDictionaries = function ( maxFolderDictionaries, location ) { var result = []; var c = 0; var path = location.pathname; var lastIndex = path.lastIndexOf( '/' ); while ( lastIndex !== -1 && ++c <= maxFolderDictionaries ){ var parent = path.substr( 0, lastIndex ); result.push( location.origin + parent + '/' + 'folderDictionary.js' ); lastIndex = parent.lastIndexOf( '/' ); } return result; }; Scope.prototype.isStrictMode = function(){ return context.isStrictMode() || this.get( context.getConf().strictModeVarName ); }; Scope.prototype.isValidVariable = function( name ){ // If strict mode is off all variable are valid if ( ! this.isStrictMode() ){ return true; } // If the variable is declared return true var declared = this.get( context.getConf().declaredVarsVarName ); var isDeclared = declared && declared.indexOf? declared.indexOf( name ) !== -1: false; if ( isDeclared ){ return true; } // Check if the variable is implicitly declared for ( var i = this.changesStack.length - 1; i >= 0; --i ){ var vars = this.changesStack[ i ]; var isImplied = vars.impliedDeclaredVars.indexOf( name ) !== -1; if ( isImplied ){ return true; } } return false; }; Scope.prototype.getVarExpression = function ( name ) { var expression = this.getExpressionFromLocal( name ); return expression !== undefined? expression: this.globalVarsExpressions[ name ]; }; Scope.prototype.getExpressionFromLocal = function ( name ) { for ( var i = this.changesStack.length - 1; i >= 0; --i ){ var vars = this.changesStack[ i ]; var expression = vars.expressions[ name ]; if ( expression !== undefined ){ return expression; } } return undefined; }; Scope.prototype.isLocalVar = function ( name ) { return this.vars[ name ] !== undefined; }; module.exports = Scope;