App-SocialCalc-Multiplayer

 view release on metacpan or  search on metacpan

socialcalc/Changes.txt  view on Meta::CPAN


2008-09-19:
ScheduleSheetCommands now starts a time-sliced loop to execute commands

2008-09-20:
2008-09-21:
2008-09-22:
2008-09-23:
Made commands, recalc, and display all be timer driven
Added deferred command execution
Added edit.busy
Made most of UI observe the busy flag, including Button and Drag additions

2008-11-06:
Added calcorder as a timesliced part of recalc.

2008-11-07:
Added recalc to coded and decoded sheet attributes.
Sheet recalc attribute is now followed, as well as new sheet.recalconce.

2008-11-10:
SpreadsheetControl now has a default status line.
Added recalc button to toolbar.

2008-11-11:
Recalc is now followed in mult-sheet recalc.

2008-11-14:
Tab switching is ignored away from sheet when editor.busy.
Initial spreadsheet.currentTab is now 0 after initialization.
Recalc button in toolbar is only displayed if recalc needed

2008-11-15:
Made spreadsheet.DoOnResize.
Fixed bug with ResizeTableEditor changing griddiv but not toplevel.

2008-11-16:
Made SocialCalc.ResetSheet only reset data stuff so Reload works in new event-driven world.

2008-11-19:
Sort range is now saved and loaded.

2008-11-24:
Added sheet.changedrendervalues to fix bugs with changed fonts, etc.
Added color chooser to settings tab
Made scroll wheel follow editor.busy

2008-11-26:
Updated simpleedit14.pl
Fixed some IE bugs with SocialCalc.SpreadsheetControlDecodeSpreadsheetSave with ^$

2008-11-29:
Fixed row hide setting load bug (typo).

2008-12-01:
Made simpleedit14.pl do server-side wikitext expansion differently than client-side.

socialcalc/socialcalc-3.js  view on Meta::CPAN


   sheetobj: null, // sheet being operated on
   parseobj: null, // SocialCalc.Parse object with the command string, etc.
   timerobj: null, // used for timeslicing
   firsttimerdelay: 50, // wait before starting cmds (for Chrome - to give time to update)
   timerdelay: 1, // wait between slices
   maxtimeslice: 100, // do another slice after this many milliseconds
   saveundo: false, // arg for ExecuteSheetCommand

   CmdExtensionCallbacks: {}, // for startcmdextension, in form: cmdname, {func:function(cmdname, data, sheet, SocialCalc.Parse object, saveundo), data:whatever}
   cmdextensionbusy: "" // if length>0, command loop waits for SocialCalc.ResumeFromCmdExtension()

//   statuscallback: null, // called during execution - obsolete: use sheet obj's
//   statuscallbackparams: null

   };

//
// SocialCalc.ScheduleSheetCommands
//
// statuscallback is called at the beginning (cmdstart) and end (cmdend).

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.
//

socialcalc/socialcalcserver.pl  view on Meta::CPAN

      spreadsheet.ExecuteCommand('redisplay', '');
      }
   else {
      spreadsheet.ExecuteCommand('recalc', '');
      }

function docmdext (name, data, sheet, cmd, saveundo) {

   var cmdstr = cmd.RestOfString();
   data.editor.EditorScheduleSheetCommands(cmdstr, false, false);
   SocialCalc.SheetCommandInfo.cmdextensionbusy = "Do Cmd Ext "+cmdstr;

   window.setTimeout(function(){SocialCalc.ResumeFromCmdExtension();}, 100);

   }

function doloadclipboardext (name, data, sheet, cmd, saveundo) {

   var cmdstr = cmd.RestOfString();
   SocialCalc.SheetCommandInfo.cmdextensionbusy = "Load Clipboard Ext "+cmdstr;

   loaddata(cmdstr);

//   window.setTimeout(function(){SocialCalc.ResumeFromCmdExtension();}, 100);
//   SocialCalc.ResumeFromCmdExtension();
   }

var loaddatatimerobj;

