App-SocialCalc-Multiplayer

 view release on metacpan or  search on metacpan

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   this.lastvisiblecol = null; // used for paging right

   this.rowpositions = []; // screen positions of the top of some rows
   this.colpositions = []; // screen positions of the left side of some rows
   this.rowheight = []; // size in pixels of each row when last checked, or null/undefined, for page up
   this.colwidth = []; // size in pixels of each column when last checked, or null/undefined, for page left

   this.ecell = null; // either null or {coord: c, row: r, col: c}
   this.state = "start"; // the keyboard states: see EditorProcessKey

   this.workingvalues = {}; // values used during keyboard editing, etc.

   // Constants:

   this.imageprefix = scc.defaultImagePrefix; // URL prefix for images (e.g., "/images/sc")
   this.idPrefix = scc.defaultTableEditorIDPrefix;
   this.pageUpDnAmount = scc.defaultPageUpDnAmount; // number of rows to move cursor on PgUp/PgDn keys (numeric)

   // Callbacks

   // recalcFunction: if present, function(editor) {...}, called to do a recalc
   // Default (sheet.RecalcSheet) does all the right stuff.

   this.recalcFunction = function(editor) {
      if (editor.context.sheetobj.RecalcSheet) {
         editor.context.sheetobj.RecalcSheet(SocialCalc.EditorSheetStatusCallback, editor);
         }
      else return null;
      };

   // ctrlkeyFunction: if present, function(editor, charname) {...}, called to handle ctrl-V, etc., at top level
   // Returns true (pass through for continued processing) or false (stop processing this key).

   this.ctrlkeyFunction = function(editor, charname) {

      var ta, ha, cell, position, cmd, sel, cliptext;

      switch (charname) {
         case "[ctrl-c]":
         case "[ctrl-x]":
            ta = editor.pasteTextarea;
            ta.value = "";
            cell=SocialCalc.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
            if (cell) {
               position = SocialCalc.GetElementPosition(cell.element);
               ta.style.left = (position.left-1)+"px";
               ta.style.top = (position.top-1)+"px";
               }
            if (editor.range.hasrange) {
               sel = SocialCalc.crToCoord(editor.range.left, editor.range.top)+
                  ":"+SocialCalc.crToCoord(editor.range.right, editor.range.bottom);
               }
            else {
               sel = editor.ecell.coord;
               }

            // get what to copy to clipboard
            cliptext = SocialCalc.ConvertSaveToOtherFormat(SocialCalc.CreateSheetSave(editor.context.sheetobj, sel), "tab");

            if (charname == "[ctrl-c]" || editor.noEdit) { // if copy or cut but in no edit
               cmd = "copy "+sel+" formulas";
               }
            else { // [ctrl-x]
               cmd = "cut "+sel+" formulas";
               }
            editor.EditorScheduleSheetCommands(cmd, true, false); // queue up command to put on SocialCalc clipboard

            /* Copy as HTML: This fails rather badly as it won't paste into Notepad as tab-delimited text. Oh well.

                ha = editor.pasteHTMLarea;
                if (editor.range.hasrange) {
                    cell = SocialCalc.GetEditorCellElement(editor, editor.range.top, editor.range.left);
                }
                else {
                    cell = SocialCalc.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
                }
                if (cell) position = SocialCalc.GetElementPosition(cell.element);
             
                if (ha) {
                    if (position) {
                        ha.style.left = (position.left-1)+"px";
                        ha.style.top = (position.top-1)+"px";
                    }
                    ha.style.visibility="visible";
                    cliptext = SocialCalc.ConvertSaveToOtherFormat(SocialCalc.CreateSheetSave(editor.context.sheetobj, sel), "html");
                    ha.innerHTML = cliptext.replace(/<tr\b[^>]*>[\d\D]*?<\/tr\b[^>]*>/i, '');
                    ha.focus();

                    var range = document.body.createControlRange();
                    range.addElement(ha.childNodes[0]);
                    range.select();
                }
            */
            ta.style.display = "block";
            ta.value = cliptext; // must follow "block" setting for Webkit
            ta.focus();
            ta.select();
            window.setTimeout(function() {
               if (!SocialCalc.GetSpreadsheetControlObject) return; // in case not loaded
               var s = SocialCalc.GetSpreadsheetControlObject();
               if (!s) return;
               var editor = s.editor;
               /*
               var ha = editor.pasteHTMLarea;
               if (ha) {
                 ha.blur();
                 ha.innerHTML = '';
                 ha.style.visibility = 'hidden';
               }
               */
               var ta = editor.pasteTextarea;
               ta.blur();
               ta.style.display = "none";
               SocialCalc.KeyboardFocus();
               }, 200);

            return true;

         case "[ctrl-v]":
            if (editor.noEdit) return true; // not if no edit

            var showPasteTextArea = function() {
                ta = editor.pasteTextarea;
                ta.value = "";

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

               var isPasteSameAsClipboard = false;

               ha = editor.pasteHTMLarea;
               if (ha) {
                 /* IE: We append a U+FFFC to every TD that's not the last of its row,
                  *     then we obtain innerText, then turn U+FFFC back to \t,
                  *     thereby preserving the cell separations (which gets discarded
                  *     if we simply paste via textarea.
                  */
                 var _ObjectReplacementCharacter_ = String.fromCharCode(0xFFFC);
                 var html = ha.innerHTML;

                 if (html.search(/<(?![Bb][Rr])[A-Za-z]/) >= 0) {
                    /* HTML Paste: Mark TDs with U+FFFC accordingly.. */
                    ha.innerHTML = html.replace(
                        /(?:<\/[Tt][Dd]>)/g,
                        _ObjectReplacementCharacter_
                    );
                }
                else {
                    /* Text Paste: In IE, \t is transformed into &nbsp;, so replace them with U+FFFC. */
                    ha.innerHTML = html.replace(
                        /&[Nn][Bb][Ss][Pp];/g,
                        _ObjectReplacementCharacter_
                    );
                 }

                 value = ha.innerText.replace(new RegExp(_ObjectReplacementCharacter_, 'g'), '\t');

                 ha.innerHTML = '';
                 ha.blur();
                 ha.style.visibility = "hidden";
               }
               else {
                 var ta = editor.pasteTextarea;
                 value = ta.value;
                 ta.blur();
                 ta.style.display = "none";
               }

               value = value.replace(/\r\n/g, "\n").replace(/\n?$/, '\n');
               var clipstr = SocialCalc.ConvertSaveToOtherFormat(SocialCalc.Clipboard.clipboard, "tab");
               if (value == clipstr || (value.length-clipstr.length==1 && value.substring(0,value.length-1)==clipstr)) {
                  isPasteSameAsClipboard = true;
               }

               var cmd = "";
               // pastes SocialCalc clipboard if did a Ctrl-C and contents still the same
               // Webkit adds an extra blank line, so need to allow for that
               if (!isPasteSameAsClipboard) {
                  cmd = "loadclipboard "+
                  SocialCalc.encodeForSave(SocialCalc.ConvertOtherFormatToSave(value, "tab")) + "\n";
                  }
               var cr;
               if (editor.range.hasrange) {
                  cr = SocialCalc.crToCoord(editor.range.left, editor.range.top);
                  }
               else {
                  cr = editor.ecell.coord;
                  }
               cmd += "paste "+cr+" formulas";
               editor.EditorScheduleSheetCommands(cmd, true, false);
               SocialCalc.KeyboardFocus();
               }, 200);
            return true;

         case "[ctrl-z]":
            editor.EditorScheduleSheetCommands("undo", true, false);
            return false;

         case "[ctrl-s]": // !!!! temporary hack
            window.setTimeout(
               function() {
                  if (!SocialCalc.GetSpreadsheetControlObject) return;
                  var s = SocialCalc.GetSpreadsheetControlObject();
                  if (!s) return;
                  var editor = s.editor;
                  var sheet = editor.context.sheetobj;
                  var cell = sheet.GetAssuredCell(editor.ecell.coord);
                  var ntvf = cell.nontextvalueformat ? sheet.valueformats[cell.nontextvalueformat-0] || "" : "";
                  var newntvf = window.prompt("Advanced Feature:\n\nCustom Numeric Format or Command", ntvf);
                  if (newntvf != null) { // not cancelled
                     if (newntvf.match(/^cmd:/)) {
                        cmd = newntvf.substring(4); // execute as command
                        }
                     else if (newntvf.match(/^edit:/)) {
                        cmd = newntvf.substring(5); // execute as command
                        if (SocialCalc.CtrlSEditor) {
                           SocialCalc.CtrlSEditor(cmd);
                           }
                        return;
                        }
                     else {
                        if (editor.range.hasrange) {
                           sel = SocialCalc.crToCoord(editor.range.left, editor.range.top)+
                              ":"+SocialCalc.crToCoord(editor.range.right, editor.range.bottom);
                           }
                        else {
                          sel = editor.ecell.coord;
                           }
                        cmd = "set "+sel+" nontextvalueformat "+newntvf;
                        }
                     editor.EditorScheduleSheetCommands(cmd, true, false);
                     }
                  },
               200);
            return false;

         default:
            break;
            }
      return true;
      };

   // Set sheet's status callback:

   context.sheetobj.statuscallback = SocialCalc.EditorSheetStatusCallback;
   context.sheetobj.statuscallbackparams = this; // this object: the table editor object


   // StatusCallback: all values are called at appropriate times, add with unique name, delete when done

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   var wval = editor.workingvalues;

   if (editor.noEdit) return;

   switch (editor.state) {
      case "start":
         editor.state = "input";
         editor.inputBox.ShowInputBox(true);
         editor.inputBox.element.disabled = false; // make sure editable and overwrite old
         editor.inputBox.Focus();
         editor.inputBox.SetText((prefix||"")+str);
         editor.inputBox.Select("end");
         wval.partialexpr = "";
         wval.ecoord = editor.ecell.coord;
         wval.erow = editor.ecell.row;
         wval.ecol = editor.ecell.col;
         editor.RangeRemove();
         break;

      case "input":
      case "inputboxdirect":
         editor.inputBox.element.focus();
         if (wval.partialexpr) {
            editor.inputBox.SetText(wval.partialexpr);
            wval.partialexpr = "";
            editor.RangeRemove();
            editor.MoveECell(wval.ecoord);
            }
         editor.inputBox.SetText(editor.inputBox.GetText()+str);
         break;

      default:
         break;
      }

   }


