mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-16 10:59:56 +00:00
1a86cb9c61
Previously we populated the reference body into all <ref> tags with the same key. Now we store an internal attribute marking which element originally had the data. If that tag is deleted the body is moved to the first <ref> tag with that name. Change-Id: If9f12bfb699e6ce85bb8f7d2ea9e6df528610a3d
154 lines
4.3 KiB
JavaScript
154 lines
4.3 KiB
JavaScript
/*!
|
|
* VisualEditor IndexValueStore class.
|
|
*
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* Index-value store
|
|
*
|
|
* @class
|
|
* @constructor
|
|
*/
|
|
ve.dm.IndexValueStore = function VeDmIndexValueStore() {
|
|
// maps hashes to indexes
|
|
this.hashStore = {};
|
|
// maps indexes to values
|
|
this.valueStore = [];
|
|
};
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Get the index of a value in the store.
|
|
*
|
|
* If the hash is not found the value is added to the store.
|
|
*
|
|
* @method
|
|
* @param {Object|string|Array} value Value to lookup or store
|
|
* @param {string} [hash] Value hash. Uses ve.getHash( value ) if not provided.
|
|
* @param {boolean} [overwrite=false] Overwrite the value in the store if the hash is already in use
|
|
* @returns {number} The index of the value in the store
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.index = function ( value, hash, overwrite ) {
|
|
var index;
|
|
if ( typeof hash !== 'string' ) {
|
|
hash = ve.getHash( value );
|
|
}
|
|
index = this.indexOfHash( hash );
|
|
if ( index === null || overwrite ) {
|
|
if ( index === null ) {
|
|
index = this.valueStore.length;
|
|
}
|
|
if ( ve.isArray( value ) ) {
|
|
this.valueStore[index] = ve.copyArray( value );
|
|
} else if ( typeof value === 'object' ) {
|
|
this.valueStore[index] = ve.cloneObject( value );
|
|
} else {
|
|
this.valueStore[index] = value;
|
|
}
|
|
this.hashStore[hash] = index;
|
|
}
|
|
return index;
|
|
};
|
|
|
|
/**
|
|
* Get the index of a hash in the store.
|
|
*
|
|
* Returns null if the hash is not found.
|
|
*
|
|
* @method
|
|
* @param {Object|string|Array} hash Value hash.
|
|
* @returns {number|null} The index of the value in the store, or undefined if it is not found
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.indexOfHash = function ( hash ) {
|
|
return hash in this.hashStore ? this.hashStore[hash] : null;
|
|
};
|
|
|
|
/**
|
|
* Get the indexes of values in the store
|
|
*
|
|
* Sames as index but with arrays.
|
|
*
|
|
* @method
|
|
* @param {Object[]} values Values to lookup or store
|
|
* @returns {Array} The indexes of the values in the store
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.indexes = function ( values ) {
|
|
var i, length, indexes = [];
|
|
for ( i = 0, length = values.length; i < length; i++ ) {
|
|
indexes.push( this.index( values[i] ) );
|
|
}
|
|
return indexes;
|
|
};
|
|
|
|
/**
|
|
* Get the value at a particular index
|
|
*
|
|
* @method
|
|
* @param {number} index Index to lookup
|
|
* @returns {Object|undefined} Value at this index, or undefined if out of bounds
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.value = function ( index ) {
|
|
return this.valueStore[index];
|
|
};
|
|
|
|
/**
|
|
* Get the values at a set of indexes
|
|
*
|
|
* Same as value but with arrays.
|
|
*
|
|
* @method
|
|
* @param {number[]} index Index to lookup
|
|
* @returns {Array} Values at these indexes, or undefined if out of bounds
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.values = function ( indexes ) {
|
|
var i, length, values = [];
|
|
for ( i = 0, length = indexes.length; i < length; i++ ) {
|
|
values.push( this.value( indexes[i] ) );
|
|
}
|
|
return values;
|
|
};
|
|
|
|
/**
|
|
* Clone a store.
|
|
*
|
|
* The returned clone is shallow: the valueStore array and the hashStore array are cloned, but
|
|
* the values inside them are copied by reference. These values are supposed to be immutable,
|
|
* though.
|
|
*
|
|
* @returns {ve.dm.IndexValueStore} New store with the same contents as this one
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.clone = function () {
|
|
var key, clone = new this.constructor();
|
|
clone.valueStore = this.valueStore.slice();
|
|
for ( key in this.hashStore ) {
|
|
clone.hashStore[key] = this.hashStore[key];
|
|
}
|
|
return clone;
|
|
};
|
|
|
|
/**
|
|
* Merge another store into this store.
|
|
*
|
|
* Objects that are in other but not in this are added to this, possibly with a different index.
|
|
* Objects present in both stores may have different indexes in each store. An object is returned
|
|
* mapping each index in other to the corresponding index in this.
|
|
*
|
|
* Objects added to the store are added by reference, not cloned like in .index()
|
|
*
|
|
* @param {ve.dm.IndexValueStore} other Store to merge into this one
|
|
* @returns {Object} Object in which the keys are indexes in other and the values are the corresponding keys in this
|
|
*/
|
|
ve.dm.IndexValueStore.prototype.merge = function ( other ) {
|
|
var key, index, mapping = {};
|
|
for ( key in other.hashStore ) {
|
|
if ( !( key in this.hashStore ) ) {
|
|
index = this.valueStore.push( other.valueStore[other.hashStore[key]] ) - 1;
|
|
this.hashStore[key] = index;
|
|
}
|
|
mapping[other.hashStore[key]] = this.hashStore[key];
|
|
}
|
|
return mapping;
|
|
}; |