function loaddata(url) {

socialcalc/socialcalcspreadsheetcontrol.js  view on Meta::CPAN

   var tabs = spreadsheet.tabs;
   var views = spreadsheet.views;

   if (typeof obj == "string") {
      newtab = obj;
      }
   else {
      newtab = obj.id.slice(spreadsheet.idPrefix.length,-3);
      }

   if (spreadsheet.editor.busy && // if busy and switching from "sheet", ignore
         (!tabs[spreadsheet.currentTab].view || tabs[spreadsheet.currentTab].view=="sheet")) {
      for (i=0; i<tabs.length; i++) {
         if(tabs[i].name==newtab && (tabs[i].view && tabs[i].view!="sheet")) {
            return;
            }
         }
      }

   if (spreadsheet.tabs[spreadsheet.currentTab].onunclick) {
      spreadsheet.tabs[spreadsheet.currentTab].onunclick(spreadsheet, spreadsheet.tabs[spreadsheet.currentTab].name);

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   this.verticaltablecontrol = null;
   this.horizontaltablecontrol = null;

   this.logo = null;

   this.cellhandles = null;

   // Dynamic properties:

   this.timeout = null; // if non-null, timer id for position calculations
   this.busy = false; // true when executing command, calculating, etc.
   this.ensureecell = false; // if true, ensure ecell is visible after timeout
   this.deferredCommands = []; // commands to execute after busy, in form: {cmdstr: "cmds", saveundo: t/f}

   this.gridposition = null; // screen coords of full grid
   this.headposition = null; // screen coords of upper left of grid within header rows
   this.firstscrollingrow = null; // row number of top row in last (the scrolling) pane
   this.firstscrollingrowtop = null;  // position of top row in last (the scrolling) pane
   this.lastnonscrollingrow = null; // row number of last displayed row in last non-scrolling
                                    // pane, or zero (for thumb position calculations)
   this.lastvisiblerow = null; // used for paging down
   this.firstscrollingcol = null; // column number of top col in last (the scrolling) pane
   this.firstscrollingcolleft = null;  // position of top col in last (the scrolling) pane

socialcalc/socialcalctableeditor.js  view on Meta::CPAN


// Methods:

SocialCalc.TableEditor.prototype.CreateTableEditor = function(width, height) {return SocialCalc.CreateTableEditor(this, width, height);};
SocialCalc.TableEditor.prototype.ResizeTableEditor = function(width, height) {return SocialCalc.ResizeTableEditor(this, width, height);};

SocialCalc.TableEditor.prototype.SaveEditorSettings = function() {return SocialCalc.SaveEditorSettings(this);};
SocialCalc.TableEditor.prototype.LoadEditorSettings = function(str, flags) {return SocialCalc.LoadEditorSettings(this, str, flags);};

SocialCalc.TableEditor.prototype.EditorRenderSheet = function() {SocialCalc.EditorRenderSheet(this);};
SocialCalc.TableEditor.prototype.EditorScheduleSheetCommands = function(cmdstr, saveundo, ignorebusy) {SocialCalc.EditorScheduleSheetCommands(this, cmdstr, saveundo, ignorebusy);};
SocialCalc.TableEditor.prototype.ScheduleSheetCommands = function(cmdstr, saveundo) {
   this.context.sheetobj.ScheduleSheetCommands(cmdstr, saveundo);
   };
SocialCalc.TableEditor.prototype.SheetUndo = function() {
   this.context.sheetobj.SheetUndo();
   };
SocialCalc.TableEditor.prototype.SheetRedo = function() {
   this.context.sheetobj.SheetRedo();
   };
SocialCalc.TableEditor.prototype.EditorStepSet = function(status, arg) {SocialCalc.EditorStepSet(this, status, arg);};

socialcalc/socialcalctableeditor.js  view on Meta::CPAN


   if (editor.ecell) editor.SetECellHeaders("selected");

   SocialCalc.AssignID(editor, editor.fullgrid, "fullgrid"); // give it an id

   editor.EditorMouseRegister();

   }

//
// EditorScheduleSheetCommands(editor, cmdstr, saveundo, ignorebusy)
//

SocialCalc.EditorScheduleSheetCommands = function(editor, cmdstr, saveundo, ignorebusy) {

   if (editor.state!="start" && !ignorebusy) { // ignore commands if editing a cell
      return;
      }

   if (editor.busy && !ignorebusy) { // hold off on commands if doing one
      editor.deferredCommands.push({cmdstr: cmdstr, saveundo: saveundo});
      return;
      }

   switch (cmdstr) {
      case "recalc":
      case "redisplay":
         editor.context.sheetobj.ScheduleSheetCommands(cmdstr, false);
         break;

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

            }
         }
      }

   switch (status) {

      case "startup":
         break;

      case "cmdstart":
         editor.busy = true;
         sheetobj.celldisplayneeded = "";
         break;

      case "cmdextension":
         break;

      case "cmdend":
         signalstatus(status);

         if (sheetobj.changedrendervalues) {

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

            editor.recalcFunction(editor);
            }
         else {
            if (sheetobj.renderneeded) {
               editor.FitToEditTable();
               sheetobj.renderneeded = false;
               editor.ScheduleRender();
               }
            else {
               editor.SchedulePositionCalculations(); // just in case command changed positions
//               editor.busy = false;
//               signalstatus("cmdendnorender");
               }
            }
         return;

      case "calcstart":
         editor.busy = true;
         break;

      case "calccheckdone":
      case "calcorder":
      case "calcstep":
      case "calcloading":
      case "calcserverfunc":
         break;

      case "calcfinished":
         signalstatus(status);
         editor.ScheduleRender();
         return;

      case "schedrender":
         editor.busy = true; // in case got here without cmd or recalc
         break;

      case "renderdone":
         break;

      case "schedposcalc":
         editor.busy = true; // in case got here without cmd or recalc
         break;

      case "doneposcalc":
         if (editor.deferredCommands.length) {
            signalstatus(status);
            dcmd = editor.deferredCommands.shift();
            editor.EditorScheduleSheetCommands(dcmd.cmdstr, dcmd.saveundo, true);
            }
         else {
            editor.busy = false;
            signalstatus(status);
            if (editor.state=="start") editor.DisplayCellContents(); // make sure up to date
            }
         return;

      default:
addmsg("Unknown status: "+status);
         break;

      }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

         break;
      default:
         progress = status;
         break;
      }

   if (!progress && params.calculating) {
      progress = scc.s_statusline_calculating;
      }

   // if there is a range, calculate sum (not during busy times)
   if (!params.calculating && !params.command && !progress && editor.range.hasrange 
       && (editor.range.left!=editor.range.right || editor.range.top!=editor.range.bottom)) {
      sum = 0;
      for (r=editor.range.top; r <= editor.range.bottom; r++) {
         for (c=editor.range.left; c <= editor.range.right; c++) {
            cell = editor.context.sheetobj.cells[SocialCalc.crToCoord(c, r)];
            if (!cell) continue;
            if (cell.valuetype && cell.valuetype.charAt(0)=="n") {
               sum += cell.datavalue-0;
               }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

      line = "set "+ecell.coord+" "+cmd;
      errortext = editor.EditorScheduleSheetCommands(line, true, false);
      }

   editor.DisplayCellContents();

   }

SocialCalc.EditorProcessMouseWheel = function(event, delta, mousewheelinfo, wobj) {

   if (wobj.functionobj.editor.busy) return; // ignore if busy

   if (delta > 0) {
      wobj.functionobj.editor.ScrollRelative(true, -1);
      }
   if (delta < 0) {
      wobj.functionobj.editor.ScrollRelative(true, +1);
      }

   }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

      editor.MoveECellCallback[f](editor);
      }

   editor.UpdateCellCSS(cell, editor.ecell.row, editor.ecell.col);
   editor.SetECellHeaders("selected");

   for (f in editor.StatusCallback) { // let status line, etc., know
      editor.StatusCallback[f].func(editor, "moveecell", newcell, editor.StatusCallback[f].params);
      }

   if (editor.busy) {
      editor.ensureecell = true; // wait for when not busy
      }
   else {
      editor.ensureecell = false;
      editor.EnsureECellVisible();
      }

   return newcell;

   }

