etherpad-lite/src/static/js/AttributeManager.js

117 lines
3.6 KiB
JavaScript
Raw Normal View History

2012-04-05 00:50:04 +02:00
var Changeset = require('./Changeset');
var ChangesetUtils = require('./ChangesetUtils');
var _ = require('./underscore');
var AttributeManager = function(rep, applyChangesetCallback)
{
this.rep = rep;
this.applyChangesetCallback = applyChangesetCallback;
this.author = '';
2012-04-05 01:07:47 +02:00
// If the first char in a line has one of the following attributes
// it will be considered as a line marker
this.lineAttributes = ['list'];
2012-04-05 00:50:04 +02:00
};
AttributeManager.prototype = _(AttributeManager.prototype).extend({
applyChangeset: function(changeset){
var cs = changeset.toString();
if (!Changeset.isIdentity(cs))
{
this.applyChangesetCallback(cs);
}
},
lineHasMarker: function(lineNum){
// get "list" attribute of first char of line
2012-04-05 01:07:47 +02:00
var that = this;
return _.find(this.lineAttributes, function(attribute){
return that.getAttributeOnLine(lineNum, attribute) != '';
}) !== undefined;
2012-04-05 00:50:04 +02:00
},
getAttributeOnLine: function(lineNum, attributeName){
// get `attributeName` attribute of first char of line
var aline = this.rep.alines[lineNum];
if (aline)
{
var opIter = Changeset.opIterator(aline);
if (opIter.hasNext())
{
return Changeset.opAttributeValue(opIter.next(), attributeName, this.rep.apool) || '';
}
}
return '';
},
/*
Sets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@param attributeKey: the name of the attribute to set, e.g. list
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
*/
setAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [
[attributeName, attributeValue]
], this.rep.apool);
}else{
// add a line marker
builder.insert('*', [
['author', this.author],
['insertorder', 'first'],
[attributeName, attributeValue]
], this.rep.apool);
}
return this.applyChangeset(builder);
},
/*
Removes a specified attribute on a line
@param lineNum: the number of the affected line
@param attributeKey: the name of the attribute to remove, e.g. list
*/
removeAttributeOnLine: function(lineNum, attributeName, attributeValue){
var loc = [0,0];
var builder = Changeset.builder(this.rep.lines.totalWidth());
var hasMarker = this.lineHasMarker(lineNum);
if(hasMarker){
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]), [
[attributeName, attributeValue]
], this.rep.apool);
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));
}
return this.applyChangeset(builder);
},
/*
Sets a specified attribute on a line
@param lineNum: the number of the line to set the attribute for
@param attributeKey: the name of the attribute to set, e.g. list
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
*/
toggleAttributeOnLine: function(lineNum, attributeName, attributeValue) {
return this.getAttributeOnLine(attributeName) ?
this.removeAttributeOnLine(lineNum, attributeName) :
this.setAttributeOnLine(lineNum, attributeName, attributeValue);
}
});
module.exports = AttributeManager;