SocialCalc.EditorDisplayCellContents = function(editor) {

   if (editor.inputBox) editor.inputBox.DisplayCellContents();

   }

SocialCalc.EditorSaveEdit = function(editor, text) {

   var result, cell, valueinfo, fch, type, value, oldvalue, cmdline;

   var sheetobj = editor.context.sheetobj;
   var wval = editor.workingvalues;

   type = "text t";
   value = typeof text == "string" ? text : editor.inputBox.GetText(); // either explicit or from input box

   oldvalue = SocialCalc.GetCellContents(sheetobj, wval.ecoord)+"";
   if (value == oldvalue) { // no change
      return;
      }
   fch = value.charAt(0);
   if (fch=="=" && value.indexOf("\n")==-1) {
      type = "formula";
      value = value.substring(1);
      }
   else if (fch=="'") {
      type = "text t";
      value = value.substring(1);
      }
   else if (value.length==0) {
      type = "empty";
      }
   else {
      valueinfo = SocialCalc.DetermineValueType(value)
      if (valueinfo.type=="n" && value==(valueinfo.value+"")) { // see if don't need "constant"
         type = "value n";
         }
      else if (valueinfo.type.charAt(0)=="t") {
         type = "text "+valueinfo.type;
         }
      else if (valueinfo.type=="") {
         type = "text t";
         }
      else {
         type = "constant "+valueinfo.type+" "+valueinfo.value;
         }
      }

   if (type.charAt(0)=="t") { // text
      value = SocialCalc.encodeForSave(value); // newlines, :, and \ are escaped
      }

   cmdline = "set "+wval.ecoord+" "+type+" "+value;
   editor.EditorScheduleSheetCommands(cmdline, true, false);

   return;

   }