socialcalc/socialcalctableeditor.js  view on Meta::CPAN


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

   var mouseinfo = SocialCalc.EditorMouseInfo;

   editor = SocialCalc.Keyboard.focusTable; // get TableEditor doing keyboard stuff
   if (!editor) return true; // we're not handling it -- let browser do default

   if (editor.busy) return; // don't do anything when busy (is this correct?)

   var cellhandles = editor.cellhandles;

   cellhandles.movedmouse = false; // detect no-op

   if (cellhandles.timer) { // cancel timer
      window.clearTimeout(cellhandles.timer);
      cellhandles.timer = null;
      }
   if (cellhandles.tooltipstimer) {

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   s.zIndex = 3;
   setStyles(control.paneslider, scc.TCpanesliderStyle);
   s.backgroundImage="url("+imageprefix+"paneslider-"+vh+".gif)";
   if (scc.TCpanesliderClass) control.paneslider.className = scc.TCpanesliderClass;
   AssignID(control.editor, control.paneslider, "paneslider"+vh);
   TooltipRegister(control.paneslider, "paneslider", vh);

   functions = {MouseDown:SocialCalc.TCPSDragFunctionStart,
                    MouseMove: SocialCalc.TCPSDragFunctionMove,
                    MouseUp: SocialCalc.TCPSDragFunctionStop,
                    Disabled: function() {return control.editor.busy;}};

   functions.control = control; // make sure this is there

   SocialCalc.DragRegister(control.paneslider, control.vertical, !control.vertical, functions);

   control.main.appendChild(control.paneslider);

   control.lessbutton = document.createElement("div");
   s = control.lessbutton.style;
   s.height = (control.vertical ? control.buttonthickness : control.controlthickness)+"px";

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   s.position = "absolute";
   setStyles(control.lessbutton, scc.TClessbuttonStyle);
   s.backgroundImage="url("+imageprefix+"less-"+vh+"n.gif)"
   if (scc.TClessbuttonClass) control.lessbutton.className = scc.TClessbuttonClass;
   AssignID(control.editor, control.lessbutton, "lessbutton"+vh);

   params = {repeatwait:scc.TClessbuttonRepeatWait, repeatinterval:scc.TClessbuttonRepeatInterval,
             normalstyle: "backgroundImage:url("+imageprefix+"less-"+vh+"n.gif);",
             downstyle: "backgroundImage:url("+imageprefix+"less-"+vh+"d.gif);",
             hoverstyle: "backgroundImage:url("+imageprefix+"less-"+vh+"h.gif);"};
   functions = {MouseDown:function(){if(!control.editor.busy) control.editor.ScrollRelative(control.vertical, -1);},
                Repeat:function(){if(!control.editor.busy) control.editor.ScrollRelative(control.vertical, -1);},
                Disabled: function() {return control.editor.busy;}};

   SocialCalc.ButtonRegister(control.lessbutton, params, functions);

   control.main.appendChild(control.lessbutton);

   control.morebutton = document.createElement("div");
   s = control.morebutton.style;
   s.height = (control.vertical ? control.buttonthickness : control.controlthickness)+"px";
   s.width = (control.vertical ? control.controlthickness : control.buttonthickness)+"px";
   s.zIndex = 2;

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   s.position = "absolute";
   setStyles(control.morebutton, scc.TCmorebuttonStyle);
   s.backgroundImage="url("+imageprefix+"more-"+vh+"n.gif)"
   if (scc.TCmorebuttonClass) control.morebutton.className = scc.TCmorebuttonClass;
   AssignID(control.editor, control.morebutton, "morebutton"+vh);

   params = {repeatwait:scc.TCmorebuttonRepeatWait, repeatinterval:scc.TCmorebuttonRepeatInterval,
             normalstyle: "backgroundImage:url("+imageprefix+"more-"+vh+"n.gif);",
             downstyle: "backgroundImage:url("+imageprefix+"more-"+vh+"d.gif);",
             hoverstyle: "backgroundImage:url("+imageprefix+"more-"+vh+"h.gif);"};
   functions = {MouseDown:function(){if(!control.editor.busy) control.editor.ScrollRelative(control.vertical, +1);},
                Repeat:function(){if(!control.editor.busy) control.editor.ScrollRelative(control.vertical, +1);},
                Disabled: function() {return control.editor.busy;}};

   SocialCalc.ButtonRegister(control.morebutton, params, functions);

   control.main.appendChild(control.morebutton);

   control.scrollarea = document.createElement("div");
   s = control.scrollarea.style;
   s.height = control.controlthickness+"px";
   s.width = control.controlthickness+"px";
   s.zIndex = 1;
   s.overflow = "hidden"; // IE will make the DIV at least font-size height...so use this
   s.position = "absolute";
   setStyles(control.scrollarea, scc.TCscrollareaStyle);
   s.backgroundImage="url("+imageprefix+"scrollarea-"+vh+".gif)";
   if (scc.TCscrollareaClass) control.scrollarea.className = scc.TCscrollareaClass;
   AssignID(control.editor, control.scrollarea, "scrollarea"+vh);

   params = {repeatwait:scc.TCscrollareaRepeatWait, repeatinterval:scc.TCscrollareaRepeatWait};
   functions = {MouseDown:SocialCalc.ScrollAreaClick, Repeat:SocialCalc.ScrollAreaClick,
                Disabled: function() {return control.editor.busy;}};
   functions.control = control;

   SocialCalc.ButtonRegister(control.scrollarea, params, functions);

   control.main.appendChild(control.scrollarea);

   control.thumb = document.createElement("div");
   s = control.thumb.style;
   s.height =  (control.vertical ? control.thumbthickness : control.controlthickness)+"px";
   s.width = (control.vertical ? control.controlthickness : control.thumbthickness)+"px";

socialcalc/socialcalctableeditor.js  view on Meta::CPAN

   s.overflow = "hidden"; // IE will make the DIV at least font-size height...so use this
   s.position = "absolute";
   setStyles(control.thumb, scc.TCthumbStyle);
   control.thumb.style.backgroundImage="url("+imageprefix+"thumb-"+vh+"n.gif)";
   if (scc.TCthumbClass) control.thumb.className = scc.TCthumbClass;
   AssignID(control.editor, control.thumb, "thumb"+vh);

   functions = {MouseDown:SocialCalc.TCTDragFunctionStart,
                MouseMove: SocialCalc.TCTDragFunctionMove,
                MouseUp: SocialCalc.TCTDragFunctionStop,
                Disabled: function() {return control.editor.busy;}};
   functions.control = control; // make sure this is there
   SocialCalc.DragRegister(control.thumb, control.vertical, !control.vertical, functions);

   params = {normalstyle: "backgroundImage:url("+imageprefix+"thumb-"+vh+"n.gif)", name:"Thumb",
             downstyle:  "backgroundImage:url("+imageprefix+"thumb-"+vh+"d.gif)",
             hoverstyle:  "backgroundImage:url("+imageprefix+"thumb-"+vh+"h.gif)"};
   SocialCalc.ButtonRegister(control.thumb, params, null); // give it button-like visual behavior

   control.main.appendChild(control.thumb);

socialcalc/socialcalctableeditor.js  view on Meta::CPAN


//
// ScrollAreaClick - Button function to process pageup/down clicks
//

SocialCalc.ScrollAreaClick = function(e, buttoninfo, bobj) {

   var control = bobj.functionobj.control;
   var bposition = SocialCalc.GetElementPosition(bobj.element);
   var clickpos = control.vertical ? buttoninfo.clientY : buttoninfo.clientX;
   if (control.editor.busy) { // ignore if busy - wait for next repeat
      return;
      }
   control.editor.PageRelative(control.vertical, clickpos > control.thumbpos ? 1 : -1);

   return;

}

//
// PositionTableControlElements



( run in 0.248 second using v1.01-cache-2.11-cpan-87723dcf8b7 )