mediawiki-extensions-Templa.../modules/ext.templateDataGenerator.data.js
Moriel Schottlender 16cca5b1a2 Trim aliases on save
Make sure that aliases get trimmed and are not getting extra spaces
when saving a parameter.
NOTE: To prevent dirty diffs, only parameters that are 'touched'
(viewed or edited directly in the editor) will be trimmed. The editor
will keep all other "wrong" values that have trailing or preceding
whitespaces as-is.

Bug: T85330
Change-Id: I64ecb88a7d736fa36b5e6debf2e94b0d37152020
2015-01-12 15:29:38 -08:00

1001 lines
29 KiB
JavaScript

( function ( $ ) {
/**
* TemplateData Dialog
* @param {Object} config Dialog configuration object
*/
TemplateDataModel = function TemplateDataModel( config ) {
config = config || {};
// Mixin constructors
OO.EventEmitter.call( this );
// Config
this.setParentPage( config.parentPage );
this.setPageSubLevel( config.isPageSubLevel );
// Properties
this.params = {};
this.description = {};
this.paramOrder = [];
this.paramIdentifierCounter = 0;
this.setPageSubLevel( !!config.isPageSubLevel );
this.setFullPageName( config.fullPageName || '' );
this.originalTemplateDataObject = null;
this.sourceCodeParameters = [];
this.templateSourceCodePromise = null;
};
/* Setup */
OO.initClass( TemplateDataModel );
OO.mixinClass( TemplateDataModel, OO.EventEmitter );
/* Events */
/**
* @event add-param
* @param {string} key Parameter key
* @param {Object} data Parameter data
*/
/**
* @event change-description
* @param {string} description New template description
* @param {Object} [language] Description language, if supplied
*/
/**
* @event change-paramOrder
* @param {string[]} orderArray Parameter key array in order
*/
/**
* @event change-property
* @param {string} paramKey Parameter key
* @param {string} prop Property name
* @param {Mixed...} value Property value
*/
/* Static Methods */
/**
* Get information from the mediaWiki API
* @param {string} page Page name
* @return {jQuery.Promise} API promise
*/
TemplateDataModel.static.getApi = function ( page ) {
var api = new mediaWiki.Api();
return api.get( {
action: 'query',
prop: 'revisions',
rvprop: 'content',
indexpageids: '1',
titles: page
} );
};
/**
* Compare two objects or strings
* @param {Object|string} obj1 Base object
* @param {Object|string} obj2 Compared object
* @param {boolean} [allowSubset] Allow the second object to be a
* partial object (or a subset) of the first.
* @return {boolean} Objects have equal values
*/
TemplateDataModel.static.compare = function ( obj1, obj2, allowSubset ) {
if ( allowSubset && obj2 === undefined ) {
return true;
}
// Make sure the objects are of the same type
if ( $.type( obj1 ) !== $.type( obj2 ) ) {
return false;
}
// Comparing objects or arrays
if ( typeof obj1 === 'object' ) {
return OO.compare( obj2, obj1, allowSubset );
}
// Everything else (primitive types, functions, etc)
return obj1 === obj2;
};
/**
* Translate obsolete parameter types into the new types
* @param {string} paramType Given type
* @return {string} Normalized non-obsolete type
*/
TemplateDataModel.static.translateObsoleteParamTypes = function ( paramType ) {
switch ( paramType ) {
case 'string/wiki-page-name':
return 'wiki-page-name';
case 'string/wiki-file-name':
return 'wiki-file-name';
case 'string/wiki-user-name':
return 'wiki-user-name';
default:
return paramType;
}
};
/**
* Retrieve information about all legal properties for a parameter.
* @param {boolean} getFullData Retrieve full information about each
* parameter. If false, the method will return an array of property
* names only.
* @return {Object|string[]} Legal property names with or without their
* definition data
*/
TemplateDataModel.static.getAllProperties = function ( getFullData ) {
var properties = {
name: {
type: 'string',
// Validation regex
restrict: /[\|=]|}}/
},
aliases: {
type: 'array',
delimiter: mw.msg( 'comma-separator' )
},
label: {
type: 'string',
allowLanguages: true
},
description: {
type: 'string',
allowLanguages: true
},
type: {
type: 'select',
children: [
'boolean',
'content',
'wiki-file-name',
'line',
'number',
'date',
'wiki-page-name',
'string',
'unbalanced-wikitext',
'undefined',
'wiki-user-name'
],
'default': 'undefined'
},
'default': {
type: 'string',
multiline: true
},
autovalue: {
type: 'string'
},
required: {
type: 'boolean'
},
suggested: {
type: 'boolean'
}
};
if ( !getFullData ) {
return Object.keys( properties );
} else {
return properties;
}
};
/**
* Retrieve the list of property names that allow for multiple languages.
* @return {string[]} Property names
*/
TemplateDataModel.static.getPropertiesWithLanguage = function () {
var prop,
result = [],
propDefinitions = this.getAllProperties( true );
for ( prop in propDefinitions ) {
if ( propDefinitions[prop].allowLanguages ) {
result.push( prop );
}
}
return result;
};
/**
* Split a string into an array and clean/trim the values
* @param {string} str String to split
* @param {string} [delim] Delimeter
* @return {string[]} Clean array
*/
TemplateDataModel.static.splitAndTrimArray = function ( str, delim ) {
var arr = [];
delim = delim || mw.msg( 'comma-separator' );
$.each( str.split( delim ), function () {
var trimmed = $.trim( this );
if ( trimmed ) {
arr.push( trimmed );
}
} );
return arr;
};
/**
* This is an adjustment of OO.simpleArrayUnion that ignores
* empty values when inserting into the unified array.
* @param {Array...} arrays Arrays to union
* @return {Array} Union of the arrays
*/
TemplateDataModel.static.arrayUnionWithoutEmpty = function () {
var result = OO.simpleArrayUnion.apply( this, arguments );
// Trim and filter empty strings
return result.filter( function ( i ) {
return $.trim( i );
} );
};
/* Methods */
/**
* Load the model from the template data string. If no templatedata tags
* are available, the model will be initialized empty.
*
* After loading the model itself, fetch the parameter list from the template
* source code and update existing parameters in the model.
*
* @param {string} templateDataString Current page wikitext
*/
TemplateDataModel.prototype.loadModel = function ( tdString ) {
var original = {},
deferred = $.Deferred();
// Store existing templatedata into the model
this.setOriginalTemplateDataObject( this.getModelFromString( tdString ) );
original = this.getOriginalTemplateDataObject();
// Initialize model
this.params = {};
if ( original ) {
// Get parameter list from the template source code
this.getParametersFromTemplateSource( tdString ).done( $.proxy( function ( params ) {
this.sourceCodeParameters = params;
this.setTemplateDescription( original.description );
this.setTemplateParamOrder( original.paramOrder );
// Mark existing parameters in the model
if ( original.params ) {
for ( var param in original.params ) {
this.addParam( param, original.params[param] );
}
}
deferred.resolve();
}, this ) );
} else {
// Bad syntax for JSON
deferred.reject();
}
return deferred.promise();
};
/**
* Go over the importable parameters and check if they are
* included in the parameter model. Return the parameter names
* that are not included yet.
* @return {string[]} Parameters that are not yet included in
* the model
*/
TemplateDataModel.prototype.getMissingParams = function () {
var i,
result = [],
allParamNames = this.getAllParamNames();
// Check source code params
for ( i = 0; i < this.sourceCodeParameters.length; i++ ) {
if ( $.inArray( this.sourceCodeParameters[i], allParamNames ) === -1 ) {
result.push( this.sourceCodeParameters[i] );
}
}
return result;
};
/**
* Add imported parameters into the model
* @return {Object} Parameters added. -1 for failure.
*/
TemplateDataModel.prototype.importSourceCodeParameters = function () {
var i, paramKey,
allParamNames = this.getAllParamNames(),
existingArray = [],
importedArray = [],
skippedArray = [];
// Check existing params
for ( i = 0; i < allParamNames.length; i++ ) {
paramKey = allParamNames[i];
if ( $.inArray( paramKey, this.sourceCodeParameters ) !== -1 ) {
existingArray.push( paramKey );
}
}
// Add sourceCodeParameters to the model
for ( i = 0; i < this.sourceCodeParameters.length; i++ ) {
if (
$.inArray( this.sourceCodeParameters[i], existingArray ) === -1 &&
this.addParam( this.sourceCodeParameters[i] )
) {
importedArray.push( this.sourceCodeParameters[i]);
} else {
skippedArray.push( this.sourceCodeParameters[i]);
}
}
return {
imported: importedArray,
skipped: skippedArray,
existing: existingArray
};
};
/**
* Look for a templatedata json string and convert it into
* the and object, if it exists.
* @param {string} templateDataString Wikitext templatedata string
* @return {Object|null} The parsed json string. Empty if no
* templatedata string was found. Null if the json string
* failed to parse.
*/
TemplateDataModel.prototype.getModelFromString = function ( templateDataString ) {
var parts;
parts = templateDataString.match(
/<templatedata>([\s\S]*?)<\/templatedata>/i
);
// Check if <templatedata> exists
if ( parts && parts[1] && $.trim( parts[1] ).length > 0 ) {
// Parse the json string
try {
return $.parseJSON( $.trim( parts[1] ) );
} catch ( err ) {
return null;
}
} else {
// Return empty model
return { params: {} };
}
};
/**
* Retrieve all existing language codes in the current templatedata model
* @return {string[]} Language codes in use
*/
TemplateDataModel.prototype.getExistingLanguageCodes = function () {
var param, prop, lang,
result = [],
languageProps = this.constructor.static.getPropertiesWithLanguage();
// Take languages from the template description
if ( $.isPlainObject( this.description ) ) {
result.concat( Object.keys( this.description ) );
}
// Go over description
if ( $.type( this.description ) ) {
for ( lang in this.description ) {
result.push( lang );
}
}
// Go over the parameters
for ( param in this.params ) {
// Go over the properties
for ( prop in this.params[param] ) {
if ( $.inArray( prop, languageProps ) !== -1 ) {
result = this.constructor.static.arrayUnionWithoutEmpty( result, Object.keys( this.params[param][prop] ) );
}
}
}
return result;
};
/**
* Retrieve parameters from the template code from source in this order:
*
* 1. Check if there's a template in the given 'wikitext' parameter. If not,
* 2. Check if there's a template in the current page. If not,
* 3. Check if the page is a subpage and go up a level to check for template code. If none found,
* 4. Repeat until we are in the root of the template
* 5. Save the name of the page where the template is taken from
*
* Cache the templateCodePromise so we don't have to do this all over again on each
* template code request.
*
* @param {string} [wikitext] Optional. Source of the template.
* @returns {jQuery.Promise} Promise resolving into template parameter array
*/
TemplateDataModel.prototype.getParametersFromTemplateSource = function ( templateDataString ) {
var params = [];
if ( !this.templateSourceCodePromise ) {
// Check given page text first
if ( templateDataString ) {
params = this.extractParametersFromTemplateCode( templateDataString );
}
if ( params.length > 0 ) {
// Cache list of parameters found in template source
this.sourceCodeParameters = params;
// There are parameters found; Resolve.
this.templateSourceCodePromise = $.Deferred().resolve( params );
} else {
// Try to find the template code
this.templateSourceCodePromise = $.Deferred();
if ( this.isPageSubLevel() && this.getParentPage() ) {
// Get the content of the parent
this.constructor.static.getApi( this.getParentPage() )
.done( $.proxy( function ( resp ) {
var pageContent = '';
// Verify that we have a sane response from the API.
// This is particularly important for unit tests, since the
// requested page from the API is the Qunit module and has no content
if (
resp.query.pages[resp.query.pageids[0]].revisions &&
resp.query.pages[resp.query.pageids[0]].revisions[0]
) {
pageContent = resp.query.pages[resp.query.pageids[0]].revisions[0]['*'];
// Get the parameters from the code
this.sourceCodeParameters = this.extractParametersFromTemplateCode( pageContent );
}
this.templateSourceCodePromise.resolve( this.sourceCodeParameters );
}, this ) )
.fail( $.proxy( function () {
// Resolve an empty parameters array
return this.templateSourceCodePromise.resolve( [] );
}, this ) );
} else {
// No template found. Resolve to empty array of parameters
this.templateSourceCodePromise.resolve( [] );
}
}
}
return this.templateSourceCodePromise;
};
/**
* Retrieve template parameters from the template code.
*
* Adapted from https://he.wikipedia.org/wiki/MediaWiki:Gadget-TemplateParamWizard.js
*
* @param {string} templateSource Source of the template.
* @returns {jQuery.Promise} A promise that resolves into an
* array of parameters that appear in the template code
*/
TemplateDataModel.prototype.extractParametersFromTemplateCode = function ( templateCode ) {
var matches,
paramNames = [],
paramExtractor = /{{3,}(.*?)[<|}]/mg;
while ( ( matches = paramExtractor.exec( templateCode ) ) !== null ) {
if ( $.inArray( matches[1], paramNames ) === -1 ) {
paramNames.push( $.trim( matches[1] ) );
}
}
return paramNames;
};
/**
* Add parameter to the model
* @param {string} key Parameter key
* @param {Object} [data] Parameter data
* @return {boolean} Parameter was added successfully
*/
TemplateDataModel.prototype.addParam = function ( key, paramData ) {
var prop, name, lang,
existingNames = this.getAllParamNames(),
data = $.extend( true, {}, paramData ),
language = this.getDefaultLanguage(),
propertiesWithLanguage = this.constructor.static.getPropertiesWithLanguage();
name = key;
// Check that the parameter is not already in the model
if ( this.params[key] || $.inArray( key, existingNames ) !== -1 ) {
// Change parameter key
key = this.getNewValidParameterKey( key );
}
// Initialize
this.params[key] = {};
// Store the key
this.params[key].name = name;
// Mark the parameter if it is in the template source
if ( $.inArray( key, this.sourceCodeParameters ) !== -1 ) {
this.params[key].inSource = true;
}
// Translate types
if ( this.params[key].type !== undefined ) {
this.params[key].normalizedType = this.constructor.static.translateObsoleteParamTypes( this.params[key].type );
}
// Go over the rest of the data
if ( data ) {
for ( prop in data ) {
if (
$.inArray( prop, propertiesWithLanguage ) !== -1 &&
$.isPlainObject( data[prop] )
) {
// Add all language properties
for ( lang in data[prop] ) {
this.setParamProperty( key, prop, data[prop], lang );
}
} else {
this.setParamProperty( key, prop, data[prop], language );
}
}
}
// Trigger the add parameter event
this.emit( 'add-param', key, this.params[key] );
return true;
};
/**
* Retrieve an array of all used parameter names. Note that parameter
* names can be different than their stored keys.
* @return {string[]} Used parameter names
*/
TemplateDataModel.prototype.getAllParamNames = function () {
var param,
result = [];
for ( param in this.params ) {
result.push( this.params[param].name );
}
return result;
};
/**
* Set the template description
* @param {string} description New template description
* @param {Object} [language] Description language, if supplied. If not given,
* will default to the wiki language.
* @fires change-description
*/
TemplateDataModel.prototype.setTemplateDescription = function ( desc, language ) {
language = language || this.getDefaultLanguage();
if ( !this.constructor.static.compare( this.description[language], desc ) ) {
if ( $.type( desc ) === 'object' ) {
$.extend( this.description, desc );
this.emit( 'change-description', desc[language], language );
} else {
this.description[language] = desc;
this.emit( 'change-description', desc, language );
}
}
};
/**
* Get the template description.
* @param {string} [language] Optional language key
* @return {string|Object} The template description. If it is set
* as multilanguage object and no language is set, the whole object
* will be returned.
*/
TemplateDataModel.prototype.getTemplateDescription = function ( language ) {
language = language || this.getDefaultLanguage();
return this.description[language];
};
/**
* Get a specific parameter's description
* @param {string} paramKey Parameter key
* @param {string} [language] Optional language key
* @return {string} Parameter description in given language.
*/
TemplateDataModel.prototype.getParamDescription = function ( paramKey, language ) {
language = language || this.getDefaultLanguage();
if ( this.params[paramKey] && this.params[paramKey].description ) {
// Return description in this language or fall back
return this.params[paramKey].description[language] || '';
}
return '';
};
/**
* Get the current wiki language code. Defaults on 'en'.
* @return {string} Wiki language
*/
TemplateDataModel.prototype.getDefaultLanguage = function () {
return mw.config.get( 'wgContentLanguage' ) || 'en';
};
/**
* Set template param order array.
* @param {string[]} orderArray Parameter key array in order
*/
TemplateDataModel.prototype.setTemplateParamOrder = function ( orderArray ) {
orderArray = orderArray || [];
// TODO: Make the compare method verify order of array?
// Copy the array
this.paramOrder = orderArray.slice();
this.emit( 'change-paramOrder', orderArray );
};
/**
* Retrieve the template paramOrder array
* @return {string[]} orderArray Parameter keys in order
*/
TemplateDataModel.prototype.getTemplateParamOrder = function () {
return this.paramOrder;
};
/**
* Set a specific parameter's property
* @param {string} paramKey Parameter key
* @param {string} prop Property name
* @param {Mixed...} value Property value
* @param {string} [language] Value language
* @returns {boolean} Operation was successful
* @fires change-property
*/
TemplateDataModel.prototype.setParamProperty = function ( paramKey, prop, value, language ) {
var propertiesWithLanguage = this.constructor.static.getPropertiesWithLanguage(),
allProps = this.constructor.static.getAllProperties( true );
language = language || this.getDefaultLanguage();
if ( !allProps[prop] ) {
// The property isn't supported yet
return false;
}
if ( allProps[prop].type === 'array' && $.type( value ) === 'string' ) {
value = this.constructor.static.splitAndTrimArray( value, allProps[prop].delimiter );
}
// Check if the property is split by language code
if ( $.inArray( prop, propertiesWithLanguage ) !== -1 ) {
// Initialize property if necessary
if ( !$.isPlainObject( this.params[paramKey][prop] ) ) {
this.params[paramKey][prop] = {};
}
value = $.isPlainObject( value ) ? value[language] : value;
// Compare with language
if ( !this.constructor.static.compare( this.params[paramKey][prop][language], value ) ) {
this.params[paramKey][prop][language] = value;
this.emit( 'change-property', paramKey, prop, value, language );
return true;
}
} else {
// Compare without language
if ( !this.constructor.static.compare( this.params[paramKey][prop], value ) ) {
this.params[paramKey][prop] = value;
this.emit( 'change-property', paramKey, prop, value, language );
return true;
}
}
return false;
};
/**
* Mark a parameter for deletion.
* Don't actually delete the parameter so we can make sure it is removed
* from the final output.
* @param {string} paramKey Parameter key
*/
TemplateDataModel.prototype.deleteParam = function ( paramKey ) {
this.params[paramKey].deleted = true;
};
/**
* Get a parameter property.
* @param {string} paramKey Parameter key
* @param {string} prop Parameter property
* @return {Mixed...|null} Property value if it exists. Returns null if the
* parameter key itself doesn't exist.
*/
TemplateDataModel.prototype.getParamProperty = function ( paramKey, prop ) {
if ( this.params[paramKey] ) {
return this.params[paramKey][prop];
}
return null;
};
/**
* Retrieve a specific parameter data
* @param {string} key Parameter key
* @return {Object} Parameter data
*/
TemplateDataModel.prototype.getParamData = function ( key ) {
return this.params[key];
};
/**
* Return the complete object of all parameters.
* @return {Object} All parameters and their data
*/
TemplateDataModel.prototype.getParams = function () {
return this.params;
};
/**
* Set the original templatedata object
* @param {Object} templatedataObj TemplateData object
*/
TemplateDataModel.prototype.setOriginalTemplateDataObject = function ( templatedataObj ) {
this.originalTemplateDataObject = $.extend( true, {}, templatedataObj );
};
/**
* Set is page sublevel
* @param {Boolean} isSubLevel Page is sublevel
*/
TemplateDataModel.prototype.setPageSubLevel = function ( isSubLevel ) {
this.subLevel = isSubLevel;
};
/**
* Get full page name
* @param {string} pageName Page name
*/
TemplateDataModel.prototype.setFullPageName = function ( pageName ) {
this.fullPageName = pageName;
};
/**
* Set parent page
* @param {string} Parent page
*/
TemplateDataModel.prototype.setParentPage = function ( parent ) {
this.parentPage = parent;
};
/**
* Get is page sublevel
* @return {boolean} Page is sublevel
*/
TemplateDataModel.prototype.isPageSubLevel = function () {
return this.subLevel;
};
/**
* Get page full name
* @return {string} Page full name
*/
TemplateDataModel.prototype.getFullPageName = function () {
return this.fullPageName;
};
/**
* Get parent page
* @return {string} Parent page
*/
TemplateDataModel.prototype.getParentPage = function () {
return this.parentPage;
};
/**
* Get original templatedata object
* @return {Object} Templatedata object
*/
TemplateDataModel.prototype.getOriginalTemplateDataObject = function () {
return this.originalTemplateDataObject;
};
/**
* Process the current model and output it as a complete templatedata string
* @return {string} Templatedata String
*/
TemplateDataModel.prototype.outputTemplateDataString = function () {
var param, paramKey, key, prop, oldKey, name, compareOrig, normalizedValue,
allProps = this.constructor.static.getAllProperties( true ),
original = this.getOriginalTemplateDataObject(),
result = $.extend( true, {}, this.getOriginalTemplateDataObject() ),
defaultLang = this.getDefaultLanguage();
// Template description
if ( this.description[defaultLang] !== undefined ) {
normalizedValue = this.propRemoveUnusedLanguages( this.description );
if ( this.isOutputInLanguageObject( result.description, normalizedValue ) ) {
result.description = normalizedValue;
} else {
// Store only one language as a string
result.description = normalizedValue[defaultLang];
}
} else {
// Delete description
delete result.description;
}
// Param order
if ( this.paramOrder.length > 0 ) {
result.paramOrder = this.paramOrder;
} else if ( result.paramOrder && this.paramOrder.length === 0 ) {
delete result.paramOrder;
}
// Attach sets as-is for now
// TODO: Work properly with sets
if ( original.sets ) {
result.sets = original.sets;
}
// Go over parameters in data
for ( paramKey in this.params ) {
key = paramKey;
if ( this.params[key].deleted ) {
delete result.params[key];
continue;
}
// Check if name was changed and change the key accordingly
name = this.params[key].name;
oldKey = key;
if ( key !== this.params[key].name ) {
key = this.params[key].name;
// See if the parameters already has something with this new key
if ( this.params[key] ) {
// Change the key to be something else
key += this.getNewValidParameterKey( key );
}
// Copy param details to new name in the model
this.params[key] = this.params[oldKey];
// Update the references to the key and param data
param = result.params[name];
// Delete the old param in both the result and model param
delete result.params[oldKey];
delete this.params[oldKey];
}
// Notice for clarity:
// Whether the parameter name was changed or not the following
// consistency with object keys will be observed:
// * oldKey: original will use oldKey (for comparison to the old value)
// * key: this.params will use key (for storing without conflict)
// * name: result will use name (for valid output)
// Check if param is new
if ( !result.params[name] ) {
// New param. Initialize it
result.params[name] = {};
}
// Go over all properties
for ( prop in allProps ) {
switch ( prop ) {
case 'name':
continue;
case 'type':
// Only include type if the original included type
// or if the current type is not undefined
if (
original.type !== undefined ||
this.params[key].type !== 'undefined'
) {
result.params[name][prop] = this.params[key].type;
}
break;
case 'required':
case 'suggested':
if ( !this.params[key][prop] ) {
// Only add a literal false value if there was a false
// value before
if ( original.params[oldKey] && original.params[oldKey][prop] === false ) {
result.params[name][prop] = false;
}
} else {
result.params[name][prop] = this.params[key][prop];
}
break;
case 'aliases':
// Only add if there's anything inside the array
if (
$.type( this.params[key][prop] ) === 'array' &&
this.params[key][prop].length > 0
) {
result.params[name][prop] = this.params[key][prop];
}
break;
default:
// Check if there's a value in the model
if ( this.params[key][prop] !== undefined ) {
if ( allProps[prop].allowLanguages ) {
normalizedValue = this.propRemoveUnusedLanguages( this.params[key][prop] );
// Check if this should be displayed with language object or directly as string
compareOrig = original.params[oldKey] ? original.params[oldKey][prop] : {};
if ( this.isOutputInLanguageObject( compareOrig, normalizedValue ) ) {
result.params[name][prop] = normalizedValue;
} else {
// Store only one language as a string
result.params[name][prop] = normalizedValue[defaultLang];
}
} else {
result.params[name][prop] = this.params[key][prop];
}
}
break;
}
}
}
return JSON.stringify( result, null, '\t' );
};
/**
* Check the key if it already exists in the parameter list. If it does,
* find a new key that doesn't, and return it.
* @param {string} key New parameter key
* @return {string} Valid new parameter key
*/
TemplateDataModel.prototype.getNewValidParameterKey = function ( key ) {
var allParamNames = this.getAllParamNames();
if ( this.params[key] || $.inArray( key, allParamNames ) !== -1 ) {
// Change the key to be something else
key += this.paramIdentifierCounter;
this.paramIdentifierCounter++;
this.getNewValidParameterKey( key );
} else {
return key;
}
};
/**
* Go over a language property and remove empty language key values
* @return {Object} Property data with only used language keys
*/
TemplateDataModel.prototype.propRemoveUnusedLanguages = function ( propData ) {
var key,
result = {};
if ( $.isPlainObject( propData ) ) {
for ( key in propData ) {
if ( propData[key] ) {
result[key] = propData[key];
}
}
}
return result;
};
/**
* Check whether the output of the current parameter property should be
* outputted in full language mode (object) or a simple string.
* @param {string} paramKey Parameter key
* @param {string} prop Param property
* @return {boolean} Output should be a full language object
*/
TemplateDataModel.prototype.isOutputInLanguageObject = function ( originalPropValue, newPropValue ) {
if (
(
// The original was already split to languages
$.type( originalPropValue ) === 'object' &&
// Original was not an empty object
!$.isEmptyObject( originalPropValue )
) ||
(
// The new value is split to languages
$.type( newPropValue ) === 'object' &&
// New object is not empty
!$.isEmptyObject( newPropValue ) &&
(
// The new value doesn't have the default language
newPropValue[this.getDefaultLanguage()] === undefined ||
// There is more than just one language in the new property
Object.keys( newPropValue ).length > 1
)
)
) {
return true;
}
return false;
};
}( jQuery ) );