//
// SocialCalc.EditorApplySetCommandsToRange(editor, cmd)
//
// Takes ecell or range and does a "set" command with cmd.
//

SocialCalc.EditorApplySetCommandsToRange = function(editor, cmd) {

   var cell, row, col, line, errortext;

   var sheetobj = editor.context.sheetobj;
   var ecell = editor.ecell;
   var range = editor.range;

   if (range.hasrange) {
      coord = SocialCalc.crToCoord(range.left, range.top)+":"+SocialCalc.crToCoord(range.right, range.bottom);
      line = "set "+coord+" "+cmd;
      errortext = editor.EditorScheduleSheetCommands(line, true, false);
      }
   else {
      line = "set "+ecell.coord+" "+cmd;
      errortext = editor.EditorScheduleSheetCommands(line, true, false);
      }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   newrownum=context.rowpanes[rowpane].first;

   for (colpane=0; colpane<context.colpanes.length; colpane++) {
      for (colnum=context.colpanes[colpane].first; colnum<=context.colpanes[colpane].last; colnum++) {
         coord=SocialCalc.crToCoord(colnum, newrownum);
         if (context.cellskip[coord]) continue;
         cell=sheetobj.cells[coord];
         if (cell && cell.rowspan>maxrowspan) maxrowspan=cell.rowspan;
         }
      }

   if (maxrowspan>1) {
      for (rownum=1; rownum<maxrowspan; rownum++) {
         if (rownum+newrownum > context.rowpanes[rowpane].last) break;
         newrow=context.RenderRow(rownum+newrownum, rowpane);
         oldchild=tbodyobj.childNodes[toprow+rownum];
         tbodyobj.replaceChild(newrow,oldchild);
         }
      }

   // if last row now includes rowspans or rowspans from above, update the size of those to remove deleted row

   bottomrownum=context.rowpanes[rowpane].last;

   for (colpane=0; colpane<context.colpanes.length; colpane++) {
      for (colnum=context.colpanes[colpane].first; colnum<=context.colpanes[colpane].last; colnum++) {
         coord=SocialCalc.crToCoord(colnum, bottomrownum);
         cell=sheetobj.cells[coord];
         if (cell && cell.rowspan>1) {
            rowneedsrefresh[bottomrownum]=true; // need to update this row
            continue;
            }
         coord=context.cellskip[SocialCalc.crToCoord(colnum, bottomrownum)];
         if (!coord) continue; // only look at spanned cells
         rownum=context.coordToCR[coord].row-0;
         if (rownum==bottomrownum ||
             rownum<context.rowpanes[rowpane].first) continue; // this row (colspan) or starts above pane
         cell=sheetobj.cells[coord];
         if (cell && cell.rowspan>1) rowneedsrefresh[rownum]=true; // remember row num to update
         }
      }

   for (rownum in rowneedsrefresh) {
      newrow=context.RenderRow(rownum, rowpane);
      oldchild=tbodyobj.childNodes[(toprow+(rownum-context.rowpanes[rowpane].first))];
      tbodyobj.replaceChild(newrow,oldchild);
      }

   return tableobj;
   }


