App-SocialCalc-Multiplayer
view release on metacpan or search on metacpan
socialcalc/socialcalc-3.js view on Meta::CPAN
// calccheckdone, calclist length [once per recalc]
// calcstep, {coord: coord, total: calclist length, count: count} [0 or more times per recalc]
// calcloading, {sheetname: name-of-sheet}
// calcserverfunc, {funcname: name-of-function, coord: coord, total: calclist length, count: count}
// calcfinished, time in milliseconds [once per recalc]
//
// During commands, data is SocialCalc.SheetCommandInfo.
// These values for status and arg are:
//
// cmdstart, cmdstr
// cmdend
//
this.statuscallback = null; // routine called with cmdstart, calcstart, etc., status and args:
// sheet.statuscallback(data, status, arg, params)
this.statuscallbackparams = null; // parameters passed to that routine
}
//
// SocialCalc.ResetSheet(sheet)
//
// Resets (and/or initializes) sheet data values.
//
SocialCalc.ResetSheet = function(sheet, reload) {
// properties:
sheet.cells = {}; // at least one for each non-blank cell: coord: cell-object
sheet.attribs = // sheet attributes
{
lastcol: 1,
lastrow: 1,
defaultlayout: 0
};
sheet.rowattribs =
{
hide: {}, // access by row number
height: {}
};
sheet.colattribs =
{
width: {}, // access by col name
hide: {}
};
sheet.names={}; // Each is: {desc: "optional description", definition: "B5, A1:B7, or =formula"}
sheet.layouts=[];
sheet.layouthash={};
sheet.fonts=[];
sheet.fonthash={};
sheet.colors=[];
sheet.colorhash={};
sheet.borderstyles=[];
sheet.borderstylehash={};
sheet.cellformats=[];
sheet.cellformathash={};
sheet.valueformats=[];
sheet.valueformathash={};
sheet.copiedfrom = ""; // if a range, then this was loaded from a saved range as clipboard content
sheet.changes = new SocialCalc.UndoStack();
sheet.renderneeded = false;
sheet.changedrendervalues = true; // if true, spans and/or fonts have changed (set by ExecuteSheetCommand & GetStyle)
sheet.recalcchangedavalue = false; // true if a recalc resulted in a change to a cell's calculated value
}
// Methods:
SocialCalc.Sheet.prototype.ResetSheet = function() {SocialCalc.ResetSheet(this);};
SocialCalc.Sheet.prototype.AddCell = function(newcell) {return this.cells[newcell.coord]=newcell;};
SocialCalc.Sheet.prototype.GetAssuredCell = function(coord) {
return this.cells[coord] || this.AddCell(new SocialCalc.Cell(coord));
};
SocialCalc.Sheet.prototype.ParseSheetSave = function(savedsheet) {SocialCalc.ParseSheetSave(savedsheet,this);};
SocialCalc.Sheet.prototype.CellFromStringParts = function(cell, parts, j) {return SocialCalc.CellFromStringParts(this, cell, parts, j);};
SocialCalc.Sheet.prototype.CreateSheetSave = function(range, canonicalize) {return SocialCalc.CreateSheetSave(this, range, canonicalize);};
SocialCalc.Sheet.prototype.CellToString = function(cell) {return SocialCalc.CellToString(this, cell);};
SocialCalc.Sheet.prototype.CanonicalizeSheet = function(full) {return SocialCalc.CanonicalizeSheet(this, full);};
SocialCalc.Sheet.prototype.EncodeCellAttributes = function(coord) {return SocialCalc.EncodeCellAttributes(this, coord);};
SocialCalc.Sheet.prototype.EncodeSheetAttributes = function() {return SocialCalc.EncodeSheetAttributes(this);};
SocialCalc.Sheet.prototype.DecodeCellAttributes = function(coord, attribs, range) {return SocialCalc.DecodeCellAttributes(this, coord, attribs, range);};
SocialCalc.Sheet.prototype.DecodeSheetAttributes = function(attribs) {return SocialCalc.DecodeSheetAttributes(this, attribs);};
SocialCalc.Sheet.prototype.ScheduleSheetCommands = function(cmd, saveundo, isRemote) {return SocialCalc.ScheduleSheetCommands(this, cmd, saveundo, isRemote);};
SocialCalc.Sheet.prototype.SheetUndo = function() {return SocialCalc.SheetUndo(this);};
SocialCalc.Sheet.prototype.SheetRedo = function() {return SocialCalc.SheetRedo(this);};
SocialCalc.Sheet.prototype.CreateAuditString = function() {return SocialCalc.CreateAuditString(this);};
SocialCalc.Sheet.prototype.GetStyleNum = function(atype, style) {return SocialCalc.GetStyleNum(this, atype, style);};
SocialCalc.Sheet.prototype.GetStyleString = function(atype, num) {return SocialCalc.GetStyleString(this, atype, num);};
SocialCalc.Sheet.prototype.RecalcSheet = function() {return SocialCalc.RecalcSheet(this);};
//
// Sheet save format:
//
// linetype:param1:param2:...
//
// Linetypes are:
//
// version:versionname - version of this format. Currently 1.4.
//
// cell:coord:type:value...:type:value... - Types are as follows:
//
// v:value - straight numeric value
// t:value - straight text/wiki-text in cell, encoded to handle \, :, newlines
// vt:fulltype:value - value with value type/subtype
// vtf:fulltype:value:formulatext - formula resulting in value with value type/subtype, value and text encoded
// vtc:fulltype:value:valuetext - formatted text constant resulting in value with value type/subtype, value and text encoded
// vf:fvalue:formulatext - formula resulting in value, value and text encoded (obsolete: only pre format version 1.1)
// fvalue - first char is "N" for numeric value, "T" for text value, "H" for HTML value, rest is the value
// e:errortext - Error text. Non-blank means formula parsing/calculation results in error.
// b:topborder#:rightborder#:bottomborder#:leftborder# - border# in sheet border list or blank if none
// l:layout# - number in cell layout list
// f:font# - number in sheet fonts list
// c:color# - sheet color list index for text
// bg:color# - sheet color list index for background color
// cf:format# - sheet cell format number for explicit format (align:left, etc.)
// cvf:valueformat# - sheet cell value format number (obsolete: only pre format v1.2)
// tvf:valueformat# - sheet cell text value format number
// ntvf:valueformat# - sheet cell non-text value format number
// colspan:numcols - number of columns spanned in merged cell
// rowspan:numrows - number of rows spanned in merged cell
// cssc:classname - name of CSS class to be used for cell when published instead of one calculated here
// csss:styletext - explicit CSS style information, encoded to handle :, etc.
// mod:allow - if "y" allow modification of cell for live "view" recalc
// comment:value - encoded text of comment for this cell (added in v1.5)
//
// col:
// w:widthval - number, "auto" (no width in <col> tag), number%, or blank (use default)
// hide: - yes/no, no is assumed if missing
// row:
// hide - yes/no, no is assumed if missing
//
// sheet:
// c:lastcol - number
// r:lastrow - number
// w:defaultcolwidth - number, "auto", number%, or blank (default->80)
// h:defaultrowheight - not used
// tf:format# - cell format number for sheet default for text values
// ntf:format# - cell format number for sheet default for non-text values (i.e., numbers)
// layout:layout# - default cell layout number in cell layout list
// font:font# - default font number in sheet font list
// vf:valueformat# - default number value format number in sheet valueformat list (obsolete: only pre format version 1.2)
// ntvf:valueformat# - default non-text (number) value format number in sheet valueformat list
// tvf:valueformat# - default text value format number in sheet valueformat list
// color:color# - default number for text color in sheet color list
// bgcolor:color# - default number for background color in sheet color list
// circularreferencecell:coord - cell coord with a circular reference
// recalc:value - on/off (on is default). If not "off", appropriate changes to the sheet cause a recalc
// needsrecalc:value - yes/no (no is default). If "yes", formula values are not up to date
//
// name:name:description:value - name definition, name in uppercase, with value being "B5", "A1:B7", or "=formula";
// description and value are encoded.
// font:fontnum:value - text of font definition (style weight size family) for font fontnum
// "*" for "style weight", size, or family, means use default (first look to sheet, then builtin)
// color:colornum:rgbvalue - text of color definition (e.g., rgb(255,255,255)) for color colornum
// border:bordernum:value - text of border definition (thickness style color) for border bordernum
// layout:layoutnum:value - text of vertical alignment and padding style for cell layout layoutnum (* for default):
// vertical-alignment:vavalue;padding:topval rightval bottomval leftval;
// cellformat:cformatnum:value - text of cell alignment (left/center/right) for cellformat cformatnum
// valueformat:vformatnum:value - text of number format (see FormatValueForDisplay) for valueformat vformatnum (changed in v1.2)
// clipboardrange:upperleftcoord:bottomrightcoord - ignored -- from wikiCalc
// clipboard:coord:type:value:... - ignored -- from wikiCalc
//
// If this is clipboard contents, then there is also information to facilitate pasting:
//
// copiedfrom:upperleftcoord:bottomrightcoord - range from which this was copied
//
// Functions:
SocialCalc.ParseSheetSave = function(savedsheet,sheetobj) {
var lines=savedsheet.split(/\r\n|\n/);
var parts=[];
var line;
var i, j, t, v, coord, cell, attribs, name;
var scc = SocialCalc.Constants;
for (i=0;i<lines.length;i++) {
line=lines[i];
parts = line.split(":");
switch (parts[0]) {
case "cell":
cell=sheetobj.GetAssuredCell(parts[1]);
j=2;
sheetobj.CellFromStringParts(cell, parts, j);
break;
case "col":
coord=parts[1];
j=2;
while (t=parts[j++]) {
switch (t) {
case "w":
sheetobj.colattribs.width[coord]=parts[j++]; // must be text - could be auto or %, etc.
break;
case "hide":
sheetobj.colattribs.hide[coord]=parts[j++];
break;
default:
throw scc.s_pssUnknownColType+" '"+t+"'";
break;
}
}
break;
case "row":
coord=parts[1]-0;
j=2;
while (t=parts[j++]) {
switch (t) {
case "h":
sheetobj.rowattribs.height[coord]=parts[j++]-0;
break;
case "hide":
sheetobj.rowattribs.hide[coord]=parts[j++];
break;
default:
throw scc.s_pssUnknownRowType+" '"+t+"'";
break;
}
}
break;
socialcalc/socialcalc-3.js view on Meta::CPAN
break;
case "recalc":
attribs.recalc=parts[j++];
break;
case "needsrecalc":
attribs.needsrecalc=parts[j++];
break;
default:
j+=1;
break;
}
}
break;
case "name":
name = SocialCalc.decodeFromSave(parts[1]).toUpperCase();
sheetobj.names[name] = {desc: SocialCalc.decodeFromSave(parts[2])};
sheetobj.names[name].definition = SocialCalc.decodeFromSave(parts[3]);
break;
case "layout":
parts=lines[i].match(/^layout\:(\d+)\:(.+)$/); // layouts can have ":" in them
sheetobj.layouts[parts[1]-0]=parts[2];
sheetobj.layouthash[parts[2]]=parts[1]-0;
break;
case "font":
sheetobj.fonts[parts[1]-0]=parts[2];
sheetobj.fonthash[parts[2]]=parts[1]-0;
break;
case "color":
sheetobj.colors[parts[1]-0]=parts[2];
sheetobj.colorhash[parts[2]]=parts[1]-0;
break;
case "border":
sheetobj.borderstyles[parts[1]-0]=parts[2];
sheetobj.borderstylehash[parts[2]]=parts[1]-0;
break;
case "cellformat":
v=SocialCalc.decodeFromSave(parts[2]);
sheetobj.cellformats[parts[1]-0]=v;
sheetobj.cellformathash[v]=parts[1]-0;
break;
case "valueformat":
v=SocialCalc.decodeFromSave(parts[2]);
sheetobj.valueformats[parts[1]-0]=v;
sheetobj.valueformathash[v]=parts[1]-0;
break;
case "version":
break;
case "copiedfrom":
sheetobj.copiedfrom = parts[1]+":"+parts[2];
break;
case "clipboardrange": // in save versions up to 1.3. Ignored.
case "clipboard":
break;
case "":
break;
default:
alert(scc.s_pssUnknownLineType+" '"+parts[0]+"'");
throw scc.s_pssUnknownLineType+" '"+parts[0]+"'";
break;
}
parts = null;
}
}
//
// SocialCalc.CellFromStringParts(sheet, cell, parts, j)
//
// Takes string that has been split by ":" in parts, starting at item j,
// and fills in cell assuming save format.
//
SocialCalc.CellFromStringParts = function(sheet, cell, parts, j) {
var cell, t, v;
while (t=parts[j++]) {
switch (t) {
case "v":
cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
cell.datatype="v";
cell.valuetype="n";
break;
case "t":
cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
cell.datatype="t";
cell.valuetype=SocialCalc.Constants.textdatadefaulttype;
break;
case "vt":
v=parts[j++];
cell.valuetype=v;
if (v.charAt(0)=="n") {
cell.datatype="v";
cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
}
else {
cell.datatype="t";
cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
}
break;
case "vtf":
v=parts[j++];
cell.valuetype=v;
if (v.charAt(0)=="n") {
cell.datavalue=SocialCalc.decodeFromSave(parts[j++])-0;
}
else {
cell.datavalue=SocialCalc.decodeFromSave(parts[j++]);
}
cell.formula=SocialCalc.decodeFromSave(parts[j++]);
socialcalc/socialcalc-3.js view on Meta::CPAN
case "f":
cell.font=parts[j++]-0;
break;
case "c":
cell.color=parts[j++]-0;
break;
case "bg":
cell.bgcolor=parts[j++]-0;
break;
case "cf":
cell.cellformat=parts[j++]-0;
break;
case "ntvf":
cell.nontextvalueformat=parts[j++]-0;
break;
case "tvf":
cell.textvalueformat=parts[j++]-0;
break;
case "colspan":
cell.colspan=parts[j++]-0;
break;
case "rowspan":
cell.rowspan=parts[j++]-0;
break;
case "cssc":
cell.cssc=parts[j++];
break;
case "csss":
cell.csss=SocialCalc.decodeFromSave(parts[j++]);
break;
case "mod":
j+=1;
break;
case "comment":
cell.comment=SocialCalc.decodeFromSave(parts[j++]);
break;
default:
throw SocialCalc.Constants.s_cfspUnknownCellType+" '"+t+"'";
break;
}
}
}
SocialCalc.sheetfields = ["defaultrowheight", "defaultcolwidth", "circularreferencecell", "recalc", "needsrecalc"];
SocialCalc.sheetfieldsshort = ["h", "w", "circularreferencecell", "recalc", "needsrecalc"];
SocialCalc.sheetfieldsxlat = ["defaulttextformat", "defaultnontextformat",
"defaulttextvalueformat", "defaultnontextvalueformat",
"defaultcolor", "defaultbgcolor", "defaultfont", "defaultlayout"];
SocialCalc.sheetfieldsxlatshort = ["tf", "ntf", "tvf", "ntvf", "color", "bgcolor", "font", "layout"];
SocialCalc.sheetfieldsxlatxlt = ["cellformat", "cellformat", "valueformat", "valueformat",
"color", "color", "font", "layout"];
//
// sheetstr = SocialCalc.CreateSheetSave(sheetobj, range, canonicalize)
//
// Creates a text representation of the sheetobj data.
// If the range is present then only those cells are saved
// (as clipboard data with "copiedfrom" set).
//
SocialCalc.CreateSheetSave = function(sheetobj, range, canonicalize) {
var cell, cr1, cr2, row, col, coord, attrib, line, value, formula, i, t, r, b, l, name, blanklen;
var result=[];
var prange;
sheetobj.CanonicalizeSheet(canonicalize || SocialCalc.Constants.doCanonicalizeSheet);
var xlt = sheetobj.xlt;
if (range) {
prange = SocialCalc.ParseRange(range);
}
else {
prange = {cr1: {row: 1, col:1},
cr2: {row: xlt.maxrow, col: xlt.maxcol}};
}
cr1 = prange.cr1;
cr2 = prange.cr2;
result.push("version:1.5");
for (row=cr1.row; row <= cr2.row; row++) {
for (col=cr1.col; col <= cr2.col; col++) {
coord = SocialCalc.crToCoord(col, row);
cell=sheetobj.cells[coord];
if (!cell) continue;
line=sheetobj.CellToString(cell);
if (line.length==0) continue; // ignore completely empty cells
line="cell:"+coord+line;
result.push(line);
}
}
for (col=1; col <= xlt.maxcol; col++) {
coord = SocialCalc.rcColname(col);
if (sheetobj.colattribs.width[coord])
result.push("col:"+coord+":w:"+sheetobj.colattribs.width[coord]);
if (sheetobj.colattribs.hide[coord])
result.push("col:"+coord+":hide:"+sheetobj.colattribs.hide[coord]);
}
for (row=1; row <= xlt.maxrow; row++) {
if (sheetobj.rowattribs.height[row])
result.push("row:"+row+":h:"+sheetobj.rowattribs.height[row]);
if (sheetobj.rowattribs.hide[row])
result.push("row:"+row+":hide:"+sheetobj.rowattribs.hide[row]);
}
line="sheet:c:"+xlt.maxcol+":r:"+xlt.maxrow;
for (i=0; i<SocialCalc.sheetfields.length; i++) { // non-xlated values
value = SocialCalc.encodeForSave(sheetobj.attribs[SocialCalc.sheetfields[i]]);
if (value) line+=":"+SocialCalc.sheetfieldsshort[i]+":"+value;
}
for (i=0; i<SocialCalc.sheetfieldsxlat.length; i++) { // xlated values
value = sheetobj.attribs[SocialCalc.sheetfieldsxlat[i]];
if (value) line+=":"+SocialCalc.sheetfieldsxlatshort[i]+":"+xlt[SocialCalc.sheetfieldsxlatxlt[i]+"sxlat"][value];
socialcalc/socialcalc-3.js view on Meta::CPAN
sci.timerobj = null;
while (!sci.parseobj.EOF()) { // go through all commands (separated by newlines)
errortext = SocialCalc.ExecuteSheetCommand(sci.sheetobj, sci.parseobj, sci.saveundo);
if (errortext) alert(errortext);
sci.parseobj.NextLine();
if (sci.cmdextensionbusy.length > 0) { // forced wait
if (sci.sheetobj.statuscallback) { // notify others if requested
sci.sheetobj.statuscallback(sci, "cmdextension", sci.cmdextensionbusy, sci.sheetobj.statuscallbackparams);
}
return;
}
if (((new Date()) - starttime) >= sci.maxtimeslice) { // if taking too long, give up CPU for a while
sci.timerobj = window.setTimeout(SocialCalc.SheetCommandsTimerRoutine, sci.timerdelay);
return;
}
}
if (sci.sheetobj.statuscallback) { // notify others if requested
sci.sheetobj.statuscallback(sci, "cmdend", "", sci.sheetobj.statuscallbackparams);
}
}
SocialCalc.ResumeFromCmdExtension = function() {
var sci = SocialCalc.SheetCommandInfo;
sci.cmdextensionbusy = "";
SocialCalc.SheetCommandsTimerRoutine();
}
//
// errortext = SocialCalc.ExecuteSheetCommand(sheet, cmd, saveundo)
//
// cmd is a SocialCalc.Parse object.
//
// Executes commands that modify the sheet data.
// Sets sheet "needsrecalc" as needed.
// Sets sheet "changedrendervalues" as needed.
//
// The cmd string may be multiple commands, separated by newlines. In that case
// only one "step" is put on the undo stack representing all the commands.
// Note that because of this, in "set A1 text ..." and "set A1 comment ..." text is
// treated as encoded (newline => \n, \ => \b, : => \c).
//
// The commands are in the forms:
//
// set sheet attributename value (plus lastcol and lastrow)
// set 22 attributename value
// set B attributename value
// set A1 attributename value1 value2... (see each attribute in code for details)
// set A1:B5 attributename value1 value2...
// erase/copy/cut/paste/fillright/filldown A1:B5 all/formulas/format
// loadclipboard save-encoded-clipboard-data
// clearclipboard
// merge C3:F3
// unmerge C3
// insertcol/insertrow C5
// deletecol/deleterow C5:E7
// movepaste/moveinsert A1:B5 A8 all/formulas/format (if insert, destination must be in same rows or columns or else paste done)
// sort cr1:cr2 col1 up/down col2 up/down col3 up/down
// name define NAME definition
// name desc NAME description
// name delete NAME
// recalc
// redisplay
// changedrendervalues
// startcmdextension extension rest-of-command
//
// If saveundo is true, then undo information is saved in sheet.changes.
//
SocialCalc.ExecuteSheetCommand = function(sheet, cmd, saveundo) {
var cmdstr, cmd1, rest, what, attrib, num, pos, pos2, errortext, undostart, val;
var cr1, cr2, col, row, cr, cell, newcell;
var fillright, rowstart, colstart, crbase, rowoffset, coloffset, basecell;
var clipsheet, cliprange, numcols, numrows, attribtable;
var colend, rowend, newcolstart, newrowstart, newcolend, newrowend, rownext, colnext, colthis, cellnext;
var lastrow, lastcol, rowbefore, colbefore, oldformula, oldcr;
var cols, dirs, lastsortcol, i, sortlist, sortcells, sortvalues, sorttypes;
var sortfunction, slen, valtype, originalrow, sortedcr;
var name, v1, v2;
var cmdextension;
var attribs = sheet.attribs;
var changes = sheet.changes;
var cellProperties = SocialCalc.CellProperties;
var scc = SocialCalc.Constants;
var ParseRange =
function() {
var prange = SocialCalc.ParseRange(what);
cr1 = prange.cr1;
cr2 = prange.cr2;
if (cr2.col > attribs.lastcol) attribs.lastcol = cr2.col;
if (cr2.row > attribs.lastrow) attribs.lastrow = cr2.row;
};
errortext = "";
cmdstr = cmd.RestOfStringNoMove();
if (saveundo) {
sheet.changes.AddDo(cmdstr);
}
cmd1 = cmd.NextToken();
switch (cmd1) {
case "set":
what = cmd.NextToken();
attrib = cmd.NextToken();
rest = cmd.RestOfString();
undostart = "set "+what+" "+attrib;
socialcalc/socialcalc-3.js view on Meta::CPAN
cell.csss = rest;
}
else if (attrib=="mod") {
rest = rest.replace(/[^yY]/g, "").toLowerCase();
cell.mod = rest;
}
else if (attrib=="comment") {
cell.comment = SocialCalc.decodeFromSave(rest);
}
else {
errortext = scc.s_escUnknownSetCoordCmd+cmdstr;
}
}
}
}
break;
case "merge":
sheet.renderneeded = true;
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
cell=sheet.GetAssuredCell(cr1.coord);
if (saveundo) changes.AddUndo("unmerge "+cr1.coord);
if (cr2.col > cr1.col) cell.colspan = cr2.col - cr1.col + 1;
else delete cell.colspan;
if (cr2.row > cr1.row) cell.rowspan = cr2.row - cr1.row + 1;
else delete cell.rowspan;
sheet.changedrendervalues = true;
break;
case "unmerge":
sheet.renderneeded = true;
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
cell=sheet.GetAssuredCell(cr1.coord);
if (saveundo) changes.AddUndo("merge "+cr1.coord+":"+SocialCalc.crToCoord(cr1.col+(cell.colspan||1)-1, cr1.row+(cell.rowspan||1)-1));
delete cell.colspan;
delete cell.rowspan;
sheet.changedrendervalues = true;
break;
case "erase":
case "cut":
sheet.renderneeded = true;
sheet.changedrendervalues = true;
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
if (cmd1=="cut") { // save copy of whole thing before erasing
if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
SocialCalc.Clipboard.clipboard = SocialCalc.CreateSheetSave(sheet, what);
}
for (row = cr1.row; row <= cr2.row; row++) {
for (col = cr1.col; col <= cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
cell=sheet.GetAssuredCell(cr);
if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
if (rest=="all") {
delete sheet.cells[cr];
}
else if (rest == "formulas") {
cell.datavalue = "";
cell.datatype = null;
cell.formula = "";
cell.valuetype = "b";
delete cell.errors;
delete cell.displaystring;
delete cell.parseinfo;
if (cell.comment) { // comments are considered content for erasing
delete cell.comment;
}
}
else if (rest == "formats") {
newcell = new SocialCalc.Cell(cr); // create a new cell without attributes
newcell.datavalue = cell.datavalue; // copy existing values
newcell.datatype = cell.datatype;
newcell.formula = cell.formula;
newcell.valuetype = cell.valuetype;
if (cell.comment) {
newcell.comment = cell.comment;
}
sheet.cells[cr] = newcell; // replace
}
}
}
attribs.needsrecalc = "yes";
break;
case "fillright":
case "filldown":
sheet.renderneeded = true;
sheet.changedrendervalues = true;
if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
if (cmd1 == "fillright") {
fillright = true;
rowstart = cr1.row;
colstart = cr1.col + 1;
}
else {
fillright = false;
rowstart = cr1.row + 1;
colstart = cr1.col;
}
for (row = rowstart; row <= cr2.row; row++) {
for (col = colstart; col <= cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
cell=sheet.GetAssuredCell(cr);
if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
if (fillright) {
crbase = SocialCalc.crToCoord(cr1.col, row);
coloffset = col - colstart + 1;
rowoffset = 0;
}
else {
crbase = SocialCalc.crToCoord(col, cr1.row);
coloffset = 0;
rowoffset = row - rowstart + 1;
}
basecell = sheet.GetAssuredCell(crbase);
if (rest == "all" || rest == "formats") {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue; // copy only format attributes
if (typeof basecell[attrib] === undefined || cellProperties[attrib] == 3) {
delete cell[attrib];
}
else {
cell[attrib] = basecell[attrib];
}
}
}
if (rest == "all" || rest == "formulas") {
cell.datavalue = basecell.datavalue;
cell.datatype = basecell.datatype;
cell.valuetype = basecell.valuetype;
if (cell.datatype == "f") { // offset relative coords, even in sheet references
cell.formula = SocialCalc.OffsetFormulaCoords(basecell.formula, coloffset, rowoffset);
}
else {
cell.formula = basecell.formula;
}
delete cell.parseinfo;
cell.errors = basecell.errors;
}
delete cell.displaystring;
}
}
attribs.needsrecalc = "yes";
break;
case "copy":
what = cmd.NextToken();
rest = cmd.RestOfString();
if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
SocialCalc.Clipboard.clipboard = SocialCalc.CreateSheetSave(sheet, what);
break;
case "loadclipboard":
rest = cmd.RestOfString();
if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
SocialCalc.Clipboard.clipboard = SocialCalc.decodeFromSave(rest);
break;
case "clearclipboard":
if (saveundo) changes.AddUndo("loadclipboard", SocialCalc.encodeForSave(SocialCalc.Clipboard.clipboard));
SocialCalc.Clipboard.clipboard = "";
break;
case "paste":
sheet.renderneeded = true;
sheet.changedrendervalues = true;
if (saveundo) changes.AddUndo("changedrendervalues"); // to take care of undone pasted spans
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
if (!SocialCalc.Clipboard.clipboard) {
break;
}
clipsheet = new SocialCalc.Sheet(); // load clipboard contents as another sheet
clipsheet.ParseSheetSave(SocialCalc.Clipboard.clipboard);
cliprange = SocialCalc.ParseRange(clipsheet.copiedfrom);
coloffset = cr1.col - cliprange.cr1.col; // get sizes, etc.
rowoffset = cr1.row - cliprange.cr1.row;
numcols = cliprange.cr2.col - cliprange.cr1.col + 1;
numrows = cliprange.cr2.row - cliprange.cr1.row + 1;
if (cr1.col+numcols-1 > attribs.lastcol) attribs.lastcol = cr1.col+numcols-1;
if (cr1.row+numrows-1 > attribs.lastrow) attribs.lastrow = cr1.row+numrows-1;
for (row = cr1.row; row < cr1.row+numrows; row++) {
for (col = cr1.col; col < cr1.col+numcols; col++) {
cr = SocialCalc.crToCoord(col, row);
cell=sheet.GetAssuredCell(cr);
if (saveundo) changes.AddUndo("set "+cr+" all", sheet.CellToString(cell));
crbase = SocialCalc.crToCoord(col-coloffset, row-rowoffset);
basecell = clipsheet.GetAssuredCell(crbase);
if (rest == "all" || rest == "formats") {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue; // copy only format attributes
if (typeof basecell[attrib] === undefined || cellProperties[attrib] == 3) {
delete cell[attrib];
}
else {
attribtable = SocialCalc.CellPropertiesTable[attrib];
if (attribtable && basecell[attrib]) { // table indexes to expand to strings since other sheet may have diff indexes
cell[attrib] = sheet.GetStyleNum(attribtable, clipsheet.GetStyleString(attribtable, basecell[attrib]));
}
else { // these are not table indexes
cell[attrib] = basecell[attrib];
}
}
}
}
if (rest == "all" || rest == "formulas") {
cell.datavalue = basecell.datavalue;
cell.datatype = basecell.datatype;
cell.valuetype = basecell.valuetype;
if (cell.datatype == "f") { // offset relative coords, even in sheet references
cell.formula = SocialCalc.OffsetFormulaCoords(basecell.formula, coloffset, rowoffset);
}
else {
cell.formula = basecell.formula;
}
delete cell.parseinfo;
cell.errors = basecell.errors;
if (basecell.comment) { // comments are pasted as part of content, though not filled, etc.
cell.comment = basecell.comment;
}
else if (cell.comment) {
delete cell.comment;
}
}
delete cell.displaystring;
}
}
attribs.needsrecalc = "yes";
break;
case "sort": // sort cr1:cr2 col1 up/down col2 up/down col3 up/down
sheet.renderneeded = true;
socialcalc/socialcalc-3.js view on Meta::CPAN
this.stack.pop();
}
this.stack.push({command: [], type: type, undo: []});
if (this.maxRedo && this.stack.length > this.maxRedo) { // limit number kept as audit trail
this.stack.shift(); // remove the extra one
}
if (this.maxUndo && this.stack.length > this.maxUndo) { // need to trim excess undo info
this.stack[this.stack.length - this.maxUndo - 1].undo = []; // only need to remove one
}
this.tos = this.stack.length - 1;
}
SocialCalc.UndoStack.prototype.AddDo = function() {
var args = [];
for (var i=0; i<arguments.length; i++) {
if (arguments[i]!=null) args.push(arguments[i]); // ignore null or undefined
}
var cmd = args.join(" ");
this.stack[this.stack.length-1].command.push(cmd);
}
SocialCalc.UndoStack.prototype.AddUndo = function() {
var args = [];
for (var i=0; i<arguments.length; i++) {
if (arguments[i]!=null) args.push(arguments[i]); // ignore null or undefined
}
var cmd = args.join(" ");
this.stack[this.stack.length-1].undo.push(cmd);
}
SocialCalc.UndoStack.prototype.TOS = function() {
if (this.tos >= 0) return this.stack[this.tos];
else return null;
}
SocialCalc.UndoStack.prototype.Undo = function() {
if (this.tos >= 0 && (!this.maxUndo || this.tos > this.stack.length - this.maxUndo - 1)) {
this.tos -= 1;
return true;
}
else {
return false;
}
}
SocialCalc.UndoStack.prototype.Redo = function() {
if (this.tos < this.stack.length-1) {
this.tos += 1;
return true;
}
else {
return false;
}
}
// *************************************
//
// Clipboard Object:
//
// This is a single object.
// Stores the clipboard, which is shared by all active sheets.
// Like the undo stack, it does not persist from one editing session to another.
//
// *************************************
SocialCalc.Clipboard = {
// properties:
clipboard: "" // empty or string in save format with "copiedfrom:" set to a range
}
// *************************************
//
// RenderContext class:
//
// *************************************
SocialCalc.RenderContext = function(sheetobj) {
var parts, num, s;
var attribs = sheetobj.attribs;
var scc = SocialCalc.Constants;
// properties:
this.sheetobj = sheetobj;
this.hideRowsCols = false; // Rendering with panes only works with "false"
// !!!! Note: not implemented yet in rendering, just saved as an attribute
this.showGrid = false;
this.showRCHeaders = false;
this.rownamewidth = scc.defaultRowNameWidth;
this.pixelsPerRow = scc.defaultAssumedRowHeight;
this.cellskip = {}; // if present, coord of cell covering this cell
this.coordToCR = {}; // for cells starting spans, coordToCR[coord]={row:row, col:col}
this.colwidth = []; // precomputed column widths, taking into account defaults
this.totalwidth = 0; // precomputed total table width
this.rowpanes = []; // for each pane, {first: firstrow, last: lastrow}
this.colpanes = []; // for each pane, {first: firstrow, last: lastrow}
this.maxcol=0; // max col and row to display, adding long spans, etc.
this.maxrow=0;
this.highlights = {}; // for each cell with special display: coord:highlightType (see this.highlightTypes)
this.cursorsuffix = ""; // added to highlights[cr]=="cursor" to get type to lookup
this.highlightTypes = // attributes to change when highlit
{
cursor: {style: scc.defaultHighlightTypeCursorStyle, className: scc.defaultHighlightTypeCursorClass},
range: {style: scc.defaultHighlightTypeRangeStyle, className: scc.defaultHighlightTypeRangeClass},
cursorinsertup: {style: "color:#FFF;backgroundColor:#A6A6A6;backgroundRepeat:repeat-x;backgroundPosition:top left;backgroundImage:url("+scc.defaultImagePrefix+"cursorinsertup.gif);", className: scc.defaultHighlightTypeCursorClass},
cursorinsertleft: {style: "color:#FFF;backgroundColor:#A6A6A6;backgroundRepeat:repeat-y;backgroundPosition:top left;backgroundImage:url("+scc.defaultImagePrefix+"cursorinsertleft.gif);", className: scc.defaultHighlightTypeCursorClass},
range2: {style: "color:#000;backgroundColor:#FFF;backgroundImage:url("+scc.defaultImagePrefix+"range2.gif);", className: ""}
}
this.cellIDprefix = scc.defaultCellIDPrefix; // if non-null, each cell will render with an ID
this.defaultlinkstyle = null; // default linkstyle object (allows you to pass values to link renderer)
this.defaultHTMLlinkstyle = {type: "html"}; // default linkstyle for standalone HTML
// constants:
this.defaultfontstyle = scc.defaultCellFontStyle;
this.defaultfontsize = scc.defaultCellFontSize;
this.defaultfontfamily = scc.defaultCellFontFamily;
this.defaultlayout = scc.defaultCellLayout;
( run in 2.122 seconds using v1.01-cache-2.11-cpan-302cb4679cc )