// *************************************
//
// InputBox class:
//
// This class deals with the text box for editing cell contents.
// It mainly controls a user input box for typed content and is used to interact with
// the keyboard code, etc.
//
// You can use this inside a formula bar control of some sort.
// You create this after you have created a table editor object (but not necessarily 
// done the CreateTableEditor method).
//
// When the user starts typing text, or double-clicks on a cell, this object
// comes into play.
//
// The element given when this is first constructed should be an input HTMLElement or
// something that acts like one. Check the code here to see what is done to it.
//
// *************************************

SocialCalc.InputBox = function(element, editor) {

   if (!element) return; // invoked without enough data to work

   this.element = element; // the input element associated with this InputBox
   this.editor = editor; // the TableEditor this belongs to
   this.inputEcho = null;

   editor.inputBox = this;

   element.onmousedown = SocialCalc.InputBoxOnMouseDown;

   editor.MoveECellCallback.formulabar = function(e){
      if (e.state!="start") return; // if not in normal keyboard mode don't replace formula bar
      editor.inputBox.DisplayCellContents(e.ecell.coord);
      };
   }


// Methods:

SocialCalc.InputBox.prototype.DisplayCellContents = function(coord) {SocialCalc.InputBoxDisplayCellContents(this, coord);};
SocialCalc.InputBox.prototype.ShowInputBox = function(show) {this.editor.inputEcho.ShowInputEcho(show);};
SocialCalc.InputBox.prototype.GetText = function() {return this.element.value;};
SocialCalc.InputBox.prototype.SetText = function(newtext) {
   if (!this.element) return;
   this.element.value=newtext;
   this.editor.inputEcho.SetText(newtext+"_");
   };
SocialCalc.InputBox.prototype.Focus = function() {SocialCalc.InputBoxFocus(this);};
SocialCalc.InputBox.prototype.Blur = function() {return this.element.blur();};
SocialCalc.InputBox.prototype.Select = function(t) {
   if (!this.element) return;
   switch (t) {
      case "end":
         if (document.selection && document.selection.createRange) {
            /* IE 4+ - Safer than setting .selectionEnd as it also works for Textareas. */
            var range = document.selection.createRange().duplicate();
            range.moveToElementText(this.element);
            range.collapse(false);
            range.select();
         } else if (this.element.selectionStart!=undefined) {
            this.element.selectionStart=this.element.value.length;
            this.element.selectionEnd=this.element.value.length;
         }
         break;
      }
   };

// Functions:

//
// SocialCalc.InputBoxDisplayCellContents(inputbox, coord)
//
// Sets input box to the contents of the specified cell (or ecell if null).
//

SocialCalc.InputBoxDisplayCellContents = function(inputbox, coord) {

   var scc = SocialCalc.Constants;

   if (!inputbox) return;
   if (!coord) coord = inputbox.editor.ecell.coord;
   var text = SocialCalc.GetCellContents(inputbox.editor.context.sheetobj, coord);
   if (text.indexOf("\n")!=-1) {
      text = scc.s_inputboxdisplaymultilinetext;
      inputbox.element.disabled = true;
      }
   else {
      inputbox.element.disabled = false;
      }
   inputbox.SetText(text);

   }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

            }

         newcoord = SocialCalc.crToCoord(crend.col, crend.row);
         if (newcoord!=mouseinfo.mouselastcoord) {
            editor.MoveECell(newcoord);
            c = editor.range2.right - editor.range2.left + crend.col;
            r = editor.range2.bottom - editor.range2.top + crend.row;
            editor.RangeAnchor(SocialCalc.crToCoord(c, r));
            editor.RangeExtend();
            }
         break;

      }

   mouseinfo.mouselastcoord = newcoord;

   }

SocialCalc.CellHandlesMouseUp = function(e) {

   var editor, element, result, coord, now, textarea, sheetobj, cellobj, wval, cstr, cmdtype, cmdtype2;
   var crstart, crend;
   var sizec, sizer, deltac, deltar;

   var event = e || window.event;

   var viewport = SocialCalc.GetViewportInfo();
   var clientX = event.clientX + viewport.horizontalScroll;
   var clientY = event.clientY + viewport.verticalScroll;

   var mouseinfo = SocialCalc.EditorMouseInfo;
   editor = mouseinfo.editor;
   if (!editor) return; // not us, ignore
   var cellhandles = editor.cellhandles;

   element = mouseinfo.element;

   mouseinfo.ignore = false;

   result = SocialCalc.GridMousePosition(editor, clientX, clientY); // get cell with up

   SocialCalc.SetDragAutoRepeat(editor, null); // stop repeating if it was

   cellhandles.mouseDown = false;
   cellhandles.noCursorSuffix = false;

   cellhandles.fillinghandle.style.display = "none";

   if (!result) result = {};
   if (!result.coord) result.coord = editor.ecell.coord;

   switch (cellhandles.dragtype) {
      case "Fill":
      case "Move":
      case "MoveI":
         cmdtype2 = " all";
            break;
      case "FillC":
      case "MoveC":
      case "MoveIC":
         cmdtype2 = " formulas";
         break;
      }

   if (!cellhandles.movedmouse) { // didn't move: just leave one cell selected
      cellhandles.dragtype = "Nothing";
      }

   switch (cellhandles.dragtype) {
      case "Nothing":
         editor.Range2Remove();
         editor.RangeRemove();
         break;

      case "Fill":
      case "FillC":

         crstart = SocialCalc.coordToCr(cellhandles.startingcoord);
         crend = SocialCalc.coordToCr(result.coord);
         if (cellhandles.filltype) {
            if (cellhandles.filltype=="Down") {
               crend.col = crstart.col;
               }
            else {
               crend.row = crstart.row;
               }
            }
         result.coord = SocialCalc.crToCoord(crend.col, crend.row);

         editor.MoveECell(result.coord);
         editor.RangeExtend();

         if (editor.cellhandles.filltype=="Right") {
            cmdtype = "right";
            }
         else {
            cmdtype = "down";
            }
         cstr = "fill"+cmdtype+" "+SocialCalc.crToCoord(editor.range.left, editor.range.top)+
                   ":"+SocialCalc.crToCoord(editor.range.right, editor.range.bottom)+cmdtype2;
         editor.EditorScheduleSheetCommands(cstr, true, false);
         break;

      case "Move":
      case "MoveC":
         editor.context.cursorsuffix = "";
         cstr = "movepaste "+
                     SocialCalc.crToCoord(editor.range2.left, editor.range2.top) + ":" +
                     SocialCalc.crToCoord(editor.range2.right, editor.range2.bottom)
                     +" "+editor.ecell.coord+cmdtype2;
         editor.EditorScheduleSheetCommands(cstr, true, false);
         editor.Range2Remove();

         break;

      case "MoveI":
      case "MoveIC":
         editor.context.cursorsuffix = "";
         sizec = editor.range2.right - editor.range2.left;
         sizer = editor.range2.bottom - editor.range2.top;
         deltac = editor.ecell.col - editor.range2.left;



( run in 3.645 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )