// @ts-nocheck
// Generated by scripts/build.js from audreyt/socialcalc. Do not hand-edit.
import { ShimNode } from './dom-shim';
export function createSocialCalcFactory() {
const host = {
setTimeout: function(cb) { cb(); return 0; },
clearTimeout: function() {}
};
let SocialCalc;
(function() {
var navigator = { language: "", userAgent: "" };
// Force the UMD's Node branch so nothing lands on the real
// globalThis.SocialCalc. define stays undefined so AMD is also skipped.
var module = { exports: {} };
var define = undefined;
// Opening half of a UMD IIFE. Inlined in build.ts — not a standalone module.
//
// Taken from https://github.com/umdjs/umd/blob/master/templates/returnExports.js
// (c) by The UMD contributors
// MIT License: https://github.com/umdjs/umd/blob/master/LICENSE.md
(function (root, factory) {
'use strict';
// Evaluate once and fan out to both deliveries:
// * browser / globalThis (root.SocialCalc) — always set
// * CommonJS / Node (module.exports) — when present
// AMD was dropped from this wrapper: the npm package is its
// canonical entry point today, and AMD loaders (RequireJS, Dojo
// legacy) have been unmaintained for years. Anyone still wiring
// AMD can wrap the CommonJS module themselves.
var exported = factory.call(root, root);
root.SocialCalc = exported;
if (typeof module === 'object' && module && module.exports) {
module.exports = exported;
}
})(this, function (window) {
'use strict';
// Factory-local bag. Formerly created in socialcalcconstants as
// `var SocialCalc; if (!SocialCalc) SocialCalc = {}`. Hoisted here so
// converted TypeScript sources can typecheck against the ambient
// `declare namespace SocialCalc` without a runtime `var SocialCalc`
// that would shadow/collapse the namespace during `tsc`.
var SocialCalc = {};
// In-place TypeScript conversion of socialcalcconstants.js (SocialCalc global script).
// Ambient API types live in socialcalcconstants.d.ts (referenced by dist/SocialCalc.d.ts).
// Vite+ strips types with Oxc before UMD concat — no runtime tax.
// Runtime SocialCalc bag is created in module-wrapper-top.js (UMD factory-local).
//
/*
// The module of the SocialCalc package with customizable constants, strings, etc.
// This is where most of the common localizations are done.
//
// (c) Copyright 2008, 2009, 2010 Socialtext, Inc.
// All Rights Reserved.
//
// The contents of this file are subject to the Artistic License 2.0; you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at http://socialcalc.org/licenses/al-20/.
//
// Some of the other files in the SocialCalc package are licensed under
// different licenses. Please note the licenses of the modules you use.
//
// Code History:
//
// Initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc.
// Based in part on the SocialCalc 1.1.0 code written in Perl.
// The SocialCalc 1.1.0 code was:
// Portions (c) Copyright 2005, 2006, 2007 Software Garden, Inc.
// All Rights Reserved.
// Portions (c) Copyright 2007 Socialtext, Inc.
// All Rights Reserved.
// The Perl SocialCalc started as modifications to the wikiCalc(R) program, version 1.0.
// wikiCalc 1.0 was written by Software Garden, Inc.
// Unless otherwise specified, referring to "SocialCalc" in comments refers to this
// JavaScript version of the code, not the SocialCalc Perl code.
//
*/
// SocialCalc bag: created by module-wrapper-top.js inside the UMD factory.
// Implementation-only mutable view for progressive init of ambient `const` members.
const ConstantsRoot = SocialCalc;
ConstantsRoot.Constants = {
cellDataType: {
v: 'value',
n: 'value',
t: 'text',
f: 'formula',
c: 'constant',
},
textdatadefaulttype: 't',
s_BrowserNotSupported: 'Browser not supported.',
s_InternalError: 'Internal SocialCalc error (probably an internal bug): ',
s_pssUnknownColType: 'Unknown col type item',
s_pssUnknownRowType: 'Unknown row type item',
s_pssUnknownLineType: 'Unknown line type',
s_cfspUnknownCellType: 'Unknown cell type item',
doCanonicalizeSheet: true,
s_escUnknownSheetCmd: 'Unknown sheet command: ',
s_escUnknownSetCoordCmd: 'Unknown set coord command: ',
s_escUnknownCmd: 'Unknown command: ',
s_caccCircRef: 'Circular reference to ',
defaultRowNameWidth: '30',
defaultAssumedRowHeight: 15,
defaultCellIDPrefix: 'cell_',
defaultCellLayout: 'padding:2px 2px 1px 2px;vertical-align:top;',
defaultCellFontStyle: 'normal normal',
defaultCellFontSize: 'small',
defaultCellFontFamily: 'Verdana,Arial,Helvetica,sans-serif',
defaultPaneDividerWidth: '3',
defaultPaneDividerHeight: '3',
defaultGridCSS: '1px solid #C0C0C0;',
defaultCommentClass: '',
defaultCommentStyle:
'background-repeat:no-repeat;background-position:top right;background-image:url(images/sc-commentbg.gif);',
defaultCommentNoGridClass: '',
defaultCommentNoGridStyle: '',
defaultReadonlyClass: '',
defaultReadonlyStyle:
'background-repeat:no-repeat;background-position:top right;background-image:url(images/sc-lockbg.gif);',
defaultReadonlyNoGridClass: '',
defaultReadonlyNoGridStyle: '',
defaultReadonlyComment: 'Locked cell',
defaultColWidth: '80',
defaultMinimumColWidth: 10,
defaultHighlightTypeCursorClass: '',
defaultHighlightTypeCursorStyle: 'color:#FFF;backgroundColor:#A6A6A6;',
defaultHighlightTypeRangeClass: '',
defaultHighlightTypeRangeStyle: 'color:#000;backgroundColor:#E5E5E5;',
defaultColnameClass: '',
defaultColnameStyle:
'overflow:visible;font-size:small;text-align:center;color:#FFFFFF;background-color:#808080;',
defaultSelectedColnameClass: '',
defaultSelectedColnameStyle:
'overflow:visible;font-size:small;text-align:center;color:#FFFFFF;background-color:#404040;',
defaultRownameClass: '',
defaultRownameStyle:
'position:relative;overflow:visible;font-size:small;text-align:right;color:#FFFFFF;background-color:#808080;',
defaultSelectedRownameClass: '',
defaultSelectedRownameStyle:
'position:relative;overflow:visible;font-size:small;text-align:right;color:#FFFFFF;background-color:#404040;',
defaultUpperLeftClass: '',
defaultUpperLeftStyle: 'font-size:small;',
defaultSkippedCellClass: '',
defaultSkippedCellStyle: 'font-size:small;background-color:#CCC',
defaultPaneDividerClass: '',
defaultPaneDividerStyle: 'font-size:small;background-color:#C0C0C0;padding:0px;',
defaultUnhideLeftClass: '',
defaultUnhideLeftStyle:
'float:right;width:9px;height:12px;cursor:pointer;background-image:url(images/sc-unhideleft.gif);padding:0;',
defaultUnhideRightClass: '',
defaultUnhideRightStyle:
'float:left;width:9px;height:12px;cursor:pointer;background-image:url(images/sc-unhideright.gif);padding:0;',
defaultUnhideTopClass: '',
defaultUnhideTopStyle:
'float:left;left:1px;position:absolute;bottom:-4px;width:12px;height:9px;cursor:pointer;background-image:url(images/sc-unhidetop.gif);padding:0;',
defaultUnhideBottomClass: '',
defaultUnhideBottomStyle:
'float:left;width:12px;height:9px;cursor:pointer;background-image:url(images/sc-unhidebottom.gif);padding:0;',
defaultColResizeBarClass: 'col-resize-bar',
defaultRowResizeBarClass: 'row-resize-bar',
s_rcMissingSheet: 'Render Context must have a sheet object',
defaultLinkFormatString:
'Link',
defaultPageLinkFormatString:
'Page',
defaultFormatp: '#,##0.0%',
defaultFormatc: '[$$]#,##0.00',
defaultFormatdt: 'd-mmm-yyyy h:mm:ss',
defaultFormatd: 'd-mmm-yyyy',
defaultFormatt: '[h]:mm:ss',
defaultDisplayTRUE: 'TRUE',
defaultDisplayFALSE: 'FALSE',
defaultImagePrefix: 'images/sc_',
defaultTableEditorIDPrefix: 'te_',
defaultPageUpDnAmount: 15,
AllowCtrlS: true,
defaultTableControlThickness: 20,
cteGriddivClass: '',
s_statusline_executing: 'Executing...',
s_statusline_displaying: 'Displaying...',
s_statusline_ordering: 'Ordering...',
s_statusline_calculating: 'Calculating...',
s_statusline_calculatingls: 'Calculating... Loading Sheet...',
s_statusline_doingserverfunc: 'doing server function ',
s_statusline_incell: ' in cell ',
s_statusline_calcstart: 'Calculation start...',
s_statusline_sum: 'SUM',
s_statusline_recalcneeded: '(Recalc needed)',
s_statusline_circref: 'Circular reference: ',
s_statusline_sendemail: 'Sending Email ',
s_inputboxdisplaymultilinetext: '[Multi-line text: Click icon on right to edit]',
defaultInputEchoClass: '',
defaultInputEchoStyle:
'filter:alpha(opacity=90);opacity:.9;backgroundColor:#FFD;border:1px solid #884;' +
'fontSize:small;padding:2px 10px 1px 2px;cursor:default;',
defaultInputEchoPromptClass: '',
defaultInputEchoPromptStyle:
'filter:alpha(opacity=90);opacity:.9;backgroundColor:#FFD;' +
'borderLeft:1px solid #884;borderRight:1px solid #884;borderBottom:1px solid #884;' +
'fontSize:small;fontStyle:italic;padding:2px 10px 1px 2px;cursor:default;',
defaultInputEchoHintClass: '',
defaultInputEchoHintStyle:
'filter:alpha(opacity=80);opacity:.8;backgroundColor:#884;border:1px solid #884;' +
'fontSize:small;fontWeight:bold;padding:2px 2px 2px 2px;color:#FFF;position:absolute;top:-20px;cursor:default;',
ietUnknownFunction: 'Unknown function ',
CH_radius1: 29,
CH_radius2: 41,
s_CHfillAllTooltip: 'Fill Contents and Formats Down/Right',
s_CHfillContentsTooltip: 'Fill Contents Only Down/Right',
s_CHmovePasteAllTooltip: 'Move Contents and Formats',
s_CHmovePasteContentsTooltip: 'Move Contents Only',
s_CHmoveInsertAllTooltip: 'Slide Contents and Formats within Row/Col',
s_CHmoveInsertContentsTooltip: 'Slide Contents within Row/Col',
s_CHindicatorOperationLookup: {
Fill: 'Fill',
FillC: 'Fill Contents',
Move: 'Move',
MoveI: 'Slide',
MoveC: 'Move Contents',
MoveIC: 'Slide Contents',
},
s_CHindicatorDirectionLookup: {
Down: ' Down',
Right: ' Right',
Horizontal: ' Horizontal',
Vertical: ' Vertical',
},
defaultTCSliderThickness: 9,
defaultTCButtonThickness: 20,
defaultTCThumbThickness: 15,
TCmainStyle: 'backgroundColor:#EEE;',
TCmainClass: '',
TCendcapStyle: 'backgroundColor:#FFF;',
TCendcapClass: '',
TCpanesliderClass: 'tc-paneslider',
s_panesliderTooltiph: 'Drag to lock pane vertically',
s_panesliderTooltipv: 'Drag to lock pane horizontally',
TClessbuttonStyle: 'backgroundColor:#AAA;',
TClessbuttonClass: '',
TClessbuttonRepeatWait: 300,
TClessbuttonRepeatInterval: 20,
TCmorebuttonStyle: 'backgroundColor:#AAA;',
TCmorebuttonClass: '',
TCmorebuttonRepeatWait: 300,
TCmorebuttonRepeatInterval: 20,
TCscrollareaStyle: 'backgroundColor:#DDD;',
TCscrollareaClass: '',
TCscrollareaRepeatWait: 500,
TCscrollareaRepeatInterval: 100,
TCthumbClass: '',
TCthumbStyle: 'backgroundColor:#CCC;',
TCPStrackinglineClass: 'tracklingine',
TCPStrackinglineStyle: 'overflow:hidden;position:absolute;zIndex:100;',
TCPStrackinglineThickness: '2px',
TCTDFSthumbstatusvClass: '',
TCTDFSthumbstatusvStyle:
'height:20px;width:auto;border:3px solid #808080;overflow:hidden;' +
'backgroundColor:#FFF;fontSize:small;position:absolute;zIndex:100;',
TCTDFSthumbstatushClass: '',
TCTDFSthumbstatushStyle:
'height:20px;width:auto;border:1px solid black;padding:2px;' +
'backgroundColor:#FFF;fontSize:small;position:absolute;zIndex:100;',
TCTDFSthumbstatusrownumClass: '',
TCTDFSthumbstatusrownumStyle:
'color:#FFF;background-color:#808080;font-size:small;white-space:nowrap;padding:3px;',
TCTDFStopOffsetv: 0,
TCTDFSleftOffsetv: -80,
s_TCTDFthumbstatusPrefixv: 'Row ',
TCTDFStopOffseth: -30,
TCTDFSleftOffseth: 0,
s_TCTDFthumbstatusPrefixh: 'Col ',
TooltipOffsetX: 2,
TooltipOffsetY: 10,
TDpopupElementClass: '',
TDpopupElementStyle:
'border:1px solid black;padding:1px 2px 2px 2px;textAlign:center;backgroundColor:#FFF;' +
'fontSize:7pt;fontFamily:Verdana,Arial,Helvetica,sans-serif;' +
'position:absolute;width:auto;zIndex:110;',
SCToolbarbackground: 'background-color:#ffffff;',
SCTabbackground: 'background-color:#CCC;',
SCTabselectedCSS:
'font-size:small;padding:6px 30px 6px 8px;color:#FFF;background-color:#404040;cursor:default;border-right:1px solid #CCC;',
SCTabplainCSS:
'font-size:small;padding:6px 30px 6px 8px;color:#FFF;background-color:#808080;cursor:default;border-right:1px solid #CCC;',
SCToolbartext: 'font-size:x-small;font-weight:bold;color:#888',
SCFormulabarheight: 30,
SCStatuslineheight: 20,
SCStatuslineCSS: 'font-size:10px;padding:3px 0px;',
SCFormatNumberFormats:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|%loc!Automatic!:general|%loc!Auto w/ commas!:[,]General|[break]:|' +
'00:00|000:000|0000:0000|00000:00000|[break]:|%loc!Formula!:formula|%loc!Hidden!:hidden|[newcol]:' +
'1234:0|1,234:#,##0|1,234.5:#,##0.0|1,234.56:#,##0.00|1,234.567:#,##0.000|1,234.5678:#,##0.0000|' +
'[break]:|1,234%:#,##0%|1,234.5%:#,##0.0%|1,234.56%:#,##0.00%|' +
'[newcol]:|$1,234:$#,##0|$1,234.5:$#,##0.0|$1,234.56:$#,##0.00|[break]:|' +
'(1,234):#,##0_);(#,##0)|(1,234.5):#,##0.0_);(#,##0.0)|(1,234.56):#,##0.00_);(#,##0.00)|[break]:|' +
'($1,234):$#,##0_);($#,##0)|($1,234.5):$#,##0.0_);($#,##0.0)|($1,234.56):$#,##0.00_);($#,##0.00)|' +
'[newcol]:|1/4/06:m/d/yy|01/04/2006:mm/dd/yyyy|2006-01-04:yyyy-mm-dd|4-Jan-06:d-mmm-yy|04-Jan-2006:dd-mmm-yyyy|January 4, 2006:mmmm d, yyyy|' +
'[break]:|1\\c23:h:mm|1\\c23 PM:h:mm AM/PM|1\\c23\\c45:h:mm:ss|01\\c23\\c45:hh:mm:ss|26\\c23 (h\\cm):[hh]:mm|69\\c45 (m\\cs):[mm]:ss|69 (s):[ss]|' +
'[newcol]:|2006-01-04 01\\c23\\c45:yyyy-mm-dd hh:mm:ss|January 4, 2006:mmmm d, yyyy hh:mm:ss|Wed:ddd|Wednesday:dddd|',
SCFormatTextFormats:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|%loc!Automatic!:general|%loc!Plain Text!:text-plain|' +
'HTML:text-html|%loc!Wikitext!:text-wiki|%loc!Link!:text-link|%loc!Formula!:formula|%loc!Hidden!:hidden|',
SCFormatPadsizes:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|%loc!No padding!:0px|' +
'[newcol]:|1 pixel:1px|2 pixels:2px|3 pixels:3px|4 pixels:4px|5 pixels:5px|' +
'6 pixels:6px|7 pixels:7px|8 pixels:8px|[newcol]:|9 pixels:9px|10 pixels:10px|11 pixels:11px|' +
'12 pixels:12px|13 pixels:13px|14 pixels:14px|16 pixels:16px|' +
'18 pixels:18px|[newcol]:|20 pixels:20px|22 pixels:22px|24 pixels:24px|28 pixels:28px|36 pixels:36px|',
SCFormatFontsizes:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|X-Small:x-small|Small:small|Medium:medium|Large:large|X-Large:x-large|' +
'[newcol]:|6pt:6pt|7pt:7pt|8pt:8pt|9pt:9pt|10pt:10pt|11pt:11pt|12pt:12pt|14pt:14pt|16pt:16pt|' +
'[newcol]:|18pt:18pt|20pt:20pt|22pt:22pt|24pt:24pt|28pt:28pt|36pt:36pt|48pt:48pt|72pt:72pt|' +
'[newcol]:|8 pixels:8px|9 pixels:9px|10 pixels:10px|11 pixels:11px|' +
'12 pixels:12px|13 pixels:13px|14 pixels:14px|[newcol]:|16 pixels:16px|' +
'18 pixels:18px|20 pixels:20px|22 pixels:22px|24 pixels:24px|28 pixels:28px|36 pixels:36px|',
SCFormatFontfamilies:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|Verdana:Verdana,Arial,Helvetica,sans-serif|' +
"Arial:arial,helvetica,sans-serif|Courier:'Courier New',Courier,monospace|",
SCFormatFontlook:
'[cancel]:|[break]:|%loc!Default!:|%loc!Normal!:normal normal|%loc!Bold!:normal bold|%loc!Italic!:italic normal|' +
'%loc!Bold Italic!:italic bold',
SCFormatTextAlignhoriz:
'[cancel]:|[break]:|%loc!Default!:|%loc!Left!:left|%loc!Center!:center|%loc!Right!:right|',
SCFormatNumberAlignhoriz:
'[cancel]:|[break]:|%loc!Default!:|%loc!Left!:left|%loc!Center!:center|%loc!Right!:right|',
SCFormatAlignVertical:
'[cancel]:|[break]:|%loc!Default!:|%loc!Top!:top|%loc!Middle!:middle|%loc!Bottom!:bottom|',
SCFormatColwidth:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|[newcol]:|' +
'20 pixels:20|40:40|60:60|80:80|100:100|120:120|140:140|160:160|' +
'[newcol]:|180 pixels:180|200:200|220:220|240:240|260:260|280:280|300:300|',
SCFormatRecalc: '[cancel]:|[break]:|%loc!Auto!:|%loc!Manual!:off|',
SCFormatUserMaxCol:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|[newcol]:|' +
'Unlimited:0|10:10|20:20|30:30|40:40|50:50|60:60|80:80|100:100|',
SCFormatUserMaxRow:
'[cancel]:|[break]:|%loc!Default!:|[custom]:|[newcol]:|' +
'Unlimited:0|10:10|20:20|30:30|40:40|50:50|60:60|80:80|100:100|',
ISCButtonNormalBackground: 'transparent',
ISCButtonBorderNormal: 'none',
ISCButtonBorderHover: 'none',
ISCButtonBorderDown: 'none',
ISCButtonDownBackground: '#888',
s_PopupListCancel: '[Cancel]',
s_PopupListCustom: 'Custom',
s_loc_align_center: 'Align Center',
s_loc_align_left: 'Align Left',
s_loc_align_right: 'Align Right',
s_loc_alignment: 'Alignment',
s_loc_audit: 'Audit',
s_loc_audit_trail_this_session: 'Audit Trail This Session',
s_loc_auto: 'Auto',
s_loc_auto_sum: 'Auto Sum',
s_loc_auto_wX_commas: 'Auto w/ commas',
s_loc_automatic: 'Automatic',
s_loc_background: 'Background',
s_loc_bold: 'Bold',
s_loc_bold_XampX_italics: 'Bold & Italics',
s_loc_bold_italic: 'Bold Italic',
s_loc_borders: 'Borders',
s_loc_borders_off: 'Borders Off',
s_loc_borders_on: 'Borders On',
s_loc_bottom: 'Bottom',
s_loc_bottom_border: 'Bottom Border',
s_loc_cell_settings: 'CELL SETTINGS',
s_loc_csv_format: 'CSV format',
s_loc_cancel: 'Cancel',
s_loc_category: 'Category',
s_loc_center: 'Center',
s_loc_clear: 'Clear',
s_loc_clear_socialcalc_clipboard: 'Clear SocialCalc Clipboard',
s_loc_clipboard: 'Clipboard',
s_loc_color: 'Color',
s_loc_column_: 'Column ',
s_loc_comment: 'Comment',
s_loc_copy: 'Copy',
s_loc_custom: 'Custom',
s_loc_cut: 'Cut',
s_loc_default: 'Default',
s_loc_default_alignment: 'Default Alignment',
s_loc_default_column_width: 'Default Column Width',
s_loc_default_font: 'Default Font',
s_loc_default_format: 'Default Format',
s_loc_default_padding: 'Default Padding',
s_loc_delete: 'Delete',
s_loc_delete_column: 'Delete Column',
s_loc_delete_contents: 'Delete Cell Contents',
s_loc_delete_row: 'Delete Row',
s_loc_description: 'Description',
s_loc_display_clipboard_in: 'Display Clipboard in',
s_loc_down: 'Down',
s_loc_edit: 'Edit',
s_loc_existing_names: 'Existing Names',
s_loc_family: 'Family',
s_loc_fill_down: 'Fill Down',
s_loc_fill_right: 'Fill Right',
s_loc_font: 'Font',
s_loc_format: 'Format',
s_loc_formula: 'Formula',
s_loc_function_list: 'Function List',
s_loc_functions: 'Functions',
s_loc_grid: 'Grid',
s_loc_hidden: 'Hidden',
s_loc_hide_column: 'Hide Column',
s_loc_hide_row: 'Hide Row',
s_loc_horizontal: 'Horizontal',
s_loc_insert_column: 'Insert Column Before',
s_loc_insert_row: 'Insert Row Before',
s_loc_italic: 'Italic',
s_loc_last_sort: 'Last Sort',
s_loc_left: 'Left',
s_loc_left_border: 'Left Border',
s_loc_link: 'Link',
s_loc_link_input_box: 'Link Input Box',
s_loc_list: 'List',
s_loc_load_socialcalc_clipboard_with_this: 'Load SocialCalc Clipboard With This',
s_loc_lock_cell: 'Lock Cell',
s_loc_major_sort: 'Major Sort',
s_loc_manual: 'Manual',
s_loc_merge_cells: 'Merge/Unmerge Cells',
s_loc_middle: 'Middle',
s_loc_minor_sort: 'Minor Sort',
s_loc_move_insert: 'Move Insert',
s_loc_move_paste: 'Move Paste',
s_loc_multiXline_input_box: 'Multi-line Input Box',
s_loc_name: 'Name',
s_loc_names: 'Names',
s_loc_no_padding: 'No padding',
s_loc_normal: 'Normal',
s_loc_number: 'Number',
s_loc_number_horizontal: 'Number Horizontal',
s_loc_ok: 'OK',
s_loc_padding: 'Padding',
s_loc_page_name: 'Page Name',
s_loc_paste: 'Paste',
s_loc_paste_formats: 'Paste Formats',
s_loc_plain_text: 'Plain Text',
s_loc_recalc: 'Recalc',
s_loc_recalculation: 'Recalculation',
s_loc_redo: 'Redo',
s_loc_right: 'Right',
s_loc_right_border: 'Right Border',
s_loc_sheet_settings: 'SHEET SETTINGS',
s_loc_save: 'Save',
s_loc_save_to: 'Save to',
s_loc_set_cell_contents: 'Set Cell Contents',
s_loc_set_cells_to_sort: 'Set Cells To Sort',
s_loc_set_value_to: 'Set Value To',
s_loc_set_to_link_format: 'Set to Link format',
s_loc_setXclear_move_from: 'Set/Clear Move From',
s_loc_show_cell_settings: 'Show Cell Settings',
s_loc_show_sheet_settings: 'Show Sheet Settings',
s_loc_show_in_new_browser_window: 'Show in new browser window',
s_loc_size: 'Size',
s_loc_socialcalcXsave_format: 'SocialCalc-save format',
s_loc_sort: 'Sort',
s_loc_sort_: 'Sort ',
s_loc_sort_cells: 'Sort Cells',
s_loc_swap_colors: 'Swap Colors',
s_loc_tabXdelimited_format: 'Tab-delimited format',
s_loc_text: 'Text',
s_loc_text_horizontal: 'Text Horizontal',
s_loc_this_is_aXbrXsample: 'This is a
sample',
s_loc_top: 'Top',
s_loc_top_border: 'Top Border',
s_loc_undone_steps: 'UNDONE STEPS',
s_loc_url: 'URL',
s_loc_undo: 'Undo',
s_loc_unlock_cell: 'Unlock Cell',
s_loc_unmerge_cells: 'Unmerge Cells',
s_loc_up: 'Up',
s_loc_value: 'Value',
s_loc_vertical: 'Vertical',
s_loc_wikitext: 'Wikitext',
s_loc_workspace: 'Workspace',
s_loc_XnewX: '[New]',
s_loc_XnoneX: '[None]',
s_loc_Xselect_rangeX: '[select range]',
SVStatuslineheight: 20,
SVStatuslineCSS: 'font-size:10px;padding:3px 0px;',
FormatNumber_separatorchar: ',',
FormatNumber_decimalchar: '.',
FormatNumber_defaultCurrency: '$',
s_FormatNumber_daynames: [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
],
s_FormatNumber_daynames3: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
s_FormatNumber_monthnames: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
s_FormatNumber_monthnames3: [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
],
s_FormatNumber_am: 'AM',
s_FormatNumber_am1: 'A',
s_FormatNumber_pm: 'PM',
s_FormatNumber_pm1: 'P',
s_parseerrexponent: 'Improperly formed number exponent',
s_parseerrchar: 'Unexpected character in formula',
s_parseerrstring: 'Improperly formed string',
s_parseerrspecialvalue: 'Improperly formed special value',
s_parseerrtwoops: 'Error in formula (two operators inappropriately in a row)',
s_parseerrmissingopenparen: 'Missing open parenthesis in list with comma(s). ',
s_parseerrcloseparennoopen: 'Closing parenthesis without open parenthesis. ',
s_parseerrmissingcloseparen: 'Missing close parenthesis. ',
s_parseerrmissingoperand: 'Missing operand. ',
s_parseerrerrorinformula: 'Error in formula.',
s_calcerrerrorvalueinformula: 'Error value in formula',
s_parseerrerrorinformulabadval: 'Error in formula resulting in bad value',
s_formularangeresult: 'Formula results in range value:',
s_calcerrnumericnan: 'Formula results in a bad numeric value',
s_calcerrnumericoverflow: 'Numeric overflow',
s_sheetunavailable: 'Sheet unavailable:',
s_calcerrcellrefmissing: 'Cell reference missing when expected.',
s_calcerrsheetnamemissing: 'Sheet name missing when expected.',
s_circularnameref: 'Circular name reference to name',
s_calcerrunknownname: 'Unknown name',
s_calcerrincorrectargstofunction: 'Incorrect arguments to function',
s_sheetfuncunknownfunction: 'Unknown function',
s_sheetfunclnarg: 'LN argument must be greater than 0',
s_sheetfunclog10arg: 'LOG10 argument must be greater than 0',
s_sheetfunclogsecondarg: 'LOG second argument must be numeric greater than 0',
s_sheetfunclogfirstarg: 'LOG first argument must be greater than 0',
s_sheetfuncroundsecondarg: 'ROUND second argument must be numeric',
s_sheetfuncddblife: 'DDB life must be greater than 1',
s_sheetfuncslnlife: 'SLN life must be greater than 1',
s_fdef_ABS: 'Absolute value function. ',
s_fdef_ACOS: 'Trigonometric arccosine function. ',
s_fdef_AND: 'True if all arguments are true. ',
s_fdef_ASIN: 'Trigonometric arcsine function. ',
s_fdef_ATAN: 'Trigonometric arctan function. ',
s_fdef_ATAN2: 'Trigonometric arc tangent function (result is in radians). ',
s_fdef_AVERAGE: 'Averages the values. ',
s_fdef_CHOOSE: 'Returns the value specified by the index. The values may be ranges of cells. ',
s_fdef_COLUMNS: 'Returns the number of columns in the range. ',
s_fdef_COS: 'Trigonometric cosine function (value is in radians). ',
s_fdef_CONCAT: 'Join Together Text & Values to Create a Single Combined Text String. ',
s_fdef_CONCATENATE: 'Join Together Text & Values to Create a Single Combined Text String. ',
s_fdef_COUNT: 'Counts the number of numeric values, not blank, text, or error. ',
s_fdef_COUNTA: 'Counts the number of non-blank values. ',
s_fdef_COUNTBLANK: 'Counts the number of blank values. (Note: "" is not blank.) ',
s_fdef_COUNTIF:
'Counts the number of number of cells in the range that meet the criteria. The criteria may be a value ("x", 15, 1+3) or a test (>25). ',
s_fdef_DATE:
'Returns the appropriate date value given numbers for year, month, and day. For example: DATE(2006,2,1) for February 1, 2006. Note: In this program, day "1" is December 31, 1899 and the year 1900 is not a leap year. Some programs use January 1, 1900, as day "1" and treat 1900 as a leap year. In both cases, though, dates on or after March 1, 1900, are the same. ',
s_fdef_DAVERAGE:
'Averages the values in the specified field in records that meet the criteria. ',
s_fdef_DAY: 'Returns the day of month for a date value. ',
s_fdef_DCOUNT:
'Counts the number of numeric values, not blank, text, or error, in the specified field in records that meet the criteria. ',
s_fdef_DCOUNTA:
'Counts the number of non-blank values in the specified field in records that meet the criteria. ',
s_fdef_DDB:
'Returns the amount of depreciation at the given period of time (the default factor is 2 for double-declining balance). ',
s_fdef_DEGREES: 'Converts value in radians into degrees. ',
s_fdef_DGET:
'Returns the value of the specified field in the single record that meets the criteria. ',
s_fdef_DMAX:
'Returns the maximum of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DMIN:
'Returns the minimum of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DPRODUCT:
'Returns the result of multiplying the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DSTDEV:
'Returns the sample standard deviation of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DSTDEVP:
'Returns the standard deviation of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DSUM:
'Returns the sum of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DVAR:
'Returns the sample variance of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_DVARP:
'Returns the variance of the numeric values in the specified field in records that meet the criteria. ',
s_fdef_EVEN: 'Rounds the value up in magnitude to the nearest even integer. ',
s_fdef_EXACT: 'Returns "true" if the values are exactly the same, including case, type, etc. ',
s_fdef_EXP: 'Returns e raised to the value power. ',
s_fdef_FACT: 'Returns factorial of the value. ',
s_fdef_FALSE: 'Returns the logical value "false". ',
s_fdef_FIND:
'Returns the starting position within string2 of the first occurrence of string1 at or after "start". If start is omitted, 1 is assumed. ',
s_fdef_FV:
'Returns the future value of repeated payments of money invested at the given rate for the specified number of periods, with optional present value (default 0) and payment type (default 0 = at end of period, 1 = beginning of period). ',
s_fdef_HLOOKUP:
'Look for the matching value for the given value in the range and return the corresponding value in the cell specified by the row offset. If rangelookup is 1 (the default) and not 0, match if within numeric brackets (match<=value) instead of exact match. ',
s_fdef_HOUR: 'Returns the hour portion of a time or date/time value. ',
s_fdef_IF:
'Results in true-value if logical-expression is TRUE or non-zero, otherwise results in false-value. ',
s_fdef_INDEX:
'Returns a cell or range reference for the specified row and column in the range. If range is 1-dimensional, then only one of rownum or colnum are needed. If range is 2-dimensional and rownum or colnum are zero, a reference to the range of just the specified column or row is returned. You can use the returned reference value in a range, e.g., sum(A1:INDEX(A2:A10,4)). ',
s_fdef_INT: 'Returns the value rounded down to the nearest integer (towards -infinity). ',
s_fdef_IRR:
'Returns the interest rate at which the cash flows in the range have a net present value of zero. Uses an iterative process that will return #NUM! error if it does not converge. There may be more than one possible solution. Providing the optional guess value may help in certain situations where it does not converge or finds an inappropriate solution (the default guess is 10%). ',
s_fdef_ISBLANK: 'Returns "true" if the value is a reference to a blank cell. ',
s_fdef_ISERR: 'Returns "true" if the value is of type "Error" but not "NA". ',
s_fdef_ISERROR: 'Returns "true" if the value is of type "Error". ',
s_fdef_ISLOGICAL: 'Returns "true" if the value is of type "Logical" (true/false). ',
s_fdef_ISNA: 'Returns "true" if the value is the error type "NA". ',
s_fdef_ISNONTEXT: 'Returns "true" if the value is not of type "Text". ',
s_fdef_ISNUMBER: 'Returns "true" if the value is of type "Number" (including logical values). ',
s_fdef_ISTEXT: 'Returns "true" if the value is of type "Text". ',
s_fdef_LEFT:
'Returns the specified number of characters from the text value. If count is omitted, 1 is assumed. ',
s_fdef_LEN: 'Returns the number of characters in the text value. ',
s_fdef_LN: 'Returns the natural logarithm of the value. ',
s_fdef_LOG: 'Returns the logarithm of the value using the specified base. ',
s_fdef_LOG10: 'Returns the base 10 logarithm of the value. ',
s_fdef_LOWER: 'Returns the text value with all uppercase characters converted to lowercase. ',
s_fdef_MATCH:
'Look for the matching value for the given value in the range and return position (the first is 1) in that range. If rangelookup is 1 (the default) and not 0, match if within numeric brackets (match<=value) instead of exact match. If rangelookup is -1, act like 1 but the bracket is match>=value. ',
s_fdef_MAX: 'Returns the maximum of the numeric values. ',
s_fdef_MID:
'Returns the specified number of characters from the text value starting from the specified position. ',
s_fdef_MIN: 'Returns the minimum of the numeric values. ',
s_fdef_MINUTE: 'Returns the minute portion of a time or date/time value. ',
s_fdef_MOD: 'Returns the remainder of the first value divided by the second. ',
s_fdef_MONTH: 'Returns the month part of a date value. ',
s_fdef_N: 'Returns the value if it is a numeric value otherwise an error. ',
s_fdef_NA: 'Returns the #N/A error value which propagates through most operations. ',
s_fdef_NOT: 'Returns FALSE if value is true, and TRUE if it is false. ',
s_fdef_NOW: 'Returns the current date/time. ',
s_fdef_NPER:
'Returns the number of periods at which payments invested each period at the given rate with optional future value (default 0) and payment type (default 0 = at end of period, 1 = beginning of period) has the given present value. ',
s_fdef_NPV:
'Returns the net present value of cash flows (which may be individual values and/or ranges) at the given rate. The flows are positive if income, negative if paid out, and are assumed at the end of each period. ',
s_fdef_ODD: 'Rounds the value up in magnitude to the nearest odd integer. ',
s_fdef_OR: 'True if any argument is true ',
s_fdef_PI: 'The value 3.1415926... ',
s_fdef_PMT:
'Returns the amount of each payment that must be invested at the given rate for the specified number of periods to have the specified present value, with optional future value (default 0) and payment type (default 0 = at end of period, 1 = beginning of period). ',
s_fdef_POWER: 'Returns the first value raised to the second value power. ',
s_fdef_PRODUCT: 'Returns the result of multiplying the numeric values. ',
s_fdef_PROPER:
'Returns the text value with the first letter of each word converted to uppercase and the others to lowercase. ',
s_fdef_PV:
'Returns the present value of the given number of payments each invested at the given rate, with optional future value (default 0) and payment type (default 0 = at end of period, 1 = beginning of period). ',
s_fdef_RADIANS: 'Converts value in degrees into radians. ',
s_fdef_RATE:
'Returns the rate at which the given number of payments each invested at the given rate has the specified present value, with optional future value (default 0) and payment type (default 0 = at end of period, 1 = beginning of period). Uses an iterative process that will return #NUM! error if it does not converge. There may be more than one possible solution. Providing the optional guess value may help in certain situations where it does not converge or finds an inappropriate solution (the default guess is 10%). ',
s_fdef_REPLACE:
'Returns text1 with the specified number of characters starting from the specified position replaced by text2. ',
s_fdef_REPT: 'Returns the text repeated the specified number of times. ',
s_fdef_RIGHT:
'Returns the specified number of characters from the text value starting from the end. If count is omitted, 1 is assumed. ',
s_fdef_ROUND:
'Rounds the value to the specified number of decimal places. If precision is negative, then round to powers of 10. The default precision is 0 (round to integer). ',
s_fdef_ROWS: 'Returns the number of rows in the range. ',
s_fdef_SECOND:
'Returns the second portion of a time or date/time value (truncated to an integer). ',
s_fdef_SIN: 'Trigonometric sine function (value is in radians) ',
s_fdef_SLN:
'Returns the amount of depreciation at each period of time using the straight-line method. ',
s_fdef_SQRT: 'Square root of the value ',
s_fdef_STDEV: 'Returns the sample standard deviation of the numeric values. ',
s_fdef_STDEVP: 'Returns the standard deviation of the numeric values. ',
s_fdef_SUBSTITUTE:
'Returns text1 with the all occurrences of oldtext replaced by newtext. If "occurrence" is present, then only that occurrence is replaced. ',
s_fdef_SUM:
'Adds the numeric values. The values to the sum function may be ranges in the form similar to A1:B5. ',
s_fdef_SUMIF:
'Sums the numeric values of cells in the range that meet the criteria. The criteria may be a value ("x", 15, 1+3) or a test (>25). If range2 is present, then range1 is tested and the corresponding range2 value is summed. ',
s_fdef_SUMIFS:
'Sums the numeric values of cells in the sum_range that meet the multiple criteria. The criteria may be a value ("x", 15, 1+3) or a test (>25). ',
s_fdef_SYD: "Depreciation by Sum of Year's Digits method. ",
s_fdef_T: 'Returns the text value or else a null string. ',
s_fdef_TAN: 'Trigonometric tangent function (value is in radians) ',
s_fdef_TIME: 'Returns the time value given the specified hour, minute, and second. ',
s_fdef_TODAY:
'Returns the current date (an integer). Note: In this program, day "1" is December 31, 1899 and the year 1900 is not a leap year. Some programs use January 1, 1900, as day "1" and treat 1900 as a leap year. In both cases, though, dates on or after March 1, 1900, are the same. ',
s_fdef_TRIM: 'Returns the text value with leading, trailing, and repeated spaces removed. ',
s_fdef_TRUE: 'Returns the logical value "true". ',
s_fdef_TRUNC:
'Truncates the value to the specified number of decimal places. If precision is negative, truncate to powers of 10. ',
s_fdef_UPPER: 'Returns the text value with all lowercase characters converted to uppercase. ',
s_fdef_VALUE:
'Converts the specified text value into a numeric value. Various forms that look like numbers (including digits followed by %, forms that look like dates, etc.) are handled. This may not handle all of the forms accepted by other spreadsheets and may be locale dependent. ',
s_fdef_VAR: 'Returns the sample variance of the numeric values. ',
s_fdef_VARP: 'Returns the variance of the numeric values. ',
s_fdef_VLOOKUP:
'Look for the matching value for the given value in the range and return the corresponding value in the cell specified by the column offset. If rangelookup is 1 (the default) and not 0, match if within numeric brackets (match>=value) instead of exact match. ',
s_fdef_WEEKDAY:
'Returns the day of week specified by the date value. If type is 1 (the default), Sunday is day and Saturday is day 7. If type is 2, Monday is day 1 and Sunday is day 7. If type is 3, Monday is day 0 and Sunday is day 6. ',
s_fdef_YEAR: 'Returns the year part of a date value. ',
s_fdef_SUMPRODUCT:
'Sums the pairwise products of 2 or more ranges. The ranges must be of equal length.',
s_fdef_CEILING:
'Rounds the given number up to the nearest integer or multiple of significance. Significance is the value to whose multiple of ten the value is to be rounded up (.01, .1, 1, 10, etc.)',
s_fdef_FLOOR:
'Rounds the given number down to the nearest multiple of significance. Significance is the value to whose multiple of ten the number is to be rounded down (.01, .1, 1, 10, etc.)',
s_farg_v: 'value',
s_farg_vn: 'value1, value2, ...',
s_farg_xy: 'valueX, valueY',
s_farg_choose: 'index, value1, value2, ...',
s_farg_range: 'range',
s_farg_rangec: 'range, criteria',
s_farg_date: 'year, month, day',
s_farg_dfunc: 'databaserange, fieldname, criteriarange',
s_farg_ddb: 'cost, salvage, lifetime, period, [factor]',
s_farg_find: 'string1, string2, [start]',
s_farg_fv: 'rate, n, payment, [pv, [paytype]]',
s_farg_hlookup: 'value, range, row, [rangelookup]',
s_farg_iffunc: 'logical-expression, true-value, [false-value]',
s_farg_index: 'range, rownum, colnum',
s_farg_irr: 'range, [guess]',
s_farg_tc: 'text, count',
s_farg_log: 'value, base',
s_farg_match: 'value, range, [rangelookup]',
s_farg_mid: 'text, start, length',
s_farg_nper: 'rate, payment, pv, [fv, [paytype]]',
s_farg_npv: 'rate, value1, value2, ...',
s_farg_pmt: 'rate, n, pv, [fv, [paytype]]',
s_farg_pv: 'rate, n, payment, [fv, [paytype]]',
s_farg_rate: 'n, payment, pv, [fv, [paytype, [guess]]]',
s_farg_replace: 'text1, start, length, text2',
s_farg_vp: 'value, [precision]',
s_farg_valpre: 'value, precision',
s_farg_csl: 'cost, salvage, lifetime',
s_farg_cslp: 'cost, salvage, lifetime, period',
s_farg_subs: 'text1, oldtext, newtext, [occurrence]',
s_farg_sumif: 'range1, criteria, [range2]',
s_farg_hms: 'hour, minute, second',
s_farg_txt: 'text',
s_farg_vlookup: 'value, range, col, [rangelookup]',
s_farg_weekday: 'date, [type]',
s_farg_dt: 'date',
s_farg_rangen: 'range1, range2, ...',
s_farg_vsig: 'value, [significance]',
function_classlist: [
'all',
'stat',
'lookup',
'datetime',
'financial',
'test',
'math',
'text',
'gui',
'action',
],
s_fclass_all: 'All',
s_fclass_stat: 'Statistics',
s_fclass_lookup: 'Lookup',
s_fclass_datetime: 'Date & Time',
s_fclass_financial: 'Financial',
s_fclass_test: 'Test',
s_fclass_math: 'Math',
s_fclass_text: 'Text',
s_fclass_action: 'Email & Copy',
s_fclass_gui: 'Button & Input',
lastone: null,
};
ConstantsRoot.ConstantsDefaultClasses = {
defaultComment: '',
defaultCommentNoGrid: '',
defaultHighlightTypeCursor: '',
defaultHighlightTypeRange: '',
defaultColname: '',
defaultSelectedColname: '',
defaultRowname: '',
defaultSelectedRowname: '',
defaultUpperLeft: '',
defaultSkippedCell: '',
defaultPaneDivider: '',
cteGriddiv: '',
defaultInputEcho: {
classname: '',
style: 'filter:alpha(opacity=90);opacity:.9;',
},
TCmain: '',
TCendcap: '',
TCpaneslider: '',
TClessbutton: '',
TCmorebutton: '',
TCscrollarea: '',
TCthumb: '',
TCPStrackingline: '',
TCTDFSthumbstatus: '',
TDpopupElement: '',
};
ConstantsRoot.ConstantsSetClasses = function (prefix) {
var defaults = SocialCalc.ConstantsDefaultClasses;
var scc = SocialCalc.Constants;
var item;
prefix = prefix || '';
for (item in defaults) {
if (typeof defaults[item] == 'string') {
scc[item + 'Class'] = prefix + (defaults[item] || item);
if (scc[item + 'Style'] !== undefined) {
scc[item + 'Style'] = '';
}
} else if (typeof defaults[item] == 'object') {
scc[item + 'Class'] = prefix + (defaults[item].classname || item);
scc[item + 'Style'] = defaults[item].style;
}
}
};
ConstantsRoot.ConstantsSetImagePrefix = function (imagePrefix) {
var scc = SocialCalc.Constants;
var oldPrefix = scc.defaultImagePrefix;
var oldHyphen = oldPrefix.endsWith('_') ? oldPrefix.slice(0, -1) + '-' : oldPrefix;
var newHyphen = imagePrefix.endsWith('_') ? imagePrefix.slice(0, -1) + '-' : imagePrefix;
for (var item in scc) {
if (typeof scc[item] == 'string') {
var s = scc[item];
if (oldPrefix) {
s = s.split(oldPrefix).join(imagePrefix);
}
if (oldHyphen && oldHyphen !== oldPrefix) {
s = s.split(oldHyphen).join(newHyphen);
}
scc[item] = s;
}
}
scc.defaultImagePrefix = imagePrefix;
};
// In-place TypeScript conversion of socialcalc-3.js (SocialCalc global script).
// Ambient API types live in socialcalc-3.d.ts (referenced by dist/SocialCalc.d.ts).
// Vite+ strips types with Oxc before UMD concat — no runtime tax.
// Typechecked core after removing @ts-nocheck.
// The main SocialCalc code module of the SocialCalc package
//
/*
// (c) Copyright 2010 Socialtext, Inc.
// All Rights Reserved.
//
// The contents of this file are subject to the Artistic License 2.0; you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at http://socialcalc.org/licenses/al-20/.
//
// Some of the other files in the SocialCalc package are licensed under
// different licenses. Please note the licenses of the modules you use.
//
// Code History:
//
// Initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc.
// Based in part on the SocialCalc 1.1.0 code written in Perl.
// The SocialCalc 1.1.0 code was:
// Portions (c) Copyright 2005, 2006, 2007 Software Garden, Inc.
// All Rights Reserved.
// Portions (c) Copyright 2007 Socialtext, Inc.
// All Rights Reserved.
// The Perl SocialCalc started as modifications to the wikiCalc(R) program, version 1.0.
// wikiCalc 1.0 was written by Software Garden, Inc.
// Unless otherwise specified, referring to "SocialCalc" in comments refers to this
// JavaScript version of the code, not the SocialCalc Perl code.
//
*/
// Mutable progressive-init bridges for ambient nested namespaces.
/*
**** Overview ****
This is the beginning of a library of routines for displaying and editing spreadsheet
data in a browser. The HTML that includes this does not need to have anything
specific to the spreadsheet or editor already present -- everything is dynamically
added to the DOM by this code, including the rendered sheet and any editing controls.
The library has a few parts. This is the main SocialCalc code module.
Other parts are the Table Editor module, the Formula module, and the Format Number module.
Note: The Table Editor module is licensed under a different license than this module.
The class/object style is derived from O'Reilly's JavaScript by Flanagan, 5th Edition,
section 9.3, page 157.
All of the data, object definitions, functions, etc., are stored as properties of the SocialCalc
object so as not to clutter up the global variables nor conflict with other names.
A design goal (not tested yet for success) is to make it possible to have more than one
spreadsheet active on a page, perhaps even open for editing. It is assumed, though, that
there is only one mouse and one keyboard (a good assumption on most PCs today but not in the
new "touch and surface world" Apple and Microsoft are working towards).
The testing has been on Windows Firefox (2 and 3),
Internet Explorer (6 and 7), Opera (9.23 and mainly later), Mac Safari (3.1), and Mac Firefox (2.0.0.6).
There are small issues with Firefox before 2.0 (cosmetic with drag handles) and larger ones
with Opera before 9.5 (the Delete key isn't recognized in some cases -- the 9.5 version was still
in beta and this bug affects other products like GMail, I believe).
The data is stored in a SocialCalc.Sheet object. The data is organized in a form similar to that
used by SocialCalc 1.1.0. There is a function for converting a normal SocialCalc spreadsheet
save data string (the spreadsheet part of a SocialCalc data file) into this internal form.
The SocialCalc.RenderContext class provides methods for rendering a table into the DOM representing
part of the spreadsheet. It is assumed that the spreadsheet could possibly be very large
and that rendering the whole thing at once could be too time consuming. It is also set up so
that it might be possible to have some of the sheet data only be loaded on demand (such as by Ajax).
The rendering can render cells to the right and below the already active area of the spreadsheet
so that you can scroll to that "clean" area without explicitly doing "add row/column". The class also
does simple operations such as "scrolling" within that table. The table may optionally include
row and column headers and may be split into panes. Most of the code assumes any number of panes,
but only the rightmost pane has scrolling code. In normal operation there would be one or two
panes horizontally and vertically. The panes may start on any row/column, though a given row/column
should only appear in one pane at a time (not all code enforces this, yet).
The RenderContext is designed to be rendered as part of a SocialCalc.TableEditor. The TableEditor
includes the spreadsheet grid as well as scrollbars, pane sliders, and (eventually) editing controls.
The layout is dynamic and may be recomputed on the fly, such as in response to resizing the browser
window.
The scrollbars and pane sliders are created using SocialCalc.TableControl objects. These in turn
make use of Dragging, ToolTip, Button, and MouseWheel functions.
The keyboard input is handled by keyboard code.
There are also some helper routines.
More comments yet to come...
*/
// SocialCalc is always defined by socialcalcconstants.js (which concatenates
// before this file in the UMD bundle). Redundant `if (!SocialCalc)` guard
// removed.
const SC = SocialCalc;
const defaultSecurityPolicy = {
sanitizeHtml: null,
allowedUrlSchemes: ['http:', 'https:', 'mailto:'],
allowedDataMimeTypes: [],
};
SC.Callbacks = {
expand_wiki: null,
expand_markup: function (displayvalue, sheetobj, linkstyle) {
return SocialCalc.default_expand_markup(displayvalue, sheetobj, linkstyle);
},
MakePageLink: null,
NormalizeSheetName: null,
untrustedContent: false,
securityPolicy: defaultSecurityPolicy,
};
SC.Cell = function (coord) {
this.coord = coord;
this.datavalue = '';
this.datatype = null;
this.formula = '';
this.valuetype = 'b';
this.readonly = false;
};
SC.CellProperties = {
coord: 1,
datavalue: 1,
datatype: 1,
formula: 1,
valuetype: 1,
errors: 1,
comment: 1,
readonly: 1,
bt: 2,
br: 2,
bb: 2,
bl: 2,
layout: 2,
font: 2,
color: 2,
bgcolor: 2,
cellformat: 2,
nontextvalueformat: 2,
textvalueformat: 2,
colspan: 2,
rowspan: 2,
cssc: 2,
csss: 2,
mod: 2,
displaystring: 3,
parseinfo: 3,
hcolspan: 3,
hrowspan: 3,
};
SC.CellPropertiesTable = {
bt: 'borderstyle',
br: 'borderstyle',
bb: 'borderstyle',
bl: 'borderstyle',
layout: 'layout',
font: 'font',
color: 'color',
bgcolor: 'color',
cellformat: 'cellformat',
nontextvalueformat: 'valueformat',
textvalueformat: 'valueformat',
};
SC.Sheet = function () {
SocialCalc.ResetSheet(this);
this.statuscallback = null;
this.statuscallbackparams = null;
};
SC.ResetSheet = function (sheet, _reload) {
sheet.cells = {};
sheet.attribs = {
lastcol: 1,
lastrow: 1,
defaultlayout: 0,
usermaxcol: 0,
usermaxrow: 0,
};
sheet.rowattribs = {
hide: {},
height: {},
};
sheet.colattribs = {
width: {},
hide: {},
};
sheet.names = {};
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.matched_cells = [];
sheet.selected_search_cell = undefined;
sheet.copiedfrom = '';
sheet.changes = new SocialCalc.UndoStack();
sheet.renderneeded = false;
sheet.changedrendervalues = true;
sheet.recalcchangedavalue = false;
sheet.hiddencolrow = '';
sheet.sci = new SocialCalc.SheetCommandInfo(sheet);
sheet.ioEventTree = {};
sheet.ioParameterList = {};
};
SC.Sheet.prototype.ResetSheet = function () {
SocialCalc.ResetSheet(this);
};
SC.Sheet.prototype.AddCell = function (newcell) {
return (this.cells[newcell.coord] = newcell);
};
SC.Sheet.prototype.LastCol = function () {
var last_col = 1;
for (var cell_id in this.cells) {
var cr = SocialCalc.coordToCr(cell_id);
if (cr.col > last_col) {
last_col = cr.col;
}
}
return last_col;
};
SC.Sheet.prototype.LastRow = function () {
var last_row = 1;
for (var cell_id in this.cells) {
var cr = SocialCalc.coordToCr(cell_id);
if (cr.row > last_row) {
last_row = cr.row;
}
}
return last_row;
};
SC.Sheet.prototype.GetAssuredCell = function (coord) {
return this.cells[coord] || this.AddCell(new SocialCalc.Cell(coord));
};
SC.Sheet.prototype.ParseSheetSave = function (savedsheet) {
SocialCalc.ParseSheetSave(savedsheet, this);
};
SC.Sheet.prototype.CellFromStringParts = function (cell, parts, j) {
return SocialCalc.CellFromStringParts(this, cell, parts, j);
};
SC.Sheet.prototype.CreateSheetSave = function (range, canonicalize) {
return SocialCalc.CreateSheetSave(this, range, canonicalize);
};
SC.Sheet.prototype.CellToString = function (cell) {
return SocialCalc.CellToString(this, cell);
};
SC.Sheet.prototype.CanonicalizeSheet = function (full) {
return SocialCalc.CanonicalizeSheet(this, full);
};
SC.Sheet.prototype.EncodeCellAttributes = function (coord) {
return SocialCalc.EncodeCellAttributes(this, coord);
};
SC.Sheet.prototype.EncodeSheetAttributes = function () {
return SocialCalc.EncodeSheetAttributes(this);
};
SC.Sheet.prototype.DecodeCellAttributes = function (coord, attribs, range) {
return SocialCalc.DecodeCellAttributes(this, coord, attribs, range);
};
SC.Sheet.prototype.DecodeSheetAttributes = function (attribs) {
return SocialCalc.DecodeSheetAttributes(this, attribs);
};
SC.Sheet.prototype.ScheduleSheetCommands = function (cmd, saveundo) {
return SocialCalc.ScheduleSheetCommands(this, cmd, saveundo);
};
SC.Sheet.prototype.SheetUndo = function () {
return SocialCalc.SheetUndo(this);
};
SC.Sheet.prototype.SheetRedo = function () {
return SocialCalc.SheetRedo(this);
};
SC.Sheet.prototype.CreateAuditString = function () {
return SocialCalc.CreateAuditString(this);
};
SC.Sheet.prototype.GetStyleNum = function (atype, style) {
return SocialCalc.GetStyleNum(this, atype, style);
};
SC.Sheet.prototype.GetStyleString = function (atype, num) {
return SocialCalc.GetStyleString(this, atype, num);
};
SC.Sheet.prototype.RecalcSheet = function () {
return SocialCalc.RecalcSheet(this);
};
SC.ParseSheetSave = function (savedsheet, sheetobj) {
var lines = savedsheet.split(/\r\n|\n/);
var parts = [];
var line;
var i;
var j;
var t;
var v;
var coord;
var cell;
var attribs;
var 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++];
break;
case 'hide':
sheetobj.colattribs.hide[coord] = parts[j++];
break;
default:
throw scc.s_pssUnknownColType + " '" + t + "'";
}
}
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;
case 'sheet':
attribs = sheetobj.attribs;
j = 1;
while ((t = parts[j++])) {
switch (t) {
case 'c':
attribs.lastcol = parts[j++] - 0;
break;
case 'r':
attribs.lastrow = parts[j++] - 0;
break;
case 'w':
attribs.defaultcolwidth = parts[j++] + '';
break;
case 'h':
attribs.defaultrowheight = parts[j++] - 0;
break;
case 'tf':
attribs.defaulttextformat = parts[j++] - 0;
break;
case 'ntf':
attribs.defaultnontextformat = parts[j++] - 0;
break;
case 'layout':
attribs.defaultlayout = parts[j++] - 0;
break;
case 'font':
attribs.defaultfont = parts[j++] - 0;
break;
case 'tvf':
attribs.defaulttextvalueformat = parts[j++] - 0;
break;
case 'ntvf':
attribs.defaultnontextvalueformat = parts[j++] - 0;
break;
case 'color':
attribs.defaultcolor = parts[j++] - 0;
break;
case 'bgcolor':
attribs.defaultbgcolor = parts[j++] - 0;
break;
case 'circularreferencecell':
attribs.circularreferencecell = parts[j++];
break;
case 'recalc':
attribs.recalc = parts[j++];
break;
case 'needsrecalc':
attribs.needsrecalc = parts[j++];
break;
case 'usermaxcol':
attribs.usermaxcol = parts[j++] - 0;
break;
case 'usermaxrow':
attribs.usermaxrow = parts[j++] - 0;
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+):(.+)$/);
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':
case 'clipboard':
break;
case '':
break;
default:
(function(){})(scc.s_pssUnknownLineType + " '" + parts[0] + "'");
throw scc.s_pssUnknownLineType + " '" + parts[0] + "'";
}
parts = null;
}
};
SC.CellFromStringParts = function (sheet, cell, parts, j) {
var t, v, ro;
while ((t = parts[j++])) {
switch (t) {
case 'v':
cell.datavalue = +SocialCalc.decodeFromSave(parts[j++]);
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++]);
} 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++]);
} else {
cell.datavalue = SocialCalc.decodeFromSave(parts[j++]);
}
cell.formula = SocialCalc.decodeFromSave(parts[j++]);
cell.datatype = 'f';
break;
case 'vtc':
v = parts[j++];
cell.valuetype = v;
if (v.charAt(0) == 'n') {
cell.datavalue = +SocialCalc.decodeFromSave(parts[j++]);
} else {
cell.datavalue = SocialCalc.decodeFromSave(parts[j++]);
}
cell.formula = SocialCalc.decodeFromSave(parts[j++]);
cell.datatype = 'c';
break;
case 'ro':
ro = SocialCalc.decodeFromSave(parts[j++]);
cell.readonly = ro.toLowerCase() == 'yes';
break;
case 'e':
cell.errors = SocialCalc.decodeFromSave(parts[j++]);
break;
case 'b':
cell.bt = parts[j++] - 0;
cell.br = parts[j++] - 0;
cell.bb = parts[j++] - 0;
cell.bl = parts[j++] - 0;
break;
case 'l':
cell.layout = parts[j++] - 0;
break;
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 + "'";
}
}
};
SC.sheetfields = [
'defaultrowheight',
'defaultcolwidth',
'circularreferencecell',
'recalc',
'needsrecalc',
'usermaxcol',
'usermaxrow',
];
SC.sheetfieldsshort = [
'h',
'w',
'circularreferencecell',
'recalc',
'needsrecalc',
'usermaxcol',
'usermaxrow',
];
SC.sheetfieldsxlat = [
'defaulttextformat',
'defaultnontextformat',
'defaulttextvalueformat',
'defaultnontextvalueformat',
'defaultcolor',
'defaultbgcolor',
'defaultfont',
'defaultlayout',
];
SC.sheetfieldsxlatshort = ['tf', 'ntf', 'tvf', 'ntvf', 'color', 'bgcolor', 'font', 'layout'];
SC.sheetfieldsxlatxlt = [
'cellformat',
'cellformat',
'valueformat',
'valueformat',
'color',
'color',
'font',
'layout',
];
SC.CreateSheetSave = function (sheetobj, range, canonicalize) {
var cell, cr1, cr2, row, col, coord, line, value, i, name;
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;
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++) {
value = SocialCalc.encodeForSave(sheetobj.attribs[SocialCalc.sheetfields[i]]);
if (value) line += ':' + SocialCalc.sheetfieldsshort[i] + ':' + value;
}
for (i = 0; i < SocialCalc.sheetfieldsxlat.length; i++) {
value = sheetobj.attribs[SocialCalc.sheetfieldsxlat[i]];
if (value)
line +=
':' +
SocialCalc.sheetfieldsxlatshort[i] +
':' +
xlt[SocialCalc.sheetfieldsxlatxlt[i] + 'sxlat'][value];
}
result.push(line);
for (i = 1; i < xlt.newborderstyles.length; i++) {
result.push('border:' + i + ':' + xlt.newborderstyles[i]);
}
for (i = 1; i < xlt.newcellformats.length; i++) {
result.push('cellformat:' + i + ':' + SocialCalc.encodeForSave(xlt.newcellformats[i]));
}
for (i = 1; i < xlt.newcolors.length; i++) {
result.push('color:' + i + ':' + xlt.newcolors[i]);
}
for (i = 1; i < xlt.newfonts.length; i++) {
result.push('font:' + i + ':' + xlt.newfonts[i]);
}
for (i = 1; i < xlt.newlayouts.length; i++) {
result.push('layout:' + i + ':' + xlt.newlayouts[i]);
}
for (i = 1; i < xlt.newvalueformats.length; i++) {
result.push('valueformat:' + i + ':' + SocialCalc.encodeForSave(xlt.newvalueformats[i]));
}
for (i = 0; i < xlt.namesorder.length; i++) {
name = xlt.namesorder[i];
result.push(
'name:' +
SocialCalc.encodeForSave(name).toUpperCase() +
':' +
SocialCalc.encodeForSave(sheetobj.names[name].desc) +
':' +
SocialCalc.encodeForSave(sheetobj.names[name].definition),
);
}
if (range) {
result.push(
'copiedfrom:' +
SocialCalc.crToCoord(cr1.col, cr1.row) +
':' +
SocialCalc.crToCoord(cr2.col, cr2.row),
);
}
result.push('');
delete sheetobj.xlt;
return result.join('\n');
};
SC.CellToString = function (sheet, cell) {
var line, value, formula, t, r, b, l, xlt;
line = '';
if (!cell) return line;
value = SocialCalc.encodeForSave(cell.datavalue);
if (cell.datatype == 'v') {
if (cell.valuetype == 'n') line += ':v:' + value;
else line += ':vt:' + cell.valuetype + ':' + value;
} else if (cell.datatype == 't') {
if (cell.valuetype == SocialCalc.Constants.textdatadefaulttype) line += ':t:' + value;
else line += ':vt:' + cell.valuetype + ':' + value;
} else {
formula = SocialCalc.encodeForSave(cell.formula);
if (cell.datatype == 'f') {
line += ':vtf:' + cell.valuetype + ':' + value + ':' + formula;
} else if (cell.datatype == 'c') {
line += ':vtc:' + cell.valuetype + ':' + value + ':' + formula;
}
}
if (cell.readonly) {
line += ':ro:yes';
}
if (cell.errors) {
line += ':e:' + SocialCalc.encodeForSave(cell.errors);
}
t = cell.bt || '';
r = cell.br || '';
b = cell.bb || '';
l = cell.bl || '';
if (sheet.xlt) {
xlt = sheet.xlt;
if (t || r || b || l)
line +=
':b:' +
xlt.borderstylesxlat[t || 0] +
':' +
xlt.borderstylesxlat[r || 0] +
':' +
xlt.borderstylesxlat[b || 0] +
':' +
xlt.borderstylesxlat[l || 0];
if (cell.layout) line += ':l:' + xlt.layoutsxlat[cell.layout];
if (cell.font) line += ':f:' + xlt.fontsxlat[cell.font];
if (cell.color) line += ':c:' + xlt.colorsxlat[cell.color];
if (cell.bgcolor) line += ':bg:' + xlt.colorsxlat[cell.bgcolor];
if (cell.cellformat) line += ':cf:' + xlt.cellformatsxlat[cell.cellformat];
if (cell.textvalueformat) line += ':tvf:' + xlt.valueformatsxlat[cell.textvalueformat];
if (cell.nontextvalueformat) line += ':ntvf:' + xlt.valueformatsxlat[cell.nontextvalueformat];
} else {
if (t || r || b || l) line += ':b:' + t + ':' + r + ':' + b + ':' + l;
if (cell.layout) line += ':l:' + cell.layout;
if (cell.font) line += ':f:' + cell.font;
if (cell.color) line += ':c:' + cell.color;
if (cell.bgcolor) line += ':bg:' + cell.bgcolor;
if (cell.cellformat) line += ':cf:' + cell.cellformat;
if (cell.textvalueformat) line += ':tvf:' + cell.textvalueformat;
if (cell.nontextvalueformat) line += ':ntvf:' + cell.nontextvalueformat;
}
if (cell.colspan) line += ':colspan:' + cell.colspan;
if (cell.rowspan) line += ':rowspan:' + cell.rowspan;
if (cell.cssc) line += ':cssc:' + cell.cssc;
if (cell.csss) line += ':csss:' + SocialCalc.encodeForSave(cell.csss);
if (cell.mod) line += ':mod:' + cell.mod;
if (cell.comment) line += ':comment:' + SocialCalc.encodeForSave(cell.comment);
return line;
};
SC.CanonicalizeSheet = function (sheetobj, full) {
var l;
var coord;
var cr;
var cell;
var filled;
var an;
var a;
var newa;
var newxlat;
var used;
var ahash;
var i;
var v;
var maxrow = 0;
var maxcol = 0;
var alist = ['borderstyle', 'cellformat', 'color', 'font', 'layout', 'valueformat'];
var xlt = {};
xlt.namesorder = [];
for (a in sheetobj.names) {
xlt.namesorder.push(a);
}
xlt.namesorder.sort();
if (!SocialCalc.Constants.doCanonicalizeSheet || !full) {
for (an = 0; an < alist.length; an++) {
a = alist[an];
xlt['new' + a + 's'] = sheetobj[a + 's'];
l = sheetobj[a + 's'].length;
newxlat = Array.from({ length: l });
newxlat[0] = '';
for (i = 1; i < l; i++) {
newxlat[i] = i;
}
xlt[a + 'sxlat'] = newxlat;
}
xlt.maxrow = sheetobj.attribs.lastrow;
xlt.maxcol = sheetobj.attribs.lastcol;
sheetobj.xlt = xlt;
return;
}
for (an = 0; an < alist.length; an++) {
a = alist[an];
xlt[a + 'sUsed'] = {};
}
var colorsUsed = xlt.colorsUsed;
var borderstylesUsed = xlt.borderstylesUsed;
var fontsUsed = xlt.fontsUsed;
var layoutsUsed = xlt.layoutsUsed;
var cellformatsUsed = xlt.cellformatsUsed;
var valueformatsUsed = xlt.valueformatsUsed;
for (coord in sheetobj.cells) {
cr = SocialCalc.coordToCr(coord);
cell = sheetobj.cells[coord];
filled = false;
if (cell.valuetype && cell.valuetype != 'b') filled = true;
if (cell.color) {
colorsUsed[cell.color] = 1;
filled = true;
}
if (cell.bgcolor) {
colorsUsed[cell.bgcolor] = 1;
filled = true;
}
if (cell.bt) {
borderstylesUsed[cell.bt] = 1;
filled = true;
}
if (cell.br) {
borderstylesUsed[cell.br] = 1;
filled = true;
}
if (cell.bb) {
borderstylesUsed[cell.bb] = 1;
filled = true;
}
if (cell.bl) {
borderstylesUsed[cell.bl] = 1;
filled = true;
}
if (cell.layout) {
layoutsUsed[cell.layout] = 1;
filled = true;
}
if (cell.font) {
fontsUsed[cell.font] = 1;
filled = true;
}
if (cell.cellformat) {
cellformatsUsed[cell.cellformat] = 1;
filled = true;
}
if (cell.textvalueformat) {
valueformatsUsed[cell.textvalueformat] = 1;
filled = true;
}
if (cell.nontextvalueformat) {
valueformatsUsed[cell.nontextvalueformat] = 1;
filled = true;
}
if (filled) {
if (cr.row > maxrow) maxrow = cr.row;
if (cr.col > maxcol) maxcol = cr.col;
}
}
for (i = 0; i < SocialCalc.sheetfieldsxlat.length; i++) {
v = sheetobj.attribs[SocialCalc.sheetfieldsxlat[i]];
if (v) {
xlt[SocialCalc.sheetfieldsxlatxlt[i] + 'sUsed'][v] = 1;
}
}
a = {
height: 1,
hide: 1,
};
for (v in a) {
for (cr in sheetobj.rowattribs[v]) {
if (cr - 0 > maxrow) maxrow = cr - 0;
}
}
a = {
hide: 1,
width: 1,
};
for (v in a) {
for (coord in sheetobj.colattribs[v]) {
cr = SocialCalc.coordToCr(coord + '1');
if (cr.col > maxcol) maxcol = cr.col;
}
}
for (an = 0; an < alist.length; an++) {
a = alist[an];
newa = [];
used = xlt[a + 'sUsed'];
for (v in used) {
newa.push(sheetobj[a + 's'][v]);
}
newa.sort();
newa.unshift('');
newxlat = [''];
ahash = sheetobj[a + 'hash'];
for (i = 1; i < newa.length; i++) {
newxlat[ahash[newa[i]]] = i;
}
xlt[a + 'sxlat'] = newxlat;
xlt['new' + a + 's'] = newa;
}
xlt.maxrow = maxrow || 1;
xlt.maxcol = maxcol || 1;
sheetobj.xlt = xlt;
};
SC.EncodeCellAttributes = function (sheet, coord) {
var i, b, bb, parts;
var result = {};
var InitAttrib = function (name) {
result[name] = {
def: true,
val: '',
};
};
var InitAttribs = function (namelist) {
for (var i = 0; i < namelist.length; i++) {
InitAttrib(namelist[i]);
}
};
var SetAttrib = function (name, v) {
result[name].def = false;
result[name].val = v || '';
};
var SetAttribStar = function (name, v) {
if (v == '*') return;
result[name].def = false;
result[name].val = v;
};
var cell = sheet.GetAssuredCell(coord);
InitAttrib('alignhoriz');
if (cell.cellformat) {
SetAttrib('alignhoriz', sheet.cellformats[cell.cellformat]);
}
InitAttribs(['alignvert', 'padtop', 'padright', 'padbottom', 'padleft']);
if (cell.layout) {
parts = sheet.layouts[cell.layout].match(
/^padding:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+);vertical-align:\s*(\S+);/,
);
SetAttribStar('padtop', parts[1]);
SetAttribStar('padright', parts[2]);
SetAttribStar('padbottom', parts[3]);
SetAttribStar('padleft', parts[4]);
SetAttribStar('alignvert', parts[5]);
}
InitAttribs(['fontfamily', 'fontlook', 'fontsize']);
if (cell.font) {
parts = sheet.fonts[cell.font].match(/^(\*|\S+? \S+?) (\S+?) (\S.*)$/);
SetAttribStar('fontfamily', parts[3]);
SetAttribStar('fontsize', parts[2]);
SetAttribStar('fontlook', parts[1]);
}
InitAttrib('textcolor');
if (cell.color) {
SetAttrib('textcolor', sheet.colors[cell.color]);
}
InitAttrib('bgcolor');
if (cell.bgcolor) {
SetAttrib('bgcolor', sheet.colors[cell.bgcolor]);
}
InitAttribs(['numberformat', 'textformat']);
if (cell.nontextvalueformat) {
SetAttrib('numberformat', sheet.valueformats[cell.nontextvalueformat]);
}
if (cell.textvalueformat) {
SetAttrib('textformat', sheet.valueformats[cell.textvalueformat]);
}
InitAttribs(['colspan', 'rowspan']);
SetAttrib('colspan', cell.colspan || 1);
SetAttrib('rowspan', cell.rowspan || 1);
for (i = 0; i < 4; i++) {
b = 'trbl'.charAt(i);
bb = 'b' + b;
InitAttrib(bb);
SetAttrib(bb, cell[bb] ? sheet.borderstyles[cell[bb]] : '');
InitAttrib(bb + 'thickness');
InitAttrib(bb + 'style');
InitAttrib(bb + 'color');
if (cell[bb]) {
parts = sheet.borderstyles[cell[bb]].match(/(\S+)\s+(\S+)\s+(\S.+)/);
SetAttrib(bb + 'thickness', parts[1]);
SetAttrib(bb + 'style', parts[2]);
SetAttrib(bb + 'color', parts[3]);
}
}
InitAttribs(['cssc', 'csss', 'mod']);
SetAttrib('cssc', cell.cssc || '');
SetAttrib('csss', cell.csss || '');
SetAttrib('mod', cell.mod || 'n');
return result;
};
SC.EncodeSheetAttributes = function (sheet) {
var value = undefined;
var parts;
var attribs = sheet.attribs;
var result = {};
var InitAttrib = function (name) {
result[name] = {
def: true,
val: '',
};
};
var InitAttribs = function (namelist) {
for (var i = 0; i < namelist.length; i++) {
InitAttrib(namelist[i]);
}
};
var SetAttrib = function (name, v) {
result[name].def = false;
result[name].val = v || value;
};
var SetAttribStar = function (name, v) {
if (v == '*') return;
result[name].def = false;
result[name].val = v;
};
InitAttrib('colwidth');
if (attribs.defaultcolwidth) {
SetAttrib('colwidth', attribs.defaultcolwidth);
}
InitAttrib('rowheight');
InitAttrib('textalignhoriz');
if (attribs.defaulttextformat) {
SetAttrib('textalignhoriz', sheet.cellformats[attribs.defaulttextformat]);
}
InitAttrib('numberalignhoriz');
if (attribs.defaultnontextformat) {
SetAttrib('numberalignhoriz', sheet.cellformats[attribs.defaultnontextformat]);
}
InitAttribs(['alignvert', 'padtop', 'padright', 'padbottom', 'padleft']);
if (attribs.defaultlayout) {
parts = sheet.layouts[attribs.defaultlayout].match(
/^padding:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+);vertical-align:\s*(\S+);/,
);
SetAttribStar('padtop', parts[1]);
SetAttribStar('padright', parts[2]);
SetAttribStar('padbottom', parts[3]);
SetAttribStar('padleft', parts[4]);
SetAttribStar('alignvert', parts[5]);
}
InitAttribs(['fontfamily', 'fontlook', 'fontsize']);
if (attribs.defaultfont) {
parts = sheet.fonts[attribs.defaultfont].match(/^(\*|\S+? \S+?) (\S+?) (\S.*)$/);
SetAttribStar('fontfamily', parts[3]);
SetAttribStar('fontsize', parts[2]);
SetAttribStar('fontlook', parts[1]);
}
InitAttrib('textcolor');
if (attribs.defaultcolor) {
SetAttrib('textcolor', sheet.colors[attribs.defaultcolor]);
}
InitAttrib('bgcolor');
if (attribs.defaultbgcolor) {
SetAttrib('bgcolor', sheet.colors[attribs.defaultbgcolor]);
}
InitAttribs(['numberformat', 'textformat']);
if (attribs.defaultnontextvalueformat) {
SetAttrib('numberformat', sheet.valueformats[attribs.defaultnontextvalueformat]);
}
if (attribs.defaulttextvalueformat) {
SetAttrib('textformat', sheet.valueformats[attribs.defaulttextvalueformat]);
}
InitAttrib('recalc');
if (attribs.recalc) {
SetAttrib('recalc', attribs.recalc);
}
InitAttrib('usermaxcol');
if (attribs.usermaxcol) {
SetAttrib('usermaxcol', attribs.usermaxcol);
}
InitAttrib('usermaxrow');
if (attribs.usermaxrow) {
SetAttrib('usermaxrow', attribs.usermaxrow);
}
return result;
};
SC.DecodeCellAttributes = function (sheet, coord, newattribs, range) {
var value, b, bb, i;
var cell = sheet.GetAssuredCell(coord);
var changed = false;
var CheckChanges = function (attribname, oldval, cmdname) {
var val;
if (newattribs[attribname]) {
if (newattribs[attribname].def) {
val = '';
} else {
val = newattribs[attribname].val;
}
if (val != (oldval || '')) {
DoCmd(cmdname + ' ' + val);
}
}
};
var cmdstr = '';
var DoCmd = function (str) {
if (cmdstr) cmdstr += '\n';
cmdstr += 'set ' + (range || coord) + ' ' + str;
changed = true;
};
CheckChanges('alignhoriz', sheet.cellformats[cell.cellformat], 'cellformat');
if (
!newattribs.alignvert.def ||
!newattribs.padtop.def ||
!newattribs.padright.def ||
!newattribs.padbottom.def ||
!newattribs.padleft.def
) {
value =
'padding:' +
(newattribs.padtop.def ? '* ' : newattribs.padtop.val + ' ') +
(newattribs.padright.def ? '* ' : newattribs.padright.val + ' ') +
(newattribs.padbottom.def ? '* ' : newattribs.padbottom.val + ' ') +
(newattribs.padleft.def ? '*' : newattribs.padleft.val) +
';vertical-align:' +
(newattribs.alignvert.def ? '*;' : newattribs.alignvert.val + ';');
} else {
value = '';
}
if (value != (sheet.layouts[cell.layout] || '')) {
DoCmd('layout ' + value);
}
if (!newattribs.fontlook.def || !newattribs.fontsize.def || !newattribs.fontfamily.def) {
value =
(newattribs.fontlook.def ? '* ' : newattribs.fontlook.val + ' ') +
(newattribs.fontsize.def ? '* ' : newattribs.fontsize.val + ' ') +
(newattribs.fontfamily.def ? '*' : newattribs.fontfamily.val);
} else {
value = '';
}
if (value != (sheet.fonts[cell.font] || '')) {
DoCmd('font ' + value);
}
CheckChanges('textcolor', sheet.colors[cell.color], 'color');
CheckChanges('bgcolor', sheet.colors[cell.bgcolor], 'bgcolor');
CheckChanges('numberformat', sheet.valueformats[cell.nontextvalueformat], 'nontextvalueformat');
CheckChanges('textformat', sheet.valueformats[cell.textvalueformat], 'textvalueformat');
for (i = 0; i < 4; i++) {
b = 'trbl'.charAt(i);
bb = 'b' + b;
CheckChanges(bb, sheet.borderstyles[cell[bb]], bb);
}
CheckChanges('cssc', cell.cssc, 'cssc');
CheckChanges('csss', cell.csss, 'csss');
if (newattribs.mod) {
if (newattribs.mod.def) {
value = 'n';
} else {
value = newattribs.mod.val;
}
if (value != (cell.mod || 'n')) {
if (value == 'n') value = '';
DoCmd('mod ' + value);
}
}
if (changed) {
return cmdstr;
} else {
return null;
}
};
SC.DecodeSheetAttributes = function (sheet, newattribs) {
var value;
var attribs = sheet.attribs;
var changed = false;
var CheckChanges = function (attribname, oldval, cmdname) {
var val;
if (newattribs[attribname]) {
if (newattribs[attribname].def) {
val = '';
} else {
val = newattribs[attribname].val;
}
if (val != (oldval || '')) {
DoCmd(cmdname + ' ' + val);
}
}
};
var cmdstr = '';
var DoCmd = function (str) {
if (cmdstr) cmdstr += '\n';
cmdstr += 'set sheet ' + str;
changed = true;
};
CheckChanges('colwidth', attribs.defaultcolwidth, 'defaultcolwidth');
CheckChanges('rowheight', attribs.defaultrowheight, 'defaultrowheight');
CheckChanges(
'textalignhoriz',
sheet.cellformats[attribs.defaulttextformat],
'defaulttextformat',
);
CheckChanges(
'numberalignhoriz',
sheet.cellformats[attribs.defaultnontextformat],
'defaultnontextformat',
);
if (
!newattribs.alignvert.def ||
!newattribs.padtop.def ||
!newattribs.padright.def ||
!newattribs.padbottom.def ||
!newattribs.padleft.def
) {
value =
'padding:' +
(newattribs.padtop.def ? '* ' : newattribs.padtop.val + ' ') +
(newattribs.padright.def ? '* ' : newattribs.padright.val + ' ') +
(newattribs.padbottom.def ? '* ' : newattribs.padbottom.val + ' ') +
(newattribs.padleft.def ? '*' : newattribs.padleft.val) +
';vertical-align:' +
(newattribs.alignvert.def ? '*;' : newattribs.alignvert.val + ';');
} else {
value = '';
}
if (value != (sheet.layouts[attribs.defaultlayout] || '')) {
DoCmd('defaultlayout ' + value);
}
if (!newattribs.fontlook.def || !newattribs.fontsize.def || !newattribs.fontfamily.def) {
value =
(newattribs.fontlook.def ? '* ' : newattribs.fontlook.val + ' ') +
(newattribs.fontsize.def ? '* ' : newattribs.fontsize.val + ' ') +
(newattribs.fontfamily.def ? '*' : newattribs.fontfamily.val);
} else {
value = '';
}
if (value != (sheet.fonts[attribs.defaultfont] || '')) {
DoCmd('defaultfont ' + value);
}
CheckChanges('textcolor', sheet.colors[attribs.defaultcolor], 'defaultcolor');
CheckChanges('bgcolor', sheet.colors[attribs.defaultbgcolor], 'defaultbgcolor');
CheckChanges(
'numberformat',
sheet.valueformats[attribs.defaultnontextvalueformat],
'defaultnontextvalueformat',
);
CheckChanges(
'textformat',
sheet.valueformats[attribs.defaulttextvalueformat],
'defaulttextvalueformat',
);
CheckChanges('recalc', sheet.attribs.recalc, 'recalc');
CheckChanges('usermaxcol', sheet.attribs.usermaxcol, 'usermaxcol');
CheckChanges('usermaxrow', sheet.attribs.usermaxrow, 'usermaxrow');
if (changed) {
return cmdstr;
} else {
return null;
}
};
SC.SheetCommandInfo = function (sheetobj) {
this.sheetobj = sheetobj;
this.timerobj = null;
this.firsttimerdelay = 50;
this.timerdelay = 1;
this.maxtimeslice = 100;
this.saveundo = false;
this.CmdExtensionCallbacks = {};
};
SC.ScheduleSheetCommands = function (sheet, cmdstr, saveundo) {
var sci = sheet.sci;
var parseobj = new SocialCalc.Parse(cmdstr);
if (sci.sheetobj.statuscallback) {
sheet.statuscallback(sci, 'cmdstart', '', sci.sheetobj.statuscallbackparams);
}
if (saveundo) {
sci.sheetobj.changes.PushChange('');
}
sci.timerobj = window.setTimeout(function () {
SocialCalc.SheetCommandsTimerRoutine(sci, parseobj, saveundo);
}, sci.firsttimerdelay);
};
SC.SheetCommandsTimerRoutine = function (sci, parseobj, saveundo) {
var errortext;
var starttime = new Date();
sci.timerobj = null;
while (!parseobj.EOF()) {
try {
errortext = SocialCalc.ExecuteSheetCommand(sci.sheetobj, parseobj, saveundo);
} catch (err) {
errortext = err instanceof Error ? err.message : String(err);
}
if (errortext) {
if (typeof alert == 'function') {
(function(){})(errortext);
} else {
console.log(errortext);
}
}
parseobj.NextLine();
if (Date.now() - starttime.getTime() >= sci.maxtimeslice) {
sci.timerobj = window.setTimeout(function () {
SocialCalc.SheetCommandsTimerRoutine(sci, parseobj, saveundo);
}, sci.timerdelay);
return;
}
}
if (sci.sheetobj.statuscallback) {
sci.sheetobj.statuscallback(sci, 'cmdend', '', sci.sheetobj.statuscallbackparams);
}
};
SC.ExecuteSheetCommand = function (sheet, cmd, saveundo) {
var cmdstr;
var cmd1;
var rest;
var what;
var attrib;
var num;
var pos;
var pos2;
var errortext;
var undostart;
var val;
var cr1;
var cr2;
var col;
var row;
var cr;
var cell;
var newcell;
var fillright;
var rowstart;
var colstart;
var crbase;
var rowoffset;
var coloffset;
var basecell;
var clipsheet;
var cliprange;
var numcols;
var numrows;
var attribtable;
var colend;
var rowend;
var newcolstart;
var newrowstart;
var newcolend;
var newrowend;
var rownext;
var colnext;
var colthis;
var lastrow;
var lastcol;
var rowbefore;
var colbefore;
var oldformula;
var oldcr;
var olddefinition;
var cols;
var dirs;
var lastsortcol;
var i;
var sortlist;
var sortcells;
var sortvalues;
var sorttypes;
var sortfunction;
var valtype;
var originalrow;
var sortedcr;
var name;
var v1;
var v2;
var cmdextension;
var editor;
var undoNum;
var trackLine;
var sourceColname, colWidth, colHide, sourceRow, rowHide;
var quashedCellCoord, quashedCell;
var slast, tb;
var value;
var inc;
var attribs = sheet.attribs;
var changes = sheet.changes;
var cellProperties = SocialCalc.CellProperties;
var scc = SocialCalc.Constants;
var cellChanged = false;
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;
if (what == 'sheet') {
sheet.renderneeded = true;
switch (attrib) {
case 'defaultcolwidth':
if (saveundo) changes.AddUndo(undostart, attribs[attrib]);
attribs[attrib] = rest;
break;
case 'defaultcolor':
case 'defaultbgcolor':
if (saveundo)
changes.AddUndo(undostart, sheet.GetStyleString('color', attribs[attrib]));
attribs[attrib] = sheet.GetStyleNum('color', rest);
break;
case 'defaultlayout':
if (saveundo)
changes.AddUndo(undostart, sheet.GetStyleString('layout', attribs[attrib]));
attribs[attrib] = sheet.GetStyleNum('layout', rest);
break;
case 'defaultfont':
if (saveundo)
changes.AddUndo(undostart, sheet.GetStyleString('font', attribs[attrib]));
if (rest == '* * *') rest = '';
attribs[attrib] = sheet.GetStyleNum('font', rest);
break;
case 'defaulttextformat':
case 'defaultnontextformat':
if (saveundo)
changes.AddUndo(undostart, sheet.GetStyleString('cellformat', attribs[attrib]));
attribs[attrib] = sheet.GetStyleNum('cellformat', rest);
break;
case 'defaulttextvalueformat':
case 'defaultnontextvalueformat':
if (saveundo)
changes.AddUndo(undostart, sheet.GetStyleString('valueformat', attribs[attrib]));
attribs[attrib] = sheet.GetStyleNum('valueformat', rest);
for (cr in sheet.cells) {
delete sheet.cells[cr].displaystring;
}
break;
case 'lastcol':
case 'lastrow':
if (saveundo) changes.AddUndo(undostart, attribs[attrib] - 0);
num = rest - 0;
attribs[attrib] = num > 0 ? num : 1;
break;
case 'recalc':
if (saveundo) changes.AddUndo(undostart, attribs[attrib]);
if (rest == 'off') {
attribs.recalc = rest;
} else {
delete attribs.recalc;
}
break;
case 'usermaxcol':
case 'usermaxrow':
if (saveundo) changes.AddUndo(undostart, attribs[attrib] - 0);
num = rest - 0;
attribs[attrib] = num > 0 ? num : 0;
break;
default:
errortext = scc.s_escUnknownSheetCmd + cmdstr;
break;
}
} else if (/^[a-z]{1,2}(:[a-z]{1,2})?$/i.test(what)) {
sheet.renderneeded = true;
what = what.toUpperCase();
pos = what.indexOf(':');
if (pos >= 0) {
cr1 = SocialCalc.coordToCr(what.substring(0, pos) + '1');
cr2 = SocialCalc.coordToCr(what.substring(pos + 1) + '1');
} else {
cr1 = SocialCalc.coordToCr(what + '1');
cr2 = cr1;
}
for (col = cr1.col; col <= cr2.col; col++) {
if (attrib == 'width') {
cr = SocialCalc.rcColname(col);
if (saveundo) changes.AddUndo('set ' + cr + ' width', sheet.colattribs.width[cr]);
if (rest.length > 0) {
sheet.colattribs.width[cr] = rest;
} else {
delete sheet.colattribs.width[cr];
}
} else if (attrib == 'hide') {
sheet.hiddencolrow = 'col';
cr = SocialCalc.rcColname(col);
if (saveundo) changes.AddUndo('set ' + cr + ' hide', sheet.colattribs.hide[cr]);
if (rest.length > 0) {
sheet.colattribs.hide[cr] = rest;
} else {
delete sheet.colattribs.hide[cr];
}
}
}
} else if (/^\d+(:\d+)?$/i.test(what)) {
sheet.renderneeded = true;
what = what.toUpperCase();
pos = what.indexOf(':');
if (pos >= 0) {
cr1 = SocialCalc.coordToCr('A' + what.substring(0, pos));
cr2 = SocialCalc.coordToCr('A' + what.substring(pos + 1));
} else {
cr1 = SocialCalc.coordToCr('A' + what);
cr2 = cr1;
}
for (row = cr1.row; row <= cr2.row; row++) {
if (attrib == 'height') {
if (saveundo) changes.AddUndo('set ' + row + ' height', sheet.rowattribs.height[row]);
if (rest.length > 0) {
sheet.rowattribs.height[row] = rest;
} else {
delete sheet.rowattribs.height[row];
}
} else if (attrib == 'hide') {
sheet.hiddencolrow = 'row';
if (saveundo) changes.AddUndo('set ' + row + ' hide', sheet.rowattribs.hide[row]);
if (rest.length > 0) {
sheet.rowattribs.hide[row] = rest;
} else {
delete sheet.rowattribs.hide[row];
}
}
}
} else if (/^[a-z]{1,2}\d+(:[a-z]{1,2}\d+)?$/i.test(what)) {
cellChanged = true;
ParseRange();
if (
cr1.row != cr2.row ||
cr1.col != cr2.col ||
sheet.celldisplayneeded ||
sheet.renderneeded
) {
sheet.renderneeded = true;
sheet.celldisplayneeded = '';
} else {
sheet.celldisplayneeded = SocialCalc.crToCoord(cr1.col, cr1.row);
}
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 (cell.readonly && attrib != 'readonly') continue;
if (saveundo) changes.AddUndo('set ' + cr + ' all', sheet.CellToString(cell));
if (attrib == 'value') {
pos = rest.indexOf(' ');
var vtype = rest.substring(0, pos);
var vrest = rest.substring(pos + 1);
delete cell.errors;
delete cell.displaystring;
delete cell.parseinfo;
if (vtype == 'n') {
cell.datavalue = vrest - 0;
cell.datatype = 'v';
cell.valuetype = 'n';
} else {
value = SocialCalc.DetermineValueType(vrest);
cell.datavalue = value.value;
cell.valuetype = value.type;
if (value.type.charAt(0) == 't') {
cell.datatype = 't';
} else {
cell.datatype = 'c';
cell.formula = vrest;
}
}
attribs.needsrecalc = 'yes';
} else if (attrib == 'text') {
pos = rest.indexOf(' ');
cell.datavalue = SocialCalc.decodeFromSave(rest.substring(pos + 1));
delete cell.errors;
cell.datatype = 't';
cell.valuetype = rest.substring(0, pos);
delete cell.displaystring;
delete cell.parseinfo;
attribs.needsrecalc = 'yes';
} else if (attrib == 'formula') {
cell.datavalue = 0;
delete cell.errors;
cell.datatype = 'f';
if (SocialCalc._app && cell.valuetype != 'e#N/A')
cell.prevvaluetype = cell.valuetype;
cell.valuetype = 'e#N/A';
cell.formula = rest;
delete cell.displaystring;
delete cell.parseinfo;
attribs.needsrecalc = 'yes';
} else if (attrib == 'constant') {
pos = rest.indexOf(' ');
pos2 = rest.substring(pos + 1).indexOf(' ');
cell.datavalue = rest.substring(pos + 1, pos + 1 + pos2) - 0;
cell.valuetype = rest.substring(0, pos);
if (cell.valuetype.charAt(0) == 'e') {
cell.errors = cell.valuetype.substring(1);
} else {
delete cell.errors;
}
cell.datatype = 'c';
cell.formula = rest.substring(pos + pos2 + 2);
delete cell.displaystring;
delete cell.parseinfo;
attribs.needsrecalc = 'yes';
} else if (attrib == 'empty') {
cell.datavalue = '';
delete cell.errors;
cell.datatype = null;
cell.formula = '';
cell.valuetype = 'b';
delete cell.displaystring;
delete cell.parseinfo;
attribs.needsrecalc = 'yes';
} else if (attrib == 'all') {
if (rest.length > 0) {
cell = new SocialCalc.Cell(cr);
sheet.CellFromStringParts(cell, rest.split(':'), 1);
sheet.cells[cr] = cell;
} else {
delete sheet.cells[cr];
}
attribs.needsrecalc = 'yes';
} else if (/^b[trbl]$/.test(attrib)) {
cell[attrib] = sheet.GetStyleNum('borderstyle', rest);
sheet.renderneeded = true;
} else if (attrib == 'color' || attrib == 'bgcolor') {
cell[attrib] = sheet.GetStyleNum('color', rest);
} else if (attrib == 'layout' || attrib == 'cellformat') {
cell[attrib] = sheet.GetStyleNum(attrib, rest);
} else if (attrib == 'font') {
if (rest == '* * *') rest = '';
cell[attrib] = sheet.GetStyleNum('font', rest);
} else if (attrib == 'textvalueformat' || attrib == 'nontextvalueformat') {
cell[attrib] = sheet.GetStyleNum('valueformat', rest);
delete cell.displaystring;
} else if (attrib == 'cssc') {
rest = rest.replace(/[^a-zA-Z0-9-]/g, '');
cell.cssc = rest;
} else if (attrib == 'csss') {
rest = rest.replace(/\n/g, '');
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 if (attrib == 'readonly') {
cell.readonly = rest.toLowerCase() == 'yes';
} 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 (cell.readonly) break;
for (row = cr1.row; row <= cr2.row; row++) {
for (col = cr1.col; col <= cr2.col; col++) {
if (!(row == cr1.row && col == cr1.col)) {
quashedCellCoord = SocialCalc.crToCoord(col, row);
quashedCell = sheet.GetAssuredCell(quashedCellCoord);
if (saveundo)
changes.AddUndo(
'set ' + quashedCellCoord + ' all',
sheet.CellToString(quashedCell),
);
delete sheet.cells[quashedCellCoord];
}
}
}
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 (cell.readonly) break;
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');
if (cmd1 == 'cut') {
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 (cell.readonly) continue;
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) {
delete cell.comment;
}
} else if (rest == 'formats') {
newcell = new SocialCalc.Cell(cr);
newcell.datavalue = cell.datavalue;
newcell.datatype = cell.datatype;
newcell.formula = cell.formula;
newcell.valuetype = cell.valuetype;
if (cell.comment) {
newcell.comment = cell.comment;
}
sheet.cells[cr] = newcell;
}
}
}
attribs.needsrecalc = 'yes';
break;
case 'fillright':
case 'filldown':
sheet.renderneeded = true;
sheet.changedrendervalues = true;
if (saveundo) changes.AddUndo('changedrendervalues');
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
function increment_amount(down, seriescol, seriesrow) {
function valid_datatype(type) {
return type == 'v' || type == 'c';
}
function increment_from_cells(startcell, endcell) {
if (valid_datatype(startcell.datatype) && valid_datatype(endcell.datatype)) {
return endcell.datavalue - startcell.datavalue;
}
return undefined;
}
var csco = SocialCalc.GetSpreadsheetControlObject();
var editor = csco && csco.editor;
var range = editor && editor.range2;
var returnval = undefined;
var startcell, endcell;
if (range && range.hasrange) {
if (
down &&
range.bottom - range.top == 1 &&
seriescol >= range.left &&
seriescol <= range.right
) {
startcell = sheet.GetAssuredCell(SocialCalc.crToCoord(seriescol, range.top));
endcell = sheet.GetAssuredCell(SocialCalc.crToCoord(seriescol, range.bottom));
returnval = increment_from_cells(startcell, endcell);
} else if (
!down &&
range.right - range.left == 1 &&
seriesrow >= range.top &&
seriesrow <= range.bottom
) {
startcell = sheet.GetAssuredCell(SocialCalc.crToCoord(range.left, seriesrow));
endcell = sheet.GetAssuredCell(SocialCalc.crToCoord(range.right, seriesrow));
returnval = increment_from_cells(startcell, endcell);
}
}
if (returnval === undefined) {
if (down && cr2.row > cr1.row) {
startcell = sheet.GetAssuredCell(SocialCalc.crToCoord(seriescol, cr1.row));
endcell = sheet.GetAssuredCell(SocialCalc.crToCoord(seriescol, cr1.row + 1));
returnval = increment_from_cells(startcell, endcell);
} else if (!down && cr2.col > cr1.col) {
startcell = sheet.GetAssuredCell(SocialCalc.crToCoord(cr1.col, seriesrow));
endcell = sheet.GetAssuredCell(SocialCalc.crToCoord(cr1.col + 1, seriesrow));
returnval = increment_from_cells(startcell, endcell);
}
}
return returnval;
}
if (cmd1 == 'fillright') {
fillright = true;
rowstart = cr1.row;
colstart = cr1.col + 1;
} else {
fillright = false;
rowstart = cr1.row + 1;
colstart = cr1.col;
}
var increments = {};
if (fillright) {
for (row = rowstart; row <= cr2.row; row++) {
increments[row] = increment_amount(false, cr1.col, row);
}
} else {
for (col = colstart; col <= cr2.col; col++) {
increments[col] = increment_amount(true, col, cr1.row);
}
}
var csco = SocialCalc.GetSpreadsheetControlObject();
var editor = csco && csco.editor;
if (editor) editor.Range2Remove();
for (row = rowstart; row <= cr2.row; row++) {
for (col = colstart; col <= cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
cell = sheet.GetAssuredCell(cr);
if (cell.readonly) continue;
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);
inc = increments[fillright ? row : col];
if (rest == 'all' || rest == 'formats') {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue;
if (typeof basecell[attrib] === 'undefined' || cellProperties[attrib] == 3) {
delete cell[attrib];
} else {
cell[attrib] = basecell[attrib];
}
}
}
if (rest == 'all' || rest == 'formulas') {
if (inc !== undefined) {
cell.datavalue = basecell.datavalue + (fillright ? coloffset : rowoffset) * inc;
} else {
cell.datavalue = basecell.datavalue;
}
cell.datatype = basecell.datatype;
cell.valuetype = basecell.valuetype;
if (cell.datatype == 'f') {
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');
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
if (!SocialCalc.Clipboard.clipboard) {
break;
}
clipsheet = new SocialCalc.Sheet();
clipsheet.ParseSheetSave(SocialCalc.Clipboard.clipboard);
cliprange = SocialCalc.ParseRange(clipsheet.copiedfrom);
numcols = Math.max(cr2.col - cr1.col + 1, cliprange.cr2.col - cliprange.cr1.col + 1);
numrows = Math.max(cr2.row - cr1.row + 1, 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 (cell.readonly) continue;
if (saveundo) changes.AddUndo('set ' + cr + ' all', sheet.CellToString(cell));
var currentClipCol =
cliprange.cr1.col + ((col - cr1.col) % (cliprange.cr2.col - cliprange.cr1.col + 1));
var currentClipRow =
cliprange.cr1.row + ((row - cr1.row) % (cliprange.cr2.row - cliprange.cr1.row + 1));
crbase = SocialCalc.crToCoord(currentClipCol, currentClipRow);
basecell = clipsheet.GetAssuredCell(crbase);
if (rest == 'all' || rest == 'formats') {
if (row == cr1.row) {
sourceColname = SocialCalc.rcColname(
cliprange.cr1.col +
((col - cr1.col) % (cliprange.cr2.col - cliprange.cr1.col + 1)),
);
colWidth = clipsheet.colattribs.width[sourceColname];
colHide = clipsheet.colattribs.hide[sourceColname];
if (colWidth != null) {
sheet.colattribs.width[SocialCalc.rcColname(col)] = colWidth;
}
if (colHide != null) {
sheet.colattribs.hide[SocialCalc.rcColname(col)] = colHide;
}
}
if (col == cr1.col) {
sourceRow =
cliprange.cr1.row +
((row - cr1.row) % (cliprange.cr2.row - cliprange.cr1.row + 1));
rowHide = clipsheet.rowattribs.hide[sourceRow];
if (rowHide != null) {
sheet.rowattribs.hide[row] = rowHide;
}
}
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue;
if (typeof basecell[attrib] === 'undefined' || cellProperties[attrib] == 3) {
delete cell[attrib];
} else {
attribtable = SocialCalc.CellPropertiesTable[attrib];
if (attribtable && basecell[attrib]) {
cell[attrib] = sheet.GetStyleNum(
attribtable,
clipsheet.GetStyleString(attribtable, basecell[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') {
cell.formula = SocialCalc.OffsetFormulaCoords(
basecell.formula,
col - currentClipCol,
row - currentClipRow,
);
} else {
cell.formula = basecell.formula;
}
delete cell.parseinfo;
cell.errors = basecell.errors;
if (basecell.comment) {
cell.comment = basecell.comment;
} else if (cell.comment) {
delete cell.comment;
}
}
delete cell.displaystring;
}
}
attribs.needsrecalc = 'yes';
break;
case 'sort':
sheet.renderneeded = true;
sheet.changedrendervalues = true;
if (saveundo) changes.AddUndo('changedrendervalues');
what = cmd.NextToken();
ParseRange();
cols = [];
dirs = [];
lastsortcol = 0;
for (i = 0; i <= 3; i++) {
cols[i] = cmd.NextToken();
dirs[i] = cmd.NextToken();
if (cols[i]) lastsortcol = i;
}
sortcells = {};
sortlist = [];
sortvalues = [];
sorttypes = [];
for (row = cr1.row; row <= cr2.row; row++) {
for (col = cr1.col; col <= cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
cell = sheet.cells[cr];
if (cell) {
sortcells[cr] = sheet.CellToString(cell);
if (saveundo) changes.AddUndo('set ' + cr + ' all', sortcells[cr]);
} else {
if (saveundo) changes.AddUndo('set ' + cr + ' all');
}
}
sortlist.push(sortlist.length);
sortvalues.push([]);
sorttypes.push([]);
slast = sorttypes.length - 1;
for (i = 0; i <= lastsortcol; i++) {
cr = cols[i] + row;
cell = sheet.GetAssuredCell(cr);
val = cell.datavalue;
valtype = cell.valuetype.charAt(0) || 'b';
if (valtype == 't') val = val.toLowerCase();
sortvalues[slast].push(val);
sorttypes[slast].push(valtype);
}
}
sortfunction = function (a, b) {
var i, a1, b1, ta, cresult;
for (i = 0; i <= lastsortcol; i++) {
if (dirs[i] == 'up') {
a1 = a;
b1 = b;
} else {
a1 = b;
b1 = a;
}
ta = sorttypes[a1][i];
tb = sorttypes[b1][i];
if (ta == 't') {
if (tb == 't') {
a1 = sortvalues[a1][i];
b1 = sortvalues[b1][i];
cresult = a1 > b1 ? 1 : a1 < b1 ? -1 : 0;
} else if (tb == 'n') {
cresult = 1;
} else if (tb == 'b') {
cresult = dirs[i] == 'up' ? -1 : 1;
} else if (tb == 'e') {
cresult = -1;
}
} else if (ta == 'n') {
if (tb == 't') {
cresult = -1;
} else if (tb == 'n') {
a1 = sortvalues[a1][i] - 0;
b1 = sortvalues[b1][i] - 0;
cresult = a1 > b1 ? 1 : a1 < b1 ? -1 : 0;
} else if (tb == 'b') {
cresult = dirs[i] == 'up' ? -1 : 1;
} else if (tb == 'e') {
cresult = -1;
}
} else if (ta == 'e') {
if (tb == 'e') {
a1 = sortvalues[a1][i];
b1 = sortvalues[b1][i];
cresult = a1 > b1 ? 1 : a1 < b1 ? -1 : 0;
} else if (tb == 'b') {
cresult = dirs[i] == 'up' ? -1 : 1;
} else {
cresult = 1;
}
} else if (ta == 'b') {
if (tb == 'b') {
cresult = 0;
} else {
cresult = dirs[i] == 'up' ? 1 : -1;
}
}
if (cresult) {
return cresult;
}
}
cresult = a > b ? 1 : a < b ? -1 : 0;
return cresult;
};
sortlist.sort(sortfunction);
for (row = cr1.row; row <= cr2.row; row++) {
originalrow = sortlist[row - cr1.row];
for (col = cr1.col; col <= cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
sortedcr = SocialCalc.crToCoord(col, originalrow + cr1.row);
if (sortcells[sortedcr]) {
cell = new SocialCalc.Cell(cr);
sheet.CellFromStringParts(cell, sortcells[sortedcr].split(':'), 1);
if (cell.datatype == 'f') {
cell.formula = SocialCalc.OffsetFormulaCoords(
cell.formula,
0,
row - cr1.row - originalrow,
{
startCol: cr1.col,
endCol: cr2.col,
startRow: cr1.row,
endRow: cr2.row,
},
);
}
sheet.cells[cr] = cell;
} else {
delete sheet.cells[cr];
}
}
}
attribs.needsrecalc = 'yes';
break;
case 'insertcol':
case 'insertrow':
sheet.renderneeded = true;
sheet.changedrendervalues = true;
sheet.widgetsClean = false;
what = cmd.NextToken();
rest = cmd.RestOfString();
ParseRange();
lastcol = attribs.lastcol;
lastrow = attribs.lastrow;
if (cmd1 == 'insertcol') {
coloffset = 1;
colend = cr1.col;
rowoffset = 0;
rowend = 1;
newcolstart = cr1.col;
newcolend = cr1.col;
newrowstart = 1;
newrowend = attribs.lastrow;
if (attribs.lastcol >= 702) {
break;
}
if (saveundo) changes.AddUndo('deletecol ' + cr1.coord);
} else {
coloffset = 0;
colend = 1;
rowoffset = 1;
rowend = cr1.row;
newcolstart = 1;
newcolend = attribs.lastcol;
newrowstart = cr1.row;
newrowend = cr1.row;
if (saveundo) changes.AddUndo('deleterow ' + cr1.coord);
}
for (row = lastrow; row >= rowend; row--) {
for (col = lastcol; col >= colend; col--) {
crbase = SocialCalc.crToCoord(col, row);
cr = SocialCalc.crToCoord(col + coloffset, row + rowoffset);
if (!sheet.cells[crbase]) {
delete sheet.cells[cr];
} else {
sheet.cells[cr] = sheet.cells[crbase];
}
}
}
for (row = newrowstart; row <= newrowend; row++) {
for (col = newcolstart; col <= newcolend; col++) {
cr = SocialCalc.crToCoord(col, row);
cell = new SocialCalc.Cell(cr);
sheet.cells[cr] = cell;
crbase = SocialCalc.crToCoord(col - coloffset, row - rowoffset);
basecell = sheet.GetAssuredCell(crbase);
for (attrib in cellProperties) {
if (cellProperties[attrib] == 2) {
if (attrib == 'colspan' || attrib == 'rowspan') continue;
cell[attrib] = basecell[attrib];
}
}
}
}
for (cr in sheet.cells) {
cell = sheet.cells[cr];
if (cell && cell.datatype == 'f') {
cell.formula = SocialCalc.AdjustFormulaCoords(
cell.formula,
cr1.col,
coloffset,
cr1.row,
rowoffset,
);
}
if (cell) {
delete cell.parseinfo;
}
}
for (name in sheet.names) {
if (sheet.names[name]) {
v1 = sheet.names[name].definition;
v2 = '';
if (v1.charAt(0) == '=') {
v2 = '=';
v1 = v1.substring(1);
}
sheet.names[name].definition =
v2 + SocialCalc.AdjustFormulaCoords(v1, cr1.col, coloffset, cr1.row, rowoffset);
}
}
for (row = attribs.lastrow; row >= rowend && cmd1 == 'insertrow'; row--) {
rownext = row + rowoffset;
for (attrib in sheet.rowattribs) {
val = sheet.rowattribs[attrib][row];
if (sheet.rowattribs[attrib][rownext] != val) {
if (val) {
sheet.rowattribs[attrib][rownext] = val;
} else {
delete sheet.rowattribs[attrib][rownext];
}
}
}
}
for (col = lastcol; col >= colend && cmd1 == 'insertcol'; col--) {
colthis = SocialCalc.rcColname(col);
colnext = SocialCalc.rcColname(col + coloffset);
for (attrib in sheet.colattribs) {
val = sheet.colattribs[attrib][colthis];
if (sheet.colattribs[attrib][colnext] != val) {
if (val) {
sheet.colattribs[attrib][colnext] = val;
} else {
delete sheet.colattribs[attrib][colnext];
}
}
}
}
var tempRenderContext = new SocialCalc.RenderContext(sheet);
tempRenderContext.CalculateCellSkipData();
var cellsToExpand = {};
for (var skipCell in tempRenderContext.cellskip) {
var skipCellCR = SocialCalc.coordToCr(skipCell),
mergerCellCoords = tempRenderContext.cellskip[skipCell];
if (cmd1 === 'insertcol' && skipCellCR.col === newcolstart) {
if (!cellsToExpand[mergerCellCoords]) {
sheet.GetAssuredCell(mergerCellCoords).colspan += coloffset;
}
cellsToExpand[mergerCellCoords] = true;
}
if (cmd1 === 'insertrow' && skipCellCR.row === newrowstart) {
if (!cellsToExpand[mergerCellCoords]) {
sheet.GetAssuredCell(mergerCellCoords).rowspan += rowoffset;
}
cellsToExpand[mergerCellCoords] = true;
}
}
attribs.lastcol = Math.min(702, attribs.lastcol + coloffset);
attribs.lastrow += rowoffset;
attribs.needsrecalc = 'yes';
break;
case 'deletecol':
case 'deleterow':
sheet.renderneeded = true;
sheet.changedrendervalues = true;
sheet.widgetsClean = false;
what = cmd.NextToken();
rest = cmd.RestOfString();
lastcol = attribs.lastcol;
lastrow = attribs.lastrow;
ParseRange();
if (cmd1 == 'deletecol') {
coloffset = cr1.col - cr2.col - 1;
rowoffset = 0;
colstart = cr2.col + 1;
rowstart = 1;
} else {
coloffset = 0;
rowoffset = cr1.row - cr2.row - 1;
colstart = 1;
rowstart = cr2.row + 1;
}
for (row = rowstart; row <= lastrow - rowoffset; row++) {
for (col = colstart; col <= lastcol - coloffset; col++) {
cr = SocialCalc.crToCoord(col + coloffset, row + rowoffset);
cell = sheet.cells[cr];
if (cell && cell.readonly) {
errortext =
'Unable to remove ' +
(cmd1 == 'deletecol' ? 'column' : 'row') +
', because cell ' +
cell.coord +
' is locked';
return errortext;
}
}
}
for (row = rowstart; row <= lastrow - rowoffset; row++) {
for (col = colstart; col <= lastcol - coloffset; col++) {
cr = SocialCalc.crToCoord(col + coloffset, row + rowoffset);
if (saveundo && (row < rowstart - rowoffset || col < colstart - coloffset)) {
cell = sheet.cells[cr];
if (!cell) {
changes.AddUndo('erase ' + cr + ' all');
} else {
changes.AddUndo('set ' + cr + ' all', sheet.CellToString(cell));
}
}
crbase = SocialCalc.crToCoord(col, row);
cell = sheet.cells[crbase];
if (!cell) {
delete sheet.cells[cr];
} else {
sheet.cells[cr] = cell;
}
}
}
for (cr in sheet.cells) {
cell = sheet.cells[cr];
if (cell) {
if (cell.datatype == 'f') {
oldformula = cell.formula;
cell.formula = SocialCalc.AdjustFormulaCoords(
oldformula,
cr1.col,
coloffset,
cr1.row,
rowoffset,
);
if (cell.formula != oldformula) {
delete cell.parseinfo;
if (saveundo && cell.formula.indexOf('#REF!') != -1) {
oldcr = SocialCalc.coordToCr(cr);
if (cmd1 == 'deletecol') {
crbase = SocialCalc.crToCoord(
oldcr.col < cr1.col ? oldcr.col : oldcr.col - coloffset,
oldcr.row,
);
} else {
crbase = SocialCalc.crToCoord(
oldcr.col,
oldcr.row < cr1.row ? oldcr.row : oldcr.row - rowoffset,
);
}
changes.AddUndo('set ' + crbase + ' formula ' + oldformula);
}
}
} else {
delete cell.parseinfo;
}
}
}
for (name in sheet.names) {
if (sheet.names[name]) {
olddefinition = sheet.names[name].definition;
v1 = olddefinition;
v2 = '';
if (v1.charAt(0) == '=') {
v2 = '=';
v1 = v1.substring(1);
}
sheet.names[name].definition =
v2 + SocialCalc.AdjustFormulaCoords(v1, cr1.col, coloffset, cr1.row, rowoffset);
if (saveundo && sheet.names[name].definition != olddefinition) {
changes.AddUndo('name define ' + name + ' ' + olddefinition);
}
}
}
for (row = rowstart; row <= lastrow - rowoffset && cmd1 == 'deleterow'; row++) {
rowbefore = row + rowoffset;
for (attrib in sheet.rowattribs) {
val = sheet.rowattribs[attrib][row];
if (sheet.rowattribs[attrib][rowbefore] != val) {
if (saveundo)
changes.AddUndo(
'set ' + rowbefore + ' ' + attrib,
sheet.rowattribs[attrib][rowbefore],
);
if (val) {
sheet.rowattribs[attrib][rowbefore] = val;
} else {
delete sheet.rowattribs[attrib][rowbefore];
}
}
}
}
for (col = colstart; col <= lastcol - coloffset && cmd1 == 'deletecol'; col++) {
colthis = SocialCalc.rcColname(col);
colbefore = SocialCalc.rcColname(col + coloffset);
for (attrib in sheet.colattribs) {
val = sheet.colattribs[attrib][colthis];
if (sheet.colattribs[attrib][colbefore] != val) {
if (saveundo)
changes.AddUndo(
'set ' + colbefore + ' ' + attrib,
sheet.colattribs[attrib][colbefore],
);
if (val) {
sheet.colattribs[attrib][colbefore] = val;
} else {
delete sheet.colattribs[attrib][colbefore];
}
}
}
}
var tempRenderContext = new SocialCalc.RenderContext(sheet);
tempRenderContext.CalculateCellSkipData();
var cellsToShrink = {};
for (var skipCell in tempRenderContext.cellskip) {
var skipCellCR = SocialCalc.coordToCr(skipCell),
mergerCellCoords = tempRenderContext.cellskip[skipCell],
mergerCellCR = tempRenderContext.coordToCR[mergerCellCoords];
if (
cmd1 === 'deletecol' &&
skipCellCR.col === colstart + coloffset &&
mergerCellCR.col < skipCellCR.col
) {
if (!cellsToShrink[mergerCellCoords]) {
sheet.GetAssuredCell(mergerCellCoords).colspan += coloffset;
}
cellsToShrink[mergerCellCoords] = true;
}
if (
cmd1 === 'deleterow' &&
skipCellCR.row === rowstart + rowoffset &&
mergerCellCR.row < skipCellCR.row
) {
if (!cellsToShrink[mergerCellCoords]) {
sheet.GetAssuredCell(mergerCellCoords).rowspan += rowoffset;
}
cellsToShrink[mergerCellCoords] = true;
}
}
if (saveundo) {
if (cmd1 == 'deletecol') {
for (col = cr1.col; col <= cr2.col; col++) {
changes.AddUndo('insertcol ' + SocialCalc.rcColname(cr1.col));
}
} else {
for (row = cr1.row; row <= cr2.row; row++) {
changes.AddUndo('insertrow ' + cr1.row);
}
}
}
if (cmd1 == 'deletecol') {
if (cr1.col <= lastcol) {
if (cr2.col <= lastcol) {
attribs.lastcol += coloffset;
} else {
attribs.lastcol = cr1.col - 1;
}
}
} else {
if (cr1.row <= lastrow) {
if (cr2.row <= lastrow) {
attribs.lastrow += rowoffset;
} else {
attribs.lastrow = cr1.row - 1;
}
}
}
attribs.needsrecalc = 'yes';
break;
case 'movepaste':
case 'moveinsert':
var movingcells;
var dest;
var destcr;
var inserthoriz;
var insertvert;
var pushamount;
var movedto;
sheet.renderneeded = true;
sheet.changedrendervalues = true;
if (saveundo) changes.AddUndo('changedrendervalues');
what = cmd.NextToken();
dest = cmd.NextToken();
rest = cmd.RestOfString();
if (rest == '') rest = 'all';
ParseRange();
destcr = SocialCalc.coordToCr(dest);
coloffset = destcr.col - cr1.col;
rowoffset = destcr.row - cr1.row;
numcols = cr2.col - cr1.col + 1;
numrows = cr2.row - cr1.row + 1;
movingcells = {};
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 (cell.readonly) continue;
if (saveundo) changes.AddUndo('set ' + cr + ' all', sheet.CellToString(cell));
movingcells[cr] = new SocialCalc.Cell(cr);
for (attrib in cellProperties) {
if (typeof cell[attrib] === 'undefined') {
continue;
} else {
movingcells[cr][attrib] = cell[attrib];
}
if (rest == 'all') {
delete cell[attrib];
}
if (rest == 'formulas') {
if (cellProperties[attrib] == 1 || cellProperties[attrib] == 3) {
delete cell[attrib];
}
}
if (rest == 'formats') {
if (cellProperties[attrib] == 2) {
delete cell[attrib];
}
}
}
if (rest == 'formulas') {
cell.datavalue = '';
cell.datatype = null;
cell.formula = '';
cell.valuetype = 'b';
}
if (rest == 'all') {
delete sheet.cells[cr];
}
}
}
if (cmd1 == 'moveinsert') {
inserthoriz = false;
insertvert = false;
if (rowoffset == 0 && (destcr.col < cr1.col || destcr.col > cr2.col)) {
if (destcr.col < cr1.col) {
pushamount = cr1.col - destcr.col;
inserthoriz = -1;
} else {
destcr.col -= 1;
coloffset = destcr.col - cr2.col;
pushamount = destcr.col - cr2.col;
inserthoriz = 1;
}
} else if (coloffset == 0 && (destcr.row < cr1.row || destcr.row > cr2.row)) {
if (destcr.row < cr1.row) {
pushamount = cr1.row - destcr.row;
insertvert = -1;
} else {
destcr.row -= 1;
rowoffset = destcr.row - cr2.row;
pushamount = destcr.row - cr2.row;
insertvert = 1;
}
} else {
cmd1 = 'movepaste';
}
}
movedto = {};
if (insertvert) {
for (row = 0; row < pushamount; row++) {
for (col = cr1.col; col <= cr2.col; col++) {
if (insertvert < 0) {
crbase = SocialCalc.crToCoord(col, destcr.row + pushamount - row - 1);
cr = SocialCalc.crToCoord(col, cr2.row - row);
} else {
crbase = SocialCalc.crToCoord(col, destcr.row - pushamount + row + 1);
cr = SocialCalc.crToCoord(col, cr1.row + row);
}
basecell = sheet.GetAssuredCell(crbase);
if (saveundo) changes.AddUndo('set ' + crbase + ' all', sheet.CellToString(basecell));
cell = sheet.GetAssuredCell(cr);
if (rest == 'all' || rest == 'formats') {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue;
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;
cell.formula = basecell.formula;
delete cell.parseinfo;
cell.errors = basecell.errors;
}
delete cell.displaystring;
movedto[crbase] = cr;
}
}
}
if (inserthoriz) {
for (col = 0; col < pushamount; col++) {
for (row = cr1.row; row <= cr2.row; row++) {
if (inserthoriz < 0) {
crbase = SocialCalc.crToCoord(destcr.col + pushamount - col - 1, row);
cr = SocialCalc.crToCoord(cr2.col - col, row);
} else {
crbase = SocialCalc.crToCoord(destcr.col - pushamount + col + 1, row);
cr = SocialCalc.crToCoord(cr1.col + col, row);
}
basecell = sheet.GetAssuredCell(crbase);
if (saveundo) changes.AddUndo('set ' + crbase + ' all', sheet.CellToString(basecell));
cell = sheet.GetAssuredCell(cr);
if (rest == 'all' || rest == 'formats') {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue;
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;
cell.formula = basecell.formula;
delete cell.parseinfo;
cell.errors = basecell.errors;
}
delete cell.displaystring;
movedto[crbase] = cr;
}
}
}
if (destcr.col + numcols - 1 > attribs.lastcol) attribs.lastcol = destcr.col + numcols - 1;
if (destcr.row + numrows - 1 > attribs.lastrow) attribs.lastrow = destcr.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 + coloffset, row + rowoffset);
cell = sheet.GetAssuredCell(cr);
if (cell.readonly) continue;
if (saveundo) changes.AddUndo('set ' + cr + ' all', sheet.CellToString(cell));
crbase = SocialCalc.crToCoord(col, row);
movedto[crbase] = cr;
if (rest == 'all' && !movingcells[crbase]) {
delete sheet.cells[cr];
continue;
}
basecell = movingcells[crbase];
if (!basecell) basecell = sheet.GetAssuredCell(crbase);
if (rest == 'all' || rest == 'formats') {
for (attrib in cellProperties) {
if (cellProperties[attrib] == 1) continue;
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;
cell.formula = basecell.formula;
delete cell.parseinfo;
cell.errors = basecell.errors;
if (basecell.comment) {
cell.comment = basecell.comment;
} else if (cell.comment) {
delete cell.comment;
}
}
delete cell.displaystring;
}
}
for (cr in sheet.cells) {
cell = sheet.cells[cr];
if (cell) {
if (cell.datatype == 'f') {
oldformula = cell.formula;
cell.formula = SocialCalc.ReplaceFormulaCoords(oldformula, movedto);
if (cell.formula != oldformula) {
delete cell.parseinfo;
if (saveundo && !movedto[cr]) {
changes.AddUndo('set ' + cr + ' formula ' + oldformula);
}
}
} else {
delete cell.parseinfo;
}
}
}
for (name in sheet.names) {
if (sheet.names[name]) {
v1 = sheet.names[name].definition;
oldformula = v1;
v2 = '';
if (v1.charAt(0) == '=') {
v2 = '=';
v1 = v1.substring(1);
}
sheet.names[name].definition = v2 + SocialCalc.ReplaceFormulaCoords(v1, movedto);
if (saveundo && sheet.names[name].definition != oldformula) {
changes.AddUndo('name define ' + name + ' ' + oldformula);
}
}
}
attribs.needsrecalc = 'yes';
break;
case 'name':
what = cmd.NextToken();
name = cmd.NextToken();
rest = cmd.RestOfString();
name = name.toUpperCase().replace(/[^A-Z0-9_.]/g, '');
if (name == '') break;
if (what == 'define') {
if (rest == '') break;
if (sheet.names[name]) {
if (saveundo)
changes.AddUndo('name define ' + name + ' ' + sheet.names[name].definition);
sheet.names[name].definition = rest;
} else {
if (saveundo) changes.AddUndo('name delete ' + name);
sheet.names[name] = {
definition: rest,
desc: '',
};
}
} else if (what == 'desc') {
if (sheet.names[name]) {
if (saveundo) changes.AddUndo('name desc ' + name + ' ' + sheet.names[name].desc);
sheet.names[name].desc = rest;
}
} else if (what == 'delete') {
if (saveundo) {
if (sheet.names[name].desc)
changes.AddUndo('name desc ' + name + ' ' + sheet.names[name].desc);
changes.AddUndo('name define ' + name + ' ' + sheet.names[name].definition);
}
delete sheet.names[name];
}
attribs.needsrecalc = 'yes';
break;
case 'recalc':
attribs.needsrecalc = 'yes';
sheet.recalconce = true;
break;
case 'redisplay':
sheet.renderneeded = true;
break;
case 'changedrendervalues':
sheet.changedrendervalues = true;
break;
case 'pane':
name = cmd.NextToken().toUpperCase();
undoNum = 1;
editor = SocialCalc.GetSpreadsheetControlObject().editor;
if (name.toUpperCase() === 'ROW') {
row = parseInt(cmd.NextToken(), 10);
if (
typeof editor.context.rowpanes[1] !== 'undefined' &&
typeof editor.context.rowpanes[1].first === 'number'
) {
undoNum = editor.context.rowpanes[1].first;
}
if (saveundo) changes.AddUndo('pane row ' + undoNum);
while (editor.context.sheetobj.rowattribs.hide[row] == 'yes') {
row++;
}
if (
(!row || row <= editor.context.rowpanes[0].first) &&
editor.context.rowpanes.length > 1
) {
editor.context.rowpanes.length = 1;
} else if (editor.context.rowpanes.length - 1 && !editor.timeout) {
editor.context.SetRowPaneFirstLast(0, editor.context.rowpanes[0].first, row - 1);
editor.context.SetRowPaneFirstLast(1, row, row);
} else {
editor.context.SetRowPaneFirstLast(0, editor.context.rowpanes[0].first, row - 1);
editor.context.SetRowPaneFirstLast(1, row, row);
}
if (editor.griddiv) {
trackLine = document.getElementById('trackingline-vertical');
if (trackLine) {
editor.griddiv.removeChild(trackLine);
editor.FitToEditTable();
}
}
} else {
col = parseInt(cmd.NextToken(), 10);
if (
typeof editor.context.colpanes[1] !== 'undefined' &&
typeof editor.context.colpanes[1].first === 'number'
) {
undoNum = editor.context.colpanes[1].first;
}
if (saveundo) changes.AddUndo('pane col ' + undoNum);
while (editor.context.sheetobj.colattribs.hide[SocialCalc.rcColname(col)] == 'yes') {
col++;
}
if (
(!col || col <= editor.context.colpanes[0].first) &&
editor.context.colpanes.length > 1
) {
editor.context.colpanes.length = 1;
} else if (editor.context.colpanes.length - 1 && !editor.timeout) {
editor.context.SetColPaneFirstLast(0, editor.context.colpanes[0].first, col - 1);
editor.context.SetColPaneFirstLast(1, col, col);
} else {
editor.context.SetColPaneFirstLast(0, editor.context.colpanes[0].first, col - 1);
editor.context.SetColPaneFirstLast(1, col, col);
}
if (editor.griddiv) {
trackLine = document.getElementById('trackingline-horizon');
if (trackLine) {
editor.griddiv.removeChild(trackLine);
editor.FitToEditTable();
}
}
}
sheet.renderneeded = true;
break;
case 'startcmdextension':
name = cmd.NextToken();
cmdextension = sheet.sci.CmdExtensionCallbacks[name];
if (cmdextension) {
cmdextension.func(name, cmdextension.data, sheet, cmd, saveundo);
}
break;
case 'settimetrigger':
case 'sendemail':
case 'submitform':
break;
default:
errortext = scc.s_escUnknownCmd + cmdstr;
break;
}
if (SocialCalc._app) {
if (cellChanged) {
if (
sheet.renderneeded == true &&
attrib != 'value' &&
attrib != 'text' &&
attrib != 'formula' &&
attrib != 'constant' &&
attrib != 'empty'
)
sheet.widgetsClean = false;
else if (attrib == 'all') sheet.widgetsClean = false;
} else {
if (sheet.renderneeded == true) sheet.widgetsClean = false;
}
}
return errortext;
};
SC.SheetUndo = function (sheet) {
var i;
var tos = sheet.changes.TOS();
var lastone = tos ? tos.undo.length - 1 : -1;
var cmdstr = '';
for (i = lastone; i >= 0; i--) {
if (cmdstr) cmdstr += '\n';
cmdstr += tos.undo[i];
}
sheet.changes.Undo();
sheet.ScheduleSheetCommands(cmdstr, false);
};
SC.SheetRedo = function (sheet) {
var tos, i;
var didredo = sheet.changes.Redo();
if (!didredo) {
sheet.ScheduleSheetCommands('', false);
return;
}
tos = sheet.changes.TOS();
var cmdstr = '';
for (i = 0; tos && i < tos.command.length; i++) {
if (cmdstr) cmdstr += '\n';
cmdstr += tos.command[i];
}
sheet.ScheduleSheetCommands(cmdstr, false);
};
SC.CreateAuditString = function (sheet) {
var i, j;
var result = '';
var stack = sheet.changes.stack;
var tos = sheet.changes.tos;
for (i = 0; i <= tos; i++) {
for (j = 0; j < stack[i].command.length; j++) {
result += stack[i].command[j] + '\n';
}
}
return result;
};
SC.GetStyleNum = function (sheet, atype, style) {
var num;
if (style.length == 0) return 0;
num = sheet[atype + 'hash'][style];
if (!num) {
if (sheet[atype + 's'].length < 1) sheet[atype + 's'].push('');
num = sheet[atype + 's'].push(style) - 1;
sheet[atype + 'hash'][style] = num;
sheet.changedrendervalues = true;
}
return num;
};
SC.GetStyleString = function (sheet, atype, num) {
if (!num) return null;
return sheet[atype + 's'][num];
};
SC.RecalcInfo = {
sheet: null,
currentState: 0,
state: {
idle: 0,
start_calc: 1,
order: 2,
calc: 3,
start_wait: 4,
done_wait: 5,
},
recalctimer: null,
maxtimeslice: 100,
timeslicedelay: 1,
starttime: 0,
queue: [],
LoadSheet: function (_sheetname) {
return false;
},
};
SC.RecalcData = function () {
this.inrecalc = true;
this.celllist = [];
this.celllistitem = 0;
this.calclist = null;
this.calclistlength = 0;
this.firstcalc = null;
this.lastcalc = null;
this.nextcalc = null;
this.count = 0;
this.checkinfo = {};
};
SC.RecalcCheckInfo = function () {
this.oldcoord = null;
this.parsepos = 0;
this.inrange = false;
this.inrangestart = false;
this.cr1 = null;
this.cr2 = null;
this.c1 = null;
this.c2 = null;
this.r1 = null;
this.r2 = null;
this.c = null;
this.r = null;
};
SC.RecalcSheet = function (sheet) {
var scri = SocialCalc.RecalcInfo;
if (scri.currentState != scri.state.idle) {
scri.queue.push(sheet);
return;
}
delete sheet.attribs.circularreferencecell;
SocialCalc.Formula.FreshnessInfoReset();
SocialCalc.RecalcClearTimeout();
scri.sheet = sheet;
scri.currentState = scri.state.start_calc;
scri.starttime = new Date();
if (sheet.statuscallback) {
sheet.statuscallback(scri, 'calcstart', null, sheet.statuscallbackparams);
}
SocialCalc.RecalcSetTimeout();
};
SC.RecalcSetTimeout = function () {
var scri = SocialCalc.RecalcInfo;
scri.recalctimer = window.setTimeout(SocialCalc.RecalcTimerRoutine, scri.timeslicedelay);
};
SC.RecalcClearTimeout = function () {
var scri = SocialCalc.RecalcInfo;
if (scri.recalctimer) {
window.clearTimeout(scri.recalctimer);
scri.recalctimer = null;
}
};
SC.RecalcLoadedSheet = function (sheetname, str, recalcneeded, live) {
var sheet;
var scri = SocialCalc.RecalcInfo;
var scf = SocialCalc.Formula;
var effectiveSheetName = sheetname || scf.SheetCache.waitingForLoading;
if (effectiveSheetName) {
sheet = SocialCalc.Formula.AddSheetToCache(effectiveSheetName, str, live);
if (recalcneeded && sheet && sheet.attribs.recalc != 'off') {
sheet.previousrecalcsheet = scri.sheet;
scri.sheet = sheet;
scri.currentState = scri.state.start_calc;
}
}
scf.SheetCache.waitingForLoading = null;
SocialCalc.RecalcSetTimeout();
};
SC.RecalcTimerRoutine = function () {
var eresult, cell, coord, status;
var starttime = new Date();
var count = 0;
var scf = SocialCalc.Formula;
var scri = SocialCalc.RecalcInfo;
var sheet = scri.sheet;
if (!sheet) {
return;
}
var recalcdata = sheet.recalcdata || (sheet.recalcdata = {});
var do_statuscallback = function (status, arg) {
if (sheet.statuscallback) {
sheet.statuscallback(recalcdata, status, arg, sheet.statuscallbackparams);
}
};
SocialCalc.RecalcClearTimeout();
if (scri.currentState == scri.state.start_calc) {
recalcdata = new SocialCalc.RecalcData();
sheet.recalcdata = recalcdata;
for (coord in sheet.cells) {
if (!coord) continue;
recalcdata.celllist.push(coord);
}
recalcdata.calclist = {};
scri.currentState = scri.state.order;
}
if (scri.currentState == scri.state.order) {
while (recalcdata.celllistitem < recalcdata.celllist.length) {
coord = recalcdata.celllist[recalcdata.celllistitem++];
SocialCalc.RecalcCheckCell(sheet, coord);
if (Date.now() - starttime.getTime() >= scri.maxtimeslice) {
do_statuscallback('calcorder', {
coord,
total: recalcdata.celllist.length,
count: recalcdata.celllistitem,
});
SocialCalc.RecalcSetTimeout();
return;
}
}
do_statuscallback('calccheckdone', recalcdata.calclistlength);
recalcdata.nextcalc = recalcdata.firstcalc;
scri.currentState = scri.state.calc;
SocialCalc.RecalcSetTimeout();
return;
}
if (scri.currentState == scri.state.start_wait) {
scri.currentState = scri.state.done_wait;
if (scri.LoadSheet) {
status = scri.LoadSheet(scf.SheetCache.waitingForLoading);
if (status) {
return;
}
}
SocialCalc.RecalcLoadedSheet(null, '', false);
return;
}
if (scri.currentState == scri.state.done_wait) {
scri.currentState = scri.state.calc;
SocialCalc.RecalcSetTimeout();
return;
}
coord = sheet.recalcdata.nextcalc;
while (coord) {
cell = sheet.cells[coord];
cell.parseinfo.coord = coord;
eresult = scf.evaluate_parsed_formula(cell.parseinfo, sheet, false);
if (scf.SheetCache.waitingForLoading) {
if (scri.firstRenderScheduled != true) {
var editor = SocialCalc.GetSpreadsheetControlObject().editor;
editor.ScheduleRender(false);
scri.firstRenderScheduled = true;
}
recalcdata.nextcalc = coord;
recalcdata.count += count;
do_statuscallback('calcloading', { sheetname: scf.SheetCache.waitingForLoading });
scri.currentState = scri.state.start_wait;
SocialCalc.RecalcSetTimeout();
return;
}
if (scf.RemoteFunctionInfo.waitingForServer) {
recalcdata.nextcalc = coord;
recalcdata.count += count;
do_statuscallback('calcserverfunc', {
funcname: scf.RemoteFunctionInfo.waitingForServer,
coord,
total: recalcdata.calclistlength,
count: recalcdata.count,
});
scri.currentState = scri.state.done_wait;
return;
}
if (cell.datavalue != eresult.value || cell.valuetype != eresult.type) {
cell.datavalue = eresult.value;
cell.valuetype = eresult.type;
delete cell.displaystring;
sheet.recalcchangedavalue = true;
}
if (eresult.error) {
cell.errors = eresult.error;
}
count++;
coord = sheet.recalcdata.calclist[coord];
if (Date.now() - starttime.getTime() >= scri.maxtimeslice) {
recalcdata.nextcalc = coord;
recalcdata.count += count;
do_statuscallback('calcstep', {
coord,
total: recalcdata.calclistlength,
count: recalcdata.count,
});
SocialCalc.RecalcSetTimeout();
return;
}
}
recalcdata.inrecalc = false;
sheet.reRenderCellList = sheet.recalcdata.celllist;
delete sheet.recalcdata;
delete sheet.attribs.needsrecalc;
scri.sheet = sheet.previousrecalcsheet || null;
if (scri.sheet) {
scri.currentState = scri.state.calc;
SocialCalc.RecalcSetTimeout();
return;
}
scf.FreshnessInfo.recalc_completed = true;
scri.currentState = scri.state.idle;
do_statuscallback('calcfinished', Date.now() - scri.starttime.getTime());
if (scri.queue.length > 0) {
sheet = scri.queue.shift();
sheet.RecalcSheet();
}
return;
};
SC.RecalcCheckCell = function (sheet, startcoord) {
var parseinfo, ttext, ttype, i, rangecoord, value, pos, pos2, cell, coordvals;
var scf = SocialCalc.Formula;
var tokentype = scf.TokenType;
var token_op = tokentype.op;
var token_name = tokentype.name;
var token_coord = tokentype.coord;
var recalcdata = sheet.recalcdata;
var checkinfo = recalcdata.checkinfo;
var sheetref = false;
var oldcoord = null;
var coord = startcoord;
mainloop: while (coord) {
cell = sheet.cells[coord];
coordvals = checkinfo[coord];
if (!cell || cell.datatype != 'f' || (coordvals && typeof coordvals != 'object')) {
coord = oldcoord;
if (checkinfo[coord]) oldcoord = checkinfo[coord].oldcoord;
continue;
}
if (!coordvals) {
coordvals = new SocialCalc.RecalcCheckInfo();
checkinfo[coord] = coordvals;
}
if (cell.errors) {
delete cell.errors;
}
if (!cell.parseinfo) {
cell.parseinfo = scf.ParseFormulaIntoTokens(cell.formula);
}
parseinfo = cell.parseinfo;
for (i = coordvals.parsepos; i < parseinfo.length; i++) {
if (coordvals.inrange) {
if (coordvals.inrangestart) {
if (coordvals.cr1.col > coordvals.cr2.col) {
coordvals.c1 = coordvals.cr2.col;
coordvals.c2 = coordvals.cr1.col;
} else {
coordvals.c1 = coordvals.cr1.col;
coordvals.c2 = coordvals.cr2.col;
}
coordvals.c = coordvals.c1 - 1;
if (coordvals.cr1.row > coordvals.cr2.row) {
coordvals.r1 = coordvals.cr2.row;
coordvals.r2 = coordvals.cr1.row;
} else {
coordvals.r1 = coordvals.cr1.row;
coordvals.r2 = coordvals.cr2.row;
}
coordvals.r = coordvals.r1;
coordvals.inrangestart = false;
} else {
}
coordvals.c += 1;
if (coordvals.c > coordvals.c2) {
coordvals.r += 1;
if (coordvals.r > coordvals.r2) {
coordvals.inrange = false;
continue;
}
coordvals.c = coordvals.c1;
}
rangecoord = SocialCalc.crToCoord(coordvals.c, coordvals.r);
coordvals.parsepos = i;
coordvals.oldcoord = oldcoord;
oldcoord = coord;
coord = rangecoord;
if (checkinfo[coord] && typeof checkinfo[coord] == 'object') {
cell.errors = SocialCalc.Constants.s_caccCircRef + startcoord;
checkinfo[startcoord] = true;
if (!recalcdata.firstcalc) recalcdata.firstcalc = startcoord;
else recalcdata.calclist[recalcdata.lastcalc] = startcoord;
recalcdata.lastcalc = startcoord;
recalcdata.calclistlength++;
sheet.attribs.circularreferencecell = coord + '|' + oldcoord;
return cell.errors;
}
continue mainloop;
}
ttype = parseinfo[i].type;
ttext = parseinfo[i].text;
if (ttype == token_op) {
if (ttext == '!') {
sheetref = true;
} else if (ttext != ':') {
sheetref = false;
}
}
if (ttype == token_name) {
value = scf.LookupName(sheet, ttext);
if (value.type == 'range') {
pos = value.value.indexOf('|');
coordvals.cr1 = SocialCalc.coordToCr(value.value.substring(0, pos));
pos2 = value.value.indexOf('|', pos + 1);
coordvals.cr2 = SocialCalc.coordToCr(value.value.substring(pos + 1, pos2));
coordvals.inrange = true;
coordvals.inrangestart = true;
i = i - 1;
continue;
} else if (value.type == 'coord') {
ttype = token_coord;
ttext = value.value;
}
}
if (ttype == token_coord) {
if (
i >= 2 &&
parseinfo[i - 1].type == token_op &&
parseinfo[i - 1].text == ':' &&
parseinfo[i - 2].type == token_coord &&
!sheetref
) {
coordvals.cr1 = SocialCalc.coordToCr(parseinfo[i - 2].text);
coordvals.cr2 = SocialCalc.coordToCr(ttext);
coordvals.inrange = true;
coordvals.inrangestart = true;
i = i - 1;
continue;
} else if (!sheetref) {
if (ttext.indexOf('$') != -1) ttext = ttext.replace(/\$/g, '');
coordvals.parsepos = i + 1;
coordvals.oldcoord = oldcoord;
oldcoord = coord;
coord = ttext;
if (checkinfo[coord] && typeof checkinfo[coord] == 'object') {
cell.errors = SocialCalc.Constants.s_caccCircRef + startcoord;
checkinfo[startcoord] = true;
if (!recalcdata.firstcalc) {
recalcdata.firstcalc = startcoord;
} else {
recalcdata.calclist[recalcdata.lastcalc] = startcoord;
}
recalcdata.lastcalc = startcoord;
recalcdata.calclistlength++;
sheet.attribs.circularreferencecell = coord + '|' + oldcoord;
return cell.errors;
}
continue mainloop;
}
}
}
sheetref = false;
checkinfo[coord] = true;
if (!recalcdata.firstcalc) {
recalcdata.firstcalc = coord;
} else {
recalcdata.calclist[recalcdata.lastcalc] = coord;
}
recalcdata.lastcalc = coord;
recalcdata.calclistlength++;
coord = oldcoord;
oldcoord = checkinfo[coord] ? checkinfo[coord].oldcoord : null;
}
return '';
};
SC.Parse = function (str) {
this.str = str;
this.pos = 0;
this.delimiter = ' ';
this.lineEnd = str.indexOf('\n');
if (this.lineEnd < 0) {
this.lineEnd = str.length;
}
};
SC.Parse.prototype.NextToken = function () {
if (this.pos < 0) return '';
var pos2 = this.str.indexOf(this.delimiter, this.pos);
var pos1 = this.pos;
if (pos2 > this.lineEnd) {
pos2 = this.lineEnd;
}
if (pos2 >= 0) {
this.pos = pos2 + 1;
return this.str.substring(pos1, pos2);
} else {
this.pos = this.lineEnd;
return this.str.substring(pos1, this.lineEnd);
}
};
SC.Parse.prototype.RestOfString = function () {
var oldpos = this.pos;
if (this.pos < 0 || this.pos >= this.lineEnd) return '';
this.pos = this.lineEnd;
return this.str.substring(oldpos, this.lineEnd);
};
SC.Parse.prototype.RestOfStringNoMove = function () {
if (this.pos < 0 || this.pos >= this.lineEnd) return '';
return this.str.substring(this.pos, this.lineEnd);
};
SC.Parse.prototype.NextLine = function () {
this.pos = this.lineEnd + 1;
this.lineEnd = this.str.indexOf('\n', this.pos);
if (this.lineEnd < 0) {
this.lineEnd = this.str.length;
}
};
SC.Parse.prototype.EOF = function () {
if (this.pos < 0 || this.pos >= this.str.length) return true;
return false;
};
SC.UndoStack = function () {
this.stack = [];
this.tos = -1;
this.maxRedo = 0;
this.maxUndo = 50;
};
SC.UndoStack.prototype.PushChange = function (type) {
while (this.stack.length > 0 && this.stack.length - 1 > this.tos) {
this.stack.pop();
}
this.stack.push({
command: [],
type,
undo: [],
});
if (this.maxRedo && this.stack.length > this.maxRedo) {
this.stack.shift();
}
if (this.maxUndo && this.stack.length > this.maxUndo) {
this.stack[this.stack.length - this.maxUndo - 1].undo = [];
}
this.tos = this.stack.length - 1;
};
SC.UndoStack.prototype.AddDo = function () {
if (!this.stack[this.stack.length - 1]) {
return;
}
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] != null) args.push(arguments[i]);
}
var cmd = args.join(' ');
this.stack[this.stack.length - 1].command.push(cmd);
};
SC.UndoStack.prototype.AddUndo = function () {
if (!this.stack[this.stack.length - 1]) {
return;
}
var args = [];
for (var i = 0; i < arguments.length; i++) {
if (arguments[i] != null) args.push(arguments[i]);
}
var cmd = args.join(' ');
this.stack[this.stack.length - 1].undo.push(cmd);
};
SC.UndoStack.prototype.TOS = function () {
if (this.tos >= 0) return this.stack[this.tos];
else return null;
};
SC.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;
}
};
SC.UndoStack.prototype.Redo = function () {
if (this.tos < this.stack.length - 1) {
this.tos += 1;
return true;
} else {
return false;
}
};
SC.Clipboard = { clipboard: '' };
SC.RenderContext = function (sheetobj) {
var attribs = sheetobj.attribs;
var scc = SocialCalc.Constants;
this.sheetobj = sheetobj;
this.hideRowsCols = false;
this.showGrid = false;
this.showRCHeaders = false;
this.rownamewidth = scc.defaultRowNameWidth;
this.pixelsPerRow = scc.defaultAssumedRowHeight;
this.cellskip = {};
this.coordToCR = {};
this.colwidth = [];
this.rowheight = [];
this.totalwidth = 0;
this.totalheight = 0;
this.rowpanes = [];
this.colpanes = [];
this.colunhideleft = [];
this.colunhideright = [];
this.rowunhidetop = [];
this.rowunhidebottom = [];
this.maxcol = 0;
this.maxrow = 0;
this.highlights = {};
this.cursorsuffix = '';
this.highlightTypes = {
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;
this.defaultlinkstyle = null;
this.defaultHTMLlinkstyle = { type: 'html' };
this.defaultfontstyle = scc.defaultCellFontStyle;
this.defaultfontsize = scc.defaultCellFontSize;
this.defaultfontfamily = scc.defaultCellFontFamily;
this.defaultlayout = scc.defaultCellLayout;
this.defaultpanedividerwidth = scc.defaultPaneDividerWidth;
this.defaultpanedividerheight = scc.defaultPaneDividerHeight;
this.gridCSS = scc.defaultGridCSS;
this.commentClassName = scc.defaultCommentClass;
this.commentCSS = scc.defaultCommentStyle;
this.commentNoGridClassName = scc.defaultCommentNoGridClass;
this.commentNoGridCSS = scc.defaultCommentNoGridStyle;
this.readonlyClassName = scc.defaultReadonlyClass;
this.readonlyCSS = scc.defaultReadonlyStyle;
this.readonlyNoGridClassName = scc.defaultReadonlyNoGridClass;
this.readonlyNoGridCSS = scc.defaultReadonlyNoGridStyle;
this.readonlyComment = scc.defaultReadonlyComment;
this.classnames = {
colname: scc.defaultColnameClass,
rowname: scc.defaultRownameClass,
selectedcolname: scc.defaultSelectedColnameClass,
selectedrowname: scc.defaultSelectedRownameClass,
upperleft: scc.defaultUpperLeftClass,
skippedcell: scc.defaultSkippedCellClass,
panedivider: scc.defaultPaneDividerClass,
unhideleft: scc.defaultUnhideLeftClass,
unhideright: scc.defaultUnhideRightClass,
unhidetop: scc.defaultUnhideTopClass,
unhidebottom: scc.defaultUnhideBottomClass,
colresizebar: scc.defaultColResizeBarClass,
rowresizebar: scc.defaultRowResizeBarClass,
};
this.explicitStyles = {
colname: scc.defaultColnameStyle,
rowname: scc.defaultRownameStyle,
selectedcolname: scc.defaultSelectedColnameStyle,
selectedrowname: scc.defaultSelectedRownameStyle,
upperleft: scc.defaultUpperLeftStyle,
skippedcell: scc.defaultSkippedCellStyle,
panedivider: scc.defaultPaneDividerStyle,
unhideleft: scc.defaultUnhideLeftStyle,
unhideright: scc.defaultUnhideRightStyle,
unhidetop: scc.defaultUnhideTopStyle,
unhidebottom: scc.defaultUnhideBottomStyle,
};
this.cellskip = null;
this.needcellskip = true;
this.fonts = [];
this.layouts = [];
this.needprecompute = true;
if (attribs) {
this.rowpanes[0] = {
first: 1,
last: attribs.lastrow,
};
this.colpanes[0] = {
first: 1,
last: attribs.lastcol,
};
this.usermaxcol = attribs.usermaxcol;
this.usermaxrow = attribs.usermaxrow;
} else throw scc.s_rcMissingSheet;
};
SC.RenderContext.prototype.PrecomputeSheetFontsAndLayouts = function () {
SocialCalc.PrecomputeSheetFontsAndLayouts(this);
};
SC.RenderContext.prototype.CalculateCellSkipData = function () {
SocialCalc.CalculateCellSkipData(this);
};
SC.RenderContext.prototype.CalculateColWidthData = function () {
SocialCalc.CalculateColWidthData(this);
};
SC.RenderContext.prototype.CalculateRowHeightData = function () {
SocialCalc.CalculateRowHeightData(this);
};
SC.RenderContext.prototype.SetRowPaneFirstLast = function (panenum, first, last) {
this.rowpanes[panenum] = {
first,
last,
};
};
SC.RenderContext.prototype.SetColPaneFirstLast = function (panenum, first, last) {
this.colpanes[panenum] = {
first,
last,
};
};
SC.RenderContext.prototype.CoordInPane = function (coord, rowpane, colpane) {
return SocialCalc.CoordInPane(this, coord, rowpane, colpane);
};
SC.RenderContext.prototype.CellInPane = function (row, col, rowpane, colpane) {
return SocialCalc.CellInPane(this, row, col, rowpane, colpane);
};
SC.RenderContext.prototype.InitializeTable = function (tableobj) {
SocialCalc.InitializeTable(this, tableobj);
};
SC.RenderContext.prototype.RenderSheet = function (oldtable, linkstyle) {
return SocialCalc.RenderSheet(this, oldtable, linkstyle);
};
SC.RenderContext.prototype.RenderColGroup = function () {
return SocialCalc.RenderColGroup(this);
};
SC.RenderContext.prototype.RenderColHeaders = function () {
return SocialCalc.RenderColHeaders(this);
};
SC.RenderContext.prototype.RenderSizingRow = function () {
return SocialCalc.RenderSizingRow(this);
};
SC.RenderContext.prototype.RenderRow = function (rownum, rowpane, linkstyle) {
return SocialCalc.RenderRow(this, rownum, rowpane, linkstyle);
};
SC.RenderContext.prototype.RenderSpacingRow = function () {
return SocialCalc.RenderSpacingRow(this);
};
SC.RenderContext.prototype.RenderCell = function (
rownum,
colnum,
rowpane,
colpane,
noElement,
linkstyle,
) {
return SocialCalc.RenderCell(this, rownum, colnum, rowpane, colpane, noElement, linkstyle);
};
SC.PrecomputeSheetFontsAndLayouts = function (context) {
var defaultfont, parts, layoutre, dparts, sparts, num, s, i;
var sheetobj = context.sheetobj;
var attribs = sheetobj.attribs;
if (attribs.defaultfont) {
defaultfont = sheetobj.fonts[attribs.defaultfont];
defaultfont = defaultfont.replace(/^\*/, SocialCalc.Constants.defaultCellFontStyle);
defaultfont = defaultfont.replace(
/(.+)\*(.+)/,
'$1' + SocialCalc.Constants.defaultCellFontSize + '$2',
);
defaultfont = defaultfont.replace(/\*$/, SocialCalc.Constants.defaultCellFontFamily);
parts = defaultfont.match(/^(\S+? \S+?) (\S+?) (\S.*)$/);
context.defaultfontstyle = parts[1];
context.defaultfontsize = parts[2];
context.defaultfontfamily = parts[3];
}
for (num = 1; num < sheetobj.fonts.length; num++) {
s = sheetobj.fonts[num];
s = s.replace(/^\*/, context.defaultfontstyle);
s = s.replace(/(.+)\*(.+)/, '$1' + context.defaultfontsize + '$2');
s = s.replace(/\*$/, context.defaultfontfamily);
parts = s.match(/^(\S+?) (\S+?) (\S+?) (\S.*)$/);
if (!parts) continue;
context.fonts[num] = {
style: parts[1],
weight: parts[2],
size: parts[3],
family: parts[4],
};
}
layoutre = /^padding:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+);vertical-align:\s*(\S+);/;
dparts = SocialCalc.Constants.defaultCellLayout.match(layoutre);
if (attribs.defaultlayout) {
sparts = sheetobj.layouts[attribs.defaultlayout].match(layoutre);
} else {
sparts = ['', '*', '*', '*', '*', '*'];
}
for (num = 1; num < sheetobj.layouts.length; num++) {
s = sheetobj.layouts[num];
parts = s.match(layoutre);
if (!parts) continue;
for (i = 1; i <= 5; i++) {
if (parts[i] == '*') {
parts[i] = sparts[i] != '*' ? sparts[i] : dparts[i];
}
}
context.layouts[num] =
'padding:' +
parts[1] +
' ' +
parts[2] +
' ' +
parts[3] +
' ' +
parts[4] +
';vertical-align:' +
parts[5] +
';';
}
context.needprecompute = false;
};
SC.CalculateCellSkipData = function (context) {
var row, col, coord, cell, colspan, rowspan, skiprow, skipcol, skipcoord;
var sheetobj = context.sheetobj;
context.maxrow = 0;
context.maxcol = 0;
context.cellskip = {};
for (row = 1; row <= sheetobj.attribs.lastrow; row++) {
for (col = 1; col <= sheetobj.attribs.lastcol; col++) {
coord = SocialCalc.crToCoord(col, row);
cell = sheetobj.cells[coord];
if (cell === undefined || context.cellskip[coord]) continue;
colspan = cell.colspan || 1;
rowspan = cell.rowspan || 1;
if (colspan > 1 || rowspan > 1) {
for (skiprow = row; skiprow < row + rowspan; skiprow++) {
for (skipcol = col; skipcol < col + colspan; skipcol++) {
skipcoord = SocialCalc.crToCoord(skipcol, skiprow);
if (skipcoord == coord) {
context.coordToCR[coord] = {
row,
col,
};
} else {
context.cellskip[skipcoord] = coord;
}
if (skiprow > context.maxrow) context.maxrow = skiprow;
if (skipcol > context.maxcol) context.maxcol = skipcol;
}
}
}
}
}
context.needcellskip = false;
};
SC.CalculateColWidthData = function (context) {
var colnum, colname, colwidth, totalwidth, colpane;
var sheetobj = context.sheetobj;
totalwidth = context.showRCHeaders ? context.rownamewidth - 0 : 0;
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
colname = SocialCalc.rcColname(colnum);
if (sheetobj.colattribs.hide[colname] == 'yes') {
context.colwidth[colnum] = 0;
} else {
colwidth =
sheetobj.colattribs.width[colname] ||
sheetobj.attribs.defaultcolwidth ||
SocialCalc.Constants.defaultColWidth;
if (colwidth == 'blank' || colwidth == 'auto') colwidth = '';
context.colwidth[colnum] = colwidth + '';
totalwidth += colwidth && colwidth - 0 > 0 ? colwidth - 0 : 10;
}
}
}
context.totalwidth = totalwidth;
};
SC.CalculateRowHeightData = function (context) {
var rownum, rowheight, totalheight, rowpane;
var sheetobj = context.sheetobj;
totalheight = context.showRCHeaders ? context.pixelsPerRow : 0;
for (rowpane = 0; rowpane < context.rowpanes.length; rowpane++) {
for (
rownum = context.rowpanes[rowpane].first;
rownum <= context.rowpanes[rowpane].last;
rownum++
) {
if (sheetobj.rowattribs.hide[rownum] === 'yes') {
context.rowheight[rownum] = 0;
} else {
rowheight =
sheetobj.rowattribs.height[rownum] ||
sheetobj.attribs.defaultrowheight ||
SocialCalc.Constants.defaultAssumedRowHeight;
if (rowheight === 'blank' || rowheight === 'auto') rowheight = '';
context.rowheight[rownum] = rowheight + '';
totalheight += rowheight && rowheight - 0 > 0 ? rowheight - 0 : 10;
}
}
}
context.totalheight = totalheight;
};
SC.InitializeTable = function (context, tableobj) {
tableobj.style.borderCollapse = 'collapse';
tableobj.cellSpacing = '0';
tableobj.cellPadding = '0';
tableobj.style.width = context.totalwidth + 'px';
};
SC.RenderSheet = function (context, oldtable, linkstyle) {
var newrow, rowpane, rownum;
var tableobj, colgroupobj, tbodyobj, parentnode;
if (context.sheetobj.changedrendervalues) {
context.needcellskip = true;
context.needprecompute = true;
context.sheetobj.changedrendervalues = false;
}
if (context.needcellskip) {
context.CalculateCellSkipData();
}
if (context.needprecompute) {
context.PrecomputeSheetFontsAndLayouts();
}
context.CalculateColWidthData();
context.CalculateRowHeightData();
tableobj = SocialCalc.document.createElement('table');
context.InitializeTable(tableobj);
colgroupobj = context.RenderColGroup();
tableobj.appendChild(colgroupobj);
tbodyobj = SocialCalc.document.createElement('tbody');
tbodyobj.appendChild(context.RenderSizingRow());
if (context.showRCHeaders) {
newrow = context.RenderColHeaders();
if (newrow) tbodyobj.appendChild(newrow);
}
for (rowpane = 0; rowpane < context.rowpanes.length; rowpane++) {
for (
rownum = context.rowpanes[rowpane].first;
rownum <= context.rowpanes[rowpane].last;
rownum++
) {
newrow = context.RenderRow(rownum, rowpane, linkstyle);
tbodyobj.appendChild(newrow);
}
if (rowpane < context.rowpanes.length - 1) {
newrow = context.RenderSpacingRow();
tbodyobj.appendChild(newrow);
}
}
tableobj.appendChild(tbodyobj);
if (oldtable) {
parentnode = oldtable.parentNode;
if (parentnode) parentnode.replaceChild(tableobj, oldtable);
}
return tableobj;
};
SC.RenderRow = function (context, rownum, rowpane, linkstyle) {
var sheetobj = context.sheetobj;
var result = SocialCalc.document.createElement('tr');
var colnum, newcol, colpane, newdiv;
if (context.showRCHeaders) {
newcol = SocialCalc.document.createElement('td');
if (context.classnames) newcol.className = context.classnames.rowname;
if (context.explicitStyles) newcol.style.cssText = context.explicitStyles.rowname;
newcol.width = context.rownamewidth;
newcol.height = context.rowheight[rownum];
newcol.style.verticalAlign = 'top';
newcol.innerHTML = rownum + '';
if (
rownum < context.rowpanes[context.rowpanes.length - 1].last &&
sheetobj.rowattribs.hide[rownum + 1] == 'yes'
) {
var container = SocialCalc.document.createElement('div');
container.style.position = 'relative';
var unhide = SocialCalc.document.createElement('div');
if (context.classnames) unhide.className = context.classnames.unhidetop;
if (context.explicitStyles) unhide.style.cssText = context.explicitStyles.unhidetop;
var fixPosition =
context.rowheight[rownum] - 0 - SocialCalc.Constants.defaultAssumedRowHeight;
fixPosition = fixPosition === 0 ? 4 : fixPosition;
unhide.style.bottom = '-' + fixPosition + 'px';
context.rowunhidetop[rownum] = unhide;
container.appendChild(unhide);
newcol.appendChild(container);
}
if (rownum > 1 && sheetobj.rowattribs.hide[rownum - 1] == 'yes') {
var unhide = SocialCalc.document.createElement('div');
if (context.classnames) unhide.className = context.classnames.unhidebottom;
if (context.explicitStyles) unhide.style.cssText = context.explicitStyles.unhidebottom;
context.rowunhidebottom[rownum] = unhide;
newcol.appendChild(unhide);
}
var resizeBar = SocialCalc.document.createElement('div');
resizeBar.className = context.classnames.rowresizebar;
newcol.appendChild(resizeBar);
result.appendChild(newcol);
}
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
newcol = context.RenderCell(rownum, colnum, rowpane, colpane, null, linkstyle);
if (newcol) result.appendChild(newcol);
}
if (colpane < context.colpanes.length - 1) {
newcol = SocialCalc.document.createElement('td');
newcol.width = context.defaultpanedividerwidth;
if (context.classnames.panedivider) newcol.className = context.classnames.panedivider;
if (context.explicitStyles.panedivider)
newcol.style.cssText = context.explicitStyles.panedivider;
newdiv = SocialCalc.document.createElement('div');
newdiv.style.width = context.defaultpanedividerwidth + 'px';
newdiv.style.overflow = 'hidden';
newcol.appendChild(newdiv);
result.appendChild(newcol);
}
}
if (sheetobj.rowattribs.hide[rownum] == 'yes') {
result.style.cssText += ';display:none';
}
return result;
};
SC.RenderSpacingRow = function (context) {
var colnum, newcol, colpane, w;
var result = SocialCalc.document.createElement('tr');
if (context.showRCHeaders) {
newcol = SocialCalc.document.createElement('td');
newcol.width = context.rownamewidth;
newcol.height = context.defaultpanedividerheight;
if (context.classnames.panedivider) newcol.className = context.classnames.panedivider;
if (context.explicitStyles.panedivider)
newcol.style.cssText = context.explicitStyles.panedivider;
result.appendChild(newcol);
}
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
newcol = SocialCalc.document.createElement('td');
w = context.colwidth[colnum];
if (w) newcol.width = w;
newcol.height = context.defaultpanedividerheight;
if (context.classnames.panedivider) newcol.className = context.classnames.panedivider;
if (context.explicitStyles.panedivider)
newcol.style.cssText = context.explicitStyles.panedivider;
result.appendChild(newcol);
}
if (colpane < context.colpanes.length - 1) {
newcol = SocialCalc.document.createElement('td');
newcol.width = context.defaultpanedividerwidth;
newcol.height = context.defaultpanedividerheight;
if (context.classnames.panedivider) newcol.className = context.classnames.panedivider;
if (context.explicitStyles.panedivider)
newcol.style.cssText = context.explicitStyles.panedivider;
result.appendChild(newcol);
}
}
return result;
};
SC.RenderColHeaders = function (context) {
var sheetobj = context.sheetobj;
var result = SocialCalc.document.createElement('tr');
var colnum, newcol, colpane;
if (!context.showRCHeaders) return null;
newcol = SocialCalc.document.createElement('td');
if (context.classnames) newcol.className = context.classnames.upperleft;
if (context.explicitStyles) newcol.style.cssText = context.explicitStyles.upperleft;
newcol.width = context.rownamewidth;
result.appendChild(newcol);
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
newcol = SocialCalc.document.createElement('td');
if (context.classnames) newcol.className = context.classnames.colname;
if (context.explicitStyles) newcol.style.cssText = context.explicitStyles.colname;
if (sheetobj.colattribs.hide[SocialCalc.rcColname(colnum)] == 'yes') {
newcol.style.cssText += ';display:none';
}
newcol.innerHTML = SocialCalc.rcColname(colnum);
if (
colnum < context.colpanes[context.colpanes.length - 1].last &&
sheetobj.colattribs.hide[SocialCalc.rcColname(colnum + 1)] == 'yes'
) {
var unhide = SocialCalc.document.createElement('div');
if (context.classnames) unhide.className = context.classnames.unhideleft;
if (context.explicitStyles) unhide.style.cssText = context.explicitStyles.unhideleft;
context.colunhideleft[colnum] = unhide;
newcol.appendChild(unhide);
}
if (colnum > 1 && sheetobj.colattribs.hide[SocialCalc.rcColname(colnum - 1)] == 'yes') {
unhide = SocialCalc.document.createElement('div');
if (context.classnames) unhide.className = context.classnames.unhideright;
if (context.explicitStyles) unhide.style.cssText = context.explicitStyles.unhideright;
context.colunhideright[colnum] = unhide;
newcol.appendChild(unhide);
}
var resizeBar = SocialCalc.document.createElement('span');
resizeBar.style.height = SocialCalc.Constants.defaultAssumedRowHeight + 'px';
resizeBar.className = context.classnames.colresizebar;
newcol.appendChild(resizeBar);
result.appendChild(newcol);
}
if (colpane < context.colpanes.length - 1) {
newcol = SocialCalc.document.createElement('td');
newcol.width = context.defaultpanedividerwidth;
if (context.classnames.panedivider) newcol.className = context.classnames.panedivider;
if (context.explicitStyles.panedivider)
newcol.style.cssText = context.explicitStyles.panedivider;
result.appendChild(newcol);
}
}
return result;
};
SC.RenderColGroup = function (context) {
var colpane, colnum, newcol, t;
var sheetobj = context.sheetobj;
var result = SocialCalc.document.createElement('colgroup');
if (context.showRCHeaders) {
newcol = SocialCalc.document.createElement('col');
newcol.width = context.rownamewidth;
result.appendChild(newcol);
}
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
newcol = SocialCalc.document.createElement('col');
if (sheetobj.colattribs.hide[SocialCalc.rcColname(colnum)] == 'yes') {
newcol.width = '1';
} else {
t = context.colwidth[colnum];
if (t) newcol.width = t;
result.appendChild(newcol);
}
}
if (colpane < context.colpanes.length - 1) {
newcol = SocialCalc.document.createElement('col');
newcol.width = context.defaultpanedividerwidth;
result.appendChild(newcol);
}
}
return result;
};
SC.RenderSizingRow = function (context) {
var colpane, colnum, newcell, t;
var sheetobj = context.sheetobj;
var result = SocialCalc.document.createElement('tr');
if (context.showRCHeaders) {
newcell = SocialCalc.document.createElement('td');
newcell.style.width = context.rownamewidth + 'px';
newcell.height = '1';
result.appendChild(newcell);
}
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
newcell = SocialCalc.document.createElement('td');
if (sheetobj.colattribs.hide[SocialCalc.rcColname(colnum)] == 'yes') {
newcell.width = '1';
} else {
t = context.colwidth[colnum];
if (t) newcell.width = t;
}
newcell.height = '1';
result.appendChild(newcell);
}
if (colpane < context.colpanes.length - 1) {
newcell = SocialCalc.document.createElement('td');
newcell.width = context.defaultpanedividerwidth;
newcell.height = '1';
result.appendChild(newcell);
}
}
return result;
};
SC.RenderCell = function (context, rownum, colnum, rowpane, colpane, noElement, linkstyle) {
var sheetobj = context.sheetobj;
var num, t, result, span, cell, endcell, sheetattribs;
var stylestr = '';
var scc;
rownum = rownum - 0;
colnum = colnum - 0;
var coord = SocialCalc.crToCoord(colnum, rownum);
if (context.cellskip[coord]) {
if (context.CoordInPane(context.cellskip[coord], rowpane, colpane)) {
return null;
}
result = noElement ? SocialCalc.CreatePseudoElement() : SocialCalc.document.createElement('td');
if (context.classnames.skippedcell) result.className = context.classnames.skippedcell;
if (context.explicitStyles.skippedcell)
result.style.cssText = context.explicitStyles.skippedcell;
result.innerHTML = ' ';
return result;
}
result = noElement ? SocialCalc.CreatePseudoElement() : SocialCalc.document.createElement('td');
if (context.cellIDprefix) {
result.id = context.cellIDprefix + coord;
}
cell = sheetobj.cells[coord];
if (!cell) {
cell = new SocialCalc.Cell(coord);
}
sheetattribs = sheetobj.attribs;
scc = SocialCalc.Constants;
if (cell.colspan > 1) {
span = 1;
for (num = 1; num < cell.colspan; num++) {
if (
sheetobj.colattribs.hide[SocialCalc.rcColname(colnum + num)] != 'yes' &&
context.CellInPane(rownum, colnum + num, rowpane, colpane)
) {
span++;
}
}
result.colSpan = span;
}
if (cell.rowspan > 1) {
span = 1;
for (num = 1; num < cell.rowspan; num++) {
if (
sheetobj.rowattribs.hide[rownum + num + ''] != 'yes' &&
context.CellInPane(rownum + num, colnum, rowpane, colpane)
)
span++;
}
result.rowSpan = span;
}
if (cell.displaystring == undefined || sheetobj.widgetsClean == false) {
cell.displaystring = SocialCalc.FormatValueForDisplay(
sheetobj,
cell.datavalue,
coord,
linkstyle || context.defaultlinkstyle,
);
}
result.innerHTML = cell.displaystring;
num = cell.layout || sheetattribs.defaultlayout;
if (num && typeof context.layouts[num] !== 'undefined') {
stylestr += context.layouts[num];
} else {
stylestr += scc.defaultCellLayout;
}
num = cell.font || sheetattribs.defaultfont;
if (num && typeof context.fonts[num] !== 'undefined') {
t = context.fonts[num];
stylestr +=
'font-style:' +
t.style +
';font-weight:' +
t.weight +
';font-size:' +
t.size +
';font-family:' +
t.family +
';';
} else {
if (scc.defaultCellFontSize) {
stylestr += 'font-size:' + scc.defaultCellFontSize + ';';
}
if (scc.defaultCellFontFamily) {
stylestr += 'font-family:' + scc.defaultCellFontFamily + ';';
}
}
num = cell.color || sheetattribs.defaultcolor;
if (num && typeof sheetobj.colors[num] !== 'undefined')
stylestr += 'color:' + sheetobj.colors[num] + ';';
num = cell.bgcolor || sheetattribs.defaultbgcolor;
if (num && typeof sheetobj.colors[num] !== 'undefined')
stylestr += 'background-color:' + sheetobj.colors[num] + ';';
num = cell.cellformat;
if (num && typeof sheetobj.cellformats[num] !== 'undefined') {
stylestr += 'text-align:' + sheetobj.cellformats[num] + ';';
} else {
t = cell.valuetype.charAt(0);
if (t == 't') {
num = sheetattribs.defaulttextformat;
if (num && typeof sheetobj.cellformats[num] !== 'undefined')
stylestr += 'text-align:' + sheetobj.cellformats[num] + ';';
} else if (t == 'n') {
num = sheetattribs.defaultnontextformat;
if (num && typeof sheetobj.cellformats[num] !== 'undefined') {
stylestr += 'text-align:' + sheetobj.cellformats[num] + ';';
} else {
stylestr += 'text-align:right;';
}
} else stylestr += 'text-align:left;';
}
if (cell.colspan > 1 || cell.rowspan > 1) {
endcell =
sheetobj.cells[
SocialCalc.crToCoord(colnum + (cell.colspan || 1) - 1, rownum + (cell.rowspan || 1) - 1)
];
}
num = cell.bt;
if (num && typeof sheetobj.borderstyles[num] !== 'undefined')
stylestr += 'border-top:' + sheetobj.borderstyles[num] + ';';
num = typeof endcell != 'undefined' ? endcell.br : cell.br;
if (num && typeof sheetobj.borderstyles[num] !== 'undefined')
stylestr += 'border-right:' + sheetobj.borderstyles[num] + ';';
else if (context.showGrid) {
if (context.CellInPane(rownum, colnum + (cell.colspan || 1), rowpane, colpane))
t = SocialCalc.crToCoord(colnum + (cell.colspan || 1), rownum);
else t = 'nomatch';
if (context.cellskip[t]) t = context.cellskip[t];
if (!sheetobj.cells[t] || !sheetobj.cells[t].bl)
stylestr += 'border-right:' + context.gridCSS;
}
num = typeof endcell != 'undefined' ? endcell.bb : cell.bb;
if (num && typeof sheetobj.borderstyles[num] !== 'undefined')
stylestr += 'border-bottom:' + sheetobj.borderstyles[num] + ';';
else if (context.showGrid) {
if (context.CellInPane(rownum + (cell.rowspan || 1), colnum, rowpane, colpane))
t = SocialCalc.crToCoord(colnum, rownum + (cell.rowspan || 1));
else t = 'nomatch';
if (context.cellskip[t]) t = context.cellskip[t];
if (!sheetobj.cells[t] || !sheetobj.cells[t].bt)
stylestr += 'border-bottom:' + context.gridCSS;
}
num = cell.bl;
if (num && typeof sheetobj.borderstyles[num] !== 'undefined')
stylestr += 'border-left:' + sheetobj.borderstyles[num] + ';';
if (cell.comment) {
result.title = cell.comment;
if (context.showGrid) {
if (context.commentClassName) {
result.className = context.commentClassName;
}
stylestr += context.commentCSS;
} else {
if (context.commentNoGridClassName) {
result.className = context.commentNoGridClassName;
}
stylestr += context.commentNoGridCSS;
}
}
if (cell.readonly) {
if (!cell.comment) {
result.title = context.readonlyComment;
}
if (context.showGrid) {
if (context.readonlyClassName) {
result.className =
(result.className ? result.className + ' ' : '') + context.readonlyClassName;
}
stylestr += context.readonlyCSS;
} else {
if (context.readonlyNoGridClassName) {
result.className =
(result.className ? result.className + ' ' : '') + context.readonlyNoGridClassName;
}
stylestr += context.readonlyNoGridCSS;
}
}
result.style.cssText = stylestr;
if (cell.cssc !== undefined) {
if (noElement) {
result.className = (result.className ? result.className + ' ' : '') + cell.cssc;
} else {
result.classList.add(cell.cssc);
}
}
t = context.highlights[coord];
if (t) {
if (t == 'cursor') t += context.cursorsuffix;
if (context.highlightTypes[t].className) {
result.className =
(result.className ? result.className + ' ' : '') + context.highlightTypes[t].className;
}
SocialCalc.setStyles(result, context.highlightTypes[t].style);
}
if (sheetobj.colattribs.hide[SocialCalc.rcColname(colnum)] == 'yes') {
result.style.cssText += ';display:none';
}
if (sheetobj.rowattribs.hide[rownum] == 'yes') {
result.style.cssText += ';display:none';
}
return result;
};
SC.CoordInPane = function (context, coord, rowpane, colpane) {
var coordToCR = context.coordToCR[coord];
if (!coordToCR || !coordToCR.row || !coordToCR.col) throw 'Bad coordToCR for ' + coord;
return context.CellInPane(coordToCR.row, coordToCR.col, rowpane, colpane);
};
SC.CellInPane = function (context, row, col, rowpane, colpane) {
var panerowlimits = context.rowpanes[rowpane];
var panecollimits = context.colpanes[colpane];
if (!panerowlimits || !panecollimits)
throw 'CellInPane called with unknown panes ' + rowpane + '/' + colpane;
if (row < panerowlimits.first || row > panerowlimits.last) return false;
if (col < panecollimits.first || col > panecollimits.last) return false;
return true;
};
SC.CreatePseudoElement = function () {
return {
style: { cssText: '' },
innerHTML: '',
className: '',
};
};
SC.decodeFromSave = function (s) {
if (typeof s != 'string') return s;
if (s.indexOf('\\') == -1) return s;
var r = s.replace(/\\c/g, ':');
r = r.replace(/\\n/g, '\n');
return r.replace(/\\b/g, '\\');
};
SC.decodeFromAjax = function (s) {
if (typeof s != 'string') return s;
if (s.indexOf('\\') == -1) return s;
var r = s.replace(/\\c/g, ':');
r = r.replace(/\\n/g, '\n');
r = r.replace(/\\e/g, ']]');
return r.replace(/\\b/g, '\\');
};
SC.encodeForSave = function (s) {
if (typeof s != 'string') return s;
if (s.indexOf('\\') != -1) s = s.replace(/\\/g, '\\b');
if (s.indexOf(':') != -1) s = s.replace(/:/g, '\\c');
if (s.indexOf('\n') != -1) s = s.replace(/\n/g, '\\n');
return s;
};
SC.SafeUrlForRender = function (rawurl, policy = SocialCalc.Callbacks.securityPolicy) {
const noTabsOrNewlines = rawurl.replace(/[\t\n\r]/g, '');
let start = 0;
let end = noTabsOrNewlines.length;
while (start < end && noTabsOrNewlines.charCodeAt(start) <= 32) start++;
while (end > start && noTabsOrNewlines.charCodeAt(end - 1) <= 32) end--;
const stripped = noTabsOrNewlines.slice(start, end);
let encoded;
try {
encoded = encodeURI(stripped);
} catch {
return null;
}
const schemeMatch = stripped.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):/);
if (!schemeMatch) {
return SocialCalc.special_chars(encoded);
}
const scheme = schemeMatch[1].toLowerCase() + ':';
if (scheme === 'data:') {
const afterScheme = stripped.slice(schemeMatch[0].length);
const mime = afterScheme.match(/^([^,;]*)/)[1].toLowerCase();
if (!mime) return null;
const allowedDataMimeTypes = policy.allowedDataMimeTypes;
for (let i = 0; i < allowedDataMimeTypes.length; i++) {
if (allowedDataMimeTypes[i].toLowerCase() === mime)
return SocialCalc.special_chars(encoded);
}
return null;
}
const allowedUrlSchemes = policy.allowedUrlSchemes;
for (let i = 0; i < allowedUrlSchemes.length; i++) {
if (allowedUrlSchemes[i].toLowerCase() === scheme) return SocialCalc.special_chars(encoded);
}
return null;
};
SC.EscapeUntrustedHtml = function (html, policy = SocialCalc.Callbacks.securityPolicy) {
if (typeof policy.sanitizeHtml === 'function') {
return policy.sanitizeHtml(html);
}
return SocialCalc.special_chars(html);
};
SC.special_chars = function (string) {
if (/[&<>"]/.test(string)) {
string = string.replace(/&/g, '&');
string = string.replace(//g, '>');
string = string.replace(/"/g, '"');
}
return string;
};
SC.Lookup = function (value, list) {
for (var i = 0; i < list.length; i++) {
if (list[i] > value) {
if (i > 0) return i - 1;
else return null;
}
}
return list.length - 1;
};
SC.setStyles = function (element, cssText) {
var parts, part, pos, name, value;
if (!cssText) return;
parts = cssText.split(';');
for (part = 0; part < parts.length; part++) {
pos = parts[part].indexOf(':');
if (pos != -1) {
name = parts[part].substring(0, pos);
value = parts[part].substring(pos + 1);
if (name && value) {
element.style[name] = value;
}
}
}
};
SC.GetViewportInfo = function () {
var result = {};
if (window.innerWidth) {
result.width = window.innerWidth;
result.height = window.innerHeight;
result.horizontalScroll = window.pageXOffset;
result.verticalScroll = window.pageYOffset;
} else {
if (document.documentElement && document.documentElement.clientWidth) {
result.width = document.documentElement.clientWidth;
result.height = document.documentElement.clientHeight;
result.horizontalScroll = document.documentElement.scrollLeft;
result.verticalScroll = document.documentElement.scrollTop;
} else if (document.body.clientWidth) {
result.width = document.body.clientWidth;
result.height = document.body.clientHeight;
result.horizontalScroll = document.body.scrollLeft;
result.verticalScroll = document.body.scrollTop;
}
}
return result;
};
SC.GetElementPosition = function (element) {
var offsetLeft = 0;
var offsetTop = 0;
while (element) {
if (SocialCalc.GetComputedStyle(element, 'position') == 'relative') break;
offsetLeft += element.offsetLeft;
offsetTop += element.offsetTop;
element = element.offsetParent;
}
return {
left: offsetLeft,
top: offsetTop,
};
};
SC.GetElementPositionWithScroll = function (element) {
var rect = element.getBoundingClientRect();
return {
left: rect.left,
right: rect.right,
top: rect.top,
bottom: rect.bottom,
width: rect.width ? rect.width : rect.right - rect.left,
height: rect.height ? rect.height : rect.bottom - rect.top,
};
};
SC.GetElementFixedParent = function (element) {
while (element) {
if (element.tagName == 'HTML') break;
if (SocialCalc.GetComputedStyle(element, 'position') == 'fixed') return element;
element = element.parentNode;
}
return false;
};
SC.GetComputedStyle = function (element, style) {
var computedStyle;
if (document.defaultView) {
computedStyle = document.defaultView.getComputedStyle(element, null);
} else {
return '';
}
return computedStyle[style];
};
SC.LookupElement = function (element, array) {
var i;
for (i = 0; i < array.length; i++) {
if (array[i].element == element) return array[i];
}
return null;
};
SC.AssignID = function (obj, element, id) {
if (obj.idPrefix) {
element.id = obj.idPrefix + id;
}
};
SC.GetCellContents = function (sheetobj, coord) {
var result = '';
var cellobj = sheetobj.cells[coord];
if (cellobj) {
switch (cellobj.datatype) {
case 'v':
result = cellobj.datavalue + '';
break;
case 't':
result = "'" + cellobj.datavalue;
break;
case 'f':
result = '=' + cellobj.formula;
break;
case 'c':
result = cellobj.formula;
break;
default:
break;
}
}
return result;
};
SC.FormatCellForExport = function (sheet, cell, _cr) {
var valuetype, valueformat, sheetattribs;
if (!cell) {
return '';
}
sheetattribs = sheet.attribs;
valuetype = cell.valuetype || 'n';
if (valuetype.charAt(0) == 't') {
return cell.datavalue + '';
}
valueformat = cell.nontextvalueformat;
if (valueformat == null || valueformat == '') {
valueformat = sheetattribs.defaultnontextvalueformat;
}
valueformat = sheet.valueformats[valueformat - 0];
if (valueformat == null || valueformat == 'none') {
valueformat = '';
}
return SocialCalc.format_number_for_display(cell.datavalue, valuetype, valueformat);
};
SC.FormatValueForDisplay = function (sheetobj, value, cr, linkstyle) {
var valueformat, valuetype, valuesubtype;
var displayvalue, valueinputwidget;
var untrusted = Boolean(SocialCalc.Callbacks.untrustedContent);
var sheetattribs = sheetobj.attribs;
var cell = sheetobj.cells[cr];
if (!cell) {
cell = new SocialCalc.Cell(cr);
}
displayvalue = value;
valuetype = cell.valuetype || '';
valuesubtype = valuetype.substring(1);
valueinputwidget = valuetype.charAt(1);
var formula_name = valuetype.substring(2);
var html_display_value = null;
var html_formated_value = null;
valuetype = valuetype.charAt(0);
if (cell.errors || valuetype == 'e') {
displayvalue = cell.errors || valuesubtype || 'Error in cell';
return displayvalue;
}
if (valuetype == 't') {
valueformat =
sheetobj.valueformats[cell.textvalueformat - 0] ||
sheetobj.valueformats[sheetattribs.defaulttextvalueformat - 0] ||
'';
if (valueformat == 'formula') {
if (cell.datatype == 'f') {
displayvalue = SocialCalc.special_chars('=' + cell.formula) || ' ';
} else if (cell.datatype == 'c') {
displayvalue = SocialCalc.special_chars("'" + cell.formula) || ' ';
} else {
displayvalue = SocialCalc.special_chars("'" + displayvalue) || ' ';
}
return displayvalue;
}
html_display_value = displayvalue;
displayvalue = SocialCalc.format_text_for_display(
displayvalue,
cell.valuetype,
valueformat,
sheetobj,
linkstyle,
cell.nontextvalueformat,
);
html_formated_value = displayvalue;
} else if (valuetype == 'n') {
valueformat = cell.nontextvalueformat;
if (valueformat == null || valueformat == '') {
valueformat = sheetattribs.defaultnontextvalueformat;
}
valueformat = sheetobj.valueformats[valueformat - 0];
if (valueformat == null || valueformat == 'none') {
valueformat = '';
}
if (valueformat == 'formula') {
if (cell.datatype == 'f') {
displayvalue = SocialCalc.special_chars('=' + cell.formula) || ' ';
} else if (cell.datatype == 'c') {
displayvalue = SocialCalc.special_chars("'" + cell.formula) || ' ';
} else {
displayvalue = SocialCalc.special_chars("'" + displayvalue) || ' ';
}
return displayvalue;
} else if (valueformat == 'forcetext') {
if (cell.datatype == 'f') {
displayvalue = SocialCalc.special_chars('=' + cell.formula) || ' ';
} else if (cell.datatype == 'c') {
displayvalue = SocialCalc.special_chars(cell.formula) || ' ';
} else {
displayvalue = SocialCalc.special_chars(displayvalue) || ' ';
}
return displayvalue;
}
html_display_value = displayvalue;
displayvalue = SocialCalc.format_number_for_display(
displayvalue,
cell.valuetype,
valueformat,
);
html_formated_value = displayvalue;
} else {
displayvalue = ' ';
}
if (
!untrusted &&
valueinputwidget == 'i' &&
html_display_value != null &&
html_formated_value != null
) {
var parameters = sheetobj.ioParameterList[cr];
var formula_details = SocialCalc.Formula.FunctionList[formula_name];
if (formula_details) {
var cell_html = formula_details[5];
var checkedValue = html_display_value == 0 ? '' : 'checked';
cell_html = cell_html.replace(/<%=checked%>/g, checkedValue);
cell_html = cell_html.replace(/<%=formated_value%>/g, html_formated_value);
cell_html = cell_html.replace(/<%=display_value%>/g, html_display_value);
var parameterValue;
if (parameters) {
for (var index = 0; index < parameters.length; index++) {
if (parameters[index].type == 'coord') {
parameterValue = sheetobj.GetAssuredCell(parameters[index].value).datavalue;
} else {
parameterValue = parameters[index].value;
}
var paramRegExp = new RegExp('<%=parameter' + index + '_value%>', 'g');
cell_html = cell_html.replace(paramRegExp, parameterValue);
}
if (parameters.html) {
for (var htmlIndex = 0; htmlIndex < parameters.html.length; htmlIndex++) {
var paramRegExp = new RegExp('<%=html' + htmlIndex + '_value%>', 'g');
cell_html = cell_html.replace(paramRegExp, parameters.html[htmlIndex]);
}
}
if (parameters.css) {
cell_html = cell_html.replace(/^(<\w+)(\W)/, "$1 style='" + parameters.css + "'$2");
}
}
return cell_html.replace(/<%=cell_reference%>/g, cr);
}
return 'error:Widget HTML missing';
}
return displayvalue;
};
SC.format_text_for_display = function (
rawvalue,
valuetype,
valueformat,
sheetobj,
linkstyle,
nontextvalueformat,
) {
var valuesubtype, dvsc, dvue;
var textval;
var displayvalue;
var untrusted = Boolean(SocialCalc.Callbacks.untrustedContent);
valuesubtype = valuetype.substring(1);
displayvalue = rawvalue;
if (valueformat == 'none' || valueformat == null) valueformat = '';
if (!/^(text-|custom|hidden)/.test(valueformat)) valueformat = '';
if (valueformat == '' || valueformat == 'General') {
if (valuesubtype == 'h') valueformat = 'text-html';
if (valuesubtype == 'w' || valuesubtype == 'r') valueformat = 'text-wiki';
if (valuesubtype == 'l') valueformat = 'text-link';
if (!valuesubtype) valueformat = 'text-plain';
}
if (valueformat == 'text-html') {
if (untrusted) {
displayvalue = SocialCalc.EscapeUntrustedHtml(displayvalue);
}
} else if (SocialCalc.Callbacks.expand_wiki && valueformat.startsWith('text-wiki')) {
displayvalue = SocialCalc.Callbacks.expand_wiki(
displayvalue,
sheetobj,
linkstyle,
valueformat,
);
if (untrusted) {
displayvalue = SocialCalc.EscapeUntrustedHtml(displayvalue);
}
} else if (valueformat == 'text-wiki') {
displayvalue =
(SocialCalc.Callbacks.expand_markup &&
SocialCalc.Callbacks.expand_markup(displayvalue, sheetobj, linkstyle)) ||
SocialCalc.special_chars('wiki-text:' + displayvalue);
if (untrusted) {
displayvalue = SocialCalc.EscapeUntrustedHtml(displayvalue);
}
} else if (valueformat == 'text-url') {
dvsc = SocialCalc.special_chars(displayvalue);
if (untrusted) {
dvue = SocialCalc.SafeUrlForRender(displayvalue);
displayvalue = dvue == null ? dvsc : '' + dvsc + '';
} else {
dvue = encodeURI(displayvalue);
displayvalue = '' + dvsc + '';
}
} else if (valueformat == 'text-link') {
displayvalue = SocialCalc.expand_text_link(displayvalue, sheetobj, linkstyle, valueformat);
} else if (valueformat == 'text-image') {
if (untrusted) {
dvue = SocialCalc.SafeUrlForRender(displayvalue);
displayvalue =
dvue == null ? SocialCalc.special_chars(displayvalue) : '
';
} else {
dvue = encodeURI(displayvalue);
displayvalue = '
';
}
} else if (valueformat.substring(0, 12) == 'text-custom:') {
dvsc = SocialCalc.special_chars(displayvalue);
dvsc = dvsc.replace(/ /g, ' ');
dvsc = dvsc.replace(/\n/g, '
');
var customTemplate = valueformat.substring(12);
textval = {};
if (untrusted && typeof SocialCalc.Callbacks.securityPolicy.sanitizeHtml === 'function') {
textval.r = displayvalue;
textval.u = encodeURI(displayvalue);
textval.s = dvsc;
displayvalue = SocialCalc.EscapeUntrustedHtml(
customTemplate.replace(/@(r|s|u)/g, function (a, c) {
return textval[c];
}),
);
} else if (untrusted) {
textval.r = SocialCalc.EscapeUntrustedHtml(displayvalue);
textval.u = SocialCalc.SafeUrlForRender(displayvalue) || '';
textval.s = dvsc;
displayvalue = customTemplate
.split(/(@[rsu])/g)
.map(function (part) {
return part === '@r' || part === '@s' || part === '@u'
? textval[part.charAt(1)]
: SocialCalc.special_chars(part);
})
.join('');
} else {
textval.r = displayvalue;
textval.u = encodeURI(displayvalue);
textval.s = dvsc;
displayvalue = customTemplate.replace(/@(r|s|u)/g, function (a, c) {
return textval[c];
});
}
} else if (valueformat.substring(0, 6) == 'custom') {
displayvalue = SocialCalc.special_chars(displayvalue);
displayvalue = displayvalue.replace(/ /g, ' ');
displayvalue = displayvalue.replace(/\n/g, '
');
displayvalue += ' (custom format)';
} else if (valueformat == 'hidden') {
displayvalue = ' ';
} else if (
nontextvalueformat != null &&
nontextvalueformat != '' &&
sheetobj.valueformats[nontextvalueformat - 0] != 'none' &&
sheetobj.valueformats[nontextvalueformat - 0] != ''
) {
valueformat = sheetobj.valueformats[nontextvalueformat];
displayvalue = SocialCalc.format_number_for_display(rawvalue, valuetype, valueformat);
} else {
displayvalue = SocialCalc.special_chars(displayvalue);
displayvalue = displayvalue.replace(/ /g, ' ');
displayvalue = displayvalue.replace(/\n/g, '
');
}
return displayvalue;
};
SC.format_number_for_display = function (rawvalue, valuetype, valueformat) {
var value, valuesubtype;
var scc = SocialCalc.Constants;
value = rawvalue - 0;
valuesubtype = valuetype.substring(1);
if (valueformat == 'Auto' || valueformat == '') {
if (valuesubtype == '%') {
valueformat = scc.defaultFormatp;
} else if (valuesubtype == '$') {
valueformat = scc.defaultFormatc;
} else if (valuesubtype == 'dt') {
valueformat = scc.defaultFormatdt;
} else if (valuesubtype == 'd') {
valueformat = scc.defaultFormatd;
} else if (valuesubtype == 't') {
valueformat = scc.defaultFormatt;
} else if (valuesubtype == 'l') {
valueformat = 'logical';
} else {
valueformat = 'General';
}
}
if (valueformat == 'logical') {
return value ? scc.defaultDisplayTRUE : scc.defaultDisplayFALSE;
}
if (valueformat == 'hidden') {
return ' ';
}
return SocialCalc.FormatNumber.formatNumberWithFormat(rawvalue, valueformat, '');
};
SC.DetermineValueType = function (rawvalue) {
var value = rawvalue + '';
var type = 't';
var tvalue;
var matches;
var year;
var hour;
var minute;
var second;
var denom;
var num;
var intgr;
var constr;
tvalue = value.replace(/^\s+/, '');
tvalue = tvalue.replace(/\s+$/, '');
if (value.length == 0) {
type = '';
} else if (value.match(/^\s+$/)) {
} else if (tvalue.match(/^[-+]?\d*(?:\.)?\d*(?:[eE][-+]?\d+)?$/)) {
value = tvalue - 0;
if (isNaN(value)) {
value = rawvalue + '';
} else {
type = 'n';
}
} else if (tvalue.match(/^[-+]?\d*(?:\.)?\d*\s*%$/)) {
value = (tvalue.slice(0, -1) - 0) / 100;
type = 'n%';
} else if (tvalue.match(/^[-+]?\$\s*\d*(?:\.)?\d*\s*$/) && tvalue.match(/\d/)) {
value = tvalue.replace(/\$/, '') - 0;
type = 'n$';
} else if (tvalue.match(/^[-+]?(\d*,\d*)+(?:\.)?\d*$/)) {
value = tvalue.replace(/,/g, '') - 0;
type = 'n';
} else if (tvalue.match(/^[-+]?(\d*,\d*)+(?:\.)?\d*\s*%$/)) {
value = (tvalue.replace(/[%,]/g, '') - 0) / 100;
type = 'n%';
} else if (tvalue.match(/^[-+]?\$\s*(\d*,\d*)+(?:\.)?\d*$/) && tvalue.match(/\d/)) {
value = tvalue.replace(/[$,]/g, '') - 0;
type = 'n$';
} else if ((matches = value.match(/^(\d{1,2})[/-](\d{1,2})[/-](\d{1,4})\s*$/))) {
year = matches[3] - 0;
year = year < 1e3 ? year + 2e3 : year;
value =
navigator.language.indexOf('fr') === 0
? SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
year,
matches[2] - 0,
matches[1] - 0,
) - 2415019
: SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
year,
matches[1] - 0,
matches[2] - 0,
) - 2415019;
type = 'nd';
} else if ((matches = value.match(/^(\d{4})[/-](\d{1,2})[/-](\d{1,2})\s*$/))) {
year = matches[1] - 0;
year = year < 1e3 ? year + 2e3 : year;
value =
SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
year,
matches[2] - 0,
matches[3] - 0,
) - 2415019;
type = 'nd';
} else if (
(matches = value.match(/^(\d{4})[/-](\d{1,2})[/-](\d{1,2}) (\d{1,2}):(\d{1,2})\s*$/))
) {
year = matches[1] - 0;
year = year < 1e3 ? year + 2e3 : year;
hour = matches[4] - 0;
minute = matches[5] - 0;
value =
SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
year,
matches[2] - 0,
matches[3] - 0,
) - 2415019;
type = 'nd';
if (hour < 24 && minute < 60) {
value += hour / 24 + minute / (24 * 60);
type = 'ndt';
}
} else if (
(matches = value.match(
/^(\d{4})[/-](\d{1,2})[/-](\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})\s*$/,
))
) {
year = matches[1] - 0;
year = year < 1e3 ? year + 2e3 : year;
hour = matches[4] - 0;
minute = matches[5] - 0;
second = matches[6] - 0;
value =
SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
year,
matches[2] - 0,
matches[3] - 0,
) - 2415019;
type = 'nd';
if (hour < 24 && minute < 60 && second < 60) {
value += hour / 24 + minute / (24 * 60) + second / (24 * 60 * 60);
type = 'ndt';
}
} else if ((matches = value.match(/^(\d{1,2}):(\d{1,2})\s*$/))) {
hour = matches[1] - 0;
minute = matches[2] - 0;
if (hour < 24 && minute < 60) {
value = hour / 24 + minute / (24 * 60);
type = 'nt';
}
} else if ((matches = value.match(/^(\d{1,2}):(\d{1,2}):(\d{1,2})\s*$/))) {
hour = matches[1] - 0;
minute = matches[2] - 0;
second = matches[3] - 0;
if (hour < 24 && minute < 60 && second < 60) {
value = hour / 24 + minute / (24 * 60) + second / (24 * 60 * 60);
type = 'nt';
}
} else if ((matches = value.match(/^\s*([-+]?\d+) (\d+)\/(\d+)\s*$/))) {
intgr = matches[1] - 0;
num = matches[2] - 0;
denom = matches[3] - 0;
if (denom && denom > 0) {
value = intgr + (intgr < 0 ? -num / denom : num / denom);
type = 'n';
}
} else if ((constr = SocialCalc.InputConstants[value.toUpperCase()])) {
num = constr.indexOf(',');
value = constr.substring(0, num) - 0;
type = constr.substring(num + 1);
} else if (tvalue.length > 8 && tvalue.substring(0, 8).toLowerCase() == 'https://') {
value = tvalue;
type = 'tl';
} else if (tvalue.length > 7 && tvalue.substring(0, 7).toLowerCase() == 'http://') {
value = tvalue;
type = 'tl';
} else if (tvalue.match(/<([A-Z][A-Z0-9]*)\b[^>]*>[\s\S]*?<\/\1>/i)) {
value = tvalue;
type = 'th';
}
return {
value,
type,
};
};
SC.InputConstants = {
TRUE: '1,nl',
FALSE: '0,nl',
'#N/A': '0,e#N/A',
'#NULL!': '0,e#NULL!',
'#NUM!': '0,e#NUM!',
'#DIV/0!': '0,e#DIV/0!',
'#VALUE!': '0,e#VALUE!',
'#REF!': '0,e#REF!',
'#NAME?': '0,e#NAME?',
};
SC.default_expand_markup = function (displayvalue, _sheetobj, _linkstyle) {
var result = displayvalue;
result = SocialCalc.special_chars(result);
result = result.replace(/ /g, ' ');
result = result.replace(/\n/g, '
');
return result;
};
SC.expand_text_link = function (displayvalue, sheetobj, linkstyle, valueformat) {
var desc, tb, str;
var scc = SocialCalc.Constants;
var url = '';
var parts = SocialCalc.ParseCellLinkText(displayvalue + '');
if (parts.desc) {
desc = SocialCalc.special_chars(parts.desc);
} else {
desc = parts.pagename ? scc.defaultPageLinkFormatString : scc.defaultLinkFormatString;
}
if (
displayvalue.length > 7 &&
displayvalue.substring(0, 7).toLowerCase() == 'http://' &&
displayvalue.charAt(displayvalue.length - 1) != '>'
) {
desc = desc.substring(7);
}
tb = parts.newwin || !linkstyle ? ' target="_blank"' : '';
if (parts.pagename) {
if (SocialCalc.Callbacks.MakePageLink) {
url = SocialCalc.Callbacks.MakePageLink(
parts.pagename,
parts.workspacename,
linkstyle,
valueformat,
);
if (SocialCalc.Callbacks.untrustedContent) {
var safePageUrl = SocialCalc.SafeUrlForRender(url);
if (safePageUrl == null) {
return desc;
}
url = safePageUrl;
}
}
} else if (SocialCalc.Callbacks.untrustedContent) {
var safeUrl = SocialCalc.SafeUrlForRender(parts.url);
if (safeUrl == null) {
return desc;
}
url = safeUrl;
} else {
url = encodeURI(parts.url);
}
str = '' + desc + '';
return str;
};
SC.ParseCellLinkText = function (str) {
var result = {
url: '',
desc: '',
newwin: false,
pagename: '',
workspace: '',
};
var pageform = false;
var urlend = str.length - 1;
var descstart = 0;
var lastlt = str.lastIndexOf('<');
var lastbrkt = str.lastIndexOf('[');
var lastbrace = str.lastIndexOf('{');
var descend = -1;
var wsend = 0;
if (
(str.charAt(urlend) != '>' || lastlt == -1) &&
(str.charAt(urlend) != ']' || lastbrkt == -1) &&
(str.charAt(urlend) != '}' ||
str.charAt(urlend - 1) != ']' ||
lastbrace == -1 ||
lastbrkt == -1 ||
lastbrkt < lastbrace)
) {
urlend++;
descend = urlend;
} else {
if (str.charAt(urlend) == '>') {
descend = lastlt - 1;
if (lastlt > 0 && str.charAt(descend) == '<' && str.charAt(urlend - 1) == '>') {
descend--;
urlend--;
result.newwin = true;
}
} else if (str.charAt(urlend) == ']') {
descend = lastbrkt - 1;
pageform = true;
if (lastbrkt > 0 && str.charAt(descend) == '[' && str.charAt(urlend - 1) == ']') {
descend--;
urlend--;
result.newwin = true;
}
} else {
descend = lastbrace - 1;
pageform = true;
wsend = lastbrkt;
urlend--;
if (lastbrkt > 0 && str.charAt(lastbrkt - 1) == '[' && str.charAt(urlend - 1) == ']') {
wsend = lastbrkt - 1;
urlend--;
result.newwin = true;
}
if (str.charAt(wsend - 1) == ' ') {
wsend--;
}
result.workspace = str.substring(lastbrace + 1, wsend) || '';
}
if (str.charAt(descend) == ' ') {
descend--;
}
if (str.charAt(descstart) == '"' && str.charAt(descend) == '"') {
descstart++;
descend--;
}
}
if (pageform) {
result.pagename = str.substring(lastbrkt + 1, urlend) || '';
} else {
result.url = str.substring(lastlt + 1, urlend) || '';
}
if (descend >= descstart) {
result.desc = str.substring(descstart, descend + 1);
}
return result;
};
SC.ConvertSaveToOtherFormat = function (savestr, outputformat, dorecalc) {
var sheet, context, clipextents, div, ele, row, col, cr, cell, str;
var result = '';
if (outputformat == 'scsave') {
return savestr;
}
if (savestr == '') {
return '';
}
sheet = new SocialCalc.Sheet();
sheet.ParseSheetSave(savestr);
if (dorecalc) {
throw 'SocialCalc.ConvertSaveToOtherFormat: Not doing recalc.';
}
if (sheet.copiedfrom) {
clipextents = SocialCalc.ParseRange(sheet.copiedfrom);
} else {
clipextents = {
cr1: {
row: 1,
col: 1,
},
cr2: {
row: sheet.attribs.lastrow,
col: sheet.attribs.lastcol,
},
};
}
if (outputformat == 'html') {
context = new SocialCalc.RenderContext(sheet);
if (sheet.copiedfrom) {
context.rowpanes[0] = {
first: clipextents.cr1.row,
last: clipextents.cr2.row,
};
context.colpanes[0] = {
first: clipextents.cr1.col,
last: clipextents.cr2.col,
};
}
div = SocialCalc.document.createElement('div');
ele = context.RenderSheet(null, context.defaultHTMLlinkstyle);
div.appendChild(ele);
result = div.innerHTML;
return result;
}
for (row = clipextents.cr1.row; row <= clipextents.cr2.row; row++) {
for (col = clipextents.cr1.col; col <= clipextents.cr2.col; col++) {
cr = SocialCalc.crToCoord(col, row);
cell = sheet.GetAssuredCell(cr);
if (cell.errors) {
str = cell.errors;
} else {
str = SocialCalc.FormatCellForExport(sheet, cell, cr);
}
if (outputformat == 'csv') {
if (str.indexOf('"') != -1) {
str = str.replace(/"/g, '""');
}
if (/[, \n"]/.test(str)) {
str = '"' + str + '"';
}
if (col > clipextents.cr1.col) {
str = ',' + str;
}
} else if (outputformat == 'tab') {
if (str.indexOf('\n') != -1) {
if (str.indexOf('"') != -1) {
str = str.replace(/"/g, '""');
}
str = '"' + str + '"';
}
if (col > clipextents.cr1.col) {
str = ' ' + str;
}
}
result += str;
}
result += '\n';
}
return result;
};
SC.ConvertOtherFormatToSave = function (inputstr, inputformat) {
var sheet;
var lines;
var i;
var line;
var value;
var inquote;
var j;
var ch;
var row;
var col;
var cr;
var maxc;
var result = '';
var AddCell = function () {
col++;
if (col > maxc) maxc = col;
cr = SocialCalc.crToCoord(col, row);
SocialCalc.SetConvertedCell(sheet, cr, value);
value = '';
};
if (inputformat == 'scsave') {
return inputstr;
}
sheet = new SocialCalc.Sheet();
lines = inputstr.split(/\r\n|\n/);
maxc = 0;
if (inputformat == 'csv') {
row = 0;
inquote = false;
for (i = 0; i < lines.length; i++) {
if (i == lines.length - 1 && lines[i] == '') break;
if (inquote) {
value += '\n';
} else {
value = '';
row++;
col = 0;
}
line = lines[i];
for (j = 0; j < line.length; j++) {
ch = line.charAt(j);
if (ch == '"') {
if (inquote) {
if (j < line.length - 1 && line.charAt(j + 1) == '"') {
j++;
value += '"';
} else {
inquote = false;
if (j == line.length - 1) {
AddCell();
}
}
} else {
inquote = true;
}
continue;
}
if (ch == ',' && !inquote) {
AddCell();
} else {
value += ch;
}
if (j == line.length - 1 && !inquote) {
AddCell();
}
}
}
if (maxc > 0) {
sheet.attribs.lastrow = row;
sheet.attribs.lastcol = maxc;
result = sheet.CreateSheetSave('A1:' + SocialCalc.crToCoord(maxc, row));
}
}
if (inputformat == 'tab') {
row = 0;
inquote = false;
for (i = 0; i < lines.length; i++) {
if (i == lines.length - 1 && lines[i] == '') break;
if (inquote) {
value += '\n';
} else {
value = '';
row++;
col = 0;
}
line = lines[i];
for (j = 0; j < line.length; j++) {
ch = line.charAt(j);
if (ch == '"') {
if (inquote) {
if (j < line.length - 1) {
if (line.charAt(j + 1) == '"') {
j++;
value += '"';
} else if (line.charAt(j + 1) == ' ') {
j++;
inquote = false;
AddCell();
}
} else {
inquote = false;
AddCell();
}
continue;
}
if (value == '') {
inquote = true;
continue;
}
}
if (ch == ' ' && !inquote) {
AddCell();
} else {
value += ch;
}
if (j == line.length - 1 && !inquote) {
AddCell();
}
}
}
if (maxc > 0) {
sheet.attribs.lastrow = row;
sheet.attribs.lastcol = maxc;
result = sheet.CreateSheetSave('A1:' + SocialCalc.crToCoord(maxc, row));
}
}
return result;
};
SC.SetConvertedCell = function (sheet, cr, rawvalue) {
var cell, value;
cell = sheet.GetAssuredCell(cr);
if (typeof rawvalue == 'string' && rawvalue.charAt(0) == '=') {
cell.datatype = 'f';
cell.formula = rawvalue.substring(1);
cell.datavalue = 0;
cell.valuetype = 'e#N/A';
delete cell.errors;
delete cell.displaystring;
delete cell.parseinfo;
return;
}
value = SocialCalc.DetermineValueType(rawvalue);
if (value.type == 'n' && value.value == rawvalue) {
cell.datatype = 'v';
cell.valuetype = 'n';
cell.datavalue = value.value;
} else if (value.type.charAt(0) == 't') {
cell.datatype = 't';
cell.valuetype = value.type;
cell.datavalue = value.value;
} else {
cell.datatype = 'c';
cell.valuetype = value.type;
cell.datavalue = value.value;
cell.formula = rawvalue;
}
};
// In-place TypeScript conversion of socialcalctableeditor.js (SocialCalc global script).
// Ambient API types live in socialcalctableeditor.d.ts (referenced by dist/SocialCalc.d.ts).
// Vite+ strips types with Oxc before UMD concat — no runtime tax.
// Typechecked core after removing @ts-nocheck.
// See js/socialcalctableeditor.d.ts for class / global shapes.
const TableEditorSC = SocialCalc;
TableEditorSC.TableEditor = function (context) {
var scc = TableEditorSC.Constants;
this.context = context;
this.toplevel = null;
this.fullgrid = null;
this.noEdit = false;
this.width = null;
this.tablewidth = null;
this.height = null;
this.tableheight = null;
this.inputBox = null;
this.inputEcho = null;
this.verticaltablecontrol = null;
this.horizontaltablecontrol = null;
this.logo = null;
this.cellhandles = null;
this.timeout = null;
this.busy = false;
this.ensureecell = false;
this.deferredCommands = [];
this.deferredEmailCommands = [];
this.gridposition = null;
this.headposition = null;
this.firstscrollingrow = null;
this.firstscrollingrowtop = null;
this.lastnonscrollingrow = null;
this.lastvisiblerow = null;
this.firstscrollingcol = null;
this.firstscrollingcolleft = null;
this.lastnonscrollingcol = null;
this.lastvisiblecol = null;
this.rowpositions = [];
this.colpositions = [];
this.rowheight = [];
this.colwidth = [];
this.ecell = null;
this.state = 'start';
this.workingvalues = {};
this.imageprefix = scc.defaultImagePrefix;
this.idPrefix = scc.defaultTableEditorIDPrefix;
this.pageUpDnAmount = scc.defaultPageUpDnAmount;
this.recalcFunction = function (editor) {
if (editor.context.sheetobj.RecalcSheet)
editor.context.sheetobj.RecalcSheet(TableEditorSC.EditorSheetStatusCallback, editor);
return null;
};
this.ctrlkeyFunction = function (editor, charname) {
var ta, cell, position, cmd, sel, cliptext;
switch (charname) {
case '[ctrl-a]':
editor.MoveECell('A1');
editor.RangeAnchor('A1');
editor.RangeExtend(
TableEditorSC.crToCoord(
editor.context.sheetobj.attribs.lastcol,
editor.context.sheetobj.attribs.lastrow,
),
);
return false;
case '[ctrl-c]':
case '[ctrl-x]':
ta = editor.pasteTextarea;
ta.value = '';
cell = TableEditorSC.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
if (cell) {
position = TableEditorSC.GetElementPosition(cell.element);
ta.style.left = position.left - 1 + 'px';
ta.style.top = position.top - 1 + 'px';
}
if (editor.range.hasrange) {
sel =
TableEditorSC.crToCoord(editor.range.left, editor.range.top) +
':' +
TableEditorSC.crToCoord(editor.range.right, editor.range.bottom);
} else {
sel = editor.ecell.coord;
}
cliptext = TableEditorSC.ConvertSaveToOtherFormat(
TableEditorSC.CreateSheetSave(editor.context.sheetobj, sel),
'tab',
);
if (charname == '[ctrl-c]' || editor.noEdit || editor.ECellReadonly()) {
cmd = 'copy ' + sel + ' formulas';
} else {
cmd = 'cut ' + sel + ' formulas';
}
editor.EditorScheduleSheetCommands(cmd, true, false);
ta.style.display = 'block';
ta.value = cliptext;
ta.focus();
ta.select();
window.setTimeout(function () {
var ta = editor.pasteTextarea;
ta.blur();
ta.style.display = 'none';
TableEditorSC.KeyboardFocus();
}, 200);
return true;
case '[ctrl-v]':
if (editor.noEdit || editor.ECellReadonly()) return true;
ta = editor.pasteTextarea;
ta.value = '';
cell = TableEditorSC.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
if (cell) {
position = TableEditorSC.GetElementPosition(cell.element);
ta.style.left = position.left - 1 + 'px';
ta.style.top = position.top - 1 + 'px';
}
ta.style.display = 'block';
ta.value = '';
ta.focus();
window.setTimeout(function () {
var ta = editor.pasteTextarea;
var value = ta.value;
ta.blur();
ta.style.display = 'none';
var cmd = '';
if (editor.pastescclipboard) {
editor.pastescclipboard = false;
} else {
var clipstr = TableEditorSC.ConvertSaveToOtherFormat(
TableEditorSC.Clipboard.clipboard,
'tab',
);
value = value.replace(/\r\n/g, '\n');
if (
value != clipstr &&
(value.length - clipstr.length != 1 ||
value.substring(0, value.length - 1) != clipstr)
) {
cmd =
'loadclipboard ' +
TableEditorSC.encodeForSave(
TableEditorSC.ConvertOtherFormatToSave(value, 'tab'),
) +
'\n';
}
}
var cr;
if (editor.range.hasrange) {
var clipsheet = new TableEditorSC.Sheet();
clipsheet.ParseSheetSave(TableEditorSC.Clipboard.clipboard);
var matches = clipsheet.copiedfrom.match(/(.+):(.+)/);
if (matches !== null && matches[1] === matches[2]) {
cr =
TableEditorSC.crToCoord(editor.range.left, editor.range.top) +
':' +
TableEditorSC.crToCoord(editor.range.right, editor.range.bottom);
} else {
cr = TableEditorSC.crToCoord(editor.range.left, editor.range.top);
}
} else {
cr = editor.ecell.coord;
}
cmd += 'paste ' + cr + ' formulas';
editor.EditorScheduleSheetCommands(cmd, true, false);
TableEditorSC.KeyboardFocus();
}, 200);
return true;
case '[ctrl-z]':
editor.EditorScheduleSheetCommands('undo', true, false);
return false;
case '[ctrl-s]':
if (!TableEditorSC.Constants.AllowCtrlS) break;
window.setTimeout(function () {
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) {
if (newntvf.match(/^cmd:/)) {
cmd = newntvf.substring(4);
} else if (newntvf.match(/^edit:/)) {
cmd = newntvf.substring(5);
if (TableEditorSC.CtrlSEditor) {
TableEditorSC.CtrlSEditor(cmd);
}
return;
} else {
if (editor.range.hasrange) {
sel =
TableEditorSC.crToCoord(editor.range.left, editor.range.top) +
':' +
TableEditorSC.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;
};
context.sheetobj.statuscallback = TableEditorSC.EditorSheetStatusCallback;
context.sheetobj.statuscallbackparams = this;
this.StatusCallback = {};
this.MoveECellCallback = {};
this.RangeChangeCallback = {};
this.SettingsCallbacks = {};
this.ecell = {
coord: 'A1',
row: 1,
col: 1,
};
context.highlights[this.ecell.coord] = 'cursor';
this.range = { hasrange: false };
this.range2 = { hasrange: false };
};
TableEditorSC.TableEditor.prototype.CreateTableEditor = function (width, height) {
return TableEditorSC.CreateTableEditor(this, width, height);
};
TableEditorSC.TableEditor.prototype.ResizeTableEditor = function (width, height) {
return TableEditorSC.ResizeTableEditor(this, width, height);
};
TableEditorSC.TableEditor.prototype.SaveEditorSettings = function () {
return TableEditorSC.SaveEditorSettings(this);
};
TableEditorSC.TableEditor.prototype.LoadEditorSettings = function (str, flags) {
return TableEditorSC.LoadEditorSettings(this, str, flags);
};
TableEditorSC.TableEditor.prototype.EditorRenderSheet = function () {
TableEditorSC.EditorRenderSheet(this);
};
TableEditorSC.TableEditor.prototype.EditorScheduleSheetCommands = function (
cmdstr,
saveundo,
ignorebusy,
) {
TableEditorSC.EditorScheduleSheetCommands(this, cmdstr, saveundo, ignorebusy);
};
TableEditorSC.TableEditor.prototype.ScheduleSheetCommands = function (cmdstr, saveundo) {
this.context.sheetobj.ScheduleSheetCommands(cmdstr, saveundo);
};
TableEditorSC.TableEditor.prototype.SheetUndo = function () {
this.context.sheetobj.SheetUndo();
};
TableEditorSC.TableEditor.prototype.SheetRedo = function () {
this.context.sheetobj.SheetRedo();
};
TableEditorSC.TableEditor.prototype.EditorStepSet = function (status, arg) {
TableEditorSC.EditorStepSet(this, status, arg);
};
TableEditorSC.TableEditor.prototype.GetStatuslineString = function (status, arg, params) {
return TableEditorSC.EditorGetStatuslineString(this, status, arg, params);
};
TableEditorSC.TableEditor.prototype.EditorMouseRegister = function () {
return TableEditorSC.EditorMouseRegister(this);
};
TableEditorSC.TableEditor.prototype.EditorMouseUnregister = function () {
return TableEditorSC.EditorMouseUnregister(this);
};
TableEditorSC.TableEditor.prototype.EditorMouseRange = function (coord) {
return TableEditorSC.EditorMouseRange(this, coord);
};
TableEditorSC.TableEditor.prototype.EditorProcessKey = function (ch, e) {
return TableEditorSC.EditorProcessKey(this, ch, e);
};
TableEditorSC.TableEditor.prototype.EditorAddToInput = function (str, prefix) {
return TableEditorSC.EditorAddToInput(this, str, prefix);
};
TableEditorSC.TableEditor.prototype.DisplayCellContents = function () {
return TableEditorSC.EditorDisplayCellContents(this);
};
TableEditorSC.TableEditor.prototype.EditorSaveEdit = function (text) {
return TableEditorSC.EditorSaveEdit(this, text);
};
TableEditorSC.TableEditor.prototype.EditorApplySetCommandsToRange = function (cmdline, type) {
return TableEditorSC.EditorApplySetCommandsToRange(this, cmdline, type);
};
TableEditorSC.TableEditor.prototype.MoveECellWithKey = function (ch) {
return TableEditorSC.MoveECellWithKey(this, ch);
};
TableEditorSC.TableEditor.prototype.MoveECell = function (newcell) {
if (TableEditorSC._app) return 'A1';
return TableEditorSC.MoveECell(this, newcell);
};
TableEditorSC.TableEditor.prototype.ReplaceCell = function (cell, row, col) {
TableEditorSC.ReplaceCell(this, cell, row, col);
};
TableEditorSC.TableEditor.prototype.UpdateCellCSS = function (cell, row, col) {
TableEditorSC.UpdateCellCSS(this, cell, row, col);
};
TableEditorSC.TableEditor.prototype.SetECellHeaders = function (selected) {
TableEditorSC.SetECellHeaders(this, selected);
};
TableEditorSC.TableEditor.prototype.EnsureECellVisible = function () {
TableEditorSC.EnsureECellVisible(this);
};
TableEditorSC.TableEditor.prototype.ECellReadonly = function (coord) {
return TableEditorSC.ECellReadonly(this, coord);
};
TableEditorSC.TableEditor.prototype.RangeAnchor = function (coord) {
TableEditorSC.RangeAnchor(this, coord);
};
TableEditorSC.TableEditor.prototype.RangeExtend = function (coord) {
TableEditorSC.RangeExtend(this, coord);
};
TableEditorSC.TableEditor.prototype.RangeRemove = function () {
TableEditorSC.RangeRemove(this);
};
TableEditorSC.TableEditor.prototype.Range2Remove = function () {
TableEditorSC.Range2Remove(this);
};
TableEditorSC.TableEditor.prototype.FitToEditTable = function () {
TableEditorSC.FitToEditTable(this);
};
TableEditorSC.TableEditor.prototype.CalculateEditorPositions = function () {
TableEditorSC.CalculateEditorPositions(this);
};
TableEditorSC.TableEditor.prototype.ScheduleRender = function (renderwidgets) {
if (TableEditorSC._app && renderwidgets == true) this.context.sheetobj.widgetsClean = false;
TableEditorSC.ScheduleRender(this);
};
TableEditorSC.TableEditor.prototype.DoRenderStep = function () {
TableEditorSC.DoRenderStep(this);
};
TableEditorSC.TableEditor.prototype.SchedulePositionCalculations = function () {
TableEditorSC.SchedulePositionCalculations(this);
};
TableEditorSC.TableEditor.prototype.DoPositionCalculations = function () {
TableEditorSC.DoPositionCalculations(this);
};
TableEditorSC.TableEditor.prototype.CalculateRowPositions = function (panenum, positions, sizes) {
return TableEditorSC.CalculateRowPositions(this, panenum, positions, sizes);
};
TableEditorSC.TableEditor.prototype.CalculateColPositions = function (panenum, positions, sizes) {
return TableEditorSC.CalculateColPositions(this, panenum, positions, sizes);
};
TableEditorSC.TableEditor.prototype.ScrollRelative = function (vertical, amount) {
TableEditorSC.ScrollRelative(this, vertical, amount);
};
TableEditorSC.TableEditor.prototype.ScrollRelativeBoth = function (vamount, hamount) {
TableEditorSC.ScrollRelativeBoth(this, vamount, hamount);
};
TableEditorSC.TableEditor.prototype.PageRelative = function (vertical, direction) {
TableEditorSC.PageRelative(this, vertical, direction);
};
TableEditorSC.TableEditor.prototype.LimitLastPanes = function () {
TableEditorSC.LimitLastPanes(this);
};
TableEditorSC.TableEditor.prototype.ScrollTableUpOneRow = function () {
return TableEditorSC.ScrollTableUpOneRow(this);
};
TableEditorSC.TableEditor.prototype.ScrollTableDownOneRow = function () {
return TableEditorSC.ScrollTableDownOneRow(this);
};
TableEditorSC.TableEditor.prototype.ScrollTableLeftOneCol = function () {
return TableEditorSC.ScrollTableLeftOneCol(this);
};
TableEditorSC.TableEditor.prototype.ScrollTableRightOneCol = function () {
return TableEditorSC.ScrollTableRightOneCol(this);
};
TableEditorSC.TableEditor.prototype.StopPropagation = function () {
return TableEditorSC.StopPropagation(this);
};
TableEditorSC.TableEditor.prototype.SetMouseMoveUp = function () {
return TableEditorSC.SetMouseMoveUp(this);
};
TableEditorSC.TableEditor.prototype.RemoveMouseMoveUp = function () {
return TableEditorSC.RemoveMouseMoveUp(this);
};
TableEditorSC.CreateTableEditor = function (editor, width, height) {
var scc = TableEditorSC.Constants;
var AssignID = TableEditorSC.AssignID;
editor.toplevel = SocialCalc.document.createElement('div');
editor.toplevel.style.position = 'relative';
AssignID(editor, editor.toplevel, 'toplevel');
editor.width = width;
editor.height = height;
editor.griddiv = SocialCalc.document.createElement('div');
editor.tablewidth = Math.max(0, width - scc.defaultTableControlThickness);
editor.tableheight = Math.max(0, height - scc.defaultTableControlThickness);
editor.griddiv.style.width = editor.tablewidth + 'px';
editor.griddiv.style.height = editor.tableheight + 'px';
editor.griddiv.style.overflow = 'hidden';
editor.griddiv.style.cursor = 'default';
if (scc.cteGriddivClass) editor.griddiv.className = scc.cteGriddivClass;
AssignID(editor, editor.griddiv, 'griddiv');
editor.FitToEditTable();
editor.EditorRenderSheet();
editor.griddiv.appendChild(editor.fullgrid);
editor.verticaltablecontrol = new TableEditorSC.TableControl(editor, true, editor.tableheight);
editor.verticaltablecontrol.CreateTableControl();
AssignID(editor, editor.verticaltablecontrol.main, 'tablecontrolv');
editor.horizontaltablecontrol = new TableEditorSC.TableControl(
editor,
false,
editor.tablewidth,
);
editor.horizontaltablecontrol.CreateTableControl();
AssignID(editor, editor.horizontaltablecontrol.main, 'tablecontrolh');
var table, tbody, tr, td, ta;
table = SocialCalc.document.createElement('table');
editor.layouttable = table;
table.setAttribute('cellspacing', '0');
table.setAttribute('cellpadding', '0');
AssignID(editor, table, 'layouttable');
tbody = SocialCalc.document.createElement('tbody');
table.appendChild(tbody);
tr = SocialCalc.document.createElement('tr');
tbody.appendChild(tr);
td = SocialCalc.document.createElement('td');
td.appendChild(editor.griddiv);
tr.appendChild(td);
if (TableEditorSC._app != true) {
td = SocialCalc.document.createElement('td');
td.appendChild(editor.verticaltablecontrol.main);
tr.appendChild(td);
}
tr = SocialCalc.document.createElement('tr');
tbody.appendChild(tr);
if (TableEditorSC._app != true) {
td = SocialCalc.document.createElement('td');
td.appendChild(editor.horizontaltablecontrol.main);
tr.appendChild(td);
}
td = SocialCalc.document.createElement('td');
if (TableEditorSC._app) {
td.style.background = 'url(' + editor.imageprefix + 'logo.gif) no-repeat right center';
} else {
td.style.background = 'url(' + editor.imageprefix + 'logo.gif) no-repeat center center';
}
td.innerHTML =
"";
tr.appendChild(td);
editor.logo = td;
AssignID(editor, editor.logo, 'logo');
var logoImg = td.firstChild && td.firstChild.firstChild;
if (logoImg) logoImg.title = 'SocialCalc';
editor.toplevel.appendChild(editor.layouttable);
if (!editor.noEdit) {
editor.inputEcho = new TableEditorSC.InputEcho(editor);
AssignID(editor, editor.inputEcho.main, 'inputecho');
}
editor.cellhandles = new TableEditorSC.CellHandles(editor);
ta = SocialCalc.document.createElement('textarea');
TableEditorSC.setStyles(
ta,
'display:none;position:absolute;height:1px;width:1px;opacity:0;filter:alpha(opacity=0);',
);
ta.value = '';
editor.pasteTextarea = ta;
AssignID(editor, editor.pasteTextarea, 'pastetextarea');
if (navigator.userAgent.match(/Safari\//) && !navigator.userAgent.match(/Chrome\//)) {
window.removeEventListener('beforepaste', TableEditorSC.SafariPasteFunction, false);
window.addEventListener('beforepaste', TableEditorSC.SafariPasteFunction, false);
window.removeEventListener('beforecopy', TableEditorSC.SafariPasteFunction, false);
window.addEventListener('beforecopy', TableEditorSC.SafariPasteFunction, false);
window.removeEventListener('beforecut', TableEditorSC.SafariPasteFunction, false);
window.addEventListener('beforecut', TableEditorSC.SafariPasteFunction, false);
}
editor.toplevel.appendChild(editor.pasteTextarea);
TableEditorSC.MouseWheelRegister(editor.toplevel, {
WheelMove: TableEditorSC.EditorProcessMouseWheel,
editor,
});
TableEditorSC.KeyboardSetFocus(editor);
TableEditorSC.EditorSheetStatusCallback(null, 'startup', null, editor);
return editor.toplevel;
};
TableEditorSC.SafariPasteFunction = function (e) {
e.preventDefault();
};
TableEditorSC.ResizeTableEditor = function (editor, width, height) {
var scc = TableEditorSC.Constants;
editor.width = width;
editor.height = height;
editor.toplevel.style.width = width + 'px';
editor.toplevel.style.height = height + 'px';
if (TableEditorSC._app) {
editor.tablewidth = Math.max(0, width);
} else {
editor.tablewidth = Math.max(0, width - scc.defaultTableControlThickness);
}
editor.tableheight = Math.max(0, height - scc.defaultTableControlThickness);
editor.griddiv.style.width = editor.tablewidth + 'px';
editor.griddiv.style.height = editor.tableheight + 'px';
editor.verticaltablecontrol.main.style.height = editor.tableheight + 'px';
editor.horizontaltablecontrol.main.style.width = editor.tablewidth + 'px';
editor.FitToEditTable();
editor.ScheduleRender();
return;
};
TableEditorSC.SaveEditorSettings = function (editor) {
var i, setting;
var context = editor.context;
var range = editor.range;
var result = '';
result += 'version:1.0\n';
for (i = 0; i < context.rowpanes.length; i++) {
result +=
'rowpane:' + i + ':' + context.rowpanes[i].first + ':' + context.rowpanes[i].last + '\n';
}
for (i = 0; i < context.colpanes.length; i++) {
result +=
'colpane:' + i + ':' + context.colpanes[i].first + ':' + context.colpanes[i].last + '\n';
}
if (editor.ecell) {
result += 'ecell:' + editor.ecell.coord + '\n';
}
if (range.hasrange) {
result +=
'range:' +
range.anchorcoord +
':' +
range.top +
':' +
range.bottom +
':' +
range.left +
':' +
range.right +
'\n';
}
for (setting in editor.SettingsCallbacks) {
result += editor.SettingsCallbacks[setting].save(editor, setting);
}
return result;
};
TableEditorSC.LoadEditorSettings = function (editor, str, flags) {
var lines = str.split(/\r\n|\n/);
var parts = [];
var line, i, cr, row, col, coord, setting;
var context = editor.context;
var highlights, range;
context.rowpanes = [
{
first: 1,
last: 1,
},
];
context.colpanes = [
{
first: 1,
last: 1,
},
];
editor.ecell = null;
editor.range = { hasrange: false };
editor.range2 = { hasrange: false };
range = editor.range;
context.highlights = {};
highlights = context.highlights;
for (i = 0; i < lines.length; i++) {
line = lines[i];
parts = line.split(':');
setting = parts[0];
switch (setting) {
case 'version':
break;
case 'rowpane':
context.rowpanes[parts[1] - 0] = {
first: parts[2] - 0,
last: parts[3] - 0,
};
break;
case 'colpane':
context.colpanes[parts[1] - 0] = {
first: parts[2] - 0,
last: parts[3] - 0,
};
break;
case 'ecell':
editor.ecell = TableEditorSC.coordToCr(parts[1]);
editor.ecell.coord = parts[1];
highlights[parts[1]] = 'cursor';
break;
case 'range':
range.hasrange = true;
range.anchorcoord = parts[1];
cr = TableEditorSC.coordToCr(range.anchorcoord);
range.anchorrow = cr.row;
range.anchorcol = cr.col;
range.top = parts[2] - 0;
range.bottom = parts[3] - 0;
range.left = parts[4] - 0;
range.right = parts[5] - 0;
for (row = range.top; row <= range.bottom; row++) {
for (col = range.left; col <= range.right; col++) {
coord = TableEditorSC.crToCoord(col, row);
if (highlights[coord] != 'cursor') {
highlights[coord] = 'range';
}
}
}
break;
default:
if (editor.SettingsCallbacks[setting]) {
editor.SettingsCallbacks[setting].load(editor, setting, line, flags);
}
break;
}
}
return;
};
TableEditorSC.EditorRenderSheet = function (editor) {
editor.EditorMouseUnregister();
var sheetobj = editor.context.sheetobj;
if (sheetobj.reRenderCellList != null && TableEditorSC._app && sheetobj.widgetsClean === true) {
for (var index in sheetobj.reRenderCellList) {
var coord = sheetobj.reRenderCellList[index];
var valuetype = sheetobj.cells[coord].valuetype;
if (valuetype.charAt(1) != 'i' || valuetype != sheetobj.cells[coord].prevvaluetype) {
var cr = TableEditorSC.coordToCr(coord);
var cell = TableEditorSC.GetEditorCellElement(editor, cr.row, cr.col);
if (cell != null) editor.ReplaceCell(cell, cr.row, cr.col);
}
}
sheetobj.reRenderCellList = [];
} else {
editor.fullgrid = editor.context.RenderSheet(editor.fullgrid);
if (sheetobj.reRenderCellList != null && TableEditorSC._app) {
sheetobj.widgetsClean = true;
sheetobj.reRenderCellList = [];
}
}
if (editor.ecell) editor.SetECellHeaders('selected');
TableEditorSC.AssignID(editor, editor.fullgrid, 'fullgrid');
if (!TableEditorSC._app) editor.fullgrid.className = 'te_download';
editor.EditorMouseRegister();
};
TableEditorSC.EditorScheduleSheetCommands = function (editor, cmdstr, saveundo, ignorebusy) {
if (editor.state != 'start' && !ignorebusy) {
return;
}
if (editor.busy && !ignorebusy) {
editor.deferredCommands.push({
cmdstr,
saveundo,
});
return;
}
var cmdTokens = cmdstr.split(' ');
switch (cmdTokens[0]) {
case 'recalc':
case 'redisplay':
editor.context.sheetobj.ScheduleSheetCommands(cmdstr, false);
break;
case 'undo':
if (TableEditorSC._app) editor.context.sheetobj.widgetsClean = false;
editor.SheetUndo();
break;
case 'redo':
if (TableEditorSC._app) editor.context.sheetobj.widgetsClean = false;
editor.SheetRedo();
break;
case 'setemailparameters':
var emailsSent;
try {
emailsSent = TableEditorSC.TriggerIoAction.Email(cmdTokens[1], cmdTokens[2]);
} finally {
if (!emailsSent || !emailsSent.length) {
editor.context.sheetobj.ScheduleSheetCommands('', false);
}
}
break;
default:
editor.context.sheetobj.ScheduleSheetCommands(cmdstr, saveundo);
break;
}
};
TableEditorSC.EditorSheetStatusCallback = function (recalcdata, status, arg, editor) {
var f, cell, dcmd;
var sheetobj = editor.context.sheetobj;
var signalstatus = function (s) {
for (f in editor.StatusCallback) {
if (editor.StatusCallback[f].func) {
editor.StatusCallback[f].func(editor, s, arg, editor.StatusCallback[f].params);
}
}
};
switch (status) {
case 'startup':
break;
case 'cmdstart':
editor.busy = true;
sheetobj.celldisplayneeded = '';
break;
case 'cmdextension':
break;
case 'cmdend':
signalstatus(status);
if (sheetobj.changedrendervalues) {
editor.context.PrecomputeSheetFontsAndLayouts();
editor.context.CalculateCellSkipData();
sheetobj.changedrendervalues = false;
}
if (sheetobj.celldisplayneeded && !sheetobj.renderneeded) {
if (
sheetobj.cells[sheetobj.celldisplayneeded] &&
sheetobj.cells[sheetobj.celldisplayneeded].valuetype != 'e#N/A'
) {
var cr = TableEditorSC.coordToCr(sheetobj.celldisplayneeded);
cell = TableEditorSC.GetEditorCellElement(editor, cr.row, cr.col);
editor.ReplaceCell(cell, cr.row, cr.col);
}
}
if (editor.deferredCommands.length) {
dcmd = editor.deferredCommands.shift();
editor.EditorScheduleSheetCommands(dcmd.cmdstr, dcmd.saveundo, true);
return;
}
if (
sheetobj.attribs.needsrecalc &&
(sheetobj.attribs.recalc != 'off' || sheetobj.recalconce) &&
editor.recalcFunction
) {
editor.FitToEditTable();
sheetobj.renderneeded = false;
if (sheetobj.recalconce) delete sheetobj.recalconce;
editor.recalcFunction(editor);
} else {
if (sheetobj.renderneeded) {
editor.FitToEditTable();
sheetobj.renderneeded = false;
editor.ScheduleRender(false);
} else {
editor.SchedulePositionCalculations();
}
}
if (sheetobj.hiddencolrow == 'col') {
if (editor.ecell !== null) {
var col = editor.ecell.col;
while (sheetobj.colattribs.hide[TableEditorSC.rcColname(col)] == 'yes') {
col++;
}
var coord = TableEditorSC.crToCoord(col, editor.ecell.row);
editor.MoveECell(coord);
sheetobj.hiddencolrow = '';
}
}
if (sheetobj.hiddencolrow == 'row') {
if (editor.ecell !== null) {
var row = editor.ecell.row;
while (sheetobj.rowattribs.hide[row] == 'yes') {
row++;
}
var coord = TableEditorSC.crToCoord(editor.ecell.col, row);
editor.MoveECell(coord);
sheetobj.hiddencolrow = '';
}
}
return;
case 'calcstart':
editor.busy = true;
break;
case 'calccheckdone':
case 'calcorder':
case 'calcstep':
case 'calcloading':
case 'calcserverfunc':
break;
case 'calcfinished':
signalstatus(status);
editor.ScheduleRender(false);
return;
case 'schedrender':
editor.busy = true;
break;
case 'renderdone':
break;
case 'schedposcalc':
editor.busy = true;
break;
case 'doneposcalc':
if (editor.deferredEmailCommands.length) {
signalstatus(status);
var emailcmd = editor.deferredEmailCommands.shift();
editor.EditorScheduleSheetCommands(emailcmd.cmdstr, emailcmd.saveundo, true);
return;
}
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();
}
return;
case 'emailing':
case 'confirmemailsent':
break;
default:
(function(){})('Unknown status: ' + status);
break;
}
signalstatus(status);
return;
};
TableEditorSC.EditorGetStatuslineString = function (editor, status, arg, params) {
var scc = TableEditorSC.Constants;
var sstr, progress, coord, circ, r, c, cell, sum;
progress = '';
switch (status) {
case 'moveecell':
case 'rangechange':
case 'startup':
break;
case 'cmdstart':
params.command = true;
document.body.style.cursor = 'progress';
editor.griddiv.style.cursor = 'progress';
progress = scc.s_statusline_executing;
break;
case 'cmdextension':
progress = 'Command Extension: ' + arg;
break;
case 'cmdend':
params.command = false;
break;
case 'schedrender':
progress = scc.s_statusline_displaying;
break;
case 'renderdone':
progress = ' ';
break;
case 'schedposcalc':
progress = scc.s_statusline_displaying;
break;
case 'cmdendnorender':
case 'doneposcalc':
document.body.style.cursor = 'default';
editor.griddiv.style.cursor = 'default';
if (params.emailing == 'sent') {
progress = params.emailreponse;
params.emailreponse = '';
params.emailing = 'done';
}
break;
case 'calcorder':
progress =
scc.s_statusline_ordering + Math.floor((100 * arg.count) / (arg.total || 1)) + '%';
break;
case 'calcstep':
progress =
scc.s_statusline_calculating + Math.floor((100 * arg.count) / (arg.total || 1)) + '%';
break;
case 'calcloading':
progress =
scc.s_statusline_calculatingls +
': ' +
(SocialCalc.Callbacks.untrustedContent
? SocialCalc.special_chars(arg.sheetname + '')
: arg.sheetname);
break;
case 'calcserverfunc':
progress =
scc.s_statusline_calculating +
Math.floor((100 * arg.count) / (arg.total || 1)) +
'%, ' +
scc.s_statusline_doingserverfunc +
arg.funcname +
scc.s_statusline_incell +
arg.coord;
break;
case 'calcstart':
params.calculating = true;
document.body.style.cursor = 'progress';
editor.griddiv.style.cursor = 'progress';
progress = scc.s_statusline_calcstart;
break;
case 'calccheckdone':
break;
case 'calcfinished':
params.calculating = false;
break;
case 'emailing':
params.emailing = 'sending';
params.emailreponse = '';
break;
case 'confirmemailsent':
params.emailing = 'sent';
if (typeof params.emailreponse === 'undefined') params.emailreponse = '';
params.emailreponse += arg;
break;
default:
progress = status;
break;
}
if (params.emailing == 'sending') {
progress += scc.s_statusline_sendemail;
}
if (params.emailing == 'sent') {
progress += params.emailreponse;
}
if (!progress && params.calculating) {
progress = scc.s_statusline_calculating;
}
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[TableEditorSC.crToCoord(c, r)];
if (!cell) continue;
if (cell.valuetype && cell.valuetype.charAt(0) == 'n') {
sum += cell.datavalue - 0;
}
}
}
sum = TableEditorSC.FormatNumber.formatNumberWithFormat(sum, '[,]General', '');
coord =
TableEditorSC.crToCoord(editor.range.left, editor.range.top) +
':' +
TableEditorSC.crToCoord(editor.range.right, editor.range.bottom);
progress =
coord +
' (' +
(editor.range.right - editor.range.left + 1) +
'x' +
(editor.range.bottom - editor.range.top + 1) +
') ' +
scc.s_statusline_sum +
'=' +
sum +
' ' +
progress;
}
sstr = (editor.ecell || {}).coord + ' ' + progress;
if (!params.calculating && editor.context.sheetobj.attribs.needsrecalc == 'yes') {
sstr += ' ' + scc.s_statusline_recalcneeded;
}
circ = editor.context.sheetobj.attribs.circularreferencecell;
if (circ) {
circ = circ.replace(/\|/, ' referenced by ');
sstr += ' ' + scc.s_statusline_circref + circ + '';
}
sstr += '';
return sstr;
};
TableEditorSC.EditorMouseInfo = {
registeredElements: [],
editor: null,
element: null,
ignore: false,
mousedowncoord: '',
mouselastcoord: '',
mouseresizecol: '',
mouseresizeclientx: null,
mouseresizedisplay: null,
};
TableEditorSC.EditorMouseRegister = function (editor) {
var mouseinfo = TableEditorSC.EditorMouseInfo;
var element = editor.fullgrid;
var i;
for (i = 0; i < mouseinfo.registeredElements.length; i++) {
if (mouseinfo.registeredElements[i].editor == editor) {
if (mouseinfo.registeredElements[i].element == element) {
return;
}
break;
}
}
if (i < mouseinfo.registeredElements.length) {
mouseinfo.registeredElements[i].element = element;
} else {
mouseinfo.registeredElements.push({
element,
editor,
});
}
element.addEventListener('mousedown', TableEditorSC.ProcessEditorMouseDown, false);
element.addEventListener('dblclick', TableEditorSC.ProcessEditorDblClick, false);
mouseinfo.ignore = false;
return;
};
TableEditorSC.EditorMouseUnregister = function (editor) {
var mouseinfo = TableEditorSC.EditorMouseInfo;
var i, oldelement;
for (i = 0; i < mouseinfo.registeredElements.length; i++) {
if (mouseinfo.registeredElements[i].editor == editor) {
break;
}
}
if (i < mouseinfo.registeredElements.length) {
oldelement = mouseinfo.registeredElements[i].element;
oldelement.removeEventListener('mousedown', TableEditorSC.ProcessEditorMouseDown, false);
oldelement.removeEventListener('dblclick', TableEditorSC.ProcessEditorDblClick, false);
mouseinfo.registeredElements.splice(i, 1);
}
return;
};
TableEditorSC.StopPropagation = function (event) {
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
if (event.preventDefault) event.preventDefault();
else event.returnValue = false;
};
TableEditorSC.SetMouseMoveUp = function (move, up, element, event) {
document.addEventListener('mousemove', move, true);
document.addEventListener('mouseup', up, true);
TableEditorSC.StopPropagation(event);
};
TableEditorSC.RemoveMouseMoveUp = function (move, up, element, event) {
TableEditorSC.StopPropagation(event);
document.removeEventListener('mousemove', move, true);
document.removeEventListener('mouseup', up, true);
};
TableEditorSC.ProcessEditorMouseDown = function (e) {
var editor, result, coord, range;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var ele = event.target || event.srcElement;
var target = ele;
if (target.nodeType == 3) target = target.parentNode;
var mobj;
if (mouseinfo.ignore) return;
for (mobj = null; !mobj && ele; ele = ele.parentNode) {
mobj = TableEditorSC.LookupElement(ele, mouseinfo.registeredElements);
}
if (!mobj) {
mouseinfo.editor = null;
return;
}
editor = mobj.editor;
mouseinfo.element = ele;
range = editor.range;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
if (!result) return;
mouseinfo.editor = editor;
if (result.rowheader) {
if (result.rowselect) TableEditorSC.ProcessEditorRowselectMouseDown(event, ele, result);
else TableEditorSC.ProcessEditorRowsizeMouseDown(event, ele, result);
return;
}
if (result.colheader) {
if (result.colselect) TableEditorSC.ProcessEditorColselectMouseDown(event, ele, result);
else TableEditorSC.ProcessEditorColsizeMouseDown(event, ele, result);
return;
}
if (!result.coord) return;
if (!range.hasrange) {
if (event.shiftKey) editor.RangeAnchor();
}
coord = editor.MoveECell(result.coord);
if (TableEditorSC._app == true) {
TableEditorSC.CmdGotFocus(true);
return;
}
var clickedCell = editor.context.sheetobj.cells[coord];
if (clickedCell && clickedCell.valuetype.charAt(1) == 'i') {
var formula_name = clickedCell.valuetype.substring(2);
var widget_id = formula_name + '_' + coord;
if (target && widget_id == target.id)
TableEditorSC.CmdGotFocus(document.getElementById(widget_id));
return;
}
if (range.hasrange) {
if (event.shiftKey) editor.RangeExtend();
else editor.RangeRemove();
}
mouseinfo.mousedowncoord = coord;
mouseinfo.mouselastcoord = coord;
editor.EditorMouseRange(coord);
TableEditorSC.KeyboardSetFocus(editor);
if (editor.state != 'start' && editor.inputBox) editor.inputBox.element.focus();
TableEditorSC.SetMouseMoveUp(
TableEditorSC.ProcessEditorMouseMove,
TableEditorSC.ProcessEditorMouseUp,
ele,
event,
);
return;
};
TableEditorSC.EditorMouseRange = function (editor, coord) {
var inputtext, wval;
var range = editor.range;
switch (editor.state) {
case 'input':
inputtext = editor.inputBox.GetText();
wval = editor.workingvalues;
if (
('(+-*/,:!&<>=^'.indexOf(inputtext.slice(-1)) >= 0 && inputtext.slice(0, 1) == '=') ||
inputtext == '='
) {
wval.partialexpr = inputtext;
}
if (wval.partialexpr) {
if (coord) {
if (range.hasrange) {
editor.inputBox.SetText(
wval.partialexpr +
TableEditorSC.crToCoord(range.left, range.top) +
':' +
TableEditorSC.crToCoord(range.right, range.bottom),
);
} else {
editor.inputBox.SetText(wval.partialexpr + coord);
}
}
} else {
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
editor.cellhandles.ShowCellHandles(true);
editor.EditorSaveEdit();
editor.inputBox.DisplayCellContents(null);
}
break;
case 'inputboxdirect':
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
editor.cellhandles.ShowCellHandles(true);
editor.EditorSaveEdit();
editor.inputBox.DisplayCellContents(null);
break;
}
};
TableEditorSC.ProcessEditorMouseMove = function (e) {
var editor, result;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
editor = mouseinfo.editor;
if (!editor) return;
if (mouseinfo.ignore) return;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
if (!result) return;
if (result && !result.coord) {
TableEditorSC.SetDragAutoRepeat(editor, result);
return;
}
TableEditorSC.SetDragAutoRepeat(editor, null);
if (!result.coord) return;
if (result.coord != mouseinfo.mouselastcoord) {
if (!event.shiftKey && !editor.range.hasrange) {
editor.RangeAnchor(mouseinfo.mousedowncoord);
}
editor.MoveECell(result.coord);
editor.RangeExtend();
}
mouseinfo.mouselastcoord = result.coord;
editor.EditorMouseRange(result.coord);
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.ProcessEditorMouseUp = function (e) {
var editor, element, result;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
editor = mouseinfo.editor;
if (!editor) return;
if (mouseinfo.ignore) return;
element = mouseinfo.element;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
TableEditorSC.SetDragAutoRepeat(editor, null);
if (!result) return;
if (!result.coord) result.coord = editor.ecell.coord;
if (editor.range.hasrange) {
editor.MoveECell(result.coord);
editor.RangeExtend();
} else if (result.coord && result.coord != mouseinfo.mousedowncoord) {
editor.RangeAnchor(mouseinfo.mousedowncoord);
editor.MoveECell(result.coord);
editor.RangeExtend();
}
editor.EditorMouseRange(result.coord);
mouseinfo.editor = null;
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.ProcessEditorMouseMove,
TableEditorSC.ProcessEditorMouseUp,
element,
event,
);
return false;
};
TableEditorSC.ProcessEditorColsizeMouseDown = function (e, ele, result) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
mouseinfo.mouseresizecolnum = result.coltoresize;
mouseinfo.mouseresizecol = TableEditorSC.rcColname(result.coltoresize);
mouseinfo.mousedownclientx = clientX;
mouseinfo.mousecoltounhide = result.coltounhide;
if (result.coltoresize) {
var sizedisplay = SocialCalc.document.createElement('div');
mouseinfo.mouseresizedisplay = sizedisplay;
sizedisplay.style.width = 'auto';
sizedisplay.style.position = 'absolute';
sizedisplay.style.zIndex = '100';
sizedisplay.style.top = editor.headposition.top + 'px';
sizedisplay.style.left = editor.colpositions[result.coltoresize] + 'px';
sizedisplay.innerHTML =
'
| | ' +
'' +
editor.context.colwidth[mouseinfo.mouseresizecolnum] +
' |
';
var szTarget =
sizedisplay.firstChild &&
sizedisplay.firstChild.lastChild &&
sizedisplay.firstChild.lastChild.firstChild &&
sizedisplay.firstChild.lastChild.firstChild.childNodes[0];
if (szTarget) TableEditorSC.setStyles(szTarget, 'filter:alpha(opacity=85);opacity:.85;');
editor.toplevel.appendChild(sizedisplay);
}
TableEditorSC.SetMouseMoveUp(
TableEditorSC.ProcessEditorColsizeMouseMove,
TableEditorSC.ProcessEditorColsizeMouseUp,
editor.toplevel,
event,
);
return;
};
TableEditorSC.ProcessEditorColsizeMouseMove = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
if (mouseinfo.mouseresizecolnum) {
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var newsize =
editor.context.colwidth[mouseinfo.mouseresizecolnum] -
0 +
(clientX - mouseinfo.mousedownclientx);
if (newsize < TableEditorSC.Constants.defaultMinimumColWidth)
newsize = TableEditorSC.Constants.defaultMinimumColWidth;
var sizedisplay = mouseinfo.mouseresizedisplay;
sizedisplay.innerHTML =
'';
TableEditorSC.setStyles(
sizedisplay.firstChild.lastChild.firstChild.childNodes[0],
'filter:alpha(opacity=85);opacity:.85;',
);
}
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.ProcessEditorColsizeMouseUp = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.ProcessEditorColsizeMouseMove,
TableEditorSC.ProcessEditorColsizeMouseUp,
editor.toplevel,
event,
);
if (mouseinfo.mousecoltounhide) {
editor.EditorScheduleSheetCommands(
'set ' + TableEditorSC.rcColname(mouseinfo.mousecoltounhide) + ' hide',
true,
false,
);
} else if (mouseinfo.mouseresizecolnum) {
var newsize =
editor.context.colwidth[mouseinfo.mouseresizecolnum] -
0 +
(clientX - mouseinfo.mousedownclientx);
if (newsize < TableEditorSC.Constants.defaultMinimumColWidth)
newsize = TableEditorSC.Constants.defaultMinimumColWidth;
editor.EditorScheduleSheetCommands(
'set ' + mouseinfo.mouseresizecol + ' width ' + newsize,
true,
false,
);
if (editor.timeout) window.clearTimeout(editor.timeout);
editor.timeout = window.setTimeout(TableEditorSC.FinishColRowSize, 1);
}
return false;
};
TableEditorSC.FinishColRowSize = function () {
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
editor.toplevel.removeChild(mouseinfo.mouseresizedisplay);
mouseinfo.mouseresizedisplay = null;
mouseinfo.editor = null;
return;
};
TableEditorSC.ProcessEditorRowselectMouseDown = function (e, ele, result) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var sheet = TableEditorSC.GetSpreadsheetControlObject().sheet;
var coord1 = TableEditorSC.crToCoord(1, result.row);
var coord2 = TableEditorSC.crToCoord(sheet.LastCol(), result.row);
var coord3 = TableEditorSC.crToCoord(editor.firstscrollingcol, result.row);
editor.RangeAnchor(coord1);
editor.RangeExtend(coord2);
editor.MoveECell(coord3);
TableEditorSC.SetMouseMoveUp(
TableEditorSC.ProcessEditorRowselectMouseMove,
TableEditorSC.ProcessEditorRowselectMouseUp,
editor.toplevel,
event,
);
};
TableEditorSC.ProcessEditorRowselectMouseMove = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var sheet = TableEditorSC.GetSpreadsheetControlObject().sheet;
if (!editor) return;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
var result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
var coord2 = TableEditorSC.crToCoord(sheet.LastCol(), result.row);
var coord3 = TableEditorSC.crToCoord(editor.firstscrollingcol, result.row);
editor.RangeExtend(coord2);
editor.MoveECell(coord3);
return;
};
TableEditorSC.ProcessEditorRowselectMouseUp = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.ProcessEditorRowselectMouseMove,
TableEditorSC.ProcessEditorRowselectMouseUp,
editor.toplevel,
event,
);
return;
};
TableEditorSC.ProcessEditorColselectMouseDown = function (e, ele, result) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var sheet = TableEditorSC.GetSpreadsheetControlObject().sheet;
var coord1 = TableEditorSC.crToCoord(result.col, 1);
var coord2 = TableEditorSC.crToCoord(result.col, sheet.LastRow());
var coord3 = TableEditorSC.crToCoord(result.col, editor.firstscrollingrow);
editor.RangeAnchor(coord1);
editor.RangeExtend(coord2);
editor.MoveECell(coord3);
TableEditorSC.SetMouseMoveUp(
TableEditorSC.ProcessEditorColselectMouseMove,
TableEditorSC.ProcessEditorColselectMouseUp,
editor.toplevel,
event,
);
};
TableEditorSC.ProcessEditorColselectMouseMove = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var sheet = TableEditorSC.GetSpreadsheetControlObject().sheet;
if (!editor) return;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
var result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
var coord2 = TableEditorSC.crToCoord(result.col, sheet.LastRow());
var coord3 = TableEditorSC.crToCoord(result.col, editor.firstscrollingrow);
editor.RangeExtend(coord2);
editor.MoveECell(coord3);
return;
};
TableEditorSC.ProcessEditorColselectMouseUp = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.ProcessEditorColselectMouseMove,
TableEditorSC.ProcessEditorColselectMouseUp,
editor.toplevel,
event,
);
return;
};
TableEditorSC.ProcessEditorRowsizeMouseDown = function (e, ele, result) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
var pos = TableEditorSC.GetSpreadsheetControlObject().spreadsheetDiv.firstChild.offsetHeight;
var clientY = event.clientY - pos;
mouseinfo.mouseresizerownum = result.rowtoresize;
mouseinfo.mouseresizerow = result.rowtoresize;
mouseinfo.mousedownclienty = clientY;
mouseinfo.mouserowtounhide = result.rowtounhide;
if (result.rowtoresize) {
var sizedisplay = SocialCalc.document.createElement('div');
mouseinfo.mouseresizedisplay = sizedisplay;
sizedisplay.style.width = editor.context.totalwidth + 'px';
sizedisplay.style.height = editor.rowpositions[result.rowtoresize] + 'px';
sizedisplay.style.position = 'absolute';
sizedisplay.style.zIndex = '100';
sizedisplay.style.top = editor.rowpositions[result.rowtoresize] + 'px';
sizedisplay.style.left = editor.headposition.left + 'px';
sizedisplay.innerHTML =
'| | ' +
'' +
editor.context.rowheight[mouseinfo.mouseresizerownum] +
' |
';
var szTarget2 =
sizedisplay.firstChild &&
sizedisplay.firstChild.lastChild &&
sizedisplay.firstChild.lastChild.firstChild &&
sizedisplay.firstChild.lastChild.firstChild.childNodes[0];
if (szTarget2) TableEditorSC.setStyles(szTarget2, 'filter:alpha(opacity=85);opacity:.5;');
editor.toplevel.appendChild(sizedisplay);
}
TableEditorSC.SetMouseMoveUp(
TableEditorSC.ProcessEditorRowsizeMouseMove,
TableEditorSC.ProcessEditorRowsizeMouseUp,
editor.toplevel,
event,
);
return;
};
TableEditorSC.ProcessEditorRowsizeMouseMove = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
if (mouseinfo.mouseresizerownum) {
var pos = TableEditorSC.GetSpreadsheetControlObject().spreadsheetDiv.firstChild.offsetHeight;
var clientY = event.clientY - pos;
var newsize =
editor.context.rowheight[mouseinfo.mouseresizerownum] -
0 +
(clientY - mouseinfo.mousedownclienty);
if (newsize < TableEditorSC.Constants.defaultAssumedRowHeight)
newsize = TableEditorSC.Constants.defaultAssumedRowHeight;
var sizedisplay = mouseinfo.mouseresizedisplay;
sizedisplay.innerHTML =
'';
TableEditorSC.setStyles(
sizedisplay.firstChild.lastChild.firstChild.childNodes[0],
'filter:alpha(opacity=85);opacity:.5;',
);
}
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.ProcessEditorRowsizeMouseUp = function (e) {
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
var pos = TableEditorSC.GetSpreadsheetControlObject().spreadsheetDiv.firstChild.offsetHeight;
var clientY = event.clientY - pos;
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.ProcessEditorRowsizeMouseMove,
TableEditorSC.ProcessEditorRowsizeMouseUp,
editor.toplevel,
event,
);
if (mouseinfo.mouserowtounhide) {
editor.EditorScheduleSheetCommands(
'set ' + mouseinfo.mouserowtounhide + ' hide',
true,
false,
);
} else if (mouseinfo.mouseresizerownum) {
var newsize =
editor.context.rowheight[mouseinfo.mouseresizerownum] -
0 +
(clientY - mouseinfo.mousedownclienty);
if (newsize < TableEditorSC.Constants.defaultAssumedRowHeight)
newsize = TableEditorSC.Constants.defaultAssumedRowHeight;
editor.EditorScheduleSheetCommands(
'set ' + mouseinfo.mouseresizerownum + ' height ' + newsize,
true,
false,
);
if (editor.timeout) window.clearTimeout(editor.timeout);
editor.timeout = window.setTimeout(TableEditorSC.FinishColRowSize, 1);
}
return false;
};
TableEditorSC.AutoRepeatInfo = {
timer: null,
mouseinfo: null,
repeatinterval: 1e3,
editor: null,
repeatcallback: null,
};
TableEditorSC.SetDragAutoRepeat = function (editor, mouseinfo, callback) {
var repeatinfo = TableEditorSC.AutoRepeatInfo;
var coord, direction;
repeatinfo.repeatcallback = callback;
if (!mouseinfo) {
if (repeatinfo.timer) {
window.clearTimeout(repeatinfo.timer);
repeatinfo.timer = null;
}
repeatinfo.mouseinfo = null;
return;
}
repeatinfo.editor = editor;
if (repeatinfo.mouseinfo) {
if (mouseinfo.rowheader || mouseinfo.rowfooter) {
if (mouseinfo.row != repeatinfo.mouseinfo.row) {
coord = TableEditorSC.crToCoord(editor.ecell.col, mouseinfo.row);
if (repeatinfo.repeatcallback) {
direction =
mouseinfo.row < repeatinfo.mouseinfo.row
? 'left'
: mouseinfo.row > repeatinfo.mouseinfo.row
? 'right'
: '';
repeatinfo.repeatcallback(coord, direction);
} else {
editor.MoveECell(coord);
editor.MoveECell(coord);
editor.RangeExtend();
editor.EditorMouseRange(coord);
}
}
} else if (mouseinfo.colheader || mouseinfo.colfooter) {
if (mouseinfo.col != repeatinfo.mouseinfo.col) {
coord = TableEditorSC.crToCoord(mouseinfo.col, editor.ecell.row);
if (repeatinfo.repeatcallback) {
direction =
mouseinfo.row < repeatinfo.mouseinfo.row
? 'left'
: mouseinfo.row > repeatinfo.mouseinfo.row
? 'right'
: '';
repeatinfo.repeatcallback(coord, direction);
} else {
editor.MoveECell(coord);
editor.RangeExtend();
editor.EditorMouseRange(coord);
}
}
}
}
repeatinfo.mouseinfo = mouseinfo;
if (mouseinfo.distance < 5) repeatinfo.repeatinterval = 333;
else if (mouseinfo.distance < 10) repeatinfo.repeatinterval = 250;
else if (mouseinfo.distance < 25) repeatinfo.repeatinterval = 100;
else if (mouseinfo.distance < 35) repeatinfo.repeatinterval = 75;
else {
if (repeatinfo.timer) {
window.clearTimeout(repeatinfo.timer);
repeatinfo.timer = null;
}
return;
}
if (!repeatinfo.timer) {
repeatinfo.timer = window.setTimeout(TableEditorSC.DragAutoRepeat, repeatinfo.repeatinterval);
}
return;
};
TableEditorSC.DragAutoRepeat = function () {
var repeatinfo = TableEditorSC.AutoRepeatInfo;
var mouseinfo = repeatinfo.mouseinfo;
var direction, coord, cr;
if (mouseinfo.rowheader) direction = 'left';
else if (mouseinfo.rowfooter) direction = 'right';
else if (mouseinfo.colheader) direction = 'up';
else if (mouseinfo.colfooter) direction = 'down';
if (repeatinfo.repeatcallback) {
cr = TableEditorSC.coordToCr(repeatinfo.editor.ecell.coord);
if (direction == 'left' && cr.col > 1) cr.col--;
else if (direction == 'right') cr.col++;
else if (direction == 'up' && cr.row > 1) cr.row--;
else if (direction == 'down') cr.row++;
coord = TableEditorSC.crToCoord(cr.col, cr.row);
repeatinfo.repeatcallback(coord, direction);
} else {
coord = repeatinfo.editor.MoveECellWithKey('[a' + direction + ']shifted');
if (coord) repeatinfo.editor.EditorMouseRange(coord);
}
repeatinfo.timer = window.setTimeout(TableEditorSC.DragAutoRepeat, repeatinfo.repeatinterval);
};
TableEditorSC.ProcessEditorDblClick = function (e) {
var editor, result;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
var ele = event.target || event.srcElement;
var mobj;
if (mouseinfo.ignore) return;
for (mobj = null; !mobj && ele; ele = ele.parentNode) {
mobj = TableEditorSC.LookupElement(ele, mouseinfo.registeredElements);
}
if (!mobj) {
mouseinfo.editor = null;
return;
}
editor = mobj.editor;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
if (!result || !result.coord) return;
mouseinfo.editor = editor;
mouseinfo.element = ele;
switch (editor.state) {
case 'start':
TableEditorSC.EditorOpenCellEdit(editor);
break;
case 'input':
break;
default:
break;
}
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.EditorOpenCellEdit = function (editor) {
var wval;
if (!editor.ecell) return true;
if (!editor.inputBox) return true;
if (editor.inputBox.element.disabled) return true;
editor.inputBox.ShowInputBox(true);
editor.inputBox.Focus();
editor.inputBox.SetText('');
editor.inputBox.DisplayCellContents();
editor.inputBox.Select('end');
wval = editor.workingvalues;
wval.partialexpr = '';
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
return;
};
TableEditorSC.EditorProcessKey = function (editor, ch, e) {
var result, coord, inputtext, f;
var wval = editor.workingvalues;
var range = editor.range;
if (typeof ch != 'string') ch = '';
switch (editor.state) {
case 'start':
if (e.shiftKey && ch.substr(0, 2) == '[a') {
ch = ch + 'shifted';
}
if (ch == '[enter]') ch = '[adown]';
if (ch == '[tab]') ch = e.shiftKey ? '[aleft]' : '[aright]';
if (ch.substr(0, 2) == '[a' || ch.substr(0, 3) == '[pg' || ch == '[home]') {
result = editor.MoveECellWithKey(ch);
return !result;
}
if (ch == '[del]' || ch == '[backspace]') {
if (!editor.noEdit && !editor.ECellReadonly()) {
editor.EditorApplySetCommandsToRange('empty', '');
}
break;
}
if (ch == '[esc]') {
if (range.hasrange) {
editor.RangeRemove();
editor.MoveECell(range.anchorcoord);
for (f in editor.StatusCallback) {
editor.StatusCallback[f].func(
editor,
'specialkey',
ch,
editor.StatusCallback[f].params,
);
}
}
return false;
}
if (ch == '[f2]') {
if (editor.noEdit || editor.ECellReadonly()) return true;
TableEditorSC.EditorOpenCellEdit(editor);
editor.state = 'inputboxdirect';
return false;
}
if ((ch.length > 1 && ch.substr(0, 1) == '[') || ch.length == 0) {
if (editor.ctrlkeyFunction && ch.length > 0) {
return editor.ctrlkeyFunction(editor, ch);
} else {
return true;
}
}
if (!editor.ecell) return true;
if (!editor.inputBox) return true;
if (editor.ECellReadonly()) return true;
editor.inputBox.element.disabled = false;
editor.state = 'input';
editor.inputBox.ShowInputBox(true);
editor.inputBox.Focus();
editor.inputBox.SetText(ch);
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':
inputtext = editor.inputBox.GetText();
if (editor.inputBox.skipOne) return false;
if (ch == '[esc]' || ch == '[enter]' || ch == '[tab]' || (ch && ch.substr(0, 2) == '[a')) {
if (
('(+-*/,:!&<>=^'.indexOf(inputtext.slice(-1)) >= 0 && inputtext.slice(0, 1) == '=') ||
inputtext == '='
) {
wval.partialexpr = inputtext;
}
if (wval.partialexpr) {
if (e.shiftKey && ch.substr(0, 2) == '[a') {
ch = ch + 'shifted';
}
coord = editor.MoveECellWithKey(ch);
if (coord) {
if (range.hasrange) {
editor.inputBox.SetText(
wval.partialexpr +
TableEditorSC.crToCoord(range.left, range.top) +
':' +
TableEditorSC.crToCoord(range.right, range.bottom),
);
} else {
editor.inputBox.SetText(wval.partialexpr + coord);
}
return false;
}
}
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
editor.cellhandles.ShowCellHandles(true);
if (ch != '[esc]') {
editor.EditorSaveEdit();
if (editor.ecell.coord != wval.ecoord) {
editor.MoveECell(wval.ecoord);
}
if (ch == '[enter]') ch = '[adown]';
if (ch == '[tab]') ch = e.shiftKey ? '[aleft]' : '[aright]';
if (ch.substr(0, 2) == '[a') {
editor.MoveECellWithKey(ch);
}
} else {
editor.inputBox.DisplayCellContents();
editor.RangeRemove();
editor.MoveECell(wval.ecoord);
}
break;
}
if (wval.partialexpr && ch == '[backspace]') {
editor.inputBox.SetText(wval.partialexpr);
wval.partialexpr = '';
editor.RangeRemove();
editor.MoveECell(wval.ecoord);
editor.inputBox.ShowInputBox(true);
return false;
}
if (ch == '[f2]') {
editor.state = 'inputboxdirect';
return false;
}
if (range.hasrange) editor.RangeRemove();
editor.MoveECell(wval.ecoord);
if (wval.partialexpr) {
editor.inputBox.ShowInputBox(true);
wval.partialexpr = '';
}
return true;
case 'inputboxdirect':
inputtext = editor.inputBox.GetText();
if (ch == '[esc]' || ch == '[enter]' || ch == '[tab]') {
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
editor.cellhandles.ShowCellHandles(true);
if (ch == '[esc]') {
editor.inputBox.DisplayCellContents();
} else {
editor.EditorSaveEdit();
if (editor.ecell.coord != wval.ecoord) {
editor.MoveECell(wval.ecoord);
}
if (ch == '[enter]') ch = '[adown]';
if (ch == '[tab]') ch = e.shiftKey ? '[aleft]' : '[aright]';
if (ch.substr(0, 2) == '[a') {
editor.MoveECellWithKey(ch);
}
}
break;
}
if (ch == '[f2]') {
editor.state = 'input';
return false;
}
return true;
case 'skip-and-start':
editor.state = 'start';
editor.cellhandles.ShowCellHandles(true);
return false;
default:
return true;
}
return false;
};
TableEditorSC.EditorAddToInput = function (editor, str, prefix) {
var wval = editor.workingvalues;
if (editor.noEdit || editor.ECellReadonly()) return;
switch (editor.state) {
case 'start':
editor.state = 'input';
editor.inputBox.ShowInputBox(true);
editor.inputBox.element.disabled = false;
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;
}
};
TableEditorSC.EditorDisplayCellContents = function (editor) {
if (editor.inputBox) editor.inputBox.DisplayCellContents();
};
TableEditorSC.EditorSaveEdit = function (editor, text) {
var 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();
oldvalue = TableEditorSC.GetCellContents(sheetobj, wval.ecoord) + '';
if (value == oldvalue) {
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);
valueinfo = TableEditorSC.DetermineValueType(value);
if (valueinfo.type.charAt(0) == 't') {
type = 'text ' + valueinfo.type;
}
} else if (value.length == 0) {
type = 'empty';
} else {
valueinfo = TableEditorSC.DetermineValueType(value);
if (valueinfo.type == 'n' && value == valueinfo.value + '') {
type = 'value n';
} else if (valueinfo.type.charAt(0) == 't') {
type = 'text ' + valueinfo.type;
} else {
type = 'constant ' + valueinfo.type + ' ' + valueinfo.value;
}
}
if (type.charAt(0) == 't') {
value = TableEditorSC.encodeForSave(value);
}
cmdline = 'set ' + wval.ecoord + ' ' + type + ' ' + value;
editor.EditorScheduleSheetCommands(cmdline, true, false);
if (typeof sheetobj.ioEventTree === 'undefined') return;
if (typeof sheetobj.ioParameterList === 'undefined') return;
if (typeof sheetobj.ioEventTree[wval.ecoord] !== 'undefined') {
TableEditorSC.EditedTriggerCell(
sheetobj.ioEventTree[wval.ecoord],
wval.ecoord,
editor,
sheetobj,
);
}
return;
};
TableEditorSC.EditedTriggerCell = function (actionFormulaCells, editedCellRef, editor, sheet) {
for (var actionCellId in actionFormulaCells) {
var parameters = sheet.ioParameterList[actionCellId];
if (typeof parameters === 'undefined') continue;
switch (parameters.function_name) {
case 'EMAILONEDIT':
case 'EMAILONEDITIF':
var cmdline = 'setemailparameters ' + actionCellId + ' ' + editedCellRef;
editor.deferredEmailCommands.push({
cmdstr: cmdline,
saveundo: false,
});
break;
}
}
};
TableEditorSC.EditorApplySetCommandsToRange = function (editor, cmd) {
var line, coord;
var ecell = editor.ecell;
var range = editor.range;
if (range.hasrange) {
coord =
TableEditorSC.crToCoord(range.left, range.top) +
':' +
TableEditorSC.crToCoord(range.right, range.bottom);
line = 'set ' + coord + ' ' + cmd;
editor.EditorScheduleSheetCommands(line, true, false);
} else {
line = 'set ' + ecell.coord + ' ' + cmd;
editor.EditorScheduleSheetCommands(line, true, false);
}
editor.DisplayCellContents();
};
TableEditorSC.EditorProcessMouseWheel = function (event, delta, mousewheelinfo, wobj) {
if (wobj.functionobj.editor.busy) return;
if (delta > 0) {
wobj.functionobj.editor.ScrollRelative(true, Math.floor(-delta * 1.5));
}
if (delta < 0) {
wobj.functionobj.editor.ScrollRelative(true, Math.ceil(-delta * 1.5));
}
};
TableEditorSC.GridMousePosition = function (editor, clientX, clientY) {
var row, rowpane, col, colpane, rowtoresize, coltoresize, unhide, pos;
var result = {};
for (row = 1; row < editor.rowpositions.length; row++) {
if (!editor.rowheight[row]) continue;
if (editor.rowpositions[row] + editor.rowheight[row] > clientY) {
break;
}
}
for (col = 1; col < editor.colpositions.length; col++) {
if (!editor.colwidth[col]) continue;
if (editor.colpositions[col] + editor.colwidth[col] > clientX) {
break;
}
}
result.row = row;
result.col = col;
if (editor.headposition && TableEditorSC._app != true) {
if (clientX < editor.headposition.left && clientX >= editor.gridposition.left) {
result.rowheader = true;
result.distance = editor.headposition.left - clientX;
result.rowtoresize = false;
result.rowselect = false;
for (rowtoresize = 1; rowtoresize < editor.rowpositions.length; rowtoresize++) {
if (!editor.rowheight[rowtoresize]) continue;
if (
editor.rowpositions[rowtoresize] + editor.rowheight[rowtoresize] - 3 <= clientY &&
editor.rowpositions[rowtoresize] + editor.rowheight[rowtoresize] + 3 >= clientY
) {
result.rowtoresize = rowtoresize;
break;
}
}
if ((unhide = editor.context.rowunhidetop[row])) {
pos = TableEditorSC.GetElementPosition(unhide);
if (
clientX >= pos.left &&
clientX < pos.left + unhide.offsetWidth &&
clientY >= editor.rowpositions[row] + editor.rowheight[row] - unhide.offsetHeight &&
clientY < editor.rowpositions[row] + editor.rowheight[row]
) {
result.rowtounhide = row + 1;
}
}
if ((unhide = editor.context.rowunhidebottom[row])) {
pos = TableEditorSC.GetElementPosition(unhide);
if (
clientX >= pos.left &&
clientX < pos.left + unhide.offsetWidth &&
clientY >= editor.rowpositions[row] &&
clientY < editor.rowpositions[row] + unhide.offsetHeight
) {
result.rowtounhide = row - 1;
}
}
if (result.rowtounhide == null) {
for (rowpane = 0; rowpane < editor.context.rowpanes.length; rowpane++) {
if (
result.rowtoresize >= editor.context.rowpanes[rowpane].first &&
result.rowtoresize <= editor.context.rowpanes[rowpane].last
) {
return result;
}
}
result.rowselect = true;
}
delete result.rowtoresize;
return result;
} else if (clientY < editor.headposition.top && clientY > editor.gridposition.top) {
result.colheader = true;
result.distance = editor.headposition.top - clientY;
result.coltoresize = false;
result.colselect = false;
for (coltoresize = 1; coltoresize < editor.colpositions.length; coltoresize++) {
if (!editor.colwidth[coltoresize]) continue;
if (
editor.colpositions[coltoresize] + editor.colwidth[coltoresize] - 3 <= clientX &&
editor.colpositions[coltoresize] + editor.colwidth[coltoresize] + 3 >= clientX
) {
result.coltoresize = coltoresize;
break;
}
}
if ((unhide = editor.context.colunhideleft[col])) {
pos = TableEditorSC.GetElementPosition(unhide);
if (
clientX >= pos.left &&
clientX < pos.left + unhide.offsetWidth &&
clientY >= pos.top &&
clientY < pos.top + unhide.offsetHeight
) {
result.coltounhide = col + 1;
}
}
if ((unhide = editor.context.colunhideright[col])) {
pos = TableEditorSC.GetElementPosition(unhide);
if (
clientX >= pos.left &&
clientX < pos.left + unhide.offsetWidth &&
clientY >= pos.top &&
clientY < pos.top + unhide.offsetHeight
) {
result.coltounhide = col - 1;
}
}
if (result.coltounhide == null) {
for (colpane = 0; colpane < editor.context.colpanes.length; colpane++) {
if (
result.coltoresize >= editor.context.colpanes[colpane].first &&
result.coltoresize <= editor.context.colpanes[colpane].last
) {
return result;
}
}
result.colselect = true;
}
delete result.coltoresize;
return result;
} else if (clientX >= editor.verticaltablecontrol.controlborder) {
result.rowfooter = true;
result.distance = clientX - editor.verticaltablecontrol.controlborder;
return result;
} else if (clientY >= editor.horizontaltablecontrol.controlborder) {
result.colfooter = true;
result.distance = clientY - editor.horizontaltablecontrol.controlborder;
return result;
} else if (clientX < editor.gridposition.left) {
result.rowheader = true;
result.distance = editor.headposition.left - clientX;
return result;
} else if (clientY <= editor.gridposition.top) {
result.colheader = true;
result.distance = editor.headposition.top - clientY;
return result;
} else {
result.coord = TableEditorSC.crToCoord(result.col, result.row);
if (editor.context.cellskip[result.coord]) {
result.coord = editor.context.cellskip[result.coord];
}
return result;
}
}
return null;
};
TableEditorSC.GetEditorCellElement = function (editor, row, col) {
var headerColOffset = 0;
var headerRowOffset = 0;
if (editor.context.showRCHeaders == false) {
var headerColOffset = -1;
var headerRowOffset = -1;
}
var rowpane, colpane, c, coord;
var rowindex = 0;
var colindex = 0;
for (rowpane = 0; rowpane < editor.context.rowpanes.length; rowpane++) {
if (
row >= editor.context.rowpanes[rowpane].first &&
row <= editor.context.rowpanes[rowpane].last
) {
for (colpane = 0; colpane < editor.context.colpanes.length; colpane++) {
if (
col >= editor.context.colpanes[colpane].first &&
col <= editor.context.colpanes[colpane].last
) {
rowindex += row - editor.context.rowpanes[rowpane].first + 2;
for (c = editor.context.colpanes[colpane].first; c <= col; c++) {
coord = editor.context.cellskip[TableEditorSC.crToCoord(c, row)];
if (!coord || !editor.context.CoordInPane(coord, rowpane, colpane)) colindex++;
}
return {
element:
editor.griddiv.firstChild.lastChild.childNodes[rowindex + headerRowOffset]
.childNodes[colindex + headerColOffset],
rowpane,
colpane,
};
}
for (
c = editor.context.colpanes[colpane].first;
c <= editor.context.colpanes[colpane].last;
c++
) {
coord = editor.context.cellskip[TableEditorSC.crToCoord(c, row)];
if (!coord || !editor.context.CoordInPane(coord, rowpane, colpane)) colindex++;
}
colindex += 1;
}
}
rowindex +=
editor.context.rowpanes[rowpane].last - editor.context.rowpanes[rowpane].first + 1 + 1;
}
return null;
};
TableEditorSC.MoveECellWithKey = function (editor, ch) {
var coord, row, col, cell;
var shifted = false;
var delta = 1;
if (!editor.ecell) {
return null;
}
if (ch.slice(-7) == 'shifted') {
ch = ch.slice(0, -7);
shifted = true;
}
row = editor.ecell.row;
col = editor.ecell.col;
cell = editor.context.sheetobj.cells[editor.ecell.coord];
switch (ch) {
case '[adown]':
row += (cell && cell.rowspan) || 1;
break;
case '[aup]':
row--;
delta = -1;
break;
case '[pgdn]':
if (editor.lastvisiblerow && editor.firstscrollingrow) {
row += editor.lastvisiblerow - editor.firstscrollingrow + ((cell && cell.rowspan) || 1);
} else {
row += editor.pageUpDnAmount - 1 + ((cell && cell.rowspan) || 1);
}
break;
case '[pgup]':
if (editor.lastvisiblerow && editor.firstscrollingrow) {
row -= editor.lastvisiblerow - editor.firstscrollingrow + 1;
} else {
row -= editor.pageUpDnAmount;
}
delta = -1;
break;
case '[aright]':
col += (cell && cell.colspan) || 1;
break;
case '[aleft]':
col--;
delta = -1;
break;
case '[home]':
row = 1;
col = 1;
break;
default:
return null;
}
if (editor.context.sheetobj.attribs.usermaxcol)
col = Math.min(editor.context.sheetobj.attribs.usermaxcol, col);
if (editor.context.sheetobj.attribs.usermaxrow)
row = Math.min(editor.context.sheetobj.attribs.usermaxrow, row);
while (editor.context.sheetobj.colattribs.hide[TableEditorSC.rcColname(col)] == 'yes') {
col += delta;
if (col < 1) {
delta = -delta;
col = 1;
}
}
while (editor.context.sheetobj.rowattribs.hide[row] == 'yes') {
row += delta;
if (row < 1) {
delta = -delta;
row = 1;
}
}
if (!editor.range.hasrange) {
if (shifted) editor.RangeAnchor();
}
coord = editor.MoveECell(TableEditorSC.crToCoord(col, row));
if (editor.range.hasrange) {
if (shifted) editor.RangeExtend();
else editor.RangeRemove();
}
return coord;
};
TableEditorSC.MoveECell = function (editor, newcell) {
var cell, f;
var highlights = editor.context.highlights;
var ecell = TableEditorSC.coordToCr(newcell);
if (
editor.context.sheetobj.attribs.usermaxcol &&
ecell.col > editor.context.sheetobj.attribs.usermaxcol
)
ecell.col = editor.context.sheetobj.attribs.usermaxcol;
if (
editor.context.sheetobj.attribs.usermaxrow &&
ecell.row > editor.context.sheetobj.attribs.usermaxrow
)
ecell.row = editor.context.sheetobj.attribs.usermaxrow;
newcell = TableEditorSC.crToCoord(ecell.col, ecell.row);
if (editor.ecell) {
if (editor.ecell.coord == newcell) return newcell;
cell = TableEditorSC.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
delete highlights[editor.ecell.coord];
if (
editor.range2.hasrange &&
editor.ecell.row >= editor.range2.top &&
editor.ecell.row <= editor.range2.bottom &&
editor.ecell.col >= editor.range2.left &&
editor.ecell.col <= editor.range2.right
) {
highlights[editor.ecell.coord] = 'range2';
}
editor.UpdateCellCSS(cell, editor.ecell.row, editor.ecell.col);
editor.SetECellHeaders('');
if (editor.cellhandles) editor.cellhandles.ShowCellHandles(false);
}
newcell = editor.context.cellskip[newcell] || newcell;
editor.ecell = TableEditorSC.coordToCr(newcell);
editor.ecell.coord = newcell;
cell = TableEditorSC.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
highlights[newcell] = 'cursor';
for (f in editor.MoveECellCallback) {
editor.MoveECellCallback[f](editor);
}
editor.UpdateCellCSS(cell, editor.ecell.row, editor.ecell.col);
editor.SetECellHeaders('selected');
for (f in editor.StatusCallback) {
editor.StatusCallback[f].func(editor, 'moveecell', newcell, editor.StatusCallback[f].params);
}
if (editor.busy) {
editor.ensureecell = true;
} else {
editor.ensureecell = false;
editor.EnsureECellVisible();
}
return newcell;
};
TableEditorSC.EnsureECellVisible = function (editor) {
var vamount = 0;
var hamount = 0;
if (editor.ecell.row > editor.lastnonscrollingrow) {
if (editor.ecell.row < editor.firstscrollingrow) {
vamount =
editor.ecell.row -
editor.firstscrollingrow -
Math.floor((editor.lastvisiblerow - editor.firstscrollingrow) / 2);
} else if (editor.ecell.row + 1 > editor.lastvisiblerow) {
vamount =
editor.ecell.row -
editor.lastvisiblerow +
Math.floor((editor.lastvisiblerow - editor.firstscrollingrow) / 2);
}
}
if (editor.ecell.col > editor.lastnonscrollingcol) {
if (editor.ecell.col < editor.firstscrollingcol) {
hamount =
editor.ecell.col -
editor.firstscrollingcol -
Math.floor((editor.lastvisiblecol - editor.firstscrollingcol) / 2);
} else if (editor.ecell.col + 1 > editor.lastvisiblecol) {
hamount =
editor.ecell.col -
editor.lastvisiblecol +
Math.floor((editor.lastvisiblecol - editor.firstscrollingcol) / 2);
}
}
if (vamount != 0 || hamount != 0) {
editor.ScrollRelativeBoth(vamount, hamount);
} else {
editor.cellhandles.ShowCellHandles(true);
}
};
TableEditorSC.ReplaceCell = function (editor, cell, row, col) {
var newelement, a;
if (!cell) return;
newelement = editor.context.RenderCell(row, col, cell.rowpane, cell.colpane, true, null);
if (newelement && cell.element) {
cell.element.innerHTML = newelement.innerHTML;
cell.element.style.cssText = '';
cell.element.className = newelement.className;
for (a in newelement.style) {
if (newelement.style[a] != 'cssText') cell.element.style[a] = newelement.style[a];
}
}
};
TableEditorSC.UpdateCellCSS = function (editor, cell, row, col) {
var newelement, a;
if (!cell) return;
newelement = editor.context.RenderCell(row, col, cell.rowpane, cell.colpane, true, null);
if (newelement) {
cell.element.style.cssText = '';
cell.element.className = newelement.className;
for (a in newelement.style) {
if (newelement.style[a] != 'cssText') cell.element.style[a] = newelement.style[a];
}
}
};
TableEditorSC.SetECellHeaders = function (editor, selected) {
if (editor.context.showRCHeaders === false) return;
var ecell = editor.ecell;
var context = editor.context;
var rowpane, colpane, first, last;
var rowindex = 0;
var colindex = 0;
var headercell;
if (!ecell) return;
while (context.sheetobj.colattribs.hide[TableEditorSC.rcColname(ecell.col)] == 'yes') {
ecell.col++;
}
while (context.sheetobj.rowattribs.hide[ecell.row] == 'yes') {
ecell.row++;
}
ecell.coord = TableEditorSC.crToCoord(ecell.col, ecell.row);
for (rowpane = 0; rowpane < context.rowpanes.length; rowpane++) {
first = context.rowpanes[rowpane].first;
last = context.rowpanes[rowpane].last;
if (ecell.row >= first && ecell.row <= last) {
var i = 2 + rowindex + ecell.row - first;
if (editor.fullgrid !== null && i >= 0) {
headercell = editor.fullgrid.childNodes[1].childNodes[i].childNodes[0];
if (headercell) {
if (context.classnames) headercell.className = context.classnames[selected + 'rowname'];
if (context.explicitStyles)
headercell.style.cssText = context.explicitStyles[selected + 'rowname'];
headercell.style.verticalAlign = 'top';
}
}
}
rowindex += last - first + 1 + 1;
}
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
first = context.colpanes[colpane].first;
last = context.colpanes[colpane].last;
if (ecell.col >= first && ecell.col <= last) {
var i = 1 + colindex + ecell.col - first;
if (editor.fullgrid !== null && i >= 0) {
headercell = editor.fullgrid.childNodes[1].childNodes[1].childNodes[i];
if (headercell) {
if (context.classnames) headercell.className = context.classnames[selected + 'colname'];
if (context.explicitStyles)
headercell.style.cssText = context.explicitStyles[selected + 'colname'];
}
}
}
colindex += last - first + 1 + 1;
}
};
TableEditorSC.ECellReadonly = function (editor, ecoord) {
if (!ecoord && editor.ecell) {
ecoord = editor.ecell.coord;
}
if (!ecoord) return false;
var cell = editor.context.sheetobj.cells[ecoord];
return cell && cell.readonly;
};
TableEditorSC.RangeAnchor = function (editor, ecoord) {
if (editor.range.hasrange) {
editor.RangeRemove();
}
editor.RangeExtend(ecoord);
};
TableEditorSC.RangeExtend = function (editor, ecoord) {
var cell, cr, coord, row, col, f;
var highlights = editor.context.highlights;
var range = editor.range;
var range2 = editor.range2;
var ecell;
if (ecoord) {
ecell = TableEditorSC.coordToCr(ecoord);
ecell.coord = ecoord;
} else ecell = editor.ecell;
if (!ecell) return;
if (!range.hasrange) {
range.anchorcoord = ecell.coord;
range.anchorrow = ecell.row;
range.top = ecell.row;
range.bottom = ecell.row;
range.anchorcol = ecell.col;
range.left = ecell.col;
range.right = ecell.col;
range.hasrange = true;
}
if (range.anchorrow < ecell.row) {
range.top = range.anchorrow;
range.bottom = ecell.row;
} else {
range.top = ecell.row;
range.bottom = range.anchorrow;
}
if (range.anchorcol < ecell.col) {
range.left = range.anchorcol;
range.right = ecell.col;
} else {
range.left = ecell.col;
range.right = range.anchorcol;
}
for (coord in highlights) {
switch (highlights[coord]) {
case 'range':
highlights[coord] = 'unrange';
break;
case 'range2':
highlights[coord] = 'unrange2';
break;
}
}
for (row = range.top; row <= range.bottom; row++) {
for (col = range.left; col <= range.right; col++) {
coord = TableEditorSC.crToCoord(col, row);
switch (highlights[coord]) {
case 'unrange':
highlights[coord] = 'range';
break;
case 'cursor':
break;
case 'unrange2':
default:
highlights[coord] = 'newrange';
break;
}
}
}
for (row = range2.top; range2.hasrange && row <= range2.bottom; row++) {
for (col = range2.left; col <= range2.right; col++) {
coord = TableEditorSC.crToCoord(col, row);
switch (highlights[coord]) {
case 'unrange2':
highlights[coord] = 'range2';
break;
case 'range':
case 'newrange':
case 'cursor':
break;
default:
highlights[coord] = 'newrange2';
break;
}
}
}
for (coord in highlights) {
switch (highlights[coord]) {
case 'unrange':
delete highlights[coord];
break;
case 'newrange':
highlights[coord] = 'range';
break;
case 'newrange2':
highlights[coord] = 'range2';
break;
case 'range':
case 'range2':
case 'cursor':
continue;
}
cr = TableEditorSC.coordToCr(coord);
cell = TableEditorSC.GetEditorCellElement(editor, cr.row, cr.col);
editor.UpdateCellCSS(cell, cr.row, cr.col);
}
for (f in editor.RangeChangeCallback) {
editor.RangeChangeCallback[f](editor);
}
coord = TableEditorSC.crToCoord(editor.range.left, editor.range.top);
if (editor.range.left != editor.range.right || editor.range.top != editor.range.bottom) {
coord += ':' + TableEditorSC.crToCoord(editor.range.right, editor.range.bottom);
}
for (f in editor.StatusCallback) {
editor.StatusCallback[f].func(editor, 'rangechange', coord, editor.StatusCallback[f].params);
}
return;
};
TableEditorSC.RangeRemove = function (editor) {
var cell, cr, coord, row, col, f;
var highlights = editor.context.highlights;
var range = editor.range;
var range2 = editor.range2;
if (!range.hasrange && !range2.hasrange) return;
for (row = range2.top; range2.hasrange && row <= range2.bottom; row++) {
for (col = range2.left; col <= range2.right; col++) {
coord = TableEditorSC.crToCoord(col, row);
switch (highlights[coord]) {
case 'range':
highlights[coord] = 'newrange2';
break;
case 'range2':
case 'cursor':
break;
default:
highlights[coord] = 'newrange2';
break;
}
}
}
for (coord in highlights) {
switch (highlights[coord]) {
case 'range':
delete highlights[coord];
break;
case 'newrange2':
highlights[coord] = 'range2';
break;
case 'cursor':
continue;
}
cr = TableEditorSC.coordToCr(coord);
cell = TableEditorSC.GetEditorCellElement(editor, cr.row, cr.col);
editor.UpdateCellCSS(cell, cr.row, cr.col);
}
range.hasrange = false;
for (f in editor.RangeChangeCallback) {
editor.RangeChangeCallback[f](editor);
}
for (f in editor.StatusCallback) {
editor.StatusCallback[f].func(editor, 'rangechange', '', editor.StatusCallback[f].params);
}
return;
};
TableEditorSC.Range2Remove = function (editor) {
var cell, cr, coord;
var highlights = editor.context.highlights;
var range2 = editor.range2;
if (!range2.hasrange) return;
for (coord in highlights) {
switch (highlights[coord]) {
case 'range2':
delete highlights[coord];
break;
case 'range':
case 'cursor':
continue;
}
cr = TableEditorSC.coordToCr(coord);
cell = TableEditorSC.GetEditorCellElement(editor, cr.row, cr.col);
editor.UpdateCellCSS(cell, cr.row, cr.col);
}
range2.hasrange = false;
return;
};
TableEditorSC.FitToEditTable = function (editor) {
var colnum, colname, colwidth, totalwidth, totalrows, rownum, rowpane, needed, colpane;
var context = editor.context;
var sheetobj = context.sheetobj;
totalwidth = context.showRCHeaders ? context.rownamewidth - 0 : 0;
for (colpane = 0; colpane < context.colpanes.length - 1; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
colname = TableEditorSC.rcColname(colnum);
if (sheetobj.colattribs.hide[colname] != 'yes') {
colwidth =
sheetobj.colattribs.width[colname] ||
sheetobj.attribs.defaultcolwidth ||
TableEditorSC.Constants.defaultColWidth;
if (colwidth == 'blank' || colwidth == 'auto') colwidth = '';
totalwidth += colwidth && colwidth - 0 > 0 ? colwidth - 0 : 10;
}
}
}
for (colnum = context.colpanes[colpane].first; colnum <= 1e4; colnum++) {
colname = TableEditorSC.rcColname(colnum);
if (sheetobj.colattribs.hide[colname] != 'yes') {
colwidth =
sheetobj.colattribs.width[colname] ||
sheetobj.attribs.defaultcolwidth ||
TableEditorSC.Constants.defaultColWidth;
if (colwidth == 'blank' || colwidth == 'auto') colwidth = '';
totalwidth += colwidth && colwidth - 0 > 0 ? colwidth - 0 : 10;
}
if (totalwidth > editor.tablewidth) break;
}
context.colpanes[colpane].last = context.sheetobj.attribs.usermaxcol || colnum;
var firstRow = context.rowpanes[0].first;
var lastRow = context.sheetobj.attribs.lastrow;
while (sheetobj.rowattribs.hide[firstRow] == 'yes' && firstRow < lastRow) firstRow++;
context.rowpanes[0].first = firstRow;
totalrows = context.showRCHeaders ? 1 : 0;
for (rowpane = 0; rowpane < context.rowpanes.length - 1; rowpane++) {
totalrows += context.rowpanes[rowpane].last - context.rowpanes[rowpane].first + 1;
for (
rownum = context.rowpanes[rowpane].first;
rownum <= context.rowpanes[rowpane].last;
rownum++
) {
if (sheetobj.rowattribs.hide[rownum] == 'yes') {
totalrows--;
}
}
}
needed = editor.tableheight - totalrows * context.pixelsPerRow;
context.rowpanes[rowpane].last =
context.sheetobj.attribs.usermaxrow ||
context.rowpanes[rowpane].first + Math.floor(needed / context.pixelsPerRow) + 1;
};
TableEditorSC.CalculateEditorPositions = function (editor) {
var rowpane, colpane, i;
editor.gridposition = TableEditorSC.GetElementPosition(editor.griddiv);
var element = editor.griddiv.firstChild.lastChild.childNodes[1].childNodes[0];
editor.headposition = TableEditorSC.GetElementPosition(element);
editor.headposition.left += element.offsetWidth;
editor.headposition.top += element.offsetHeight;
editor.rowpositions = [];
for (rowpane = 0; rowpane < editor.context.rowpanes.length; rowpane++) {
editor.CalculateRowPositions(rowpane, editor.rowpositions, editor.rowheight);
}
for (i = 0; i < editor.rowpositions.length; i++) {
if (editor.rowpositions[i] > editor.gridposition.top + editor.tableheight) break;
}
editor.lastvisiblerow = i - 1;
editor.colpositions = [];
for (colpane = 0; colpane < editor.context.colpanes.length; colpane++) {
editor.CalculateColPositions(colpane, editor.colpositions, editor.colwidth);
}
for (i = 0; i < editor.colpositions.length; i++) {
if (editor.colpositions[i] > editor.gridposition.left + editor.tablewidth) break;
}
editor.lastvisiblecol = i - 1;
editor.firstscrollingrow = editor.context.rowpanes[editor.context.rowpanes.length - 1].first;
while (editor.context.sheetobj.rowattribs.hide[editor.firstscrollingrow] == 'yes') {
editor.firstscrollingrow++;
}
editor.firstscrollingrowtop =
editor.rowpositions[editor.firstscrollingrow] || editor.headposition.top;
editor.lastnonscrollingrow =
editor.context.rowpanes.length - 1 > 0
? editor.context.rowpanes[editor.context.rowpanes.length - 2].last
: 0;
editor.firstscrollingcol = editor.context.colpanes[editor.context.colpanes.length - 1].first;
while (
editor.context.sheetobj.colattribs.hide[TableEditorSC.rcColname(editor.firstscrollingcol)] ==
'yes'
) {
editor.firstscrollingcol++;
}
editor.firstscrollingcolleft =
editor.colpositions[editor.firstscrollingcol] || editor.headposition.left;
editor.lastnonscrollingcol =
editor.context.colpanes.length - 1 > 0
? editor.context.colpanes[editor.context.colpanes.length - 2].last
: 0;
editor.verticaltablecontrol.ComputeTableControlPositions();
editor.horizontaltablecontrol.ComputeTableControlPositions();
};
TableEditorSC.ScheduleRender = function (editor) {
if (editor.ignoreRender == true) return;
if (editor.timeout) window.clearTimeout(editor.timeout);
TableEditorSC.EditorSheetStatusCallback(null, 'schedrender', null, editor);
editor.timeout = window.setTimeout(function () {
TableEditorSC.DoRenderStep(editor);
}, 1);
};
TableEditorSC.DoRenderStep = function (editor) {
editor.timeout = null;
editor.EditorRenderSheet();
TableEditorSC.EditorSheetStatusCallback(null, 'renderdone', null, editor);
TableEditorSC.EditorSheetStatusCallback(null, 'schedposcalc', null, editor);
editor.timeout = window.setTimeout(function () {
TableEditorSC.DoPositionCalculations(editor);
}, 1);
};
TableEditorSC.SchedulePositionCalculations = function (editor) {
TableEditorSC.EditorSheetStatusCallback(null, 'schedposcalc', null, editor);
editor.timeout = window.setTimeout(function () {
TableEditorSC.DoPositionCalculations(editor);
}, 1);
};
TableEditorSC.DoPositionCalculations = function (editor) {
editor.timeout = null;
editor.CalculateEditorPositions();
editor.verticaltablecontrol.PositionTableControlElements();
editor.horizontaltablecontrol.PositionTableControlElements();
TableEditorSC.EditorSheetStatusCallback(null, 'doneposcalc', null, editor);
if (editor.ensureecell && editor.ecell && !editor.deferredCommands.length) {
editor.ensureecell = false;
editor.EnsureECellVisible();
}
editor.cellhandles.ShowCellHandles(true);
};
TableEditorSC.CalculateRowPositions = function (editor, panenum, positions, sizes) {
var toprow, rowpane, rownum, offset, trowobj;
var context = editor.context;
var tbodyobj;
if (!context.showRCHeaders) return;
tbodyobj = editor.fullgrid.lastChild;
toprow = 2;
for (rowpane = 0; rowpane < panenum; rowpane++) {
toprow += context.rowpanes[rowpane].last - context.rowpanes[rowpane].first + 2;
}
offset = 0;
for (
rownum = context.rowpanes[rowpane].first;
rownum <= context.rowpanes[rowpane].last;
rownum++
) {
trowobj = tbodyobj.childNodes[toprow + offset];
offset++;
if (!trowobj) {
continue;
}
if (!positions[rownum]) {
positions[rownum] = trowobj.firstChild.offsetTop;
sizes[rownum] = trowobj.firstChild.offsetHeight;
}
}
return;
};
TableEditorSC.CalculateColPositions = function (editor, panenum, positions, sizes) {
var leftcol, colpane, colnum, offset, trowobj, cellposition;
var context = editor.context;
var tbodyobj;
if (!context.showRCHeaders) return;
tbodyobj = editor.fullgrid.lastChild;
leftcol = 1;
for (colpane = 0; colpane < panenum; colpane++) {
leftcol += context.colpanes[colpane].last - context.colpanes[colpane].first + 2;
}
trowobj = tbodyobj.childNodes[1];
offset = 0;
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
cellposition = TableEditorSC.GetElementPosition(trowobj.childNodes[leftcol + offset]);
if (!positions[colnum]) {
positions[colnum] = cellposition.left;
if (trowobj.childNodes[leftcol + offset]) {
sizes[colnum] = trowobj.childNodes[leftcol + offset].offsetWidth;
}
}
offset++;
}
return;
};
TableEditorSC.ScrollRelative = function (editor, vertical, amount) {
if (vertical) {
editor.ScrollRelativeBoth(amount, 0);
} else {
editor.ScrollRelativeBoth(0, amount);
}
return;
};
TableEditorSC.ScrollRelativeBoth = function (editor, vamount, hamount) {
var context = editor.context;
var dv = vamount > 0 ? 1 : -1,
dh = hamount > 0 ? 1 : -1;
var vplen = context.rowpanes.length;
var vlimit = vplen > 1 ? context.rowpanes[vplen - 2].last + 1 : 1;
if (context.rowpanes[vplen - 1].first + vamount < vlimit) {
vamount = -context.rowpanes[vplen - 1].first + vlimit;
}
var hplen = context.colpanes.length;
var hlimit = hplen > 1 ? context.colpanes[hplen - 2].last + 1 : 1;
if (context.colpanes[hplen - 1].first + hamount < hlimit) {
hamount = -context.colpanes[hplen - 1].first + hlimit;
}
while (
context.sheetobj.colattribs.hide[
TableEditorSC.rcColname(context.colpanes[hplen - 1].first + hamount)
] == 'yes'
) {
hamount += dh;
if (hamount < 1) {
hamount = 0;
break;
}
}
while (context.sheetobj.rowattribs.hide[context.rowpanes[vplen - 1].first + vamount] == 'yes') {
vamount += dv;
if (vamount < 1) {
vamount = 0;
break;
}
}
if ((vamount == 1 || vamount == -1) && hamount == 0) {
if (vamount == 1) {
editor.ScrollTableUpOneRow();
} else {
editor.ScrollTableDownOneRow();
}
if (editor.ecell) editor.SetECellHeaders('selected');
editor.SchedulePositionCalculations();
return;
}
if (vamount != 0 || hamount != 0) {
context.rowpanes[vplen - 1].first += vamount;
context.rowpanes[vplen - 1].last += vamount;
context.colpanes[hplen - 1].first += hamount;
context.colpanes[hplen - 1].last += hamount;
editor.LimitLastPanes();
editor.FitToEditTable();
editor.ScheduleRender();
}
};
TableEditorSC.PageRelative = function (editor, vertical, direction) {
var context = editor.context;
var panes = vertical ? 'rowpanes' : 'colpanes';
var lastpane = context[panes][context[panes].length - 1];
var lastvisible = vertical ? 'lastvisiblerow' : 'lastvisiblecol';
var sizearray = vertical ? editor.rowheight : editor.colwidth;
var defaultsize = vertical
? TableEditorSC.Constants.defaultAssumedRowHeight
: TableEditorSC.Constants.defaultColWidth;
var size, newfirst, totalsize, current;
if (direction > 0) {
newfirst = editor[lastvisible];
if (newfirst == lastpane.first) newfirst += 1;
} else {
if (vertical) {
totalsize = editor.tableheight - (editor.firstscrollingrowtop - editor.gridposition.top);
} else {
totalsize = editor.tablewidth - (editor.firstscrollingcolleft - editor.gridposition.left);
}
totalsize -=
sizearray[editor[lastvisible]] > 0 ? sizearray[editor[lastvisible]] : defaultsize;
for (newfirst = lastpane.first - 1; newfirst > 0; newfirst--) {
size = sizearray[newfirst] > 0 ? sizearray[newfirst] : defaultsize;
if (totalsize < size) break;
totalsize -= size;
}
current = lastpane.first;
if (newfirst >= current) newfirst = current - 1;
if (newfirst < 1) newfirst = 1;
}
lastpane.first = newfirst;
lastpane.last = newfirst + 1;
editor.LimitLastPanes();
editor.FitToEditTable();
editor.ScheduleRender();
};
TableEditorSC.LimitLastPanes = function (editor) {
var context = editor.context;
var plen;
plen = context.rowpanes.length;
if (plen > 1 && context.rowpanes[plen - 1].first <= context.rowpanes[plen - 2].last)
context.rowpanes[plen - 1].first = context.rowpanes[plen - 2].last + 1;
if (
context.sheetobj.attribs.usermaxrow &&
context.rowpanes[plen - 1].first > context.sheetobj.attribs.usermaxrow
)
context.rowpanes[plen - 1].first = context.sheetobj.attribs.usermaxrow;
plen = context.colpanes.length;
if (plen > 1 && context.colpanes[plen - 1].first <= context.colpanes[plen - 2].last)
context.colpanes[plen - 1].first = context.colpanes[plen - 2].last + 1;
if (
context.sheetobj.attribs.usermaxcol &&
context.colpanes[plen - 1].first > context.sheetobj.attribs.usermaxcol
)
context.colpanes[plen - 1].first = context.sheetobj.attribs.usermaxcol;
};
TableEditorSC.ScrollTableUpOneRow = function (editor) {
var toprow,
rowpane,
rownum,
colnum,
colpane,
cell,
oldrownum,
maxrowspan,
newbottomrow,
newrow,
oldchild,
bottomrownum,
coord;
var rowneedsrefresh = {};
var context = editor.context;
var sheetobj = context.sheetobj;
var tableobj = editor.fullgrid;
var tbodyobj;
tbodyobj = tableobj.lastChild;
toprow = context.showRCHeaders ? 2 : 1;
for (rowpane = 0; rowpane < context.rowpanes.length - 1; rowpane++) {
toprow += context.rowpanes[rowpane].last - context.rowpanes[rowpane].first + 2;
}
if (
context.sheetobj.attribs.usermaxrow &&
context.sheetobj.attribs.usermaxrow - context.rowpanes[rowpane].first < 1
) {
return tableobj;
}
tbodyobj.removeChild(tbodyobj.childNodes[toprow]);
context.rowpanes[rowpane].first++;
context.rowpanes[rowpane].last++;
editor.FitToEditTable();
context.CalculateColWidthData();
if (
!context.sheetobj.attribs.usermaxrow ||
context.rowpanes[rowpane].last != context.sheetobj.attribs.usermaxrow
) {
newbottomrow = context.RenderRow(context.rowpanes[rowpane].last, rowpane);
tbodyobj.appendChild(newbottomrow);
}
maxrowspan = 1;
oldrownum = context.rowpanes[rowpane].first - 1;
for (colpane = 0; colpane < context.colpanes.length; colpane++) {
for (
colnum = context.colpanes[colpane].first;
colnum <= context.colpanes[colpane].last;
colnum++
) {
coord = TableEditorSC.crToCoord(colnum, oldrownum);
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 + oldrownum >= context.rowpanes[rowpane].last) break;
newrow = context.RenderRow(rownum + oldrownum, rowpane);
oldchild = tbodyobj.childNodes[toprow + rownum - 1];
tbodyobj.replaceChild(newrow, oldchild);
}
}
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 = context.cellskip[TableEditorSC.crToCoord(colnum, bottomrownum)];
if (!coord) continue;
rownum = context.coordToCR[coord].row - 0;
if (rownum == context.rowpanes[rowpane].last || rownum < context.rowpanes[rowpane].first)
continue;
cell = sheetobj.cells[coord];
if (cell && cell.rowspan > 1) rowneedsrefresh[rownum] = true;
}
}
for (rownum in rowneedsrefresh) {
newrow = context.RenderRow(rownum, rowpane);
oldchild = tbodyobj.childNodes[toprow + (Number(rownum) - context.rowpanes[rowpane].first)];
tbodyobj.replaceChild(newrow, oldchild);
}
return tableobj;
};
TableEditorSC.ScrollTableDownOneRow = function (editor) {
var toprow,
rowpane,
rownum,
colnum,
colpane,
cell,
newrownum,
maxrowspan,
newrow,
oldchild,
bottomrownum,
coord;
var rowneedsrefresh = {};
var context = editor.context;
var sheetobj = context.sheetobj;
var tableobj = editor.fullgrid;
var tbodyobj;
tbodyobj = tableobj.lastChild;
toprow = context.showRCHeaders ? 2 : 1;
for (rowpane = 0; rowpane < context.rowpanes.length - 1; rowpane++) {
toprow += context.rowpanes[rowpane].last - context.rowpanes[rowpane].first + 2;
}
if (!context.sheetobj.attribs.usermaxrow) {
tbodyobj.removeChild(
tbodyobj.childNodes[
toprow + (context.rowpanes[rowpane].last - context.rowpanes[rowpane].first)
],
);
}
context.rowpanes[rowpane].first--;
context.rowpanes[rowpane].last--;
editor.FitToEditTable();
context.CalculateColWidthData();
newrow = context.RenderRow(context.rowpanes[rowpane].first, rowpane);
tbodyobj.insertBefore(newrow, tbodyobj.childNodes[toprow]);
maxrowspan = 1;
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 = TableEditorSC.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);
}
}
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 = TableEditorSC.crToCoord(colnum, bottomrownum);
cell = sheetobj.cells[coord];
if (cell && cell.rowspan > 1) {
rowneedsrefresh[bottomrownum] = true;
continue;
}
coord = context.cellskip[TableEditorSC.crToCoord(colnum, bottomrownum)];
if (!coord) continue;
rownum = context.coordToCR[coord].row - 0;
if (rownum == bottomrownum || rownum < context.rowpanes[rowpane].first) continue;
cell = sheetobj.cells[coord];
if (cell && cell.rowspan > 1) rowneedsrefresh[rownum] = true;
}
}
for (rownum in rowneedsrefresh) {
newrow = context.RenderRow(rownum, rowpane);
oldchild = tbodyobj.childNodes[toprow + (Number(rownum) - context.rowpanes[rowpane].first)];
tbodyobj.replaceChild(newrow, oldchild);
}
return tableobj;
};
TableEditorSC.ScrollTableLeftOneCol = function (editor) {
return TableEditorSC.ScrollRelative(editor, false, -1);
};
TableEditorSC.ScrollTableRightOneCol = function (editor) {
return TableEditorSC.ScrollRelative(editor, false, 1);
};
TableEditorSC.InputBox = function (element, editor) {
if (!element) return;
this.element = element;
this.editor = editor;
this.inputEcho = null;
editor.inputBox = this;
element.onmousedown = TableEditorSC.InputBoxOnMouseDown;
editor.MoveECellCallback.formulabar = function (e) {
if (e.state != 'start') return;
editor.inputBox.DisplayCellContents(e.ecell.coord);
};
};
TableEditorSC.InputBox.prototype.DisplayCellContents = function (coord) {
TableEditorSC.InputBoxDisplayCellContents(this, coord);
};
TableEditorSC.InputBox.prototype.ShowInputBox = function (show) {
this.editor.inputEcho.ShowInputEcho(show);
};
TableEditorSC.InputBox.prototype.GetText = function () {
return this.element.value;
};
TableEditorSC.InputBox.prototype.SetText = function (newtext) {
if (!this.element) return;
this.element.value = newtext;
this.editor.inputEcho.SetText(newtext + '_');
};
TableEditorSC.InputBox.prototype.Focus = function () {
TableEditorSC.InputBoxFocus(this);
};
TableEditorSC.InputBox.prototype.Blur = function () {
return this.element.blur();
};
TableEditorSC.InputBox.prototype.Select = function (t) {
if (!this.element) return;
switch (t) {
case 'end':
if (this.element.selectionStart != undefined) {
this.element.selectionStart = this.element.value.length;
this.element.selectionEnd = this.element.value.length;
}
break;
}
};
TableEditorSC.InputBoxDisplayCellContents = function (inputbox, coord) {
var scc = TableEditorSC.Constants;
if (!inputbox) return;
if (!coord) {
if (!inputbox.editor) return;
if (!inputbox.editor.ecell) return;
coord = inputbox.editor.ecell.coord;
}
var text = TableEditorSC.GetCellContents(inputbox.editor.context.sheetobj, coord);
if (text.indexOf('\n') != -1) {
text = scc.s_inputboxdisplaymultilinetext;
inputbox.element.disabled = true;
} else if (inputbox.editor.ECellReadonly()) {
inputbox.element.disabled = true;
} else {
inputbox.element.disabled = false;
}
inputbox.SetText(text);
};
TableEditorSC.InputBoxFocus = function (inputbox) {
if (!inputbox) return;
inputbox.element.focus();
var editor = inputbox.editor;
editor.state = 'input';
var wval = editor.workingvalues;
wval.partialexpr = '';
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
};
TableEditorSC.InputBoxOnMouseDown = function (_e) {
var editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
var wval = editor.workingvalues;
switch (editor.state) {
case 'start':
editor.state = 'inputboxdirect';
wval.partialexpr = '';
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
editor.inputEcho.ShowInputEcho(true);
break;
case 'input':
wval.partialexpr = '';
editor.MoveECell(wval.ecoord);
editor.state = 'inputboxdirect';
TableEditorSC.KeyboardFocus();
break;
case 'inputboxdirect':
break;
}
return undefined;
};
TableEditorSC.InputEcho = function (editor) {
var scc = TableEditorSC.Constants;
this.editor = editor;
this.text = '';
this.interval = null;
this.container = null;
this.main = null;
this.prompt = null;
this.hint = null;
this.functionbox = null;
this.container = SocialCalc.document.createElement('div');
TableEditorSC.setStyles(this.container, 'display:none;position:absolute;zIndex:10;');
this.main = SocialCalc.document.createElement('div');
if (scc.defaultInputEchoClass) this.main.className = scc.defaultInputEchoClass;
if (scc.defaultInputEchoStyle) TableEditorSC.setStyles(this.main, scc.defaultInputEchoStyle);
this.main.innerHTML = ' ';
this.hint = SocialCalc.document.createElement('div');
if (scc.defaultInputEchoHintClass) this.hint.className = scc.defaultInputEchoHintClass;
if (scc.defaultInputEchoHintStyle)
TableEditorSC.setStyles(this.hint, scc.defaultInputEchoHintStyle);
this.hint.innerHTML = '';
this.container.appendChild(this.hint);
this.container.appendChild(this.main);
this.prompt = SocialCalc.document.createElement('div');
if (scc.defaultInputEchoPromptClass) this.prompt.className = scc.defaultInputEchoPromptClass;
if (scc.defaultInputEchoPromptStyle)
TableEditorSC.setStyles(this.prompt, scc.defaultInputEchoPromptStyle);
this.prompt.innerHTML = '';
this.container.appendChild(this.prompt);
TableEditorSC.DragRegister(
this.main,
true,
true,
{
MouseDown: TableEditorSC.DragFunctionStart,
MouseMove: TableEditorSC.DragFunctionPosition,
MouseUp: TableEditorSC.DragFunctionPosition,
Disabled: null,
positionobj: this.container,
},
this.editor.toplevel,
);
editor.toplevel.appendChild(this.container);
};
TableEditorSC.InputEcho.prototype.ShowInputEcho = function (show) {
return TableEditorSC.ShowInputEcho(this, show);
};
TableEditorSC.InputEcho.prototype.SetText = function (str) {
return TableEditorSC.SetInputEchoText(this, str);
};
TableEditorSC.ShowInputEcho = function (inputecho, show) {
var cell, position;
var editor = inputecho.editor;
if (!editor) return;
if (show) {
editor.cellhandles.ShowCellHandles(false);
cell = TableEditorSC.GetEditorCellElement(editor, editor.ecell.row, editor.ecell.col);
if (cell) {
position = TableEditorSC.GetElementPosition(cell.element);
inputecho.container.style.left = position.left - 1 + 'px';
inputecho.container.style.top = position.top - 1 + 'px';
}
inputecho.hint.innerHTML = editor.ecell.coord;
inputecho.container.style.display = 'block';
if (inputecho.interval) window.clearInterval(inputecho.interval);
inputecho.interval = window.setInterval(TableEditorSC.InputEchoHeartbeat, 50);
} else {
if (inputecho.interval) window.clearInterval(inputecho.interval);
inputecho.container.style.display = 'none';
}
};
TableEditorSC.SetInputEchoText = function (inputecho, str) {
var scc = TableEditorSC.Constants;
var fname, fstr;
var newstr = TableEditorSC.special_chars(str);
newstr = newstr.replace(/\n/g, '
');
if (inputecho.text != newstr) {
inputecho.main.innerHTML = newstr;
inputecho.text = newstr;
}
var parts = str.match(/.*[+\-*/&^<>=,(]([A-Za-z][A-Za-z][\w.]*?)\([^)]*$/);
if (str.charAt(0) == '=' && parts) {
fname = parts[1].toUpperCase();
if (TableEditorSC.Formula.FunctionList[fname]) {
TableEditorSC.Formula.FillFunctionInfo();
fstr = TableEditorSC.special_chars(
fname + '(' + TableEditorSC.Formula.FunctionArgString(fname) + ')',
);
} else {
fstr = scc.ietUnknownFunction + fname;
}
if (inputecho.prompt.innerHTML != fstr) {
inputecho.prompt.innerHTML = fstr;
inputecho.prompt.style.display = 'block';
}
} else if (inputecho.prompt.style.display != 'none') {
inputecho.prompt.innerHTML = '';
inputecho.prompt.style.display = 'none';
}
};
TableEditorSC.InputEchoHeartbeat = function () {
var editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
editor.inputEcho.SetText(editor.inputBox.GetText() + '_');
return undefined;
};
TableEditorSC.InputEchoMouseDown = function (_e) {
var editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
editor.inputBox.element.focus();
return undefined;
};
TableEditorSC.CellHandles = function (editor) {
if (editor.noEdit) return;
this.editor = editor;
this.noCursorSuffix = false;
this.movedmouse = false;
this.draghandle = SocialCalc.document.createElement('div');
TableEditorSC.setStyles(
this.draghandle,
'display:none;position:absolute;zIndex:8;border:1px solid white;width:4px;height:4px;fontSize:1px;backgroundColor:#0E93D8;cursor:default;',
);
this.draghandle.innerHTML = ' ';
editor.toplevel.appendChild(this.draghandle);
TableEditorSC.AssignID(editor, this.draghandle, 'draghandle');
var imagetype = 'png';
this.dragpalette = SocialCalc.document.createElement('div');
TableEditorSC.setStyles(
this.dragpalette,
'display:none;position:absolute;zIndex:8;width:90px;height:90px;fontSize:1px;textAlign:center;cursor:default;' +
'backgroundImage:url(' +
TableEditorSC.Constants.defaultImagePrefix +
'drag-handles.' +
imagetype +
');',
);
this.dragpalette.innerHTML = ' ';
editor.toplevel.appendChild(this.dragpalette);
TableEditorSC.AssignID(editor, this.dragpalette, 'dragpalette');
this.dragtooltip = SocialCalc.document.createElement('div');
TableEditorSC.setStyles(
this.dragtooltip,
'display:none;position:absolute;zIndex:9;border:1px solid black;width:100px;height:auto;fontSize:10px;backgroundColor:#FFFFFF;',
);
this.dragtooltip.innerHTML = ' ';
editor.toplevel.appendChild(this.dragtooltip);
TableEditorSC.AssignID(editor, this.dragtooltip, 'dragtooltip');
this.fillinghandle = SocialCalc.document.createElement('div');
TableEditorSC.setStyles(
this.fillinghandle,
'display:none;position:absolute;zIndex:9;border:1px solid black;width:auto;height:14px;fontSize:10px;backgroundColor:#FFFFFF;',
);
this.fillinghandle.innerHTML = ' ';
editor.toplevel.appendChild(this.fillinghandle);
TableEditorSC.AssignID(editor, this.fillinghandle, 'fillinghandle');
this.draghandle.addEventListener(
'mousemove',
TableEditorSC.CellHandlesMouseMoveOnHandle,
false,
);
this.dragpalette.addEventListener('mousedown', TableEditorSC.CellHandlesMouseDown, false);
this.dragpalette.addEventListener(
'mousemove',
TableEditorSC.CellHandlesMouseMoveOnHandle,
false,
);
};
TableEditorSC.CellHandles.prototype.ShowCellHandles = function (show, moveshow) {
return TableEditorSC.ShowCellHandles(this, show, moveshow);
};
TableEditorSC.ShowCellHandles = function (cellhandles, show, moveshow) {
var cell;
var editor = cellhandles.editor;
var doshow = false;
var row, col;
var colinc = 1,
rowinc = 1;
if (!editor) return;
if (!editor.ecell) return;
showCellHandlesBlock: {
if (!show) break showCellHandlesBlock;
row = editor.ecell.row;
col = editor.ecell.col;
if (editor.state != 'start') break showCellHandlesBlock;
if (row >= editor.lastvisiblerow) break showCellHandlesBlock;
if (col >= editor.lastvisiblecol) break showCellHandlesBlock;
if (row < editor.firstscrollingrow) break showCellHandlesBlock;
if (col < editor.firstscrollingcol) break showCellHandlesBlock;
while (
editor.context.sheetobj.colattribs.hide[TableEditorSC.rcColname(col + colinc)] == 'yes'
) {
colinc++;
}
while (editor.context.sheetobj.rowattribs.hide[row + rowinc] == 'yes') {
rowinc++;
}
cell =
editor.context.sheetobj.cells[TableEditorSC.crToCoord(col + colinc - 1, row + rowinc - 1)];
if (typeof cell != 'undefined') {
colinc += (cell.colspan || 1) - 1;
rowinc += (cell.rowspan || 1) - 1;
}
if (editor.rowpositions[row + rowinc] + 20 > editor.horizontaltablecontrol.controlborder) {
break showCellHandlesBlock;
}
if (editor.rowpositions[row + rowinc] - 10 < editor.headposition.top) {
break showCellHandlesBlock;
}
if (editor.colpositions[col + colinc] + 20 > editor.verticaltablecontrol.controlborder) {
break showCellHandlesBlock;
}
if (editor.colpositions[col + colinc] - 30 < editor.headposition.left) {
break showCellHandlesBlock;
}
cellhandles.draghandle.style.left = editor.colpositions[col + colinc] - 1 + 'px';
cellhandles.draghandle.style.top = editor.rowpositions[row + rowinc] - 1 + 'px';
cellhandles.draghandle.style.display = 'block';
if (moveshow) {
cellhandles.draghandle.style.display = 'none';
cellhandles.dragpalette.style.left = editor.colpositions[col + colinc] - 45 + 'px';
cellhandles.dragpalette.style.top = editor.rowpositions[row + rowinc] - 45 + 'px';
cellhandles.dragpalette.style.display = 'block';
cellhandles.dragtooltip.style.left = editor.colpositions[col + colinc] - 45 + 'px';
cellhandles.dragtooltip.style.top = editor.rowpositions[row + rowinc] + 45 + 'px';
cellhandles.dragtooltip.style.display = 'none';
}
doshow = true;
}
if (!doshow) {
cellhandles.draghandle.style.display = 'none';
}
if (!moveshow) {
cellhandles.dragpalette.style.display = 'none';
cellhandles.dragtooltip.style.display = 'none';
}
};
TableEditorSC.CellHandlesMouseMoveOnHandle = function (e) {
var scc = TableEditorSC.Constants;
var event = e || window.event;
var target = event.target || event.srcElement;
var editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
var cellhandles = editor.cellhandles;
if (!cellhandles.editor) return true;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
if (!editor.cellhandles.mouseDown) {
editor.cellhandles.ShowCellHandles(true, true);
if (target == cellhandles.dragpalette) {
var whichhandle = TableEditorSC.SegmentDivHit(
[scc.CH_radius1, scc.CH_radius2],
editor.cellhandles.dragpalette,
clientX,
clientY,
);
if (whichhandle == 0) {
TableEditorSC.CellHandlesHoverTimeout();
return;
}
}
if (cellhandles.timer) {
window.clearTimeout(cellhandles.timer);
cellhandles.timer = null;
}
cellhandles.timer = window.setTimeout(TableEditorSC.CellHandlesHoverTimeout, 3e3);
}
return;
};
TableEditorSC.SegmentDivHit = function (segtable, divWithMouseHit, x, y) {
var width = divWithMouseHit.offsetWidth;
var height = divWithMouseHit.offsetHeight;
var left = divWithMouseHit.offsetLeft;
var top = divWithMouseHit.offsetTop;
var v = 0;
var table = segtable;
var quadrant = '';
var len = Math.sqrt(
Math.pow(x - left - (width / 2 - 0.5), 2) + Math.pow(y - top - (height / 2 - 0.5), 2),
);
if (table.length == 2) {
if (x >= left && x < left + width / 2 && y >= top && y < top + height / 2) {
if (len <= segtable[0]) v = -1;
else if (len <= segtable[1]) v = 1;
}
if (x >= left + width / 2 && x < left + width && y >= top && y < top + height / 2) {
if (len <= segtable[0]) v = -2;
else if (len <= segtable[1]) v = 2;
}
if (x >= left + width / 2 && x < left + width && y >= top + height / 2 && y < top + height) {
if (len <= segtable[0]) v = -3;
else if (len <= segtable[1]) v = 3;
}
if (x >= left && x < left + width / 2 && y >= top + height / 2 && y < top + height) {
if (len <= segtable[0]) v = -4;
else if (len <= segtable[1]) v = 4;
}
return v;
}
while (true) {
if (x >= left && x < left + width / 2 && y >= top && y < top + height / 2) {
quadrant += '1';
v = table[0];
if (typeof v == 'number') {
break;
}
table = v;
width = width / 2;
height = height / 2;
continue;
}
if (x >= left + width / 2 && x < left + width && y >= top && y < top + height / 2) {
quadrant += '2';
v = table[1];
if (typeof v == 'number') {
break;
}
table = v;
width = width / 2;
left = left + width;
height = height / 2;
continue;
}
if (x >= left + width / 2 && x < left + width && y >= top + height / 2 && y < top + height) {
quadrant += '3';
v = table[2];
if (typeof v == 'number') {
break;
}
table = v;
width = width / 2;
left = left + width;
height = height / 2;
top = top + height;
continue;
}
if (x >= left && x < left + width / 2 && y >= top + height / 2 && y < top + height) {
quadrant += '4';
v = table[3];
if (typeof v == 'number') {
break;
}
table = v;
width = width / 2;
height = height / 2;
top = top + height;
continue;
}
return 0;
}
return v;
};
TableEditorSC.CellHandlesHoverTimeout = function () {
var editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
var cellhandles = editor.cellhandles;
if (cellhandles.timer) {
window.clearTimeout(cellhandles.timer);
cellhandles.timer = null;
}
editor.cellhandles.ShowCellHandles(true, false);
return undefined;
};
TableEditorSC.CellHandlesMouseDown = function (e) {
var scc = TableEditorSC.Constants;
var editor, coord, range;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
editor = TableEditorSC.Keyboard.focusTable;
if (!editor) return true;
if (editor.busy) return;
var cellhandles = editor.cellhandles;
cellhandles.movedmouse = false;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
if (cellhandles.timer) {
window.clearTimeout(cellhandles.timer);
cellhandles.timer = null;
}
cellhandles.dragtooltip.innerHTML = ' ';
cellhandles.dragtooltip.style.display = 'none';
range = editor.range;
var whichhandle = TableEditorSC.SegmentDivHit(
[scc.CH_radius1, scc.CH_radius2],
editor.cellhandles.dragpalette,
clientX,
clientY,
);
if (whichhandle == 1 || whichhandle == -1 || whichhandle == 0) {
cellhandles.ShowCellHandles(true, false);
return;
}
mouseinfo.ignore = true;
if (whichhandle == -3) {
cellhandles.dragtype = 'Fill';
cellhandles.noCursorSuffix = false;
} else if (whichhandle == 3) {
cellhandles.dragtype = 'FillC';
cellhandles.noCursorSuffix = false;
} else if (whichhandle == -2) {
cellhandles.dragtype = 'Move';
cellhandles.noCursorSuffix = true;
} else if (whichhandle == -4) {
cellhandles.dragtype = 'MoveI';
cellhandles.noCursorSuffix = false;
} else if (whichhandle == 2) {
cellhandles.dragtype = 'MoveC';
cellhandles.noCursorSuffix = true;
} else if (whichhandle == 4) {
cellhandles.dragtype = 'MoveIC';
cellhandles.noCursorSuffix = false;
}
cellhandles.filltype = null;
switch (cellhandles.dragtype) {
case 'Fill':
case 'FillC':
if (!range.hasrange) {
editor.RangeAnchor();
}
editor.range2.top = editor.range.top;
editor.range2.right = editor.range.right;
editor.range2.bottom = editor.range.bottom;
editor.range2.left = editor.range.left;
editor.range2.hasrange = true;
break;
case 'Move':
case 'MoveI':
case 'MoveC':
case 'MoveIC':
if (!range.hasrange) {
editor.RangeAnchor();
}
editor.range2.top = editor.range.top;
editor.range2.right = editor.range.right;
editor.range2.bottom = editor.range.bottom;
editor.range2.left = editor.range.left;
editor.range2.hasrange = true;
editor.RangeRemove();
break;
default:
return;
}
cellhandles.fillinghandle.style.left = clientX + 'px';
cellhandles.fillinghandle.style.top = clientY - 17 + 'px';
cellhandles.fillinghandle.innerHTML =
scc.s_CHindicatorOperationLookup[cellhandles.dragtype] +
(scc.s_CHindicatorDirectionLookup[editor.cellhandles.filltype] || '');
cellhandles.fillinghandle.style.display = 'block';
cellhandles.ShowCellHandles(true, false);
cellhandles.mouseDown = true;
mouseinfo.editor = editor;
coord = editor.ecell.coord;
cellhandles.startingcoord = coord;
cellhandles.startingX = clientX;
cellhandles.startingY = clientY;
mouseinfo.mouselastcoord = coord;
TableEditorSC.KeyboardSetFocus(editor);
document.addEventListener('mousemove', TableEditorSC.CellHandlesMouseMove, true);
document.addEventListener('mouseup', TableEditorSC.CellHandlesMouseUp, true);
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.CellHandlesMouseMove = function (e) {
var scc = TableEditorSC.Constants;
var editor, result;
var crstart, crend, c, r;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
editor = mouseinfo.editor;
if (!editor) return;
var cellhandles = editor.cellhandles;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
if (!result) return;
if (result && !result.coord) {
TableEditorSC.SetDragAutoRepeat(editor, result, TableEditorSC.CellHandlesDragAutoRepeat);
return;
}
TableEditorSC.SetDragAutoRepeat(editor, null);
if (!result.coord) return;
crstart = TableEditorSC.coordToCr(editor.cellhandles.startingcoord);
crend = TableEditorSC.coordToCr(result.coord);
cellhandles.movedmouse = true;
switch (cellhandles.dragtype) {
case 'Fill':
case 'FillC':
if (result.coord == cellhandles.startingcoord) {
cellhandles.filltype = null;
cellhandles.startingX = clientX;
cellhandles.startingY = clientY;
} else if (cellhandles.filltype) {
if (cellhandles.filltype == 'Down') {
crend.col = crstart.col;
if (crend.row < crstart.row) crend.row = crstart.row;
} else {
crend.row = crstart.row;
if (crend.col < crstart.col) crend.col = crstart.col;
}
} else {
if (Math.abs(clientY - cellhandles.startingY) > 10) cellhandles.filltype = 'Down';
else if (Math.abs(clientX - cellhandles.startingX) > 10) cellhandles.filltype = 'Right';
crend.col = crstart.col;
crend.row = crstart.row;
}
result.coord = TableEditorSC.crToCoord(crend.col, crend.row);
if (result.coord != mouseinfo.mouselastcoord) {
editor.MoveECell(result.coord);
editor.RangeExtend();
}
break;
case 'Move':
case 'MoveC':
if (result.coord != mouseinfo.mouselastcoord) {
editor.MoveECell(result.coord);
c = editor.range2.right - editor.range2.left + result.col;
r = editor.range2.bottom - editor.range2.top + result.row;
editor.RangeAnchor(TableEditorSC.crToCoord(c, r));
editor.RangeExtend();
}
break;
case 'MoveI':
case 'MoveIC':
if (result.coord == cellhandles.startingcoord) {
cellhandles.filltype = null;
cellhandles.startingX = clientX;
cellhandles.startingY = clientY;
} else if (cellhandles.filltype) {
if (cellhandles.filltype == 'Vertical') {
crend.col = editor.range2.left;
if (crend.row >= editor.range2.top && crend.row <= editor.range2.bottom + 1)
crend.row = editor.range2.bottom + 2;
} else {
crend.row = editor.range2.top;
if (crend.col >= editor.range2.left && crend.col <= editor.range2.right + 1)
crend.col = editor.range2.right + 2;
}
} else {
if (Math.abs(clientY - cellhandles.startingY) > 10) cellhandles.filltype = 'Vertical';
else if (Math.abs(clientX - cellhandles.startingX) > 10)
cellhandles.filltype = 'Horizontal';
crend.col = crstart.col;
crend.row = crstart.row;
}
result.coord = TableEditorSC.crToCoord(crend.col, crend.row);
if (result.coord != mouseinfo.mouselastcoord) {
editor.MoveECell(result.coord);
if (!cellhandles.filltype) editor.RangeRemove();
else {
c = editor.range2.right - editor.range2.left + crend.col;
r = editor.range2.bottom - editor.range2.top + crend.row;
editor.RangeAnchor(TableEditorSC.crToCoord(c, r));
editor.RangeExtend();
}
}
break;
}
cellhandles.fillinghandle.style.left = clientX + 'px';
cellhandles.fillinghandle.style.top = clientY - 17 + 'px';
cellhandles.fillinghandle.innerHTML =
scc.s_CHindicatorOperationLookup[cellhandles.dragtype] +
(scc.s_CHindicatorDirectionLookup[editor.cellhandles.filltype] || '');
cellhandles.fillinghandle.style.display = 'block';
mouseinfo.mouselastcoord = result.coord;
TableEditorSC.StopPropagation(event);
return;
};
TableEditorSC.CellHandlesDragAutoRepeat = function (coord, direction) {
var mouseinfo = TableEditorSC.EditorMouseInfo;
var editor = mouseinfo.editor;
if (!editor) return;
var cellhandles = editor.cellhandles;
var crstart = TableEditorSC.coordToCr(editor.cellhandles.startingcoord);
var crend = TableEditorSC.coordToCr(coord);
var newcoord, c, r;
var vscroll = 0;
var hscroll = 0;
if (direction == 'left') hscroll = -1;
else if (direction == 'right') hscroll = 1;
else if (direction == 'up') vscroll = -1;
else if (direction == 'down') vscroll = 1;
editor.ScrollRelativeBoth(vscroll, hscroll);
switch (cellhandles.dragtype) {
case 'Fill':
case 'FillC':
if (cellhandles.filltype) {
if (cellhandles.filltype == 'Down') {
crend.col = crstart.col;
if (crend.row < crstart.row) crend.row = crstart.row;
} else {
crend.row = crstart.row;
if (crend.col < crstart.col) crend.col = crstart.col;
}
} else {
crend.col = crstart.col;
crend.row = crstart.row;
}
newcoord = TableEditorSC.crToCoord(crend.col, crend.row);
if (newcoord != mouseinfo.mouselastcoord) {
editor.MoveECell(coord);
editor.RangeExtend();
}
break;
case 'Move':
case 'MoveC':
if (coord != mouseinfo.mouselastcoord) {
editor.MoveECell(coord);
c = editor.range2.right - editor.range2.left + editor.ecell.col;
r = editor.range2.bottom - editor.range2.top + editor.ecell.row;
editor.RangeAnchor(TableEditorSC.crToCoord(c, r));
editor.RangeExtend();
}
break;
case 'MoveI':
case 'MoveIC':
if (cellhandles.filltype) {
if (cellhandles.filltype == 'Vertical') {
crend.col = editor.range2.left;
if (crend.row >= editor.range2.top && crend.row <= editor.range2.bottom + 1)
crend.row = editor.range2.bottom + 2;
} else {
crend.row = editor.range2.top;
if (crend.col >= editor.range2.left && crend.col <= editor.range2.right + 1)
crend.col = editor.range2.right + 2;
}
} else {
crend.col = crstart.col;
crend.row = crstart.row;
}
newcoord = TableEditorSC.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(TableEditorSC.crToCoord(c, r));
editor.RangeExtend();
}
break;
}
mouseinfo.mouselastcoord = newcoord;
};
TableEditorSC.CellHandlesMouseUp = function (e) {
var editor, result, cstr, cmdtype, cmdtype2;
var crstart, crend;
var sizec, sizer;
var event = e || window.event;
var mouseinfo = TableEditorSC.EditorMouseInfo;
editor = mouseinfo.editor;
if (!editor) return;
var cellhandles = editor.cellhandles;
mouseinfo.ignore = false;
var pos = TableEditorSC.GetElementPositionWithScroll(editor.toplevel);
var clientX = event.clientX - pos.left;
var clientY = event.clientY - pos.top;
result = TableEditorSC.GridMousePosition(editor, clientX, clientY);
TableEditorSC.SetDragAutoRepeat(editor, null);
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) {
cellhandles.dragtype = 'Nothing';
}
switch (cellhandles.dragtype) {
case 'Nothing':
editor.Range2Remove();
editor.RangeRemove();
break;
case 'Fill':
case 'FillC':
crstart = TableEditorSC.coordToCr(cellhandles.startingcoord);
crend = TableEditorSC.coordToCr(result.coord);
if (cellhandles.filltype) {
if (cellhandles.filltype == 'Down') {
crend.col = crstart.col;
} else {
crend.row = crstart.row;
}
}
result.coord = TableEditorSC.crToCoord(crend.col, crend.row);
editor.MoveECell(result.coord);
editor.RangeExtend();
if (editor.cellhandles.filltype == 'Right') {
cmdtype = 'right';
} else {
cmdtype = 'down';
}
cstr =
'fill' +
cmdtype +
' ' +
TableEditorSC.crToCoord(editor.range.left, editor.range.top) +
':' +
TableEditorSC.crToCoord(editor.range.right, editor.range.bottom) +
cmdtype2;
editor.EditorScheduleSheetCommands(cstr, true, false);
break;
case 'Move':
case 'MoveC':
editor.context.cursorsuffix = '';
cstr =
'movepaste ' +
TableEditorSC.crToCoord(editor.range2.left, editor.range2.top) +
':' +
TableEditorSC.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;
cstr =
'moveinsert ' +
TableEditorSC.crToCoord(editor.range2.left, editor.range2.top) +
':' +
TableEditorSC.crToCoord(editor.range2.right, editor.range2.bottom) +
' ' +
editor.ecell.coord +
cmdtype2;
editor.EditorScheduleSheetCommands(cstr, true, false);
editor.Range2Remove();
editor.RangeRemove();
editor.RangeAnchor(
TableEditorSC.crToCoord(editor.ecell.col + sizec, editor.ecell.row + sizer),
);
editor.RangeExtend();
break;
}
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.CellHandlesMouseMove,
TableEditorSC.CellHandlesMouseUp,
cellhandles.draghandle,
event,
);
mouseinfo.editor = null;
return false;
};
TableEditorSC.TableControl = function (editor, vertical, size) {
var scc = TableEditorSC.Constants;
this.editor = editor;
this.vertical = vertical;
this.size = size;
this.main = null;
this.endcap = null;
this.paneslider = null;
this.lessbutton = null;
this.morebutton = null;
this.scrollarea = null;
this.thumb = null;
this.controlborder = null;
this.endcapstart = null;
this.panesliderstart = null;
this.lessbuttonstart = null;
this.morebuttonstart = null;
this.scrollareastart = null;
this.scrollareaend = null;
this.scrollareasize = null;
this.thumbpos = null;
this.controlthickness = scc.defaultTableControlThickness;
this.sliderthickness = scc.defaultTCSliderThickness;
this.buttonthickness = scc.defaultTCButtonThickness;
this.thumbthickness = scc.defaultTCThumbThickness;
this.minscrollingpanesize =
this.buttonthickness + this.buttonthickness + this.thumbthickness + 20;
};
TableEditorSC.TableControl.prototype.CreateTableControl = function () {
return TableEditorSC.CreateTableControl(this);
};
TableEditorSC.TableControl.prototype.PositionTableControlElements = function () {
TableEditorSC.PositionTableControlElements(this);
};
TableEditorSC.TableControl.prototype.ComputeTableControlPositions = function () {
TableEditorSC.ComputeTableControlPositions(this);
};
TableEditorSC.CreateTableControl = function (control) {
var s;
var functions;
var params;
var AssignID = TableEditorSC.AssignID;
var setStyles = TableEditorSC.setStyles;
var scc = TableEditorSC.Constants;
var imageprefix = control.editor.imageprefix;
var vh = control.vertical ? 'v' : 'h';
var SCLoc = TableEditorSC.LocalizeString;
control.main = SocialCalc.document.createElement('div');
s = control.main.style;
s.height = (control.vertical ? control.size : control.controlthickness) + 'px';
s.width = (control.vertical ? control.controlthickness : control.size) + 'px';
s.zIndex = 0;
setStyles(control.main, scc.TCmainStyle);
s.backgroundImage = 'url(' + imageprefix + 'main-' + vh + '.gif)';
if (scc.TCmainClass) control.main.className = scc.TCmainClass;
control.main.style.display = 'none';
control.endcap = SocialCalc.document.createElement('div');
s = control.endcap.style;
s.height = control.controlthickness + 'px';
s.width = control.controlthickness + 'px';
s.zIndex = 1;
s.overflow = 'hidden';
s.position = 'absolute';
setStyles(control.endcap, scc.TCendcapStyle);
s.backgroundImage = 'url(' + imageprefix + 'endcap-' + vh + '.gif)';
if (scc.TCendcapClass) control.endcap.className = scc.TCendcapClass;
AssignID(control.editor, control.endcap, 'endcap' + vh);
control.main.appendChild(control.endcap);
control.paneslider = SocialCalc.document.createElement('div');
s = control.paneslider.style;
s.height = (control.vertical ? control.sliderthickness : control.controlthickness) + 'px';
s.overflow = 'hidden';
s.width = (control.vertical ? control.controlthickness : control.sliderthickness) + 'px';
s.position = 'absolute';
s[control.vertical ? 'top' : 'left'] = '4px';
s.zIndex = 3;
s.backgroundImage = 'url(' + imageprefix + 'paneslider-' + vh + '.gif)';
if (scc.TCpanesliderClass) control.paneslider.className = scc.TCpanesliderClass;
AssignID(control.editor, control.paneslider, 'paneslider' + vh);
control.paneslider.title = SCLoc(
control.vertical ? 'Drag to lock pane horizontally' : 'Drag to lock pane vertically',
);
functions = {
MouseDown: TableEditorSC.TCPSDragFunctionStart,
MouseMove: TableEditorSC.TCPSDragFunctionMove,
MouseUp: TableEditorSC.TCPSDragFunctionStop,
Disabled: function () {
return control.editor.busy;
},
};
functions.control = control;
if (TableEditorSC._app != true)
TableEditorSC.DragRegister(
control.paneslider,
control.vertical,
!control.vertical,
functions,
control.editor.toplevel,
);
control.main.appendChild(control.paneslider);
control.lessbutton = SocialCalc.document.createElement('div');
s = control.lessbutton.style;
s.height = (control.vertical ? control.buttonthickness : control.controlthickness) + 'px';
s.width = (control.vertical ? control.controlthickness : control.buttonthickness) + 'px';
s.zIndex = 2;
s.overflow = 'hidden';
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;
},
};
TableEditorSC.ButtonRegister(control.editor, control.lessbutton, params, functions);
control.main.appendChild(control.lessbutton);
control.morebutton = SocialCalc.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;
s.overflow = 'hidden';
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;
},
};
TableEditorSC.ButtonRegister(control.editor, control.morebutton, params, functions);
control.main.appendChild(control.morebutton);
control.scrollarea = SocialCalc.document.createElement('div');
s = control.scrollarea.style;
s.height = control.controlthickness + 'px';
s.width = control.controlthickness + 'px';
s.zIndex = 1;
s.overflow = 'hidden';
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: TableEditorSC.ScrollAreaClick,
Repeat: TableEditorSC.ScrollAreaClick,
Disabled: function () {
return control.editor.busy;
},
};
functions.control = control;
TableEditorSC.ButtonRegister(control.editor, control.scrollarea, params, functions);
control.main.appendChild(control.scrollarea);
control.thumb = SocialCalc.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';
s.zIndex = 2;
s.overflow = 'hidden';
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: TableEditorSC.TCTDragFunctionStart,
MouseMove: TableEditorSC.TCTDragFunctionMove,
MouseUp: TableEditorSC.TCTDragFunctionStop,
Disabled: function () {
return control.editor.busy;
},
};
functions.control = control;
if (TableEditorSC._app != true)
TableEditorSC.DragRegister(
control.thumb,
control.vertical,
!control.vertical,
functions,
control.editor.toplevel,
);
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)',
};
TableEditorSC.ButtonRegister(control.editor, control.thumb, params, null);
control.main.appendChild(control.thumb);
return control.main;
};
TableEditorSC.ScrollAreaClick = function (e, buttoninfo, bobj) {
var control = bobj.functionobj.control;
var pos = TableEditorSC.GetElementPositionWithScroll(control.editor.toplevel);
var clickpos = control.vertical ? buttoninfo.clientY - pos.top : buttoninfo.clientX - pos.left;
if (control.editor.busy) {
return;
}
control.editor.PageRelative(control.vertical, clickpos > control.thumbpos ? 1 : -1);
return;
};
TableEditorSC.PositionTableControlElements = function (control) {
var border, realend, thumbpos;
var editor = control.editor;
if (control.vertical) {
border = control.controlborder + 'px';
control.endcap.style.top = control.endcapstart + 'px';
control.endcap.style.left = border;
control.paneslider.style.top = control.panesliderstart + 'px';
control.paneslider.style.left = border;
control.lessbutton.style.top = control.lessbuttonstart + 'px';
control.lessbutton.style.left = border;
control.morebutton.style.top = control.morebuttonstart + 'px';
control.morebutton.style.left = border;
control.scrollarea.style.top = control.scrollareastart + 'px';
control.scrollarea.style.left = border;
control.scrollarea.style.height = control.scrollareasize + 'px';
realend = Math.max(editor.context.sheetobj.attribs.lastrow, editor.firstscrollingrow + 1);
thumbpos =
((editor.firstscrollingrow - (editor.lastnonscrollingrow + 1)) *
(control.scrollareasize - 3 * control.thumbthickness)) /
(realend - (editor.lastnonscrollingrow + 1)) +
control.scrollareastart -
1;
thumbpos = Math.floor(thumbpos);
control.thumb.style.top = thumbpos + 'px';
control.thumb.style.left = border;
} else {
border = control.controlborder + 'px';
control.endcap.style.left = control.endcapstart + 'px';
control.endcap.style.top = border;
control.paneslider.style.left = control.panesliderstart + 'px';
control.paneslider.style.top = border;
control.lessbutton.style.left = control.lessbuttonstart + 'px';
control.lessbutton.style.top = border;
control.morebutton.style.left = control.morebuttonstart + 'px';
control.morebutton.style.top = border;
control.scrollarea.style.left = control.scrollareastart + 'px';
control.scrollarea.style.top = border;
control.scrollarea.style.width = control.scrollareasize + 'px';
realend = Math.max(editor.context.sheetobj.attribs.lastcol, editor.firstscrollingcol + 1);
thumbpos =
((editor.firstscrollingcol - (editor.lastnonscrollingcol + 1)) *
(control.scrollareasize - control.thumbthickness)) /
(realend - editor.lastnonscrollingcol) +
control.scrollareastart -
1;
thumbpos = Math.floor(thumbpos);
control.thumb.style.left = thumbpos + 'px';
control.thumb.style.top = border;
}
control.thumbpos = thumbpos;
control.main.style.display = 'block';
};
TableEditorSC.ComputeTableControlPositions = function (control) {
var editor = control.editor;
if (!editor.gridposition || !editor.headposition)
throw "Can't compute table control positions before editor positions";
if (control.vertical) {
control.controlborder = editor.gridposition.left + editor.tablewidth;
control.endcapstart = editor.gridposition.top;
control.panesliderstart = editor.firstscrollingrowtop - control.sliderthickness;
control.lessbuttonstart = editor.firstscrollingrowtop - 1;
control.morebuttonstart =
editor.gridposition.top + editor.tableheight - control.buttonthickness;
control.scrollareastart = editor.firstscrollingrowtop - 1 + control.buttonthickness;
control.scrollareaend = control.morebuttonstart - 1;
control.scrollareasize = control.scrollareaend - control.scrollareastart + 1;
} else {
control.controlborder = editor.gridposition.top + editor.tableheight;
control.endcapstart = editor.gridposition.left;
control.panesliderstart = editor.firstscrollingcolleft - control.sliderthickness;
control.lessbuttonstart = editor.firstscrollingcolleft - 1;
control.morebuttonstart =
editor.gridposition.left + editor.tablewidth - control.buttonthickness;
control.scrollareastart = editor.firstscrollingcolleft - 1 + control.buttonthickness;
control.scrollareaend = control.morebuttonstart - 1;
control.scrollareasize = control.scrollareaend - control.scrollareastart + 1;
}
};
TableEditorSC.TCPSDragFunctionStart = function (event, draginfo, dobj) {
var editor = dobj.functionobj.control.editor;
var scc = TableEditorSC.Constants;
TableEditorSC.DragFunctionStart(event, draginfo, dobj);
draginfo.trackingline = SocialCalc.document.createElement('div');
draginfo.trackingline.style.height = dobj.vertical
? scc.TCPStrackinglineThickness
: editor.tableheight - (editor.headposition.top - editor.gridposition.top) + 'px';
draginfo.trackingline.style.width = dobj.vertical
? editor.tablewidth - (editor.headposition.left - editor.gridposition.left) + 'px'
: scc.TCPStrackinglineThickness;
draginfo.trackingline.style.backgroundImage =
'url(' + editor.imageprefix + 'trackingline-' + (dobj.vertical ? 'v' : 'h') + '.gif)';
if (scc.TCPStrackinglineClass) draginfo.trackingline.className = scc.TCPStrackinglineClass;
TableEditorSC.setStyles(draginfo.trackingline, scc.TCPStrackinglineStyle);
if (dobj.vertical) {
var row = TableEditorSC.Lookup(
draginfo.clientY + dobj.functionobj.control.sliderthickness,
editor.rowpositions,
);
draginfo.trackingline.style.top =
(editor.rowpositions[row] || editor.headposition.top) + 'px';
draginfo.trackingline.style.left = editor.headposition.left + 'px';
draginfo.trackingline.id = 'trackingline-vertical';
if (editor.context.rowpanes.length - 1) {
editor.context.SetRowPaneFirstLast(
1,
editor.context.rowpanes[0].last + 1,
editor.context.rowpanes[0].last + 1,
);
editor.FitToEditTable();
editor.ScheduleRender();
}
} else {
var col = TableEditorSC.Lookup(
draginfo.clientX + dobj.functionobj.control.sliderthickness,
editor.colpositions,
);
draginfo.trackingline.style.top = editor.headposition.top + 'px';
draginfo.trackingline.style.left =
(editor.colpositions[col] || editor.headposition.left) + 'px';
draginfo.trackingline.id = 'trackingline-horizon';
if (editor.context.colpanes.length - 1) {
editor.context.SetColPaneFirstLast(
1,
editor.context.colpanes[0].last + 1,
editor.context.colpanes[0].last + 1,
);
editor.FitToEditTable();
editor.ScheduleRender();
}
}
editor.griddiv.appendChild(draginfo.trackingline);
};
TableEditorSC.TCPSDragFunctionMove = function (event, draginfo, dobj) {
var row, col, max, min;
var control = dobj.functionobj.control;
var sliderthickness = control.sliderthickness;
var editor = control.editor;
if (dobj.vertical) {
max = control.morebuttonstart - control.minscrollingpanesize - draginfo.offsetY;
if (draginfo.clientY > max) draginfo.clientY = max;
min = editor.headposition.top - sliderthickness - draginfo.offsetY;
if (draginfo.clientY < min) draginfo.clientY = min;
row = TableEditorSC.Lookup(draginfo.clientY + sliderthickness, editor.rowpositions);
while (editor.context.sheetobj.rowattribs.hide[row] == 'yes') {
row++;
}
draginfo.trackingline.style.top =
(editor.rowpositions[row] || editor.headposition.top) + 'px';
} else {
max = control.morebuttonstart - control.minscrollingpanesize - draginfo.offsetX;
if (draginfo.clientX > max) draginfo.clientX = max;
min = editor.headposition.left - sliderthickness - draginfo.offsetX;
if (draginfo.clientX < min) draginfo.clientX = min;
col = TableEditorSC.Lookup(draginfo.clientX + sliderthickness, editor.colpositions);
while (editor.context.sheetobj.colattribs.hide[TableEditorSC.rcColname(col)] == 'yes') {
col++;
}
draginfo.trackingline.style.left =
(editor.colpositions[col] || editor.headposition.left) + 'px';
}
TableEditorSC.DragFunctionPosition(event, draginfo, dobj);
};
TableEditorSC.TCPSDragFunctionStop = function (event, draginfo, dobj) {
var row, col, max, min;
var control = dobj.functionobj.control;
var sliderthickness = control.sliderthickness;
var editor = control.editor;
if (dobj.vertical) {
max = control.morebuttonstart - control.minscrollingpanesize - draginfo.offsetY;
if (draginfo.clientY > max) draginfo.clientY = max;
min = editor.headposition.top - sliderthickness - draginfo.offsetY;
if (draginfo.clientY < min) draginfo.clientY = min;
row = TableEditorSC.Lookup(draginfo.clientY + sliderthickness, editor.rowpositions);
if (row > editor.context.sheetobj.attribs.lastrow)
row = editor.context.sheetobj.attribs.lastrow;
while (editor.context.sheetobj.rowattribs.hide[row] == 'yes') {
row++;
}
editor.EditorScheduleSheetCommands('pane row ' + row, true, false);
} else {
max = control.morebuttonstart - control.minscrollingpanesize - draginfo.offsetX;
if (draginfo.clientX > max) draginfo.clientX = max;
min = editor.headposition.left - sliderthickness - draginfo.offsetX;
if (draginfo.clientX < min) draginfo.clientX = min;
col = TableEditorSC.Lookup(draginfo.clientX + sliderthickness, editor.colpositions);
if (col > editor.context.sheetobj.attribs.lastcol)
col = editor.context.sheetobj.attribs.lastcol;
while (editor.context.sheetobj.colattribs.hide[TableEditorSC.rcColname(col)] == 'yes') {
col++;
}
editor.EditorScheduleSheetCommands('pane col ' + col, true, false);
}
};
TableEditorSC.TCTDragFunctionStart = function (event, draginfo, dobj) {
var control = dobj.functionobj.control;
var editor = control.editor;
var scc = TableEditorSC.Constants;
TableEditorSC.DragFunctionStart(event, draginfo, dobj);
if (draginfo.thumbstatus) {
if (draginfo.thumbstatus.rowmsgele) draginfo.thumbstatus.rowmsgele = null;
if (draginfo.thumbstatus.rowpreviewele) draginfo.thumbstatus.rowpreviewele = null;
editor.toplevel.removeChild(draginfo.thumbstatus);
draginfo.thumbstatus = null;
}
draginfo.thumbstatus = SocialCalc.document.createElement('div');
if (dobj.vertical) {
if (scc.TCTDFSthumbstatusvClass) draginfo.thumbstatus.className = scc.TCTDFSthumbstatusvClass;
TableEditorSC.setStyles(draginfo.thumbstatus, scc.TCTDFSthumbstatusvStyle);
draginfo.thumbstatus.style.top = draginfo.clientY + scc.TCTDFStopOffsetv + 'px';
draginfo.thumbstatus.style.left = control.controlborder - 10 - editor.tablewidth / 2 + 'px';
draginfo.thumbstatus.style.width = editor.tablewidth / 2 + 'px';
draginfo.thumbcontext = new TableEditorSC.RenderContext(editor.context.sheetobj);
draginfo.thumbcontext.showGrid = true;
draginfo.thumbcontext.rowpanes = [
{
first: 1,
last: 1,
},
];
var pane = editor.context.colpanes[editor.context.colpanes.length - 1];
draginfo.thumbcontext.colpanes = [
{
first: pane.first,
last: pane.last,
},
];
draginfo.thumbstatus.innerHTML =
'';
draginfo.thumbstatus.rowmsgele =
draginfo.thumbstatus.firstChild.firstChild.firstChild.firstChild.firstChild;
draginfo.thumbstatus.rowpreviewele =
draginfo.thumbstatus.firstChild.firstChild.firstChild.childNodes[1].firstChild;
editor.toplevel.appendChild(draginfo.thumbstatus);
TableEditorSC.TCTDragFunctionRowSetStatus(draginfo, editor, editor.firstscrollingrow || 1);
} else {
if (scc.TCTDFSthumbstatushClass) draginfo.thumbstatus.className = scc.TCTDFSthumbstatushClass;
TableEditorSC.setStyles(draginfo.thumbstatus, scc.TCTDFSthumbstatushStyle);
draginfo.thumbstatus.style.top = control.controlborder + scc.TCTDFStopOffseth + 'px';
draginfo.thumbstatus.style.left = draginfo.clientX + scc.TCTDFSleftOffseth + 'px';
editor.toplevel.appendChild(draginfo.thumbstatus);
draginfo.thumbstatus.innerHTML =
scc.s_TCTDFthumbstatusPrefixh + TableEditorSC.rcColname(editor.firstscrollingcol);
}
};
TableEditorSC.TCTDragFunctionRowSetStatus = function (draginfo, editor, row) {
var scc = TableEditorSC.Constants;
var msg = scc.s_TCTDFthumbstatusPrefixv + row + ' ';
draginfo.thumbstatus.rowmsgele.innerHTML = msg;
draginfo.thumbcontext.rowpanes = [
{
first: row,
last: row,
},
];
draginfo.thumbrowshown = row;
draginfo.thumbcontext.RenderSheet(draginfo.thumbstatus.rowpreviewele.firstChild, {
type: 'html',
});
};
TableEditorSC.TCTDragFunctionMove = function (event, draginfo, dobj) {
var first, msg;
var control = dobj.functionobj.control;
var editor = control.editor;
var scc = TableEditorSC.Constants;
if (dobj.vertical) {
if (draginfo.clientY > control.scrollareaend - draginfo.offsetY - control.thumbthickness + 2)
draginfo.clientY = control.scrollareaend - draginfo.offsetY - control.thumbthickness + 2;
if (draginfo.clientY < control.scrollareastart - draginfo.offsetY - 1)
draginfo.clientY = control.scrollareastart - draginfo.offsetY - 1;
draginfo.thumbstatus.style.top = draginfo.clientY + 'px';
first =
((draginfo.clientY + draginfo.offsetY - control.scrollareastart + 1) /
(control.scrollareasize - control.thumbthickness)) *
(editor.context.sheetobj.attribs.lastrow - editor.lastnonscrollingrow) +
editor.lastnonscrollingrow +
1;
first = Math.floor(first);
if (first <= editor.lastnonscrollingrow) first = editor.lastnonscrollingrow + 1;
if (first > editor.context.sheetobj.attribs.lastrow)
first = editor.context.sheetobj.attribs.lastrow;
if (first != draginfo.thumbrowshown) {
TableEditorSC.TCTDragFunctionRowSetStatus(draginfo, editor, first);
}
} else {
if (draginfo.clientX > control.scrollareaend - draginfo.offsetX - control.thumbthickness + 2)
draginfo.clientX = control.scrollareaend - draginfo.offsetX - control.thumbthickness + 2;
if (draginfo.clientX < control.scrollareastart - draginfo.offsetX - 1)
draginfo.clientX = control.scrollareastart - draginfo.offsetX - 1;
draginfo.thumbstatus.style.left = draginfo.clientX + 'px';
first =
((draginfo.clientX + draginfo.offsetX - control.scrollareastart + 1) /
(control.scrollareasize - control.thumbthickness)) *
(editor.context.sheetobj.attribs.lastcol - editor.lastnonscrollingcol) +
editor.lastnonscrollingcol +
1;
first = Math.floor(first);
if (first <= editor.lastnonscrollingcol) first = editor.lastnonscrollingcol + 1;
if (first > editor.context.sheetobj.attribs.lastcol)
first = editor.context.sheetobj.attribs.lastcol;
msg = scc.s_TCTDFthumbstatusPrefixh + TableEditorSC.rcColname(first);
draginfo.thumbstatus.innerHTML = msg;
}
TableEditorSC.DragFunctionPosition(event, draginfo, dobj);
};
TableEditorSC.TCTDragFunctionStop = function (event, draginfo, dobj) {
var first;
var control = dobj.functionobj.control;
var editor = control.editor;
if (dobj.vertical) {
first =
((draginfo.clientY + draginfo.offsetY - control.scrollareastart + 1) /
(control.scrollareasize - control.thumbthickness)) *
(editor.context.sheetobj.attribs.lastrow - editor.lastnonscrollingrow) +
editor.lastnonscrollingrow +
1;
first = Math.floor(first);
if (first <= editor.lastnonscrollingrow) first = editor.lastnonscrollingrow + 1;
if (first > editor.context.sheetobj.attribs.lastrow)
first = editor.context.sheetobj.attribs.lastrow;
editor.context.SetRowPaneFirstLast(editor.context.rowpanes.length - 1, first, first + 1);
} else {
first =
((draginfo.clientX + draginfo.offsetX - control.scrollareastart + 1) /
(control.scrollareasize - control.thumbthickness)) *
(editor.context.sheetobj.attribs.lastcol - editor.lastnonscrollingcol) +
editor.lastnonscrollingcol +
1;
first = Math.floor(first);
if (first <= editor.lastnonscrollingcol) first = editor.lastnonscrollingcol + 1;
if (first > editor.context.sheetobj.attribs.lastcol)
first = editor.context.sheetobj.attribs.lastcol;
editor.context.SetColPaneFirstLast(editor.context.colpanes.length - 1, first, first + 1);
}
editor.FitToEditTable();
if (draginfo.thumbstatus.rowmsgele) draginfo.thumbstatus.rowmsgele = null;
if (draginfo.thumbstatus.rowpreviewele) draginfo.thumbstatus.rowpreviewele = null;
editor.toplevel.removeChild(draginfo.thumbstatus);
draginfo.thumbstatus = null;
editor.ScheduleRender();
};
TableEditorSC.DragInfo = {
registeredElements: [],
draggingElement: null,
startX: 0,
startY: 0,
startZ: 0,
clientX: 0,
clientY: 0,
offsetX: 0,
offsetY: 0,
relativeOffset: {
left: 0,
top: 0,
},
};
TableEditorSC.DragRegister = function (element, vertical, horizontal, functionobj, parent) {
var draginfo = TableEditorSC.DragInfo;
if (!functionobj) {
functionobj = {
MouseDown: TableEditorSC.DragFunctionStart,
MouseMove: TableEditorSC.DragFunctionPosition,
MouseUp: TableEditorSC.DragFunctionPosition,
Disabled: null,
};
}
draginfo.registeredElements.push({
element,
vertical,
horizontal,
functionobj,
parent,
});
element.addEventListener('mousedown', TableEditorSC.DragMouseDown, false);
};
TableEditorSC.DragUnregister = function (element) {
var draginfo = TableEditorSC.DragInfo;
var i;
if (!element) return;
for (i = 0; i < draginfo.registeredElements.length; i++) {
if (draginfo.registeredElements[i].element == element) {
draginfo.registeredElements.splice(i, 1);
element.removeEventListener('mousedown', TableEditorSC.DragMouseDown, false);
return;
}
}
return;
};
TableEditorSC.DragMouseDown = function (event) {
var e = event || window.event;
var draginfo = TableEditorSC.DragInfo;
var dobj = TableEditorSC.LookupElement(e.target || e.srcElement, draginfo.registeredElements);
if (!dobj) return;
if (dobj && dobj.functionobj && dobj.functionobj.Disabled) {
if (dobj.functionobj.Disabled(e, draginfo, dobj)) {
return;
}
}
draginfo.draggingElement = dobj;
if (dobj.parent) {
draginfo.relativeOffset = TableEditorSC.GetElementPositionWithScroll(dobj.parent);
}
draginfo.clientX = e.clientX - draginfo.relativeOffset.left;
draginfo.clientY = e.clientY - draginfo.relativeOffset.top;
draginfo.startX = draginfo.clientX;
draginfo.startY = draginfo.clientY;
draginfo.startZ = dobj.element.style.zIndex;
draginfo.offsetX = 0;
draginfo.offsetY = 0;
dobj.element.style.zIndex = '100';
TableEditorSC.SetMouseMoveUp(
TableEditorSC.DragMouseMove,
TableEditorSC.DragMouseUp,
dobj.element,
e,
);
if (dobj && dobj.functionobj && dobj.functionobj.MouseDown)
dobj.functionobj.MouseDown(e, draginfo, dobj);
return false;
};
TableEditorSC.DragMouseMove = function (event) {
var e = event || window.event;
var draginfo = TableEditorSC.DragInfo;
var dobj = draginfo.draggingElement;
draginfo.clientX = e.clientX - draginfo.relativeOffset.left;
draginfo.clientY = e.clientY - draginfo.relativeOffset.top;
TableEditorSC.StopPropagation(e);
if (dobj && dobj.functionobj && dobj.functionobj.MouseMove)
dobj.functionobj.MouseMove(e, draginfo, dobj);
return false;
};
TableEditorSC.DragMouseUp = function (event) {
var e = event || window.event;
var draginfo = TableEditorSC.DragInfo;
var dobj = draginfo.draggingElement;
draginfo.clientX = e.clientX - draginfo.relativeOffset.left;
draginfo.clientY = e.clientY - draginfo.relativeOffset.top;
dobj.element.style.zIndex = draginfo.startZ;
if (dobj && dobj.functionobj && dobj.functionobj.MouseUp)
dobj.functionobj.MouseUp(e, draginfo, dobj);
TableEditorSC.RemoveMouseMoveUp(
TableEditorSC.DragMouseMove,
TableEditorSC.DragMouseUp,
dobj.element,
e,
);
draginfo.draggingElement = null;
return false;
};
TableEditorSC.DragFunctionStart = function (event, draginfo, dobj) {
var element = dobj.functionobj.positionobj || dobj.element;
draginfo.offsetY = parseInt(element.style.top) - draginfo.clientY;
draginfo.offsetX = parseInt(element.style.left) - draginfo.clientX;
};
TableEditorSC.DragFunctionPosition = function (event, draginfo, dobj) {
var element = dobj.functionobj.positionobj || dobj.element;
if (dobj.vertical) element.style.top = draginfo.clientY + draginfo.offsetY + 'px';
if (dobj.horizontal) element.style.left = draginfo.clientX + draginfo.offsetX + 'px';
};
TableEditorSC.ButtonInfo = {
registeredElements: [],
buttonElement: null,
doingHover: false,
buttonDown: false,
timer: null,
relativeOffset: null,
clientX: 0,
clientY: 0,
};
TableEditorSC.ButtonRegister = function (editor, element, paramobj, functionobj) {
var buttoninfo = TableEditorSC.ButtonInfo;
if (!paramobj) paramobj = {};
buttoninfo.registeredElements.push({
name: paramobj.name,
element,
editor,
normalstyle: paramobj.normalstyle,
hoverstyle: paramobj.hoverstyle,
downstyle: paramobj.downstyle,
repeatwait: paramobj.repeatwait,
repeatinterval: paramobj.repeatinterval,
functionobj,
});
element.addEventListener('mousedown', TableEditorSC.ButtonMouseDown, false);
element.addEventListener('mouseover', TableEditorSC.ButtonMouseOver, false);
element.addEventListener('mouseout', TableEditorSC.ButtonMouseOut, false);
return;
};
TableEditorSC.ButtonMouseOver = function (event) {
var e = event || window.event;
var buttoninfo = TableEditorSC.ButtonInfo;
var bobj = TableEditorSC.LookupElement(e.target || e.srcElement, buttoninfo.registeredElements);
if (!bobj) return;
if (buttoninfo.buttonDown) {
if (buttoninfo.buttonElement == bobj) {
buttoninfo.doingHover = true;
}
return;
}
if (buttoninfo.buttonElement && buttoninfo.buttonElement != bobj && buttoninfo.doingHover) {
TableEditorSC.setStyles(
buttoninfo.buttonElement.element,
buttoninfo.buttonElement.normalstyle,
);
}
buttoninfo.buttonElement = bobj;
buttoninfo.doingHover = true;
TableEditorSC.setStyles(bobj.element, bobj.hoverstyle);
if (bobj && bobj.functionobj && bobj.functionobj.MouseOver)
bobj.functionobj.MouseOver(e, buttoninfo, bobj);
return;
};
TableEditorSC.ButtonMouseOut = function (event) {
var e = event || window.event;
var buttoninfo = TableEditorSC.ButtonInfo;
if (buttoninfo.buttonDown) {
buttoninfo.doingHover = false;
return;
}
var bobj = TableEditorSC.LookupElement(e.target || e.srcElement, buttoninfo.registeredElements);
if (buttoninfo.doingHover) {
if (buttoninfo.buttonElement)
TableEditorSC.setStyles(
buttoninfo.buttonElement.element,
buttoninfo.buttonElement.normalstyle,
);
buttoninfo.buttonElement = null;
buttoninfo.doingHover = false;
}
if (bobj && bobj.functionobj && bobj.functionobj.MouseOut)
bobj.functionobj.MouseOut(e, buttoninfo, bobj);
return;
};
TableEditorSC.ButtonMouseDown = function (event) {
var e = event || window.event;
var buttoninfo = TableEditorSC.ButtonInfo;
var bobj = TableEditorSC.LookupElement(e.target || e.srcElement, buttoninfo.registeredElements);
if (!bobj) return;
if (bobj && bobj.functionobj && bobj.functionobj.Disabled) {
if (bobj.functionobj.Disabled(e, buttoninfo, bobj)) {
return;
}
}
buttoninfo.buttonElement = bobj;
buttoninfo.buttonDown = true;
TableEditorSC.setStyles(bobj.element, buttoninfo.buttonElement.downstyle);
document.addEventListener('mouseup', TableEditorSC.ButtonMouseUp, true);
TableEditorSC.StopPropagation(e);
buttoninfo.relativeOffset = TableEditorSC.GetElementPositionWithScroll(bobj.editor.toplevel);
buttoninfo.clientX = e.clientX - buttoninfo.relativeOffset.left;
buttoninfo.clientY = e.clientY - buttoninfo.relativeOffset.top;
if (bobj && bobj.functionobj && bobj.functionobj.MouseDown)
bobj.functionobj.MouseDown(e, buttoninfo, bobj);
if (bobj.repeatwait) {
buttoninfo.timer = window.setTimeout(TableEditorSC.ButtonRepeat, bobj.repeatwait);
}
return;
};
TableEditorSC.ButtonMouseUp = function (event) {
var e = event || window.event;
var buttoninfo = TableEditorSC.ButtonInfo;
var bobj = buttoninfo.buttonElement;
if (buttoninfo.timer) {
window.clearTimeout(buttoninfo.timer);
buttoninfo.timer = null;
}
if (!buttoninfo.buttonDown) return;
TableEditorSC.StopPropagation(e);
document.removeEventListener('mouseup', TableEditorSC.ButtonMouseUp, true);
if (buttoninfo.buttonElement.downstyle) {
if (buttoninfo.doingHover)
TableEditorSC.setStyles(bobj.element, buttoninfo.buttonElement.hoverstyle);
else TableEditorSC.setStyles(bobj.element, buttoninfo.buttonElement.normalstyle);
}
buttoninfo.buttonDown = false;
if (bobj && bobj.functionobj && bobj.functionobj.MouseUp)
bobj.functionobj.MouseUp(e, buttoninfo, bobj);
};
TableEditorSC.ButtonRepeat = function () {
var buttoninfo = TableEditorSC.ButtonInfo;
var bobj = buttoninfo.buttonElement;
if (!bobj) return;
if (bobj && bobj.functionobj && bobj.functionobj.Repeat)
bobj.functionobj.Repeat(null, buttoninfo, bobj);
buttoninfo.timer = window.setTimeout(TableEditorSC.ButtonRepeat, bobj.repeatinterval || 100);
};
TableEditorSC.MouseWheelInfo = { registeredElements: [] };
TableEditorSC.MouseWheelRegister = function (element, functionobj) {
var mousewheelinfo = TableEditorSC.MouseWheelInfo;
mousewheelinfo.registeredElements.push({
element,
functionobj,
});
element.addEventListener('DOMMouseScroll', TableEditorSC.ProcessMouseWheel, false);
element.addEventListener('mousewheel', TableEditorSC.ProcessMouseWheel, false);
return;
};
TableEditorSC.ProcessMouseWheel = function (e) {
var event = e || window.event;
var delta;
if (TableEditorSC.Keyboard.passThru) return;
var mousewheelinfo = TableEditorSC.MouseWheelInfo;
var ele = event.target || event.srcElement;
var wobj;
for (wobj = null; !wobj && ele; ele = ele.parentNode) {
wobj = TableEditorSC.LookupElement(ele, mousewheelinfo.registeredElements);
}
if (!wobj) return;
if (event.wheelDelta) {
delta = event.wheelDelta / 120;
} else delta = -event.detail / 3;
if (!delta) delta = 0;
if (wobj.functionobj && wobj.functionobj.WheelMove)
wobj.functionobj.WheelMove(event, delta, mousewheelinfo, wobj);
if (event.preventDefault) event.preventDefault();
event.returnValue = false;
};
TableEditorSC.keyboardTables = {
specialKeysCommon: {
8: '[backspace]',
9: '[tab]',
13: '[enter]',
25: '[tab]',
27: '[esc]',
33: '[pgup]',
34: '[pgdn]',
35: '[end]',
36: '[home]',
37: '[aleft]',
38: '[aup]',
39: '[aright]',
40: '[adown]',
45: '[ins]',
46: '[del]',
113: '[f2]',
},
controlKeysIE: {
65: '[ctrl-a]',
67: '[ctrl-c]',
83: '[ctrl-s]',
86: '[ctrl-v]',
88: '[ctrl-x]',
90: '[ctrl-z]',
},
specialKeysSafari: {
8: '[backspace]',
9: '[tab]',
13: '[enter]',
25: '[tab]',
27: '[esc]',
63232: '[aup]',
63233: '[adown]',
63234: '[aleft]',
63235: '[aright]',
63272: '[del]',
63273: '[home]',
63275: '[end]',
63276: '[pgup]',
63277: '[pgdn]',
63237: '[f2]',
},
controlKeysSafari: {
97: '[ctrl-a]',
99: '[ctrl-c]',
115: '[ctrl-s]',
118: '[ctrl-v]',
120: '[ctrl-x]',
122: '[ctrl-z]',
},
ignoreKeysSafari: {
63236: '[f1]',
63238: '[f3]',
63239: '[f4]',
63240: '[f5]',
63241: '[f6]',
63242: '[f7]',
63243: '[f8]',
63244: '[f9]',
63245: '[f10]',
63246: '[f11]',
63247: '[f12]',
63289: '[numlock]',
},
specialKeysFirefox: {
8: '[backspace]',
9: '[tab]',
13: '[enter]',
25: '[tab]',
27: '[esc]',
33: '[pgup]',
34: '[pgdn]',
35: '[end]',
36: '[home]',
37: '[aleft]',
38: '[aup]',
39: '[aright]',
40: '[adown]',
45: '[ins]',
46: '[del]',
113: '[f2]',
},
controlKeysFirefox: {
97: '[ctrl-a]',
99: '[ctrl-c]',
115: '[ctrl-s]',
118: '[ctrl-v]',
120: '[ctrl-x]',
122: '[ctrl-z]',
},
};
TableEditorSC.Keyboard = {
areListener: false,
focusTable: null,
passThru: null,
didProcessKey: false,
statusFromProcessKey: false,
repeatingKeyPress: false,
chForProcessKey: '',
};
TableEditorSC.KeyboardSetFocus = function (editor) {
TableEditorSC.Keyboard.focusTable = editor;
if (!TableEditorSC.Keyboard.areListener) {
document.onkeydown = TableEditorSC.ProcessKeyDown;
document.onkeypress = TableEditorSC.ProcessKeyPress;
TableEditorSC.Keyboard.areListener = true;
}
if (TableEditorSC.Keyboard.passThru) {
if (TableEditorSC.Keyboard.passThru.blur) {
TableEditorSC.Keyboard.passThru.blur();
}
TableEditorSC.Keyboard.passThru = null;
}
window.focus();
};
TableEditorSC.KeyboardFocus = function () {
TableEditorSC.Keyboard.passThru = null;
window.focus();
};
TableEditorSC.ProcessKeyDown = function (e) {
var kt = TableEditorSC.keyboardTables;
kt.didProcessKey = false;
kt.statusFromProcessKey = false;
kt.repeatingKeyPress = false;
var ch = '';
var status = true;
if (TableEditorSC._app) return;
if (TableEditorSC.Keyboard.passThru) return;
e = e || window.event;
if (e.which == undefined) {
ch = kt.specialKeysCommon[e.keyCode];
if (!ch) {
if (e.ctrlKey) {
ch = kt.controlKeysIE[e.keyCode];
}
if (!ch) return true;
}
status = TableEditorSC.ProcessKey(ch, e);
if (!status) {
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
}
} else {
ch = kt.specialKeysCommon[e.keyCode];
if (!ch) {
if (e.ctrlKey || e.metaKey) {
ch = kt.controlKeysIE[e.keyCode];
}
if (!ch) return true;
}
status = TableEditorSC.ProcessKey(ch, e);
kt.didProcessKey = true;
kt.statusFromProcessKey = status;
kt.chForProcessKey = ch;
}
return status;
};
TableEditorSC.ProcessKeyPress = function (e) {
var kt = TableEditorSC.keyboardTables;
var ch = '';
e = e || window.event;
if (TableEditorSC._app) return;
if (TableEditorSC.Keyboard.passThru) return;
if (kt.didProcessKey) {
if (kt.repeatingKeyPress) {
return TableEditorSC.ProcessKey(kt.chForProcessKey, e);
} else {
kt.repeatingKeyPress = true;
return kt.statusFromProcessKey;
}
}
if (e.which == undefined) {
ch = String.fromCharCode(e.keyCode);
} else {
if (!e.which) return false;
if (e.keyCode == e.charCode) {
ch = kt.specialKeysSafari[e.keyCode];
if (!ch) {
if (kt.ignoreKeysSafari[e.keyCode]) return true;
if (e.metaKey) {
ch = kt.controlKeysSafari[e.keyCode];
} else {
ch = String.fromCharCode(e.which);
}
}
} else {
if (kt.specialKeysFirefox[e.keyCode]) {
return true;
}
ch = String.fromCharCode(e.which);
if (e.ctrlKey || e.metaKey) {
ch = kt.controlKeysFirefox[e.which];
}
}
}
var status = TableEditorSC.ProcessKey(ch, e);
if (!status) {
if (e.preventDefault) e.preventDefault();
e.returnValue = false;
}
return status;
};
TableEditorSC.ProcessKey = function (ch, e) {
var ft = TableEditorSC.Keyboard.focusTable;
if (!ft) return true;
return ft.EditorProcessKey(ch, e);
};
// In-place TypeScript conversion of the SocialCalc number-formatting module.
// Ambient API types live in formatnumber2.d.ts (referenced by dist/SocialCalc.d.ts).
// Vite+ strips types with Oxc before UMD concat — no runtime tax.
//
/*
// SocialCalc Number Formatting Library
//
// Part of the SocialCalc package.
//
// (c) Copyright 2008 Socialtext, Inc.
// All Rights Reserved.
//
// The contents of this file are subject to the Artistic License 2.0; you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at http://socialcalc.org/licenses/al-20/.
//
// Some of the other files in the SocialCalc package are licensed under
// different licenses. Please note the licenses of the modules you use.
//
// Code History:
//
// Initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc.
// Based in part on the SocialCalc 1.1.0 code written in Perl.
// The SocialCalc 1.1.0 code was:
// Portions (c) Copyright 2005, 2006, 2007 Software Garden, Inc.
// All Rights Reserved.
// Portions (c) Copyright 2007 Socialtext, Inc.
// All Rights Reserved.
// The Perl SocialCalc started as modifications to the wikiCalc(R) program, version 1.0.
// wikiCalc 1.0 was written by Software Garden, Inc.
// Unless otherwise specified, referring to "SocialCalc" in comments refers to this
// JavaScript version of the code, not the SocialCalc Perl code.
//
*/
// Redundant `if (!SocialCalc)` guard removed — SocialCalc is defined by
// socialcalcconstants.js earlier in the concatenated UMD bundle.
// Implementation-only mutable view of FormatNumber.
// Public formatnumber2.d.ts keeps `const` members for consumers; this module
// still performs the legacy one-time progressive assignment at load.
SocialCalc.FormatNumber = {};
const FormatNumberMut = SocialCalc.FormatNumber;
FormatNumberMut.format_definitions = {};
FormatNumberMut.separatorchar = ',';
FormatNumberMut.decimalchar = '.';
FormatNumberMut.daynames = [
'Sunday',
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
];
FormatNumberMut.daynames3 = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
FormatNumberMut.monthnames3 = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
FormatNumberMut.monthnames = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
FormatNumberMut.allowedcolors = {
BLACK: '#000000',
BLUE: '#0000FF',
CYAN: '#00FFFF',
GREEN: '#00FF00',
MAGENTA: '#FF00FF',
RED: '#FF0000',
WHITE: '#FFFFFF',
YELLOW: '#FFFF00',
};
FormatNumberMut.alloweddates = {
H: 'h]',
M: 'm]',
MM: 'mm]',
S: 's]',
SS: 'ss]',
};
FormatNumberMut.commands = {
copy: 1,
color: 2,
integer_placeholder: 3,
fraction_placeholder: 4,
decimal: 5,
currency: 6,
general: 7,
separator: 8,
date: 9,
comparison: 10,
section: 11,
style: 12,
};
FormatNumberMut.datevalues = {
julian_offset: 2415019,
seconds_in_a_day: 24 * 60 * 60,
seconds_in_an_hour: 60 * 60,
};
FormatNumberMut.formatNumberWithFormat = function (rawvalue, format_string, currency_char) {
var scc = SocialCalc.Constants;
var scfn = SocialCalc.FormatNumber;
var op = 0,
operandstr = '',
fromend = 0,
cval = 0,
operandstrlc = '';
var startval = 0,
estartval = 0;
var hrs = 0,
mins = 0,
secs = 0,
ehrs = 0,
emins = 0,
esecs = 0;
var ampmstr;
var ymd = {
year: 0,
month: 0,
day: 0,
};
var minOK = 0,
mspos = 0;
var result = '';
var thisformat;
var section = 0,
gotcomparison = 0,
compop = '',
compval = 0,
cpos = 0,
oppos = 0;
var sectioninfo;
var i = 0,
decimalscale = 0,
scaledvalue = 0,
strvalue = '',
strparts = null,
integervalue = '',
fractionvalue = '';
var integerdigits2 = 0,
integerpos = 0,
fractionpos = 0,
textcolor = '',
textstyle = '',
separatorchar = '',
decimalchar = '';
var value = 0;
if (typeof rawvalue == 'string' && !rawvalue.length) return '';
value = Number(rawvalue);
if (!isFinite(value)) {
if (typeof rawvalue == 'string') {
return scfn.formatTextWithFormat(rawvalue, format_string);
} else {
return 'NaN';
}
}
rawvalue = value;
var negativevalue = value < 0 ? 1 : 0;
if (negativevalue) value = -value;
var zerovalue = value == 0 ? 1 : 0;
currency_char = currency_char || scc.FormatNumber_defaultCurrency;
scfn.parse_format_string(scfn.format_definitions, format_string);
thisformat = scfn.format_definitions[format_string];
if (!thisformat) throw 'Format not parsed error!';
section = thisformat.sectioninfo.length - 1;
if (thisformat.hascomparison) {
section = 0;
gotcomparison = 0;
for (cpos = 0; ; cpos++) {
op = thisformat.operators[cpos];
operandstr = thisformat.operands[cpos];
if (!op) {
if (gotcomparison) {
format_string = 'General';
scfn.parse_format_string(scfn.format_definitions, format_string);
thisformat = scfn.format_definitions[format_string];
section = 0;
}
break;
}
if (op == scfn.commands.section) {
if (!gotcomparison) {
break;
}
gotcomparison = 0;
section++;
continue;
}
if (op == scfn.commands.comparison) {
i = operandstr.indexOf(':');
compop = operandstr.substring(0, i);
compval = Number(operandstr.substring(i + 1));
if (
(compop == '<' && rawvalue < compval) ||
(compop == '<=' && rawvalue <= compval) ||
(compop == '=' && rawvalue == compval) ||
(compop == '<>' && rawvalue != compval) ||
(compop == '>=' && rawvalue >= compval) ||
(compop == '>' && rawvalue > compval)
) {
break;
}
gotcomparison = 1;
}
}
} else if (section > 0) {
if (section == 1) {
if (negativevalue) {
negativevalue = 0;
section = 1;
} else {
section = 0;
}
} else if (section == 2 || section == 3) {
if (negativevalue) {
negativevalue = 0;
section = 1;
} else if (zerovalue) {
section = 2;
} else {
section = 0;
}
}
}
sectioninfo = thisformat.sectioninfo[section];
var sectionCommas = sectioninfo.commas || 0;
var sectionPercent = sectioninfo.percent || 0;
var sectionFractionDigits = sectioninfo.fractiondigits || 0;
var sectionIntegerDigits = sectioninfo.integerdigits || 0;
var sectionStart = sectioninfo.sectionstart || 0;
if (sectionCommas > 0) {
for (i = 0; i < sectionCommas; i++) {
value /= 1e3;
}
}
if (sectionPercent > 0) {
for (i = 0; i < sectionPercent; i++) {
value *= 100;
}
}
decimalscale = 1;
for (i = 0; i < sectionFractionDigits; i++) {
decimalscale *= 10;
}
scaledvalue = Math.floor(value * decimalscale + 0.5);
scaledvalue = scaledvalue / decimalscale;
if (!isFinite(scaledvalue)) return 'NaN';
strvalue = scaledvalue + '';
if (scaledvalue == 0 && (sectioninfo.fractiondigits || sectioninfo.integerdigits)) {
negativevalue = 0;
}
if (strvalue.indexOf('e') >= 0) {
if (sectionPercent > 0) {
var scipct = (negativevalue ? '-' : '') + strvalue;
for (i = 0; i < sectionPercent; i++) {
scipct += '%';
}
return scipct;
}
return rawvalue + '';
}
strparts = strvalue.match(/^\+{0,1}(\d*)(?:\.(\d*)){0,1}$/);
integervalue = strparts[1];
if (!integervalue || integervalue == '0') integervalue = '';
fractionvalue = strparts[2];
if (!fractionvalue) fractionvalue = '';
if (sectioninfo.hasdate) {
if (rawvalue < 0) {
return '??-???-?? ??:??:??';
}
startval = (rawvalue - Math.floor(rawvalue)) * scfn.datevalues.seconds_in_a_day;
estartval = rawvalue * scfn.datevalues.seconds_in_a_day;
hrs = Math.floor(startval / scfn.datevalues.seconds_in_an_hour);
ehrs = Math.floor(estartval / scfn.datevalues.seconds_in_an_hour);
startval = startval - hrs * scfn.datevalues.seconds_in_an_hour;
mins = Math.floor(startval / 60);
emins = Math.floor(estartval / 60);
secs = startval - mins * 60;
decimalscale = 1;
for (i = 0; i < sectionFractionDigits; i++) {
decimalscale *= 10;
}
secs = Math.floor(secs * decimalscale + 0.5);
secs = secs / decimalscale;
esecs = Math.floor(estartval * decimalscale + 0.5);
esecs = esecs / decimalscale;
if (secs >= 60) {
secs = 0;
mins++;
emins++;
if (mins >= 60) {
mins = 0;
hrs++;
ehrs++;
if (hrs >= 24) {
hrs = 0;
rawvalue++;
}
}
}
fractionvalue = secs - Math.floor(secs) + '';
fractionvalue = fractionvalue.substring(2);
ymd = SocialCalc.FormatNumber.convert_date_julian_to_gregorian(
Math.floor(rawvalue + scfn.datevalues.julian_offset),
);
minOK = 0;
mspos = sectionStart;
for (; ; mspos++) {
op = thisformat.operators[mspos];
operandstr = thisformat.operands[mspos];
if (!op) break;
if (op == scfn.commands.section) break;
if (op == scfn.commands.date) {
if (
(operandstr.toLowerCase() == 'am/pm' || operandstr.toLowerCase() == 'a/p') &&
!ampmstr
) {
if (hrs >= 12) {
hrs -= 12;
ampmstr =
operandstr.toLowerCase() == 'a/p' ? scc.s_FormatNumber_pm1 : scc.s_FormatNumber_pm;
} else {
ampmstr =
operandstr.toLowerCase() == 'a/p' ? scc.s_FormatNumber_am1 : scc.s_FormatNumber_am;
}
if (operandstr.indexOf(ampmstr) < 0) ampmstr = ampmstr.toLowerCase();
}
if (minOK && (operandstr == 'm' || operandstr == 'mm')) {
thisformat.operands[mspos] += 'in';
}
if (operandstr.charAt(0) == 'h') {
minOK = 1;
} else {
minOK = 0;
}
} else if (op != scfn.commands.copy) {
minOK = 0;
}
}
minOK = 0;
for (--mspos; ; mspos--) {
op = thisformat.operators[mspos];
operandstr = thisformat.operands[mspos];
if (!op) break;
if (op == scfn.commands.section) break;
if (op == scfn.commands.date) {
if (minOK && (operandstr == 'm' || operandstr == 'mm')) {
thisformat.operands[mspos] += 'in';
}
if (operandstr == 'ss') {
minOK = 1;
} else {
minOK = 0;
}
} else if (op != scfn.commands.copy) {
minOK = 0;
}
}
}
integerdigits2 = 0;
integerpos = 0;
fractionpos = 0;
textcolor = '';
textstyle = '';
separatorchar = scc.FormatNumber_separatorchar;
if (separatorchar.indexOf(' ') >= 0) separatorchar = separatorchar.replace(/ /g, ' ');
decimalchar = scc.FormatNumber_decimalchar;
if (decimalchar.indexOf(' ') >= 0) decimalchar = decimalchar.replace(/ /g, ' ');
oppos = sectionStart;
while ((op = thisformat.operators[oppos])) {
operandstr = thisformat.operands[oppos++];
if (op == scfn.commands.copy) {
result += operandstr;
} else if (op == scfn.commands.color) {
textcolor = operandstr;
} else if (op == scfn.commands.style) {
textstyle = operandstr;
} else if (op == scfn.commands.integer_placeholder) {
if (negativevalue) {
result += '-';
negativevalue = 0;
}
integerdigits2++;
if (integerdigits2 == 1) {
if (integervalue.length > sectionIntegerDigits) {
for (; integerpos < integervalue.length - sectionIntegerDigits; integerpos++) {
result += integervalue.charAt(integerpos);
if (sectioninfo.thousandssep) {
fromend = integervalue.length - integerpos - 1;
if (fromend > 2 && fromend % 3 == 0) {
result += separatorchar;
}
}
}
}
}
if (
integervalue.length < sectionIntegerDigits &&
integerdigits2 <= sectionIntegerDigits - integervalue.length
) {
if (operandstr == '0' || operandstr == '?') {
result += operandstr == '0' ? '0' : ' ';
if (sectioninfo.thousandssep) {
fromend = sectionIntegerDigits - integerdigits2;
if (fromend > 2 && fromend % 3 == 0) {
result += separatorchar;
}
}
}
} else {
result += integervalue.charAt(integerpos);
if (sectioninfo.thousandssep) {
fromend = integervalue.length - integerpos - 1;
if (fromend > 2 && fromend % 3 == 0) {
result += separatorchar;
}
}
integerpos++;
}
} else if (op == scfn.commands.fraction_placeholder) {
if (fractionpos >= fractionvalue.length) {
if (operandstr == '0' || operandstr == '?') {
result += operandstr == '0' ? '0' : ' ';
}
} else {
result += fractionvalue.charAt(fractionpos);
}
fractionpos++;
} else if (op == scfn.commands.decimal) {
if (negativevalue) {
result += '-';
negativevalue = 0;
}
result += decimalchar;
} else if (op == scfn.commands.currency) {
if (negativevalue) {
result += '-';
negativevalue = 0;
}
result += (operandstr === '$' ? currency_char : operandstr) || operandstr;
} else if (op == scfn.commands.general) {
if (value != 0) {
var factor = Math.floor(Math.LOG10E * Math.log(value));
factor = Math.pow(10, 13 - factor);
value = Math.floor(factor * value + 0.5) / factor;
if (!isFinite(value)) return 'NaN';
}
if (negativevalue) {
result += '-';
}
strvalue = value + '';
if (strvalue.indexOf('e') >= 0) {
result += strvalue;
continue;
}
strparts = strvalue.match(/^\+{0,1}(\d*)(?:\.(\d*)){0,1}$/);
integervalue = strparts[1];
if (!integervalue || integervalue == '0') integervalue = '';
fractionvalue = strparts[2];
if (!fractionvalue) fractionvalue = '';
integerpos = 0;
fractionpos = 0;
if (integervalue.length) {
for (; integerpos < integervalue.length; integerpos++) {
result += integervalue.charAt(integerpos);
if (sectioninfo.thousandssep) {
fromend = integervalue.length - integerpos - 1;
if (fromend > 2 && fromend % 3 == 0) {
result += separatorchar;
}
}
}
} else {
result += '0';
}
if (fractionvalue.length) {
result += decimalchar;
for (; fractionpos < fractionvalue.length; fractionpos++) {
result += fractionvalue.charAt(fractionpos);
}
}
} else if (op == scfn.commands.date) {
operandstrlc = operandstr.toLowerCase();
if (operandstrlc == 'y' || operandstrlc == 'yy') {
result += (ymd.year + '').substring(2);
} else if (operandstrlc == 'yyyy') {
result += ymd.year + '';
} else if (operandstrlc == 'd') {
result += ymd.day + '';
} else if (operandstrlc == 'dd') {
cval = 1e3 + ymd.day;
result += (cval + '').substr(2);
} else if (operandstrlc == 'ddd') {
cval = Math.floor(rawvalue + 6) % 7;
result += scc.s_FormatNumber_daynames3[cval];
} else if (operandstrlc == 'dddd') {
cval = Math.floor(rawvalue + 6) % 7;
result += scc.s_FormatNumber_daynames[cval];
} else if (operandstrlc == 'm') {
result += ymd.month + '';
} else if (operandstrlc == 'mm') {
cval = 1e3 + ymd.month;
result += (cval + '').substr(2);
} else if (operandstrlc == 'mmm') {
result += scc.s_FormatNumber_monthnames3[ymd.month - 1];
} else if (operandstrlc == 'mmmm') {
result += scc.s_FormatNumber_monthnames[ymd.month - 1];
} else if (operandstrlc == 'mmmmm') {
result += scc.s_FormatNumber_monthnames[ymd.month - 1].charAt(0);
} else if (operandstrlc == 'h') {
result += hrs + '';
} else if (operandstrlc == 'h]') {
result += ehrs + '';
} else if (operandstrlc == 'mmin') {
cval = 1e3 + mins + '';
result += String(cval).substr(2);
} else if (operandstrlc == 'mm]') {
if (emins < 100) {
cval = 1e3 + emins + '';
result += String(cval).substr(2);
} else {
result += emins + '';
}
} else if (operandstrlc == 'min') {
result += mins + '';
} else if (operandstrlc == 'm]') {
result += emins + '';
} else if (operandstrlc == 'hh') {
cval = 1e3 + hrs + '';
result += String(cval).substr(2);
} else if (operandstrlc == 's') {
cval = Math.floor(secs);
result += cval + '';
} else if (operandstrlc == 'ss') {
cval = 1e3 + Math.floor(secs) + '';
result += String(cval).substr(2);
} else if (operandstrlc == 'am/pm' || operandstrlc == 'a/p') {
result += ampmstr || '';
} else if (operandstrlc == 'ss]') {
if (esecs < 100) {
cval = 1e3 + Math.floor(esecs) + '';
result += String(cval).substr(2);
} else {
cval = Math.floor(esecs);
result += cval + '';
}
}
} else if (op == scfn.commands.section) break;
else if (op == scfn.commands.comparison) continue;
else result += '!! Parse error !!';
}
if (textcolor) {
result = '' + result + '';
}
if (textstyle) {
result = '' + result + '';
}
return result;
};
FormatNumberMut.formatTextWithFormat = function (rawvalue, format_string) {
var scfn = SocialCalc.FormatNumber;
var value = rawvalue + '';
var result = '';
var section;
var sectioninfo;
var op, oppos;
var operandstr;
var thisformat;
var textcolor = '';
var textstyle = '';
scfn.parse_format_string(scfn.format_definitions, format_string);
thisformat = scfn.format_definitions[format_string];
if (!thisformat) throw 'Format not parsed error!';
section = thisformat.sectioninfo.length - 1;
if (section == 0) {
section = 0;
} else if (section == 3) {
section = 3;
} else {
return value;
}
sectioninfo = thisformat.sectioninfo[section];
oppos = sectioninfo.sectionstart || 0;
while ((op = thisformat.operators[oppos])) {
operandstr = thisformat.operands[oppos++];
if (op == scfn.commands.copy) {
if (operandstr == '@') {
result += value;
} else {
result += operandstr.replace(/ /g, ' ');
}
} else if (op == scfn.commands.color) {
textcolor = operandstr;
} else if (op == scfn.commands.style) {
textstyle = operandstr;
}
}
if (textcolor) {
result = '' + result + '';
}
if (textstyle) {
result = '' + result + '';
}
return result;
};
FormatNumberMut.parse_format_string = function (format_defs, format_string) {
var scfn = SocialCalc.FormatNumber;
var thisformat;
var section;
var sectioninfo;
var integerpart = 1;
var lastwasinteger;
var lastwasslash;
var lastwasasterisk;
var lastwasunderscore;
var inquote,
quotestr = '';
var inbracket,
bracketstr = '',
bracketdata;
var ingeneral;
var ampmstr, part;
var indate;
var chpos;
var ch;
if (format_defs[format_string]) return;
thisformat = {
operators: [],
operands: [],
sectioninfo: [{}],
};
format_defs[format_string] = thisformat;
section = 0;
sectioninfo = thisformat.sectioninfo[section];
sectioninfo.sectionstart = 0;
sectioninfo.integerdigits = 0;
sectioninfo.fractiondigits = 0;
sectioninfo.commas = 0;
sectioninfo.percent = 0;
for (chpos = 0; chpos < format_string.length; chpos++) {
ch = format_string.charAt(chpos);
if (inquote) {
if (ch == '"') {
inquote = 0;
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(quotestr);
continue;
}
quotestr += ch;
continue;
}
if (inbracket) {
if (ch == ']') {
inbracket = 0;
bracketdata = SocialCalc.FormatNumber.parse_format_bracket(bracketstr);
if (bracketdata.operator == scfn.commands.separator) {
sectioninfo.thousandssep = 1;
continue;
}
if (bracketdata.operator == scfn.commands.date) {
sectioninfo.hasdate = 1;
}
if (bracketdata.operator == scfn.commands.comparison) {
thisformat.hascomparison = 1;
}
thisformat.operators.push(bracketdata.operator);
thisformat.operands.push(bracketdata.operand);
continue;
}
bracketstr += ch;
continue;
}
if (lastwasslash) {
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(ch);
lastwasslash = false;
continue;
}
if (lastwasasterisk) {
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(ch + ch + ch + ch + ch);
lastwasasterisk = false;
continue;
}
if (lastwasunderscore) {
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(' ');
lastwasunderscore = false;
continue;
}
if (ingeneral) {
if ('general'.charAt(ingeneral) == ch.toLowerCase()) {
ingeneral++;
if (ingeneral == 7) {
thisformat.operators.push(scfn.commands.general);
thisformat.operands.push(ch);
ingeneral = 0;
}
continue;
}
ingeneral = 0;
}
if (indate) {
if (indate.charAt(0) == ch) {
indate += ch;
continue;
}
thisformat.operators.push(scfn.commands.date);
thisformat.operands.push(indate);
sectioninfo.hasdate = 1;
indate = '';
}
if (ampmstr) {
ampmstr += ch;
part = ampmstr.toLowerCase();
if (part == 'am/pm' || part == 'a/p') {
thisformat.operators.push(scfn.commands.date);
thisformat.operands.push(ampmstr);
ampmstr = '';
}
continue;
}
if (ch == '#' || ch == '0' || ch == '?') {
if (integerpart) {
sectioninfo.integerdigits++;
if (sectioninfo.commas) {
sectioninfo.thousandssep = 1;
sectioninfo.commas = 0;
}
lastwasinteger = 1;
thisformat.operators.push(scfn.commands.integer_placeholder);
thisformat.operands.push(ch);
} else {
sectioninfo.fractiondigits++;
lastwasinteger = 1;
thisformat.operators.push(scfn.commands.fraction_placeholder);
thisformat.operands.push(ch);
}
} else if (ch == '.') {
lastwasinteger = 0;
thisformat.operators.push(scfn.commands.decimal);
thisformat.operands.push(ch);
integerpart = 0;
} else if (ch == '$') {
lastwasinteger = 0;
thisformat.operators.push(scfn.commands.currency);
thisformat.operands.push('$');
} else if (ch == ',') {
if (lastwasinteger) {
sectioninfo.commas++;
} else {
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(ch);
}
} else if (ch == '%') {
lastwasinteger = 0;
sectioninfo.percent++;
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(ch);
} else if (ch == '"') {
lastwasinteger = 0;
inquote = 1;
quotestr = '';
} else if (ch == '[') {
lastwasinteger = 0;
inbracket = 1;
bracketstr = '';
} else if (ch == '\\') {
lastwasslash = 1;
lastwasinteger = 0;
} else if (ch == '*') {
lastwasasterisk = 1;
lastwasinteger = 0;
} else if (ch == '_') {
lastwasunderscore = 1;
lastwasinteger = 0;
} else if (ch == ';') {
section++;
thisformat.sectioninfo[section] = {};
sectioninfo = thisformat.sectioninfo[section];
sectioninfo.sectionstart = 1 + thisformat.operators.length;
sectioninfo.integerdigits = 0;
sectioninfo.fractiondigits = 0;
sectioninfo.commas = 0;
sectioninfo.percent = 0;
integerpart = 1;
lastwasinteger = 0;
thisformat.operators.push(scfn.commands.section);
thisformat.operands.push(ch);
} else if (ch.toLowerCase() == 'g') {
ingeneral = 1;
lastwasinteger = 0;
} else if (ch.toLowerCase() == 'a') {
ampmstr = ch;
lastwasinteger = 0;
} else if ('dmyhHs'.indexOf(ch) >= 0) {
indate = ch;
} else {
lastwasinteger = 0;
thisformat.operators.push(scfn.commands.copy);
thisformat.operands.push(ch);
}
}
if (indate) {
thisformat.operators.push(scfn.commands.date);
thisformat.operands.push(indate);
sectioninfo.hasdate = 1;
}
return;
};
FormatNumberMut.parse_format_bracket = function (bracketstr) {
var scfn = SocialCalc.FormatNumber;
var scc = SocialCalc.Constants;
var bracketdata = {
operator: 0,
operand: '',
};
var parts;
if (bracketstr.charAt(0) == '$') {
bracketdata.operator = scfn.commands.currency;
parts = bracketstr.match(/^\$(.+?)(-.+?){0,1}$/);
if (parts) {
bracketdata.operand = parts[1];
} else {
bracketdata.operand = bracketstr.substring(1) || scc.FormatNumber_defaultCurrency || '$';
}
} else if (bracketstr == '?$') {
bracketdata.operator = scfn.commands.currency;
bracketdata.operand = '[?$]';
} else if (scfn.allowedcolors[bracketstr.toUpperCase()]) {
bracketdata.operator = scfn.commands.color;
bracketdata.operand = scfn.allowedcolors[bracketstr.toUpperCase()];
} else if ((parts = bracketstr.match(/^style=([^"]*)$/))) {
bracketdata.operator = scfn.commands.style;
bracketdata.operand = parts[1];
} else if (bracketstr == ',') {
bracketdata.operator = scfn.commands.separator;
bracketdata.operand = bracketstr;
} else if (scfn.alloweddates[bracketstr.toUpperCase()]) {
bracketdata.operator = scfn.commands.date;
bracketdata.operand = scfn.alloweddates[bracketstr.toUpperCase()];
} else if ((parts = bracketstr.match(/^[<>=]/))) {
parts = bracketstr.match(/^([<>=]+)(.+)$/);
bracketdata.operator = scfn.commands.comparison;
bracketdata.operand = parts ? parts[1] + ':' + parts[2] : bracketstr;
} else {
bracketdata.operator = scfn.commands.copy;
bracketdata.operand = '[' + bracketstr + ']';
}
return bracketdata;
};
FormatNumberMut.convert_date_gregorian_to_julian = function (year, month, day) {
var juliandate;
juliandate =
day -
32075 +
SocialCalc.intFunc((1461 * (year + 4800 + SocialCalc.intFunc((month - 14) / 12))) / 4);
juliandate += SocialCalc.intFunc(
(367 * (month - 2 - SocialCalc.intFunc((month - 14) / 12) * 12)) / 12,
);
juliandate =
juliandate -
SocialCalc.intFunc(
(3 * SocialCalc.intFunc((year + 4900 + SocialCalc.intFunc((month - 14) / 12)) / 100)) / 4,
);
return juliandate;
};
FormatNumberMut.convert_date_julian_to_gregorian = function (juliandate) {
var L, N, I, J, K;
L = juliandate + 68569;
N = Math.floor((4 * L) / 146097);
L = L - Math.floor((146097 * N + 3) / 4);
I = Math.floor((4e3 * (L + 1)) / 1461001);
L = L - Math.floor((1461 * I) / 4) + 31;
J = Math.floor((80 * L) / 2447);
K = L - Math.floor((2447 * J) / 80);
L = Math.floor(J / 11);
J = J + 2 - 12 * L;
I = 100 * (N - 49) + I + L;
return {
year: I,
month: J,
day: K,
};
};
SocialCalc.intFunc = function (n) {
if (n < 0) {
return -Math.floor(-n);
} else {
return Math.floor(n);
}
};
// In-place TypeScript conversion of formula1.js (SocialCalc global script).
// Ambient API types live in formula1.d.ts (referenced by dist/SocialCalc.d.ts).
// Intermediate: typechecked core after removing @ts-nocheck.
// Opts this module into strict TypeScript checking; sibling .d.ts provides types.
//
/*
// SocialCalc Spreadsheet Formula Library
//
// Part of the SocialCalc package
//
// (c) Copyright 2008 Socialtext, Inc.
// All Rights Reserved.
//
// The contents of this file are subject to the Artistic License 2.0; you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at http://socialcalc.org/licenses/al-20/.
//
// Some of the other files in the SocialCalc package are licensed under
// different licenses. Please note the licenses of the modules you use.
//
// Code History:
//
// Initially coded by Dan Bricklin of Software Garden, Inc., for Socialtext, Inc.
// Based in part on the SocialCalc 1.1.0 code written in Perl.
// The SocialCalc 1.1.0 code was:
// Portions (c) Copyright 2005, 2006, 2007 Software Garden, Inc.
// All Rights Reserved.
// Portions (c) Copyright 2007 Socialtext, Inc.
// All Rights Reserved.
// The Perl SocialCalc started as modifications to the wikiCalc(R) program, version 1.0.
// wikiCalc 1.0 was written by Software Garden, Inc.
// Unless otherwise specified, referring to "SocialCalc" in comments refers to this
// JavaScript version of the code, not the SocialCalc Perl code.
//
*/
// Redundant `if (!SocialCalc)` guard removed — SocialCalc bag is created by
// module-wrapper-top.js inside the UMD factory.
// Implementation-only mutable views for progressive init of ambient Formula API.
// Reads still go through SocialCalc.Formula (typed ambient); writes use FormulaMut.
SocialCalc.Formula = {};
const FormulaMut = SocialCalc.Formula;
SocialCalc.TriggerIoAction = {};
const TriggerIoMut = SocialCalc.TriggerIoAction;
FormulaMut.ParseState = {
num: 1,
alpha: 2,
coord: 3,
string: 4,
stringquote: 5,
numexp1: 6,
numexp2: 7,
alphanumeric: 8,
specialvalue: 9,
};
FormulaMut.TokenType = {
num: 1,
coord: 2,
op: 3,
name: 4,
error: 5,
string: 6,
space: 7,
};
FormulaMut.CharClass = {
num: 1,
numstart: 2,
op: 3,
eof: 4,
alpha: 5,
incoord: 6,
error: 7,
quote: 8,
space: 9,
specialstart: 10,
};
FormulaMut.CharClassTable = {
' ': 9,
'!': 3,
'"': 8,
"'": 8,
'#': 10,
$: 6,
'%': 3,
'&': 3,
'(': 3,
')': 3,
'*': 3,
'+': 3,
',': 3,
'-': 3,
'.': 2,
'/': 3,
0: 1,
1: 1,
2: 1,
3: 1,
4: 1,
5: 1,
6: 1,
7: 1,
8: 1,
9: 1,
':': 3,
'<': 3,
'=': 3,
'>': 3,
A: 5,
B: 5,
C: 5,
D: 5,
E: 5,
F: 5,
G: 5,
H: 5,
I: 5,
J: 5,
K: 5,
L: 5,
M: 5,
N: 5,
O: 5,
P: 5,
Q: 5,
R: 5,
S: 5,
T: 5,
U: 5,
V: 5,
W: 5,
X: 5,
Y: 5,
Z: 5,
'^': 3,
_: 5,
a: 5,
b: 5,
c: 5,
d: 5,
e: 5,
f: 5,
g: 5,
h: 5,
i: 5,
j: 5,
k: 5,
l: 5,
m: 5,
n: 5,
o: 5,
p: 5,
q: 5,
r: 5,
s: 5,
t: 5,
u: 5,
v: 5,
w: 5,
x: 5,
y: 5,
z: 5,
};
FormulaMut.UpperCaseTable = {
a: 'A',
b: 'B',
c: 'C',
d: 'D',
e: 'E',
f: 'F',
g: 'G',
h: 'H',
i: 'I',
j: 'J',
k: 'K',
l: 'L',
m: 'M',
n: 'N',
o: 'O',
p: 'P',
q: 'Q',
r: 'R',
s: 'S',
t: 'T',
u: 'U',
v: 'V',
w: 'W',
x: 'X',
y: 'Y',
z: 'Z',
A: 'A',
B: 'B',
C: 'C',
D: 'D',
E: 'E',
F: 'F',
G: 'G',
H: 'H',
I: 'I',
J: 'J',
K: 'K',
L: 'L',
M: 'M',
N: 'N',
O: 'O',
P: 'P',
Q: 'Q',
R: 'R',
S: 'S',
T: 'T',
U: 'U',
V: 'V',
W: 'W',
X: 'X',
Y: 'Y',
Z: 'Z',
};
FormulaMut.SpecialConstants = {
'#NULL!': '0,e#NULL!',
'#NUM!': '0,e#NUM!',
'#DIV/0!': '0,e#DIV/0!',
'#VALUE!': '0,e#VALUE!',
'#REF!': '0,e#REF!',
'#NAME?': '0,e#NAME?',
'#N/A': '0,e#N/A',
};
FormulaMut.TokenPrecedence = {
'!': 1,
':': 2,
',': 2,
M: -3,
P: -3,
'%': 4,
'^': 5,
'*': 6,
'/': 6,
'+': 7,
'-': 7,
'&': 8,
'<': 9,
'>': 9,
'=': 9,
G: 9,
L: 9,
N: 9,
};
FormulaMut.TokenOpExpansion = {
G: '>=',
L: '<=',
M: '-',
N: '<>',
P: '+',
};
FormulaMut.TypeLookupTable = {
unaryminus: {
'n*': '|n*:1|',
'e*': '|e*:1|',
't*': '|t*:e#VALUE!|',
b: '|b:n|',
},
unaryplus: {
'n*': '|n*:1|',
'e*': '|e*:1|',
't*': '|t*:e#VALUE!|',
b: '|b:n|',
},
unarypercent: {
'n*': '|n:n%|n*:n|',
'e*': '|e*:1|',
't*': '|t*:e#VALUE!|',
b: '|b:n|',
},
plus: {
'n%': '|n%:n%|nd:n|nt:n|ndt:n|n$:n|n:n|n*:n|b:n|e*:2|t*:e#VALUE!|',
nd: '|n%:n|nd:nd|nt:ndt|ndt:ndt|n$:n|n:nd|n*:n|b:n|e*:2|t*:e#VALUE!|',
nt: '|n%:n|nd:ndt|nt:nt|ndt:ndt|n$:n|n:nt|n*:n|b:n|e*:2|t*:e#VALUE!|',
ndt: '|n%:n|nd:ndt|nt:ndt|ndt:ndt|n$:n|n:ndt|n*:n|b:n|e*:2|t*:e#VALUE!|',
n$: '|n%:n|nd:n|nt:n|ndt:n|n$:n$|n:n$|n*:n|b:n|e*:2|t*:e#VALUE!|',
nl: '|n%:n|nd:n|nt:n|ndt:n|n$:n|n:n|n*:n|b:n|e*:2|t*:e#VALUE!|',
n: '|n%:n|nd:nd|nt:nt|ndt:ndt|n$:n$|n:n|n*:n|b:n|e*:2|t*:e#VALUE!|',
b: '|n%:n%|nd:nd|nt:nt|ndt:ndt|n$:n$|n:n|n*:n|b:n|e*:2|t*:e#VALUE!|',
't*': '|ni:1|n*:e#VALUE!|t*:e#VALUE!|b:e#VALUE!|e*:2|',
'n*': '|ni:1|e*:2|',
'e*': '|e*:1|n*:1|t*:1|b:1|',
},
concat: {
t: '|t:t|th:th|tw:tw|tl:t|tr:tr|t*:2|e*:2|',
th: '|t:th|th:th|tw:t|tl:th|tr:t|t*:t|e*:2|',
tw: '|t:tw|th:t|tw:tw|tl:tw|tr:tw|t*:t|e*:2|',
tl: '|t:tl|th:th|tw:tw|tl:tl|tr:tr|t*:t|e*:2|',
't*': '|t*:t|e*:2|',
'e*': '|e*:1|n*:1|t*:1|',
},
oneargnumeric: {
'n*': '|n*:n|',
'e*': '|e*:1|',
't*': '|t*:e#VALUE!|',
b: '|b:n|',
},
twoargnumeric: {
'n*': '|n*:n|t*:e#VALUE!|e*:2|',
'e*': '|e*:1|n*:1|t*:1|',
't*': '|t*:e#VALUE!|n*:e#VALUE!|e*:2|',
},
propagateerror: {
'n*': '|n*:2|e*:2|',
'e*': '|e*:2|',
't*': '|t*:2|e*:2|',
b: '|b:2|e*:2|',
},
};
FormulaMut.evaluate_parsed_formula = function (parseinfo, sheet, allowrangereturn) {
var result;
var scf = SocialCalc.Formula;
var revpolish;
revpolish = scf.ConvertInfixToPolish(parseinfo);
result = scf.EvaluatePolish(parseinfo, revpolish, sheet, allowrangereturn);
return result;
};
if (typeof SocialCalc.debug_log === 'undefined') SocialCalc.debug_log = [];
SocialCalc.DebugLog = function (_logObject) {};
FormulaMut.EvaluatePolish = function (parseinfo, revpolish, sheet, allowrangereturn) {
var scf = SocialCalc.Formula;
var scc = SocialCalc.Constants;
var tokentype = scf.TokenType;
var lookup_result_type = scf.LookupResultType;
var typelookup = scf.TypeLookupTable;
var operand_as_number = scf.OperandAsNumber;
var operand_as_text = scf.OperandAsText;
var operand_value_and_type = scf.OperandValueAndType;
var operands_as_coord_on_sheet = scf.OperandsAsCoordOnSheet;
var format_number_for_display =
SocialCalc.format_number_for_display ||
function (v) {
return v + '';
};
var errortext = '';
var function_start = -1;
var missingOperandError = {
value: '',
type: 'e#VALUE!',
error: scc.s_parseerrmissingoperand,
};
var operand = [];
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
var i,
rii,
prii,
ttype,
ttext,
value,
value1,
value2,
tostype,
tostype2,
resulttype,
valuetype,
cond,
vmatch,
smatch;
if (!parseinfo.length || !(revpolish instanceof Array)) {
return {
value: '',
type: 'e#VALUE!',
error: typeof revpolish == 'string' ? revpolish : '',
};
}
var parameterInfo = [];
for (i = 0; i < revpolish.length; i++) {
rii = revpolish[i];
if (rii == function_start) {
PushOperand('start', 0);
continue;
}
prii = parseinfo[rii];
ttype = prii.type;
ttext = prii.text;
parameterInfo.push(prii);
if (ttype == tokentype.num) {
PushOperand('n', ttext - 0);
} else if (ttype == tokentype.coord) {
PushOperand('coord', ttext);
} else if (ttype == tokentype.string) {
PushOperand('t', ttext);
} else if (ttype == tokentype.op) {
if (operand.length <= 0) {
return missingOperandError;
}
if (ttext == 'M') {
value1 = operand_as_number(sheet, operand);
resulttype = lookup_result_type(value1.type, value1.type, typelookup.unaryminus);
PushOperand(resulttype, -value1.value);
} else if (ttext == 'P') {
value1 = operand_as_number(sheet, operand);
resulttype = lookup_result_type(value1.type, value1.type, typelookup.unaryplus);
PushOperand(resulttype, value1.value);
} else if (ttext == '%') {
value1 = operand_as_number(sheet, operand);
resulttype = lookup_result_type(value1.type, value1.type, typelookup.unarypercent);
PushOperand(resulttype, 0.01 * value1.value);
} else if (ttext == '&') {
if (operand.length <= 1) {
return missingOperandError;
}
value2 = operand_as_text(sheet, operand);
value1 = operand_as_text(sheet, operand);
resulttype = lookup_result_type(value1.type, value2.type, typelookup.concat);
PushOperand(resulttype, value1.value + value2.value);
} else if (ttext == ':') {
if (operand.length <= 1) {
return missingOperandError;
}
value1 = scf.OperandsAsRangeOnSheet(sheet, operand);
PushOperand(value1.type, value1.value);
} else if (ttext == '!') {
if (operand.length <= 1) {
return missingOperandError;
}
value1 = operands_as_coord_on_sheet(sheet, operand);
if (value1.error) {
errortext = errortext || value1.error;
}
PushOperand(value1.type, value1.value);
} else if (
ttext == '<' ||
ttext == 'L' ||
ttext == '=' ||
ttext == 'G' ||
ttext == '>' ||
ttext == 'N'
) {
if (operand.length <= 1) {
errortext = scc.s_parseerrmissingoperand;
break;
}
value2 = operand_value_and_type(sheet, operand);
value1 = operand_value_and_type(sheet, operand);
if (value1.type.charAt(0) == 'n' && value2.type.charAt(0) == 'n') {
cond = 0;
if (ttext == '<') {
cond = value1.value < value2.value ? 1 : 0;
} else if (ttext == 'L') {
cond = value1.value <= value2.value ? 1 : 0;
} else if (ttext == '=') {
cond = value1.value == value2.value ? 1 : 0;
} else if (ttext == 'G') {
cond = value1.value >= value2.value ? 1 : 0;
} else if (ttext == '>') {
cond = value1.value > value2.value ? 1 : 0;
} else if (ttext == 'N') {
cond = value1.value != value2.value ? 1 : 0;
}
PushOperand('nl', cond);
} else if (value1.type.charAt(0) == 'e') {
PushOperand(value1.type, 0);
} else if (value2.type.charAt(0) == 'e') {
PushOperand(value2.type, 0);
} else {
tostype = value1.type.charAt(0);
tostype2 = value2.type.charAt(0);
if (tostype == 'n') {
value1.value = format_number_for_display(value1.value, 'n', '');
} else if (tostype == 'b') {
value1.value = '';
}
if (tostype2 == 'n') {
value2.value = format_number_for_display(value2.value, 'n', '');
} else if (tostype2 == 'b') {
value2.value = '';
}
cond = 0;
value1.value = value1.value.toLowerCase();
value2.value = value2.value.toLowerCase();
if (ttext == '<') {
cond = value1.value < value2.value ? 1 : 0;
} else if (ttext == 'L') {
cond = value1.value <= value2.value ? 1 : 0;
} else if (ttext == '=') {
cond = value1.value == value2.value ? 1 : 0;
} else if (ttext == 'G') {
cond = value1.value >= value2.value ? 1 : 0;
} else if (ttext == '>') {
cond = value1.value > value2.value ? 1 : 0;
} else if (ttext == 'N') {
cond = value1.value != value2.value ? 1 : 0;
}
PushOperand('nl', cond);
}
} else {
if (operand.length <= 1) {
errortext = scc.s_parseerrmissingoperand;
break;
}
if (ttext == '+') {
value2 = operand_value_and_type(sheet, operand);
value1 = operand_value_and_type(sheet, operand);
resulttype = lookup_result_type(value1.type, value2.type, typelookup.plus);
PushOperand(resulttype, value1.value + value2.value);
} else {
value2 = operand_as_number(sheet, operand);
value1 = operand_as_number(sheet, operand);
}
if (ttext == '-') {
resulttype = lookup_result_type(value1.type, value2.type, typelookup.plus);
PushOperand(resulttype, value1.value - value2.value);
} else if (ttext == '*') {
resulttype = lookup_result_type(value1.type, value2.type, typelookup.plus);
PushOperand(resulttype, value1.value * value2.value);
} else if (ttext == '/') {
resulttype = lookup_result_type(value1.type, value2.type, typelookup.plus);
if (resulttype.charAt(0) == 'e') {
PushOperand(resulttype, 0);
} else if (value2.value != 0) {
PushOperand(resulttype, value1.value / value2.value);
} else {
PushOperand('e#DIV/0!', 0);
}
} else if (ttext == '^') {
resulttype = lookup_result_type(value1.type, value2.type, typelookup.plus);
if (resulttype.charAt(0) == 'e') {
PushOperand(resulttype, 0);
} else {
value1.value = Math.pow(value1.value, value2.value);
value1.type = 'n';
if (isNaN(value1.value)) {
value1.value = 0;
value1.type = 'e#NUM!';
}
PushOperand(value1.type, value1.value);
}
}
}
} else if (ttype == tokentype.name) {
if (
(rii > 0 && parseinfo[rii - 1].type == tokentype.op && parseinfo[rii - 1].text == ':') ||
(rii + 1 < parseinfo.length &&
parseinfo[rii + 1].type == tokentype.op &&
parseinfo[rii + 1].text == ':')
) {
if (operand.length && operand[operand.length - 1].type == 'start') {
operand.pop();
}
PushOperand('name', ttext);
} else {
errortext = scf.CalculateFunction(ttext, operand, sheet, parseinfo.coord);
if (errortext) break;
}
} else {
errortext = scc.s_InternalError + 'Unknown token ' + ttype + ' (' + ttext + '). ';
break;
}
}
value = operand[0] ? operand[0].value : '';
tostype = operand[0] ? operand[0].type : '';
if (tostype == 'name') {
value1 = SocialCalc.Formula.LookupName(sheet, value);
value = value1.value;
tostype = value1.type;
errortext = errortext || value1.error;
}
if (tostype == 'coord') {
value1 = operand_value_and_type(sheet, operand);
value = value1.value;
tostype = value1.type;
if (tostype == 'b') {
tostype = 'n';
value = 0;
}
}
if (operand.length > 1 && !errortext) {
errortext += scc.s_parseerrerrorinformula;
}
valuetype = tostype;
if (tostype.charAt(0) == 'e') {
errortext = errortext || tostype.substring(1) || scc.s_calcerrerrorvalueinformula;
} else if (tostype == 'range') {
vmatch = value.match(/^(.*)\|(.*)\|/);
smatch = vmatch[1].indexOf('!');
if (smatch >= 0) {
vmatch[1] =
vmatch[1].substring(smatch + 1) + '!' + vmatch[1].substring(0, smatch).toUpperCase();
} else {
vmatch[1] = vmatch[1].toUpperCase();
}
value = vmatch[1] + ':' + vmatch[2].toUpperCase();
if (!allowrangereturn) {
errortext = scc.s_formularangeresult + ' ' + value;
}
}
if (errortext && valuetype.charAt(0) != 'e') {
value = errortext;
valuetype = 'e';
}
if (valuetype.charAt(0) == 'n') {
const numericIsNaN = isNaN(value);
if (numericIsNaN || !isFinite(value)) {
value = 0;
valuetype = 'e#NUM!';
errortext = numericIsNaN ? scc.s_calcerrnumericnan : scc.s_calcerrnumericoverflow;
}
}
return {
value,
type: valuetype,
error: errortext,
};
};
FormulaMut.LookupName = function (sheet, name, isEnd) {
var pos, specialc, parseinfo;
var names = sheet.names;
var value = {};
var startedwalk = false;
if (names[name.toUpperCase()]) {
value.value = names[name.toUpperCase()].definition;
if (value.value.charAt(0) == '=') {
if (!sheet.checknamecirc) {
sheet.checknamecirc = {};
startedwalk = true;
} else {
if (sheet.checknamecirc[name]) {
value.type = 'e#NAME?';
value.error = SocialCalc.Constants.s_circularnameref + ' "' + name + '".';
return value;
}
}
sheet.checknamecirc[name] = true;
parseinfo = SocialCalc.Formula.ParseFormulaIntoTokens(value.value.substring(1));
value = SocialCalc.Formula.evaluate_parsed_formula(parseinfo, sheet, 1);
delete sheet.checknamecirc[name];
if (startedwalk) {
delete sheet.checknamecirc;
}
if (value.type != 'range') return value;
}
pos = value.value.indexOf(':');
if (pos != -1) {
value.type = 'range';
value.value = value.value.substring(0, pos) + '|' + value.value.substring(pos + 1) + '|';
value.value = value.value.toUpperCase();
} else {
value.type = 'coord';
value.value = value.value.toUpperCase();
}
return value;
} else if ((specialc = SocialCalc.Formula.SpecialConstants[name.toUpperCase()])) {
pos = specialc.indexOf(',');
value.value = specialc.substring(0, pos) - 0;
value.type = specialc.substring(pos + 1);
return value;
} else if (/^[a-zA-Z][a-zA-Z]?$/.test(name)) {
value.type = 'coord';
value.value = name.toUpperCase() + (isEnd ? sheet.attribs.lastrow : 1);
return value;
} else {
value.value = '';
value.type = 'e#NAME?';
value.error = SocialCalc.Constants.s_calcerrunknownname + ' "' + name + '"';
return value;
}
};
FormulaMut.StepThroughRangeDown = function (operand, rangevalue) {
var value1, value2, sequence, pos1, pos2, sheet1, rp, c, r, count;
var scf = SocialCalc.Formula;
pos1 = rangevalue.indexOf('|');
pos2 = rangevalue.indexOf('|', pos1 + 1);
value1 = rangevalue.substring(0, pos1);
value2 = rangevalue.substring(pos1 + 1, pos2);
sequence = rangevalue.substring(pos2 + 1) - 0;
pos1 = value1.indexOf('!');
if (pos1 != -1) {
sheet1 = value1.substring(pos1);
value1 = value1.substring(0, pos1);
} else {
sheet1 = '';
}
rp = scf.OrderRangeParts(value1, value2);
if (rp.c1 < 1 || rp.c2 < 1 || rp.c1 > 702 || rp.c2 > 702 || rp.r1 < 1 || rp.r2 < 1) {
return {
value: 0,
type: 'e#REF!',
};
}
count = 0;
for (r = rp.r1; r <= rp.r2; r++) {
for (c = rp.c1; c <= rp.c2; c++) {
count++;
if (count > sequence) {
if (r != rp.r2 || c != rp.c2) {
scf.PushOperand(operand, 'range', value1 + sheet1 + '|' + value2 + '|' + count);
}
return {
value: SocialCalc.crToCoord(c, r) + sheet1,
type: 'coord',
};
}
}
}
return undefined;
};
FormulaMut.DecodeRangeParts = function (sheetdata, range) {
var value1, value2, pos1, pos2, sheet1, coordsheetdata, rp;
var scf = SocialCalc.Formula;
pos1 = range.indexOf('|');
pos2 = range.indexOf('|', pos1 + 1);
value1 = range.substring(0, pos1);
value2 = range.substring(pos1 + 1, pos2);
pos1 = value1.indexOf('!');
if (pos1 != -1) {
sheet1 = value1.substring(pos1 + 1);
value1 = value1.substring(0, pos1);
} else {
sheet1 = '';
}
coordsheetdata = sheetdata;
if (sheet1) {
coordsheetdata = scf.FindInSheetCache(sheet1);
if (coordsheetdata == null) {
return null;
}
}
rp = scf.OrderRangeParts(value1, value2);
if (rp.c1 < 1 || rp.c2 < 1 || rp.c1 > 702 || rp.c2 > 702 || rp.r1 < 1 || rp.r2 < 1) {
return null;
}
return {
sheetdata: coordsheetdata,
sheetname: sheet1,
col1num: rp.c1,
ncols: rp.c2 - rp.c1 + 1,
row1num: rp.r1,
nrows: rp.r2 - rp.r1 + 1,
};
};
if (!SocialCalc.Formula.FunctionList) {
FormulaMut.FunctionList = {};
}
FormulaMut.FunctionClasses = null;
FormulaMut.FunctionArgDefs = {};
FormulaMut.StoreIoEventFormula = function (
function_name,
coord,
operand_reverse,
sheet,
io_parameters,
) {
var operand = [];
SocialCalc.Formula.Clone(operand, operand_reverse);
operand.reverse();
if (operand.length == 0) return;
if (typeof sheet.ioEventTree === 'undefined') sheet.ioEventTree = {};
if (typeof sheet.ioParameterList === 'undefined') sheet.ioParameterList = {};
if (typeof sheet.ioTimeTriggerList === 'undefined') sheet.ioTimeTriggerList = {};
if (typeof sheet.radioGroupList === 'undefined') sheet.radioGroupList = {};
if (typeof sheet.ioParameterList[coord] === 'undefined') sheet.ioParameterList[coord] = {};
sheet.ioParameterList[coord] = operand;
sheet.ioParameterList[coord].function_name = function_name;
if (io_parameters == 'TimeTrigger') {
var PushTriggerTime = function (list, coordA1, sheetData) {
var cell = sheetData.cells[coordA1];
if (typeof cell !== 'undefined' && cell.valuetype.charAt(0) == 'n') {
list.push(cell.datavalue);
}
};
var triggerTimeCellId = SocialCalc.Formula.PlainCoord(operand[0].value);
var currentTriggerTimeList = [];
if (operand[0].type == 'range') {
let rangeinfo = SocialCalc.Formula.DecodeRangeParts(sheet, triggerTimeCellId);
for (var i = 0; i < rangeinfo.ncols; i++) {
for (var j = 0; j < rangeinfo.nrows; j++) {
var cellCoord = SocialCalc.crToCoord(rangeinfo.col1num + i, rangeinfo.row1num + j);
PushTriggerTime(currentTriggerTimeList, cellCoord, sheet);
}
}
}
if (operand[0].type == 'coord') {
PushTriggerTime(currentTriggerTimeList, triggerTimeCellId, sheet);
}
if (operand[0].type.charAt(0) == 'n') {
currentTriggerTimeList.push(operand[0].value);
}
if (
typeof sheet.ioTimeTriggerList[coord] === 'undefined' ||
SocialCalc.Formula.ArrayValuesEqual(
sheet.ioTimeTriggerList[coord],
currentTriggerTimeList,
) == false
) {
sheet.ioTimeTriggerList[coord] = currentTriggerTimeList;
var timeZoneOffsetMins = new Date().getTimezoneOffset();
var start_1_1_1970 = 25569;
var triggerUTCTimeList = [];
for (var index = 0; index < currentTriggerTimeList.length; ++index)
triggerUTCTimeList[index] = Math.floor(
(currentTriggerTimeList[index] - start_1_1_1970) * 24 * 60 + timeZoneOffsetMins,
);
sheet.ScheduleSheetCommands(
'settimetrigger ' + coord + ' ' + triggerUTCTimeList.toString(),
);
}
}
if (
io_parameters == 'EventTree' &&
(operand[0].type == 'coord' || operand[0].type == 'range')
) {
var triggerCellId = operand[0].value.replace(/\$/g, '');
var PushTriggerCord = function (list, index, v) {
if (typeof list[index] === 'undefined') list[index] = {};
list[index][v] = v;
};
if (operand[0].type == 'range') {
var rangeinfo = SocialCalc.Formula.DecodeRangeParts(sheet, triggerCellId);
for (var i = 0; i < rangeinfo.ncols; i++) {
for (var j = 0; j < rangeinfo.nrows; j++) {
var cellcr = SocialCalc.crToCoord(rangeinfo.col1num + i, rangeinfo.row1num + j);
PushTriggerCord(sheet.ioEventTree, cellcr, coord);
}
}
}
if (operand[0].type == 'coord') {
PushTriggerCord(sheet.ioEventTree, triggerCellId, coord);
}
}
if (io_parameters == 'Input') {
var formDataViewer = null;
if (SocialCalc.CurrentSpreadsheetControlObject != null) {
formDataViewer = SocialCalc.CurrentSpreadsheetControlObject.formDataViewer;
} else if (SocialCalc.CurrentSpreadsheetViewerObject != null) {
formDataViewer = SocialCalc.CurrentSpreadsheetViewerObject.formDataViewer;
}
if (formDataViewer == null) {
return;
}
if (formDataViewer != null && formDataViewer.loaded == true) {
if (formDataViewer.formFields == null) SocialCalc.Formula.LoadFormFields();
var formFieldName = (function_name + coord).toLowerCase();
var sheetCmd = null;
if (formDataViewer.formFields[formFieldName] == null) {
var col = (formDataViewer.formFields[formFieldName] =
formDataViewer.formFieldsLength++ + 2);
var headerCoord = SocialCalc.crToCoord(col, 1);
sheetCmd =
'set ' +
headerCoord +
' text t ' +
SocialCalc.encodeForSave(function_name.toLowerCase() + coord);
}
if (operand[0].type.charAt(0) == 't' || operand[0].type.charAt(0) == 'n') {
var valueCoord = SocialCalc.crToCoord(formDataViewer.formFields[formFieldName], 2);
if (
formDataViewer.sheet.cells[valueCoord] == null ||
formDataViewer.sheet.cells[valueCoord].datavalue != operand[0].value
) {
var sheetCmdTwo =
'set ' + valueCoord + ' text t ' + SocialCalc.encodeForSave(operand[0].value);
if (sheetCmd != null) sheetCmd = sheetCmd + '\n' + sheetCmdTwo;
else sheetCmd = sheetCmdTwo;
}
}
if (sheetCmd != null) formDataViewer.sheet.ScheduleSheetCommands(sheetCmd, false);
}
}
};
FormulaMut.Clone = function (destination, source) {
for (var property in source) {
if (
typeof source[property] === 'object' &&
source[property] !== null &&
destination[property]
) {
SocialCalc.Formula.Clone(destination[property], source[property]);
} else {
destination[property] = source[property];
}
}
};
FormulaMut.LoadFormFields = function () {
var formDataViewer =
SocialCalc.CurrentSpreadsheetControlObject != null
? SocialCalc.CurrentSpreadsheetControlObject.formDataViewer
: SocialCalc.CurrentSpreadsheetViewerObject.formDataViewer;
formDataViewer.formFields = {};
if (formDataViewer.sheet.cells.A1 == null) {
formDataViewer.sheet.ScheduleSheetCommands(
'set A1 text t ' + SocialCalc.encodeForSave('FieldName:'),
false,
);
}
if (formDataViewer.sheet.cells.A2 == null) {
formDataViewer.sheet.ScheduleSheetCommands(
'set A2 text t ' + SocialCalc.encodeForSave('Pending:'),
false,
);
}
var col = 2;
while (true) {
var coord = SocialCalc.crToCoord(col, 1);
var cell = formDataViewer.sheet.cells[coord];
if (!cell) break;
formDataViewer.formFields[cell.datavalue.toLowerCase()] = col;
col++;
}
formDataViewer.formFieldsLength = col - 2;
};
FormulaMut.CalculateFunction = function (fname, operand, sheet, coord) {
var fobj, ffunc, argnum, ttext;
var foperand;
var scf = SocialCalc.Formula;
var errortext = '';
fobj = scf.FunctionList[fname];
if (fobj) {
foperand = [];
ffunc = fobj[0];
argnum = fobj[1];
scf.CopyFunctionArgs(operand, foperand);
if (foperand.length === 0 && sheet.names && sheet.names[fname.toUpperCase()]) {
scf.PushOperand(operand, 'name', fname);
return '';
}
if (fobj[6] && fobj[6] != '') {
SocialCalc.DebugLog('action:' + fname);
scf.StoreIoEventFormula(fname, coord, foperand, sheet, fobj[6]);
}
if (argnum != 100) {
if (argnum < 0) {
if (foperand.length < -argnum) {
errortext = scf.FunctionArgsError(fname, operand);
return errortext;
}
} else {
if (foperand.length != argnum) {
errortext = scf.FunctionArgsError(fname, operand);
return errortext;
}
}
}
errortext = ffunc(fname, operand, foperand, sheet, coord);
} else {
ttext = fname;
if (operand.length && operand[operand.length - 1].type == 'start') {
operand.pop();
scf.PushOperand(operand, 'name', ttext);
} else {
errortext = SocialCalc.Constants.s_sheetfuncunknownfunction + ' ' + ttext + '. ';
}
}
return errortext;
};
FormulaMut.FunctionArgsError = function (fname, operand) {
var errortext = SocialCalc.Constants.s_calcerrincorrectargstofunction + ' ' + fname + '. ';
SocialCalc.Formula.PushOperand(operand, 'e#VALUE!', errortext);
return errortext;
};
FormulaMut.FunctionSpecificError = function (fname, operand, errortype, errortext) {
SocialCalc.Formula.PushOperand(operand, errortype, errortext);
return errortext;
};
FormulaMut.CheckForErrorValue = function (operand, v) {
if (v.type.charAt(0) == 'e') {
operand.push(v);
return true;
} else {
return false;
}
};
FormulaMut.FillFunctionInfo = function () {
var scf = SocialCalc.Formula;
var scc = SocialCalc.Constants;
var fname, f, classes, cname, i;
if (scf.FunctionClasses) {
return;
}
for (fname in scf.FunctionList) {
f = scf.FunctionList[fname];
if (f[2]) {
scf.FunctionArgDefs[f[2]] = scc['s_farg_' + f[2]] || '';
}
if (!f[3]) {
if (scc['s_fdef_' + fname]) {
scf.FunctionList[fname][3] = scc['s_fdef_' + fname];
}
}
}
scf.FunctionClasses = {};
for (i = 0; i < scc.function_classlist.length; i++) {
cname = scc.function_classlist[i];
scf.FunctionClasses[cname] = {
name: scc['s_fclass_' + cname],
items: [],
};
}
for (fname in scf.FunctionList) {
f = scf.FunctionList[fname];
classes = f[4] ? f[4].split(',') : [];
classes.push('all');
for (i = 0; i < classes.length; i++) {
cname = classes[i];
scf.FunctionClasses[cname].items.push(fname);
}
}
for (cname in scf.FunctionClasses) {
scf.FunctionClasses[cname].items.sort();
}
};
FormulaMut.FunctionArgString = function (fname) {
var scf = SocialCalc.Formula;
var fdata = scf.FunctionList[fname];
var nargs, i, str;
var adef = fdata[2];
if (!adef) {
nargs = fdata[1];
if (nargs == 0) {
adef = ' ';
} else if (nargs > 0) {
str = 'v1';
for (i = 2; i <= nargs; i++) {
str += ', v' + i;
}
return str;
} else {
str = 'v1';
for (i = 2; i < -nargs; i++) {
str += ', v' + i;
}
return str + ', ...';
}
}
str = scf.FunctionArgDefs[adef] || adef;
return str;
};
FormulaMut.SeriesFunctions = function (fname, operand, foperand, sheet) {
var value1, t, v1;
var scf = SocialCalc.Formula;
var operand_value_and_type = scf.OperandValueAndType;
var lookup_result_type = scf.LookupResultType;
var typelookupplus = scf.TypeLookupTable.plus;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
var concat = '';
var sum = 0;
var resulttypesum = '';
var count = 0;
var counta = 0;
var countblank = 0;
var product = 1;
var maxval;
var minval;
var mk = 0,
sk = 0,
mk1 = 0,
sk1 = 0;
while (foperand.length > 0) {
value1 = operand_value_and_type(sheet, foperand);
t = value1.type.charAt(0);
if (t == 'n') count += 1;
if (t != 'b') counta += 1;
if (t == 'b') countblank += 1;
if (t != 'e' && t != 'b') concat = concat + value1.value;
if (t == 'n') {
v1 = value1.value - 0;
sum += v1;
product *= v1;
maxval = maxval != undefined ? (v1 > maxval ? v1 : maxval) : v1;
minval = minval != undefined ? (v1 < minval ? v1 : minval) : v1;
if (count == 1) {
mk1 = v1;
sk1 = 0;
} else {
mk = mk1 + (v1 - mk1) / count;
sk = sk1 + (v1 - mk1) * (v1 - mk);
sk1 = sk;
mk1 = mk;
}
resulttypesum = lookup_result_type(
value1.type,
resulttypesum || value1.type,
typelookupplus,
);
} else if (t == 'e' && resulttypesum.charAt(0) != 'e') {
resulttypesum = value1.type;
}
}
resulttypesum = resulttypesum || 'n';
switch (fname) {
case 'CONCAT':
case 'CONCATENATE':
PushOperand('t', concat);
break;
case 'SUM':
PushOperand(resulttypesum, sum);
break;
case 'PRODUCT':
PushOperand(resulttypesum, product);
break;
case 'MIN':
PushOperand(resulttypesum, minval || 0);
break;
case 'MAX':
PushOperand(resulttypesum, maxval || 0);
break;
case 'COUNT':
PushOperand('n', count);
break;
case 'COUNTA':
PushOperand('n', counta);
break;
case 'COUNTBLANK':
PushOperand('n', countblank);
break;
case 'AVERAGE':
if (count > 0) {
PushOperand(resulttypesum, sum / count);
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'STDEV':
if (count > 1) {
PushOperand(resulttypesum, Math.sqrt(sk / (count - 1)));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'STDEVP':
if (count > 1) {
PushOperand(resulttypesum, Math.sqrt(sk / count));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'VAR':
if (count > 1) {
PushOperand(resulttypesum, sk / (count - 1));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'VARP':
if (count > 1) {
PushOperand(resulttypesum, sk / count);
} else {
PushOperand('e#DIV/0!', 0);
}
break;
}
return null;
};
SocialCalc.Formula.FunctionList['AVERAGE'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['CONCAT'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'text',
];
SocialCalc.Formula.FunctionList['CONCATENATE'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'text',
];
SocialCalc.Formula.FunctionList['COUNT'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['COUNTA'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['COUNTBLANK'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['MAX'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['MIN'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['PRODUCT'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['STDEV'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['STDEVP'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['SUM'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['VAR'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
SocialCalc.Formula.FunctionList['VARP'] = [
SocialCalc.Formula.SeriesFunctions,
-1,
'vn',
null,
'stat',
];
FormulaMut.SumProductFunction = function (fname, operand, foperand, sheet) {
var range,
sum = 0;
var products = [];
var scf = SocialCalc.Formula;
var ncols = 0,
nrows = 0;
var rangeinfo, i, j, k, cellcr, cell, value;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
while (foperand.length > 0) {
range = scf.TopOfStackValueAndType(sheet, foperand);
if (range.type != 'range') {
PushOperand('e#VALUE!', 0);
return;
}
rangeinfo = scf.DecodeRangeParts(sheet, range.value);
if (!rangeinfo) {
PushOperand('e#REF!', 0);
return;
}
if (!ncols) ncols = rangeinfo.ncols;
else if (ncols != rangeinfo.ncols) {
PushOperand('e#VALUE!', 0);
return;
}
if (!nrows) nrows = rangeinfo.nrows;
else if (nrows != rangeinfo.nrows) {
PushOperand('e#VALUE!', 0);
return;
}
for (i = 0; i < rangeinfo.ncols; i++) {
for (j = 0; j < rangeinfo.nrows; j++) {
k = i * rangeinfo.nrows + j;
cellcr = SocialCalc.crToCoord(rangeinfo.col1num + i, rangeinfo.row1num + j);
cell = rangeinfo.sheetdata.GetAssuredCell(cellcr);
value = cell.valuetype == 'n' ? cell.datavalue : 0;
products[k] = (typeof products[k] !== 'undefined' ? products[k] : 1) * value;
}
}
}
for (i = 0; i < products.length; i++) {
sum += products[i];
}
PushOperand('n', sum);
return;
};
SocialCalc.Formula.FunctionList['SUMPRODUCT'] = [
SocialCalc.Formula.SumProductFunction,
-1,
'rangen',
'',
'stat',
];
FormulaMut.DSeriesFunctions = function (fname, operand, foperand, sheet) {
var cr, dbrange, fieldname, criteriarange;
var fieldasnum, targetcol, i, j, k, cell, criteriafieldnums, criterianum;
var testok, criteriacr, criteria, testcol, testcr;
var t, v1;
var scf = SocialCalc.Formula;
var lookup_result_type = scf.LookupResultType;
var typelookupplus = scf.TypeLookupTable.plus;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
var value1 = {};
var sum = 0;
var resulttypesum = '';
var count = 0;
var counta = 0;
var countblank = 0;
var countmatches = 0;
var product = 1;
var maxval;
var minval;
var mk = 0,
sk = 0,
mk1 = 0,
sk1 = 0;
dbrange = scf.TopOfStackValueAndType(sheet, foperand);
fieldname = scf.OperandValueAndType(sheet, foperand);
criteriarange = scf.TopOfStackValueAndType(sheet, foperand);
var dbinfo, criteriainfo;
if (dbrange.type != 'range' || criteriarange.type != 'range') {
return scf.FunctionArgsError(fname, operand);
}
dbinfo = scf.DecodeRangeParts(sheet, dbrange.value);
criteriainfo = scf.DecodeRangeParts(sheet, criteriarange.value);
fieldasnum = scf.FieldToColnum(
dbinfo.sheetdata,
dbinfo.col1num,
dbinfo.ncols,
dbinfo.row1num,
fieldname.value,
fieldname.type,
);
if (fieldasnum <= 0) {
PushOperand('e#VALUE!', 0);
return;
}
targetcol = dbinfo.col1num + fieldasnum - 1;
criteriafieldnums = [];
for (i = 0; i < criteriainfo.ncols; i++) {
cell = criteriainfo.sheetdata.GetAssuredCell(
SocialCalc.crToCoord(criteriainfo.col1num + i, criteriainfo.row1num),
);
criterianum = scf.FieldToColnum(
dbinfo.sheetdata,
dbinfo.col1num,
dbinfo.ncols,
dbinfo.row1num,
cell.datavalue,
cell.valuetype,
);
if (criterianum <= 0) {
PushOperand('e#VALUE!', 0);
return;
}
criteriafieldnums.push(dbinfo.col1num + criterianum - 1);
}
for (i = 1; i < dbinfo.nrows; i++) {
testok = false;
CRITERIAROW: for (j = 1; j < criteriainfo.nrows; j++) {
for (k = 0; k < criteriainfo.ncols; k++) {
criteriacr = SocialCalc.crToCoord(criteriainfo.col1num + k, criteriainfo.row1num + j);
cell = criteriainfo.sheetdata.GetAssuredCell(criteriacr);
criteria = cell.datavalue;
if (typeof criteria == 'string' && criteria.length == 0) continue;
testcol = criteriafieldnums[k];
testcr = SocialCalc.crToCoord(testcol, dbinfo.row1num + i);
cell = dbinfo.sheetdata.GetAssuredCell(testcr);
if (!scf.TestCriteria(cell.datavalue, cell.valuetype || 'b', criteria)) {
continue CRITERIAROW;
}
}
testok = true;
break CRITERIAROW;
}
if (!testok) {
continue;
}
cr = SocialCalc.crToCoord(targetcol, dbinfo.row1num + i);
cell = dbinfo.sheetdata.GetAssuredCell(cr);
value1.value = cell.datavalue;
value1.type = cell.valuetype;
t = value1.type.charAt(0);
countmatches += 1;
if (t == 'n') count += 1;
if (t != 'b') counta += 1;
if (t == 'b') countblank += 1;
if (t == 'n') {
v1 = value1.value - 0;
sum += v1;
product *= v1;
maxval = maxval != undefined ? (v1 > maxval ? v1 : maxval) : v1;
minval = minval != undefined ? (v1 < minval ? v1 : minval) : v1;
if (count == 1) {
mk1 = v1;
sk1 = 0;
} else {
mk = mk1 + (v1 - mk1) / count;
sk = sk1 + (v1 - mk1) * (v1 - mk);
sk1 = sk;
mk1 = mk;
}
resulttypesum = lookup_result_type(
value1.type,
resulttypesum || value1.type,
typelookupplus,
);
} else if (t == 'e' && resulttypesum.charAt(0) != 'e') {
resulttypesum = value1.type;
}
}
resulttypesum = resulttypesum || 'n';
switch (fname) {
case 'DSUM':
PushOperand(resulttypesum, sum);
break;
case 'DPRODUCT':
PushOperand(resulttypesum, count == 0 ? 0 : product);
break;
case 'DMIN':
PushOperand(resulttypesum, minval || 0);
break;
case 'DMAX':
PushOperand(resulttypesum, maxval || 0);
break;
case 'DCOUNT':
PushOperand('n', count);
break;
case 'DCOUNTA':
PushOperand('n', counta);
break;
case 'DAVERAGE':
if (count > 0) {
PushOperand(resulttypesum, sum / count);
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'DSTDEV':
if (count > 1) {
PushOperand(resulttypesum, Math.sqrt(sk / (count - 1)));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'DSTDEVP':
if (count > 1) {
PushOperand(resulttypesum, Math.sqrt(sk / count));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'DVAR':
if (count > 1) {
PushOperand(resulttypesum, sk / (count - 1));
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'DVARP':
if (count > 1) {
PushOperand(resulttypesum, sk / count);
} else {
PushOperand('e#DIV/0!', 0);
}
break;
case 'DGET':
if (countmatches == 1) {
PushOperand(value1.type, value1.value);
} else if (countmatches == 0) {
PushOperand('e#VALUE!', 0);
} else {
PushOperand('e#NUM!', 0);
}
break;
}
return;
};
SocialCalc.Formula.FunctionList['DAVERAGE'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DCOUNT'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DCOUNTA'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DGET'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DMAX'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DMIN'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DPRODUCT'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DSTDEV'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DSTDEVP'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DSUM'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DVAR'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
SocialCalc.Formula.FunctionList['DVARP'] = [
SocialCalc.Formula.DSeriesFunctions,
3,
'dfunc',
'',
'stat',
];
FormulaMut.FieldToColnum = function (sheet, col1num, ncols, row1num, fieldname, fieldtype) {
var colnum, cell, value;
if (fieldtype.charAt(0) == 'n') {
colnum = fieldname - 0;
if (colnum <= 0 || colnum > ncols) {
return 0;
}
return Math.floor(colnum);
}
if (fieldtype.charAt(0) != 't') {
return 0;
}
fieldname = fieldname ? fieldname.toLowerCase() : '';
for (colnum = 0; colnum < ncols; colnum++) {
cell = sheet.GetAssuredCell(SocialCalc.crToCoord(col1num + colnum, row1num));
value = cell.datavalue;
value = (value + '').toLowerCase();
if (value == fieldname) {
return colnum + 1;
}
}
return 0;
};
FormulaMut.LookupFunctions = function (fname, operand, foperand, sheet) {
var lookupvalue, range, rangelookup, rangeinfo;
var offsetvalue = 0;
var c = 0,
r = 0,
csave = 0,
rsave = 0;
var cincr, rincr;
var previousOK, cell, value, valuetype, cr;
var scf = SocialCalc.Formula;
var operand_value_and_type = scf.OperandValueAndType;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
lookupvalue = operand_value_and_type(sheet, foperand);
if (lookupvalue.type.charAt(0) == 'e') {
PushOperand(lookupvalue.type, 0);
return;
}
if (typeof lookupvalue.value == 'string') {
lookupvalue.value = lookupvalue.value.toLowerCase();
}
range = scf.TopOfStackValueAndType(sheet, foperand);
rangelookup = 1;
if (fname == 'MATCH') {
if (foperand.length) {
rangelookup = scf.OperandAsNumber(sheet, foperand);
if (rangelookup.type.charAt(0) != 'n') {
PushOperand('e#VALUE!', 0);
return;
}
if (foperand.length) {
scf.FunctionArgsError(fname, operand);
return 0;
}
rangelookup = rangelookup.value - 0;
}
} else {
offsetvalue = scf.OperandAsNumber(sheet, foperand);
if (offsetvalue.type.charAt(0) != 'n') {
PushOperand('e#VALUE!', 0);
return;
}
offsetvalue = Math.floor(offsetvalue.value);
if (foperand.length) {
rangelookup = scf.OperandAsNumber(sheet, foperand);
if (rangelookup.type.charAt(0) != 'n') {
PushOperand('e#VALUE!', 0);
return;
}
if (foperand.length) {
scf.FunctionArgsError(fname, operand);
return 0;
}
rangelookup = rangelookup.value ? 1 : 0;
}
}
lookupvalue.type = lookupvalue.type.charAt(0);
if (lookupvalue.type == 'n') {
lookupvalue.value = lookupvalue.value - 0;
}
if (range.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
rangeinfo = scf.DecodeRangeParts(sheet, range.value, range.type);
if (!rangeinfo) {
PushOperand('e#REF!', 0);
return;
}
c = 0;
r = 0;
cincr = 0;
rincr = 0;
if (fname == 'HLOOKUP') {
cincr = 1;
if (offsetvalue > rangeinfo.nrows) {
PushOperand('e#REF!', 0);
return;
}
} else if (fname == 'VLOOKUP') {
rincr = 1;
if (offsetvalue > rangeinfo.ncols) {
PushOperand('e#REF!', 0);
return;
}
} else {
if (rangeinfo.ncols > 1) {
if (rangeinfo.nrows > 1) {
PushOperand('e#N/A', 0);
return;
}
cincr = 1;
} else {
rincr = 1;
}
}
if (offsetvalue < 1 && fname != 'MATCH') {
PushOperand('e#VALUE!', 0);
return 0;
}
for (;;) {
cr = SocialCalc.crToCoord(rangeinfo.col1num + c, rangeinfo.row1num + r);
cell = rangeinfo.sheetdata.GetAssuredCell(cr);
value = cell.datavalue;
valuetype = cell.valuetype ? cell.valuetype.charAt(0) : 'b';
if (valuetype == 'n') {
value = value - 0;
}
if (rangelookup) {
if (lookupvalue.type == 'n' && valuetype == 'n') {
if (lookupvalue.value == value) {
break;
}
if (
(rangelookup > 0 && lookupvalue.value > value) ||
(rangelookup < 0 && lookupvalue.value < value)
) {
previousOK = 1;
csave = c;
rsave = r;
} else if (previousOK) {
previousOK = 2;
break;
}
} else if (lookupvalue.type == 't' && valuetype == 't') {
value = typeof value == 'string' ? value.toLowerCase() : '';
if (lookupvalue.value == value) {
break;
}
if (
(rangelookup > 0 && lookupvalue.value > value) ||
(rangelookup < 0 && lookupvalue.value < value)
) {
previousOK = 1;
csave = c;
rsave = r;
} else if (previousOK) {
previousOK = 2;
break;
}
}
} else {
if (lookupvalue.type == 'n' && valuetype == 'n') {
if (lookupvalue.value == value) {
break;
}
} else if (lookupvalue.type == 't' && valuetype == 't') {
value = typeof value == 'string' ? value.toLowerCase() : '';
if (lookupvalue.value == value) {
break;
}
}
}
r += rincr;
c += cincr;
if (r >= rangeinfo.nrows || c >= rangeinfo.ncols) {
if (previousOK) {
previousOK = 2;
break;
}
PushOperand('e#N/A', 0);
return;
}
}
if (previousOK == 2) {
r = rsave;
c = csave;
}
if (fname == 'MATCH') {
value = c + r + 1;
valuetype = 'n';
} else {
cr = SocialCalc.crToCoord(
rangeinfo.col1num + c + (fname == 'VLOOKUP' ? offsetvalue - 1 : 0),
rangeinfo.row1num + r + (fname == 'HLOOKUP' ? offsetvalue - 1 : 0),
);
cell = rangeinfo.sheetdata.GetAssuredCell(cr);
value = cell.datavalue;
valuetype = cell.valuetype;
}
PushOperand(valuetype, value);
return;
};
SocialCalc.Formula.FunctionList['HLOOKUP'] = [
SocialCalc.Formula.LookupFunctions,
-3,
'hlookup',
'',
'lookup',
];
SocialCalc.Formula.FunctionList['MATCH'] = [
SocialCalc.Formula.LookupFunctions,
-2,
'match',
'',
'lookup',
];
SocialCalc.Formula.FunctionList['VLOOKUP'] = [
SocialCalc.Formula.LookupFunctions,
-3,
'vlookup',
'',
'lookup',
];
FormulaMut.IndexFunction = function (fname, operand, foperand, sheet) {
var range, sheetname, indexinfo, rowindex, colindex, result, resulttype;
var scf = SocialCalc.Formula;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
range = scf.TopOfStackValueAndType(sheet, foperand);
if (range.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
indexinfo = scf.DecodeRangeParts(sheet, range.value, range.type);
if (indexinfo.sheetname) {
sheetname = '!' + indexinfo.sheetname;
} else {
sheetname = '';
}
rowindex = { value: 0 };
colindex = { value: 0 };
if (foperand.length) {
rowindex = scf.OperandAsNumber(sheet, foperand);
if (rowindex.type.charAt(0) != 'n' || rowindex.value < 0) {
PushOperand('e#VALUE!', 0);
return;
}
if (foperand.length) {
colindex = scf.OperandAsNumber(sheet, foperand);
if (colindex.type.charAt(0) != 'n' || colindex.value < 0) {
PushOperand('e#VALUE!', 0);
return;
}
if (foperand.length) {
scf.FunctionArgsError(fname, operand);
return 0;
}
} else {
if (indexinfo.nrows == 1) {
colindex.value = rowindex.value;
rowindex.value = 0;
}
}
}
if (rowindex.value > indexinfo.nrows || colindex.value > indexinfo.ncols) {
PushOperand('e#REF!', 0);
return;
}
if (rowindex.value == 0) {
if (colindex.value == 0) {
if (indexinfo.nrows == 1 && indexinfo.ncols == 1) {
result = SocialCalc.crToCoord(indexinfo.col1num, indexinfo.row1num) + sheetname;
resulttype = 'coord';
} else {
result =
SocialCalc.crToCoord(indexinfo.col1num, indexinfo.row1num) +
sheetname +
'|' +
SocialCalc.crToCoord(
indexinfo.col1num + indexinfo.ncols - 1,
indexinfo.row1num + indexinfo.nrows - 1,
) +
'|';
resulttype = 'range';
}
} else {
if (indexinfo.nrows == 1) {
result =
SocialCalc.crToCoord(indexinfo.col1num + colindex.value - 1, indexinfo.row1num) +
sheetname;
resulttype = 'coord';
} else {
result =
SocialCalc.crToCoord(indexinfo.col1num + colindex.value - 1, indexinfo.row1num) +
sheetname +
'|' +
SocialCalc.crToCoord(
indexinfo.col1num + colindex.value - 1,
indexinfo.row1num + indexinfo.nrows - 1,
) +
'|';
resulttype = 'range';
}
}
} else {
if (colindex.value == 0) {
if (indexinfo.ncols == 1) {
result =
SocialCalc.crToCoord(indexinfo.col1num, indexinfo.row1num + rowindex.value - 1) +
sheetname;
resulttype = 'coord';
} else {
result =
SocialCalc.crToCoord(indexinfo.col1num, indexinfo.row1num + rowindex.value - 1) +
sheetname +
'|' +
SocialCalc.crToCoord(
indexinfo.col1num + indexinfo.ncols - 1,
indexinfo.row1num + rowindex.value - 1,
) +
'|';
resulttype = 'range';
}
} else {
result =
SocialCalc.crToCoord(
indexinfo.col1num + colindex.value - 1,
indexinfo.row1num + rowindex.value - 1,
) + sheetname;
resulttype = 'coord';
}
}
PushOperand(resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['INDEX'] = [
SocialCalc.Formula.IndexFunction,
-1,
'index',
'',
'lookup',
];
FormulaMut.CountifSumifFunctions = function (fname, operand, foperand, sheet) {
var range, criteria, sumrange, f2operand, value1, value2;
var sum = 0;
var resulttypesum = '';
var count = 0;
var scf = SocialCalc.Formula;
var operand_value_and_type = scf.OperandValueAndType;
var lookup_result_type = scf.LookupResultType;
var typelookupplus = scf.TypeLookupTable.plus;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
range = scf.TopOfStackValueAndType(sheet, foperand);
criteria = scf.OperandAsText(sheet, foperand);
if (fname == 'SUMIF') {
if (foperand.length == 1) {
sumrange = scf.TopOfStackValueAndType(sheet, foperand);
} else if (foperand.length == 0) {
sumrange = {
value: range.value,
type: range.type,
};
} else {
scf.FunctionArgsError(fname, operand);
return 0;
}
} else {
sumrange = {
value: range.value,
type: range.type,
};
}
if (criteria.type.charAt(0) == 'e') criteria.value = null;
if (range.type != 'coord' && range.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
if (fname == 'SUMIF' && sumrange.type != 'coord' && sumrange.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
foperand.push(range);
f2operand = [];
f2operand.push(sumrange);
while (foperand.length) {
value1 = operand_value_and_type(sheet, foperand);
value2 = operand_value_and_type(sheet, f2operand);
if (!scf.TestCriteria(value1.value, value1.type, criteria.value)) {
continue;
}
count += 1;
if (value2.type.charAt(0) == 'n') {
sum += value2.value - 0;
resulttypesum = lookup_result_type(
value2.type,
resulttypesum || value2.type,
typelookupplus,
);
} else if (value2.type.charAt(0) == 'e' && resulttypesum.charAt(0) != 'e') {
resulttypesum = value2.type;
}
}
resulttypesum = resulttypesum || 'n';
if (fname == 'SUMIF') {
PushOperand(resulttypesum, sum);
} else if (fname == 'COUNTIF') {
PushOperand('n', count);
}
return;
};
SocialCalc.Formula.FunctionList['COUNTIF'] = [
SocialCalc.Formula.CountifSumifFunctions,
2,
'rangec',
'',
'stat',
];
SocialCalc.Formula.FunctionList['SUMIF'] = [
SocialCalc.Formula.CountifSumifFunctions,
-2,
'sumif',
'',
'stat',
];
FormulaMut.SumifsFunction = function (fname, operand, foperand, sheet) {
var range, criteria, sumrange, f2operand, value1, value2;
var sum = 0;
var resulttypesum = '';
var scf = SocialCalc.Formula;
var operand_value_and_type = scf.OperandValueAndType;
var lookup_result_type = scf.LookupResultType;
var typelookupplus = scf.TypeLookupTable.plus;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
sumrange = scf.TopOfStackValueAndType(sheet, foperand);
if (sumrange.type != 'coord' && sumrange.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
var ranges = [],
criterias = [];
while (foperand.length) {
range = scf.TopOfStackValueAndType(sheet, foperand);
criteria = scf.OperandAsText(sheet, foperand);
if (criteria.type.charAt(0) == 'e') criteria.value = null;
if (range.type != 'coord' && range.type != 'range') {
scf.FunctionArgsError(fname, operand);
return 0;
}
ranges.push([range]);
criterias.push(criteria);
}
f2operand = [];
f2operand.push(sumrange);
while (f2operand.length) {
value2 = operand_value_and_type(sheet, f2operand);
var all_good = true;
for (var i = 0; i < ranges.length; i++) {
value1 = operand_value_and_type(sheet, ranges[i]);
if (!all_good) {
continue;
}
if (!scf.TestCriteria(value1.value, value1.type, criterias[i].value)) {
all_good = false;
}
}
if (!all_good) {
continue;
}
if (value2.type.charAt(0) == 'n') {
sum += value2.value - 0;
resulttypesum = lookup_result_type(
value2.type,
resulttypesum || value2.type,
typelookupplus,
);
} else if (value2.type.charAt(0) == 'e' && resulttypesum.charAt(0) != 'e') {
resulttypesum = value2.type;
}
}
resulttypesum = resulttypesum || 'n';
PushOperand(resulttypesum, sum);
return;
};
SocialCalc.Formula.FunctionList['SUMIFS'] = [
SocialCalc.Formula.SumifsFunction,
-3,
'sum_range, criteria_range1, criteria1, [criteria_range2, criteria2, ... criteria_range_n, criteria_n]',
'',
'stat',
];
FormulaMut.IfFunction = function (fname, operand, foperand, sheet) {
var cond, t;
var scf = SocialCalc.Formula;
cond = SocialCalc.Formula.OperandValueAndType(sheet, foperand);
t = cond.type.charAt(0);
if (t == 'e') {
operand.push({
type: cond.type,
value: 0,
});
return;
}
if (t != 'n' && t != 'b') {
operand.push({
type: 'e#VALUE!',
value: 0,
});
return;
}
var op1, op2;
op1 = foperand.pop();
if (foperand.length == 1) {
op2 = foperand.pop();
} else if (foperand.length == 0) {
op2 = {
type: 'n',
value: 0,
};
} else {
scf.FunctionArgsError(fname, operand);
return;
}
operand.push(cond.value ? op1 : op2);
};
SocialCalc.Formula.FunctionList['IF'] = [SocialCalc.Formula.IfFunction, -2, 'iffunc', '', 'test'];
FormulaMut.DateFunction = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var result = 0;
var year = scf.OperandAsNumber(sheet, foperand);
var month = scf.OperandAsNumber(sheet, foperand);
var day = scf.OperandAsNumber(sheet, foperand);
var resulttype = scf.LookupResultType(year.type, month.type, scf.TypeLookupTable.twoargnumeric);
resulttype = scf.LookupResultType(resulttype, day.type, scf.TypeLookupTable.twoargnumeric);
if (resulttype.charAt(0) == 'n') {
result =
SocialCalc.FormatNumber.convert_date_gregorian_to_julian(
Math.floor(year.value),
Math.floor(month.value),
Math.floor(day.value),
) - SocialCalc.FormatNumber.datevalues.julian_offset;
resulttype = 'nd';
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['DATE'] = [
SocialCalc.Formula.DateFunction,
3,
'date',
'',
'datetime',
];
FormulaMut.TimeFunction = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var result = 0;
var hours = scf.OperandAsNumber(sheet, foperand);
var minutes = scf.OperandAsNumber(sheet, foperand);
var seconds = scf.OperandAsNumber(sheet, foperand);
var resulttype = scf.LookupResultType(
hours.type,
minutes.type,
scf.TypeLookupTable.twoargnumeric,
);
resulttype = scf.LookupResultType(resulttype, seconds.type, scf.TypeLookupTable.twoargnumeric);
if (resulttype.charAt(0) == 'n') {
result = (hours.value * 60 * 60 + minutes.value * 60 + seconds.value) / (24 * 60 * 60);
resulttype = 'nt';
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['TIME'] = [
SocialCalc.Formula.TimeFunction,
3,
'hms',
'',
'datetime',
];
FormulaMut.DMYFunctions = function (fname, operand, foperand, sheet) {
var ymd, dtype, doffset;
var scf = SocialCalc.Formula;
var result = 0;
var datevalue = scf.OperandAsNumber(sheet, foperand);
var resulttype = scf.LookupResultType(
datevalue.type,
datevalue.type,
scf.TypeLookupTable.oneargnumeric,
);
if (resulttype.charAt(0) == 'n') {
ymd = SocialCalc.FormatNumber.convert_date_julian_to_gregorian(
Math.floor(datevalue.value + SocialCalc.FormatNumber.datevalues.julian_offset),
);
switch (fname) {
case 'DAY':
result = ymd.day;
break;
case 'MONTH':
result = ymd.month;
break;
case 'YEAR':
result = ymd.year;
break;
case 'WEEKDAY':
dtype = { value: 1 };
if (foperand.length) {
dtype = scf.OperandAsNumber(sheet, foperand);
if (dtype.type.charAt(0) != 'n' || dtype.value < 1 || dtype.value > 3) {
scf.PushOperand(operand, 'e#VALUE!', 0);
return;
}
if (foperand.length) {
scf.FunctionArgsError(fname, operand);
return;
}
}
doffset = 6;
if (dtype.value > 1) {
doffset -= 1;
}
result = (Math.floor(datevalue.value + doffset) % 7) + (dtype.value < 3 ? 1 : 0);
break;
}
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['DAY'] = [
SocialCalc.Formula.DMYFunctions,
1,
'v',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['MONTH'] = [
SocialCalc.Formula.DMYFunctions,
1,
'v',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['YEAR'] = [
SocialCalc.Formula.DMYFunctions,
1,
'v',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['WEEKDAY'] = [
SocialCalc.Formula.DMYFunctions,
-1,
'weekday',
'',
'datetime',
];
FormulaMut.HMSFunctions = function (fname, operand, foperand, sheet) {
var hours, minutes, seconds, fraction;
var scf = SocialCalc.Formula;
var result = 0;
var datetime = scf.OperandAsNumber(sheet, foperand);
var resulttype = scf.LookupResultType(
datetime.type,
datetime.type,
scf.TypeLookupTable.oneargnumeric,
);
if (resulttype.charAt(0) == 'n') {
if (datetime.value < 0) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
fraction = datetime.value - Math.floor(datetime.value);
fraction *= 24;
hours = Math.floor(fraction);
fraction -= Math.floor(fraction);
fraction *= 60;
minutes = Math.floor(fraction);
fraction -= Math.floor(fraction);
fraction *= 60;
seconds = Math.floor(fraction + (datetime.value >= 0 ? 0.5 : -0.5));
if (fname == 'HOUR') {
result = hours;
} else if (fname == 'MINUTE') {
result = minutes;
} else if (fname == 'SECOND') {
result = seconds;
}
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['HOUR'] = [
SocialCalc.Formula.HMSFunctions,
1,
'v',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['MINUTE'] = [
SocialCalc.Formula.HMSFunctions,
1,
'v',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['SECOND'] = [
SocialCalc.Formula.HMSFunctions,
1,
'v',
'',
'datetime',
];
FormulaMut.ExactFunction = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'nl';
var value1 = scf.OperandValueAndType(sheet, foperand);
var v1type = value1.type.charAt(0);
var value2 = scf.OperandValueAndType(sheet, foperand);
var v2type = value2.type.charAt(0);
if (v1type == 't') {
if (v2type == 't') {
result = value1.value == value2.value ? 1 : 0;
} else if (v2type == 'b') {
result = value1.value.length ? 0 : 1;
} else if (v2type == 'n') {
result = value1.value == value2.value + '' ? 1 : 0;
} else if (v2type == 'e') {
result = value2.value;
resulttype = value2.type;
}
} else if (v1type == 'n') {
if (v2type == 'n') {
result = value1.value - 0 == value2.value - 0 ? 1 : 0;
} else if (v2type == 'b') {
result = 0;
} else if (v2type == 't') {
result = value1.value + '' == value2.value ? 1 : 0;
} else if (v2type == 'e') {
result = value2.value;
resulttype = value2.type;
}
} else if (v1type == 'b') {
if (v2type == 't') {
result = value2.value.length ? 0 : 1;
} else if (v2type == 'b') {
result = 1;
} else if (v2type == 'n') {
result = 0;
} else if (v2type == 'e') {
result = value2.value;
resulttype = value2.type;
}
} else if (v1type == 'e') {
result = value1.value;
resulttype = value1.type;
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['EXACT'] = [SocialCalc.Formula.ExactFunction, 2, '', '', 'text'];
FormulaMut.ArgList = {
FIND: [1, 1, 0],
LEFT: [1, 0],
LEN: [1],
LOWER: [1],
MID: [1, 0, 0],
PROPER: [1],
REPLACE: [1, 0, 0, 1],
REPT: [1, 0],
RIGHT: [1, 0],
SUBSTITUTE: [1, 1, 1, 0],
TRIM: [1],
HEXCODE: [1],
UPPER: [1],
};
FormulaMut.StringFunctions = function (fname, operand, foperand, sheet) {
var i, value, offset, len, start, count;
var fulltext, oldtext, newtext, which, oldpos, pos;
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'e#VALUE!';
var numargs = foperand.length;
var argdef = scf.ArgList[fname];
var operand_value = [];
var operand_type = [];
for (i = 1; i <= numargs; i++) {
if (i > argdef.length) {
scf.FunctionArgsError(fname, operand);
return;
}
if (argdef[i - 1] == 0) value = scf.OperandAsNumber(sheet, foperand);
else value = scf.OperandAsText(sheet, foperand);
operand_value[i] = value.value;
operand_type[i] = value.type;
if (value.type.charAt(0) == 'e') {
scf.PushOperand(operand, value.type, result);
return;
}
}
switch (fname) {
case 'FIND':
offset = operand_type[3] ? operand_value[3] - 1 : 0;
if (offset < 0) {
result = 'Start is before string';
} else {
result = operand_value[2].indexOf(operand_value[1], offset);
if (result >= 0) {
result += 1;
resulttype = 'n';
} else {
result = 'Not found';
}
}
break;
case 'LEFT':
len = operand_type[2] ? operand_value[2] - 0 : 1;
if (len < 0) {
result = 'Negative length';
} else {
result = operand_value[1].substring(0, len);
resulttype = 't';
}
break;
case 'LEN':
result = operand_value[1].length;
resulttype = 'n';
break;
case 'LOWER':
result = operand_value[1].toLowerCase();
resulttype = 't';
break;
case 'MID':
start = operand_value[2] - 0;
len = operand_value[3] - 0;
if (len < 1 || start < 1) {
result = 'Bad arguments';
} else {
result = operand_value[1].substring(start - 1, start + len - 1);
resulttype = 't';
}
break;
case 'PROPER':
result = operand_value[1].replace(/\b\w+\b/g, function (word) {
return word.substring(0, 1).toUpperCase() + word.substring(1);
});
resulttype = 't';
break;
case 'REPLACE':
start = operand_value[2] - 0;
len = operand_value[3] - 0;
if (len < 0 || start < 1) {
result = 'Bad arguments';
} else {
result =
operand_value[1].substring(0, start - 1) +
operand_value[4] +
operand_value[1].substring(start - 1 + len);
resulttype = 't';
}
break;
case 'REPT':
count = operand_value[2] - 0;
if (count < 0) {
result = 'Negative count';
} else {
result = '';
for (; count > 0; count--) {
result += operand_value[1];
}
resulttype = 't';
}
break;
case 'RIGHT':
len = operand_type[2] ? operand_value[2] - 0 : 1;
if (len < 0) {
result = 'Negative length';
} else {
result = operand_value[1].slice(-len);
resulttype = 't';
}
break;
case 'SUBSTITUTE':
fulltext = operand_value[1];
oldtext = operand_value[2];
newtext = operand_value[3];
if (operand_value[4] != null) {
which = operand_value[4] - 0;
if (which <= 0) {
result = 'Non-positive instance number';
break;
}
} else {
which = 0;
}
count = 0;
oldpos = 0;
result = '';
while (true) {
pos = fulltext.indexOf(oldtext, oldpos);
if (pos >= 0) {
count++;
result += fulltext.substring(oldpos, pos);
if (which == 0) {
result += newtext;
} else if (which == count) {
result += newtext + fulltext.substring(pos + oldtext.length);
break;
} else {
result += oldtext;
}
oldpos = pos + oldtext.length;
} else {
result += fulltext.substring(oldpos);
break;
}
}
resulttype = 't';
break;
case 'TRIM':
result = operand_value[1];
result = result.replace(/^ */, '');
result = result.replace(/ *$/, '');
result = result.replace(/ +/g, ' ');
resulttype = 't';
break;
case 'HEXCODE':
result = String(operand_value[1]);
var code = result.charCodeAt(0);
if (55296 <= code && code <= 56319) {
var next = result.charCodeAt(1);
if (56320 <= next && next <= 57343) {
code = (code - 55296) * 1024 + (next - 56320) + 65536;
}
}
result = code.toString(16).toUpperCase();
resulttype = 't';
break;
case 'UPPER':
result = operand_value[1].toUpperCase();
resulttype = 't';
break;
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['FIND'] = [
SocialCalc.Formula.StringFunctions,
-2,
'find',
'',
'text',
];
SocialCalc.Formula.FunctionList['LEFT'] = [
SocialCalc.Formula.StringFunctions,
-2,
'tc',
'',
'text',
];
SocialCalc.Formula.FunctionList['LEN'] = [
SocialCalc.Formula.StringFunctions,
1,
'txt',
'',
'text',
];
SocialCalc.Formula.FunctionList['LOWER'] = [
SocialCalc.Formula.StringFunctions,
1,
'txt',
'',
'text',
];
SocialCalc.Formula.FunctionList['MID'] = [
SocialCalc.Formula.StringFunctions,
3,
'mid',
'',
'text',
];
SocialCalc.Formula.FunctionList['PROPER'] = [
SocialCalc.Formula.StringFunctions,
1,
'v',
'',
'text',
];
SocialCalc.Formula.FunctionList['REPLACE'] = [
SocialCalc.Formula.StringFunctions,
4,
'replace',
'',
'text',
];
SocialCalc.Formula.FunctionList['REPT'] = [
SocialCalc.Formula.StringFunctions,
2,
'tc',
'',
'text',
];
SocialCalc.Formula.FunctionList['RIGHT'] = [
SocialCalc.Formula.StringFunctions,
-1,
'tc',
'',
'text',
];
SocialCalc.Formula.FunctionList['SUBSTITUTE'] = [
SocialCalc.Formula.StringFunctions,
-3,
'subs',
'',
'text',
];
SocialCalc.Formula.FunctionList['TRIM'] = [
SocialCalc.Formula.StringFunctions,
1,
'v',
'',
'text',
];
SocialCalc.Formula.FunctionList['HEXCODE'] = [
SocialCalc.Formula.StringFunctions,
1,
'v',
'',
'text',
];
SocialCalc.Formula.FunctionList['UPPER'] = [
SocialCalc.Formula.StringFunctions,
1,
'v',
'',
'text',
];
FormulaMut.IsFunctions = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'nl';
var value = scf.OperandValueAndType(sheet, foperand);
var t = value.type.charAt(0);
switch (fname) {
case 'ISBLANK':
result = value.type == 'b' ? 1 : 0;
break;
case 'ISERR':
result = t == 'e' ? (value.type == 'e#N/A' ? 0 : 1) : 0;
break;
case 'ISERROR':
result = t == 'e' ? 1 : 0;
break;
case 'ISLOGICAL':
result = value.type == 'nl' ? 1 : 0;
break;
case 'ISNA':
result = value.type == 'e#N/A' ? 1 : 0;
break;
case 'ISNONTEXT':
result = t == 't' ? 0 : 1;
break;
case 'ISNUMBER':
result = t == 'n' ? 1 : 0;
break;
case 'ISTEXT':
result = t == 't' ? 1 : 0;
break;
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['ISBLANK'] = [SocialCalc.Formula.IsFunctions, 1, 'v', '', 'test'];
SocialCalc.Formula.FunctionList['ISERR'] = [SocialCalc.Formula.IsFunctions, 1, 'v', '', 'test'];
SocialCalc.Formula.FunctionList['ISERROR'] = [SocialCalc.Formula.IsFunctions, 1, 'v', '', 'test'];
SocialCalc.Formula.FunctionList['ISLOGICAL'] = [
SocialCalc.Formula.IsFunctions,
1,
'v',
'',
'test',
];
SocialCalc.Formula.FunctionList['ISNA'] = [SocialCalc.Formula.IsFunctions, 1, 'v', '', 'test'];
SocialCalc.Formula.FunctionList['ISNONTEXT'] = [
SocialCalc.Formula.IsFunctions,
1,
'v',
'',
'test',
];
SocialCalc.Formula.FunctionList['ISNUMBER'] = [
SocialCalc.Formula.IsFunctions,
1,
'v',
'',
'test',
];
SocialCalc.Formula.FunctionList['ISTEXT'] = [SocialCalc.Formula.IsFunctions, 1, 'v', '', 'test'];
FormulaMut.NTVFunctions = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'e#VALUE!';
var value = scf.OperandValueAndType(sheet, foperand);
var t = value.type.charAt(0);
switch (fname) {
case 'N':
result = t == 'n' ? value.value - 0 : 0;
resulttype = 'n';
break;
case 'T':
result = t == 't' ? value.value + '' : '';
resulttype = 't';
break;
case 'VALUE':
if (t == 'n' || t == 'b') {
result = value.value || 0;
resulttype = 'n';
} else if (t == 't') {
value = SocialCalc.DetermineValueType(value.value);
if (value.type.charAt(0) != 'n') {
result = 0;
resulttype = 'e#VALUE!';
} else {
result = value.value - 0;
resulttype = 'n';
}
}
break;
}
if (t == 'e') {
resulttype = value.type;
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['N'] = [SocialCalc.Formula.NTVFunctions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['T'] = [SocialCalc.Formula.NTVFunctions, 1, 'v', '', 'text'];
SocialCalc.Formula.FunctionList['VALUE'] = [SocialCalc.Formula.NTVFunctions, 1, 'v', '', 'text'];
FormulaMut.Math1Functions = function (fname, operand, foperand, sheet) {
var v1, value, f;
var result = {};
var scf = SocialCalc.Formula;
v1 = scf.OperandAsNumber(sheet, foperand);
value = v1.value;
result.type = scf.LookupResultType(v1.type, v1.type, scf.TypeLookupTable.oneargnumeric);
if (result.type == 'n') {
switch (fname) {
case 'ABS':
value = Math.abs(value);
break;
case 'ACOS':
if (value >= -1 && value <= 1) {
value = Math.acos(value);
} else {
result.type = 'e#NUM!';
}
break;
case 'ASIN':
if (value >= -1 && value <= 1) {
value = Math.asin(value);
} else {
result.type = 'e#NUM!';
}
break;
case 'ATAN':
value = Math.atan(value);
break;
case 'COS':
value = Math.cos(value);
break;
case 'DEGREES':
value = (value * 180) / Math.PI;
break;
case 'EVEN':
value = value < 0 ? -value : value;
if (value != Math.floor(value)) {
value = Math.floor(value + 1) + (Math.floor(value + 1) % 2);
} else {
value = value + (value % 2);
}
if (v1.value < 0) value = -value;
break;
case 'EXP':
value = Math.exp(value);
break;
case 'FACT':
f = 1;
value = Math.floor(value);
for (; value > 0; value--) {
f *= value;
}
value = f;
break;
case 'INT':
value = Math.floor(value);
break;
case 'LN':
if (value <= 0) {
result.type = 'e#NUM!';
result.error = SocialCalc.Constants.s_sheetfunclnarg;
}
value = Math.log(value);
break;
case 'LOG10':
if (value <= 0) {
result.type = 'e#NUM!';
result.error = SocialCalc.Constants.s_sheetfunclog10arg;
}
value = Math.log(value) / Math.log(10);
break;
case 'ODD':
value = value < 0 ? -value : value;
if (value != Math.floor(value)) {
value = Math.floor(value + 1) + (1 - (Math.floor(value + 1) % 2));
} else {
value = value + (1 - (value % 2));
}
if (v1.value < 0) value = -value;
break;
case 'RADIANS':
value = (value * Math.PI) / 180;
break;
case 'SIN':
value = Math.sin(value);
break;
case 'SQRT':
if (value >= 0) {
value = Math.sqrt(value);
} else {
result.type = 'e#NUM!';
}
break;
case 'TAN':
if (Math.cos(value) != 0) {
value = Math.tan(value);
} else {
result.type = 'e#NUM!';
}
break;
}
}
result.value = value;
operand.push(result);
return null;
};
SocialCalc.Formula.FunctionList['ABS'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['ACOS'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['ASIN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['ATAN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['COS'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['DEGREES'] = [
SocialCalc.Formula.Math1Functions,
1,
'v',
'',
'math',
];
SocialCalc.Formula.FunctionList['EVEN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['EXP'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['FACT'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['INT'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['LN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['LOG10'] = [
SocialCalc.Formula.Math1Functions,
1,
'v',
'',
'math',
];
SocialCalc.Formula.FunctionList['ODD'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['RADIANS'] = [
SocialCalc.Formula.Math1Functions,
1,
'v',
'',
'math',
];
SocialCalc.Formula.FunctionList['SIN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['SQRT'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
SocialCalc.Formula.FunctionList['TAN'] = [SocialCalc.Formula.Math1Functions, 1, 'v', '', 'math'];
FormulaMut.Math2Functions = function (fname, operand, foperand, sheet) {
var xval, yval, quotient, decimalscale, i;
var result = {};
var scf = SocialCalc.Formula;
xval = scf.OperandAsNumber(sheet, foperand);
yval = scf.OperandAsNumber(sheet, foperand);
result.type = scf.LookupResultType(xval.type, yval.type, scf.TypeLookupTable.twoargnumeric);
if (result.type == 'n') {
switch (fname) {
case 'ATAN2':
if (xval.value == 0 && yval.value == 0) {
result.type = 'e#DIV/0!';
} else {
result.value = Math.atan2(yval.value, xval.value);
}
break;
case 'POWER':
result.value = Math.pow(xval.value, yval.value);
if (isNaN(result.value)) {
result.value = 0;
result.type = 'e#NUM!';
}
break;
case 'MOD':
if (yval.value == 0) {
result.type = 'e#DIV/0!';
} else {
quotient = xval.value / yval.value;
quotient = Math.floor(quotient);
result.value = xval.value - quotient * yval.value;
}
break;
case 'TRUNC':
decimalscale = 1;
if (yval.value >= 0) {
yval.value = Math.floor(yval.value);
for (i = 0; i < yval.value; i++) {
decimalscale *= 10;
}
result.value = Math.floor(Math.abs(xval.value) * decimalscale) / decimalscale;
} else if (yval.value < 0) {
yval.value = Math.floor(-yval.value);
for (i = 0; i < yval.value; i++) {
decimalscale *= 10;
}
result.value = Math.floor(Math.abs(xval.value) / decimalscale) * decimalscale;
}
if (xval.value < 0) {
result.value = -result.value;
}
}
}
operand.push(result);
return null;
};
SocialCalc.Formula.FunctionList['ATAN2'] = [
SocialCalc.Formula.Math2Functions,
2,
'xy',
'',
'math',
];
SocialCalc.Formula.FunctionList['MOD'] = [SocialCalc.Formula.Math2Functions, 2, '', '', 'math'];
SocialCalc.Formula.FunctionList['POWER'] = [SocialCalc.Formula.Math2Functions, 2, '', '', 'math'];
SocialCalc.Formula.FunctionList['TRUNC'] = [
SocialCalc.Formula.Math2Functions,
2,
'valpre',
'',
'math',
];
FormulaMut.LogFunction = function (fname, operand, foperand, sheet) {
var value, value2;
var result = {};
var scf = SocialCalc.Formula;
result.value = 0;
value = scf.OperandAsNumber(sheet, foperand);
result.type = scf.LookupResultType(value.type, value.type, scf.TypeLookupTable.oneargnumeric);
if (foperand.length == 1) {
value2 = scf.OperandAsNumber(sheet, foperand);
if (value2.type.charAt(0) != 'n' || value2.value <= 0) {
scf.FunctionSpecificError(
fname,
operand,
'e#NUM!',
SocialCalc.Constants.s_sheetfunclogsecondarg,
);
return 0;
}
} else if (foperand.length != 0) {
scf.FunctionArgsError(fname, operand);
return 0;
} else {
value2 = {
value: Math.E,
type: 'n',
};
}
if (result.type == 'n') {
if (value.value <= 0) {
scf.FunctionSpecificError(
fname,
operand,
'e#NUM!',
SocialCalc.Constants.s_sheetfunclogfirstarg,
);
return 0;
}
result.value = Math.log(value.value) / Math.log(value2.value);
}
operand.push(result);
return;
};
SocialCalc.Formula.FunctionList['LOG'] = [SocialCalc.Formula.LogFunction, -1, 'log', '', 'math'];
FormulaMut.RoundFunction = function (fname, operand, foperand, sheet) {
var value2, decimalscale, scaledvalue, i;
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'e#VALUE!';
var value = scf.OperandValueAndType(sheet, foperand);
resulttype = scf.LookupResultType(value.type, value.type, scf.TypeLookupTable.oneargnumeric);
if (foperand.length == 1) {
value2 = scf.OperandValueAndType(sheet, foperand);
if (value2.type.charAt(0) != 'n') {
scf.FunctionSpecificError(
fname,
operand,
'e#NUM!',
SocialCalc.Constants.s_sheetfuncroundsecondarg,
);
return 0;
}
} else if (foperand.length != 0) {
scf.FunctionArgsError(fname, operand);
return 0;
} else {
value2 = {
value: 0,
type: 'n',
};
}
if (resulttype == 'n') {
value2.value = value2.value - 0;
if (value2.value == 0) {
result = Math.round(value.value);
} else if (value2.value > 0) {
decimalscale = 1;
value2.value = Math.floor(value2.value);
for (i = 0; i < value2.value; i++) {
decimalscale *= 10;
}
scaledvalue = Math.round(value.value * decimalscale);
result = scaledvalue / decimalscale;
} else if (value2.value < 0) {
decimalscale = 1;
value2.value = Math.floor(-value2.value);
for (i = 0; i < value2.value; i++) {
decimalscale *= 10;
}
scaledvalue = Math.round(value.value / decimalscale);
result = scaledvalue * decimalscale;
}
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['ROUND'] = [
SocialCalc.Formula.RoundFunction,
-1,
'vp',
'',
'math',
];
FormulaMut.CeilingFloorFunctions = function (fname, operand, foperand, sheet) {
var scf = SocialCalc.Formula;
var val, sig, t;
var PushOperand = function (t, v) {
operand.push({
type: t,
value: v,
});
};
val = scf.OperandValueAndType(sheet, foperand);
t = val.type.charAt(0);
if (t != 'n') {
PushOperand('e#VALUE!', 0);
return;
}
if (val.value == 0) {
PushOperand('n', 0);
return;
}
if (foperand.length == 1) {
sig = scf.OperandValueAndType(sheet, foperand);
t = sig.type.charAt(0);
if (t != 'n') {
PushOperand('e#VALUE!', 0);
return;
}
} else if (foperand.length == 0) {
sig = {
type: 'n',
value: val.value > 0 ? 1 : -1,
};
} else {
PushOperand('e#VALUE!', 0);
return;
}
if (sig.value == 0) {
PushOperand('n', 0);
return;
}
if (sig.value * val.value < 0) {
PushOperand('e#NUM!', 0);
return;
}
switch (fname) {
case 'CEILING':
PushOperand('n', Math.ceil(val.value / sig.value) * sig.value);
break;
case 'FLOOR':
PushOperand('n', Math.floor(val.value / sig.value) * sig.value);
break;
}
return;
};
SocialCalc.Formula.FunctionList['CEILING'] = [
SocialCalc.Formula.CeilingFloorFunctions,
-1,
'vsig',
'',
'math',
];
SocialCalc.Formula.FunctionList['FLOOR'] = [
SocialCalc.Formula.CeilingFloorFunctions,
-1,
'vsig',
'',
'math',
];
FormulaMut.AndOrFunctions = function (fname, operand, foperand, sheet) {
var value1, result;
var scf = SocialCalc.Formula;
var resulttype = '';
if (fname == 'AND') {
result = 1;
} else if (fname == 'OR') {
result = 0;
}
while (foperand.length) {
value1 = scf.OperandValueAndType(sheet, foperand);
if (value1.type.charAt(0) == 'n') {
value1.value = value1.value - 0;
if (fname == 'AND') {
result = value1.value != 0 ? result : 0;
} else if (fname == 'OR') {
result = value1.value != 0 ? 1 : result;
}
resulttype = scf.LookupResultType(
value1.type,
resulttype || 'nl',
scf.TypeLookupTable.propagateerror,
);
} else if (value1.type.charAt(0) == 'e' && resulttype.charAt(0) != 'e') {
resulttype = value1.type;
}
}
if (resulttype.length < 1) {
resulttype = 'e#VALUE!';
result = 0;
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['AND'] = [
SocialCalc.Formula.AndOrFunctions,
-1,
'vn',
'',
'test',
];
SocialCalc.Formula.FunctionList['OR'] = [SocialCalc.Formula.AndOrFunctions, -1, 'vn', '', 'test'];
FormulaMut.NotFunction = function (fname, operand, foperand, sheet) {
var result = 0;
var scf = SocialCalc.Formula;
var value = scf.OperandValueAndType(sheet, foperand);
var resulttype = scf.LookupResultType(
value.type,
value.type,
scf.TypeLookupTable.propagateerror,
);
if (value.type.charAt(0) == 'n' || value.type == 'b') {
result = value.value - 0 != 0 ? 0 : 1;
resulttype = 'nl';
} else if (value.type.charAt(0) == 't') {
resulttype = 'e#VALUE!';
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['NOT'] = [SocialCalc.Formula.NotFunction, 1, 'v', '', 'test'];
FormulaMut.ChooseFunction = function (fname, operand, foperand, sheet) {
var resulttype, count, value1;
var result = 0;
var scf = SocialCalc.Formula;
var cindex = scf.OperandAsNumber(sheet, foperand);
if (cindex.type.charAt(0) != 'n') {
cindex.value = 0;
}
cindex.value = Math.floor(cindex.value);
count = 0;
while (foperand.length) {
value1 = scf.TopOfStackValueAndType(sheet, foperand);
count += 1;
if (cindex.value == count) {
result = value1.value;
resulttype = value1.type;
break;
}
}
if (resulttype) {
scf.PushOperand(operand, resulttype, result);
} else {
scf.PushOperand(operand, 'e#VALUE!', 0);
}
return;
};
SocialCalc.Formula.FunctionList['CHOOSE'] = [
SocialCalc.Formula.ChooseFunction,
-2,
'choose',
'',
'lookup',
];
FormulaMut.ColumnsRowsFunctions = function (fname, operand, foperand, sheet) {
var resulttype, rangeinfo;
var result = 0;
var scf = SocialCalc.Formula;
var value1 = scf.TopOfStackValueAndType(sheet, foperand);
if (value1.type == 'coord') {
result = 1;
resulttype = 'n';
} else if (value1.type == 'range') {
rangeinfo = scf.DecodeRangeParts(sheet, value1.value);
if (!rangeinfo) {
result = 0;
resulttype = 'e#REF!';
} else if (fname == 'COLUMNS') {
result = rangeinfo.ncols;
resulttype = 'n';
} else if (fname == 'ROWS') {
result = rangeinfo.nrows;
resulttype = 'n';
} else {
result = 0;
resulttype = 'n';
}
} else {
result = 0;
resulttype = 'e#VALUE!';
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['COLUMNS'] = [
SocialCalc.Formula.ColumnsRowsFunctions,
1,
'range',
'',
'lookup',
];
SocialCalc.Formula.FunctionList['ROWS'] = [
SocialCalc.Formula.ColumnsRowsFunctions,
1,
'range',
'',
'lookup',
];
FormulaMut.ZeroArgFunctions = function (fname, operand, _foperand, _sheet) {
var startval, tzoffset, start_1_1_1970, seconds_in_a_day, nowdays;
var result = {
value: 0,
type: '',
};
switch (fname) {
case 'FALSE':
result.type = 'nl';
result.value = 0;
break;
case 'NA':
result.type = 'e#N/A';
break;
case 'NOW':
startval = new Date();
tzoffset = startval.getTimezoneOffset();
startval = startval.getTime() / 1e3;
start_1_1_1970 = 25569;
seconds_in_a_day = 24 * 60 * 60;
nowdays = start_1_1_1970 + startval / seconds_in_a_day - tzoffset / (24 * 60);
result.value = nowdays;
result.type = 'ndt';
SocialCalc.Formula.FreshnessInfo.volatile.NOW = true;
break;
case 'PI':
result.type = 'n';
result.value = Math.PI;
break;
case 'TODAY':
startval = new Date();
tzoffset = startval.getTimezoneOffset();
startval = startval.getTime() / 1e3;
start_1_1_1970 = 25569;
seconds_in_a_day = 24 * 60 * 60;
nowdays = start_1_1_1970 + startval / seconds_in_a_day - tzoffset / (24 * 60);
result.value = Math.floor(nowdays);
result.type = 'nd';
SocialCalc.Formula.FreshnessInfo.volatile.TODAY = true;
break;
case 'TRUE':
result.type = 'nl';
result.value = 1;
break;
case 'RAND':
result.type = 'n';
result.value = Math.random();
SocialCalc.Formula.FreshnessInfo.volatile.RAND = true;
break;
}
operand.push(result);
return null;
};
SocialCalc.Formula.FunctionList['FALSE'] = [
SocialCalc.Formula.ZeroArgFunctions,
0,
'',
'',
'test',
];
SocialCalc.Formula.FunctionList['NA'] = [SocialCalc.Formula.ZeroArgFunctions, 0, '', '', 'test'];
SocialCalc.Formula.FunctionList['NOW'] = [
SocialCalc.Formula.ZeroArgFunctions,
0,
'',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['RAND'] = [
SocialCalc.Formula.ZeroArgFunctions,
0,
'',
'',
'math',
];
SocialCalc.Formula.FunctionList['PI'] = [SocialCalc.Formula.ZeroArgFunctions, 0, '', '', 'math'];
SocialCalc.Formula.FunctionList['TODAY'] = [
SocialCalc.Formula.ZeroArgFunctions,
0,
'',
'',
'datetime',
];
SocialCalc.Formula.FunctionList['TRUE'] = [
SocialCalc.Formula.ZeroArgFunctions,
0,
'',
'',
'test',
];
FormulaMut.DDBFunction = function (fname, operand, foperand, sheet) {
var method, depreciation, accumulateddepreciation, i;
var scf = SocialCalc.Formula;
var cost = scf.OperandAsNumber(sheet, foperand);
var salvage = scf.OperandAsNumber(sheet, foperand);
var lifetime = scf.OperandAsNumber(sheet, foperand);
var period = scf.OperandAsNumber(sheet, foperand);
if (scf.CheckForErrorValue(operand, cost)) return;
if (scf.CheckForErrorValue(operand, salvage)) return;
if (scf.CheckForErrorValue(operand, lifetime)) return;
if (scf.CheckForErrorValue(operand, period)) return;
if (lifetime.value < 1) {
scf.FunctionSpecificError(fname, operand, 'e#NUM!', SocialCalc.Constants.s_sheetfuncddblife);
return 0;
}
method = {
value: 2,
type: 'n',
};
if (foperand.length > 0) {
method = scf.OperandAsNumber(sheet, foperand);
}
if (foperand.length != 0) {
scf.FunctionArgsError(fname, operand);
return 0;
}
if (scf.CheckForErrorValue(operand, method)) return;
depreciation = 0;
accumulateddepreciation = 0;
for (i = 1; i <= period.value - 0 && i <= lifetime.value; i++) {
depreciation = (cost.value - accumulateddepreciation) * (method.value / lifetime.value);
if (cost.value - accumulateddepreciation - depreciation < salvage.value) {
depreciation = cost.value - accumulateddepreciation - salvage.value;
}
accumulateddepreciation += depreciation;
}
scf.PushOperand(operand, 'n$', depreciation);
return;
};
SocialCalc.Formula.FunctionList['DDB'] = [
SocialCalc.Formula.DDBFunction,
-4,
'ddb',
'',
'financial',
];
FormulaMut.SLNFunction = function (fname, operand, foperand, sheet) {
var depreciation;
var scf = SocialCalc.Formula;
var cost = scf.OperandAsNumber(sheet, foperand);
var salvage = scf.OperandAsNumber(sheet, foperand);
var lifetime = scf.OperandAsNumber(sheet, foperand);
if (scf.CheckForErrorValue(operand, cost)) return;
if (scf.CheckForErrorValue(operand, salvage)) return;
if (scf.CheckForErrorValue(operand, lifetime)) return;
if (lifetime.value < 1) {
scf.FunctionSpecificError(fname, operand, 'e#NUM!', SocialCalc.Constants.s_sheetfuncslnlife);
return 0;
}
depreciation = (cost.value - salvage.value) / lifetime.value;
scf.PushOperand(operand, 'n$', depreciation);
return;
};
SocialCalc.Formula.FunctionList['SLN'] = [
SocialCalc.Formula.SLNFunction,
3,
'csl',
'',
'financial',
];
FormulaMut.SYDFunction = function (fname, operand, foperand, sheet) {
var depreciation, sumperiods;
var scf = SocialCalc.Formula;
var cost = scf.OperandAsNumber(sheet, foperand);
var salvage = scf.OperandAsNumber(sheet, foperand);
var lifetime = scf.OperandAsNumber(sheet, foperand);
var period = scf.OperandAsNumber(sheet, foperand);
if (scf.CheckForErrorValue(operand, cost)) return;
if (scf.CheckForErrorValue(operand, salvage)) return;
if (scf.CheckForErrorValue(operand, lifetime)) return;
if (scf.CheckForErrorValue(operand, period)) return;
if (lifetime.value < 1 || period.value <= 0) {
scf.PushOperand(operand, 'e#NUM!', 0);
return 0;
}
sumperiods = ((lifetime.value + 1) * lifetime.value) / 2;
depreciation =
((cost.value - salvage.value) * (lifetime.value - period.value + 1)) / sumperiods;
scf.PushOperand(operand, 'n$', depreciation);
return;
};
SocialCalc.Formula.FunctionList['SYD'] = [
SocialCalc.Formula.SYDFunction,
4,
'cslp',
'',
'financial',
];
FormulaMut.InterestFunctions = function (fname, operand, foperand, sheet) {
var resulttype, result, dval, eval_, fval;
var pv, fv, rate, n, payment, paytype, guess, part1, part2, part3, part4, part5;
var olddelta, maxloop, tries, delta, epsilon, oldrate, m;
var scf = SocialCalc.Formula;
var aval = scf.OperandAsNumber(sheet, foperand);
var bval = scf.OperandAsNumber(sheet, foperand);
var cval = scf.OperandAsNumber(sheet, foperand);
resulttype = scf.LookupResultType(aval.type, bval.type, scf.TypeLookupTable.twoargnumeric);
resulttype = scf.LookupResultType(resulttype, cval.type, scf.TypeLookupTable.twoargnumeric);
if (foperand.length) {
dval = scf.OperandAsNumber(sheet, foperand);
resulttype = scf.LookupResultType(resulttype, dval.type, scf.TypeLookupTable.twoargnumeric);
if (foperand.length) {
eval_ = scf.OperandAsNumber(sheet, foperand);
resulttype = scf.LookupResultType(
resulttype,
eval_.type,
scf.TypeLookupTable.twoargnumeric,
);
if (foperand.length) {
if (fname != 'RATE') {
scf.FunctionArgsError(fname, operand);
return 0;
}
fval = scf.OperandAsNumber(sheet, foperand);
resulttype = scf.LookupResultType(
resulttype,
fval.type,
scf.TypeLookupTable.twoargnumeric,
);
}
}
}
if (resulttype == 'n') {
switch (fname) {
case 'FV':
rate = aval.value;
n = bval.value;
payment = cval.value;
pv = dval != null ? dval.value : 0;
paytype = eval_ != null ? (eval_.value ? 1 : 0) : 0;
if (rate == 0) {
fv = -pv - payment * n;
} else {
fv = -(
pv * Math.pow(1 + rate, n) +
(payment * (1 + rate * paytype) * (Math.pow(1 + rate, n) - 1)) / rate
);
}
result = fv;
resulttype = 'n$';
break;
case 'NPER':
rate = aval.value;
payment = bval.value;
pv = cval.value;
fv = dval != null ? dval.value : 0;
paytype = eval_ != null ? (eval_.value ? 1 : 0) : 0;
if (rate == 0) {
if (payment == 0) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
n = (pv + fv) / -payment;
} else {
part1 = (payment * (1 + rate * paytype)) / rate;
part2 = pv + part1;
if (part2 == 0 || rate <= -1) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
part3 = (part1 - fv) / part2;
if (part3 <= 0) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
part4 = Math.log(part3);
part5 = Math.log(1 + rate);
n = part4 / part5;
}
result = n;
resulttype = 'n';
break;
case 'PMT':
rate = aval.value;
n = bval.value;
pv = cval.value;
fv = dval != null ? dval.value : 0;
paytype = eval_ != null ? (eval_.value ? 1 : 0) : 0;
if (n == 0) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
} else if (rate == 0) {
payment = (fv - pv) / n;
} else {
payment =
(0 - fv - pv * Math.pow(1 + rate, n)) /
(((1 + rate * paytype) * (Math.pow(1 + rate, n) - 1)) / rate);
}
result = payment;
resulttype = 'n$';
break;
case 'PV':
rate = aval.value;
n = bval.value;
payment = cval.value;
fv = dval != null ? dval.value : 0;
paytype = eval_ != null ? (eval_.value ? 1 : 0) : 0;
if (rate == -1) {
scf.PushOperand(operand, 'e#DIV/0!', 0);
return;
} else if (rate == 0) {
pv = -fv - payment * n;
} else {
pv =
(-fv - (payment * (1 + rate * paytype) * (Math.pow(1 + rate, n) - 1)) / rate) /
Math.pow(1 + rate, n);
}
result = pv;
resulttype = 'n$';
break;
case 'RATE':
n = aval.value;
payment = bval.value;
pv = cval.value;
fv = dval != null ? dval.value : 0;
paytype = eval_ != null ? (eval_.value ? 1 : 0) : 0;
guess = fval != null ? fval.value : 0.1;
maxloop = 100;
tries = 0;
delta = 1;
epsilon = 1e-7;
rate = guess || 1e-8;
while ((delta >= 0 ? delta : -delta) > epsilon && rate != oldrate) {
delta =
fv +
pv * Math.pow(1 + rate, n) +
(payment * (1 + rate * paytype) * (Math.pow(1 + rate, n) - 1)) / rate;
if (olddelta != null) {
m = (delta - olddelta) / (rate - oldrate) || 0.001;
oldrate = rate;
rate = rate - delta / m;
olddelta = delta;
} else {
oldrate = rate;
rate = 1.1 * rate;
olddelta = delta;
}
tries++;
if (tries >= maxloop) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
}
result = rate;
resulttype = 'n%';
break;
}
}
scf.PushOperand(operand, resulttype, result);
return;
};
SocialCalc.Formula.FunctionList['FV'] = [
SocialCalc.Formula.InterestFunctions,
-3,
'fv',
'',
'financial',
];
SocialCalc.Formula.FunctionList['NPER'] = [
SocialCalc.Formula.InterestFunctions,
-3,
'nper',
'',
'financial',
];
SocialCalc.Formula.FunctionList['PMT'] = [
SocialCalc.Formula.InterestFunctions,
-3,
'pmt',
'',
'financial',
];
SocialCalc.Formula.FunctionList['PV'] = [
SocialCalc.Formula.InterestFunctions,
-3,
'pv',
'',
'financial',
];
SocialCalc.Formula.FunctionList['RATE'] = [
SocialCalc.Formula.InterestFunctions,
-3,
'rate',
'',
'financial',
];
FormulaMut.NPVFunction = function (fname, operand, foperand, sheet) {
var resulttypenpv, rate, sum, factor, value1;
var scf = SocialCalc.Formula;
rate = scf.OperandAsNumber(sheet, foperand);
if (scf.CheckForErrorValue(operand, rate)) return;
sum = 0;
resulttypenpv = 'n';
factor = 1;
while (foperand.length) {
value1 = scf.OperandValueAndType(sheet, foperand);
if (value1.type.charAt(0) == 'e' && resulttypenpv.charAt(0) != 'e') {
resulttypenpv = value1.type;
break;
}
if (
value1.type.charAt(0) == 'n' ||
value1.type.charAt(0) == 'b' ||
value1.type.charAt(0) == 't'
) {
factor *= 1 + rate.value;
if (factor == 0) {
scf.PushOperand(operand, 'e#DIV/0!', 0);
return;
}
var cash = value1.type.charAt(0) == 'n' ? value1.value - 0 : 0;
sum += cash / factor;
if (value1.type.charAt(0) == 'n') {
resulttypenpv = scf.LookupResultType(
value1.type,
resulttypenpv || value1.type,
scf.TypeLookupTable.plus,
);
}
}
}
if (resulttypenpv.charAt(0) == 'n') {
resulttypenpv = 'n$';
}
scf.PushOperand(operand, resulttypenpv, sum);
return;
};
SocialCalc.Formula.FunctionList['NPV'] = [
SocialCalc.Formula.NPVFunction,
-2,
'npv',
'',
'financial',
];
FormulaMut.IRRFunction = function (fname, operand, foperand, sheet) {
var value1, guess, oldsum, maxloop, tries, epsilon, rate, oldrate, m, sum, factor, i;
var rangeoperand = [];
var cashflows = [];
var hasNumericCashflow = false;
var scf = SocialCalc.Formula;
rangeoperand.push(foperand.pop());
while (rangeoperand.length) {
value1 = scf.OperandValueAndType(sheet, rangeoperand);
if (value1.type.charAt(0) == 'n') {
cashflows.push(value1.value);
hasNumericCashflow = true;
} else if (value1.type.charAt(0) == 'b' || value1.type.charAt(0) == 't') {
cashflows.push(0);
} else if (value1.type.charAt(0) == 'e') {
scf.PushOperand(operand, 'e#VALUE!', 0);
return;
}
}
if (!cashflows.length || !hasNumericCashflow) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
guess = { value: 0 };
if (foperand.length) {
guess = scf.OperandAsNumber(sheet, foperand);
if (guess.type.charAt(0) != 'n' && guess.type.charAt(0) != 'b') {
scf.PushOperand(operand, 'e#VALUE!', 0);
return;
}
if (foperand.length) {
scf.FunctionArgsError(fname, operand);
return;
}
}
guess.value = guess.value || 0.1;
maxloop = 20;
tries = 0;
epsilon = 1e-7;
rate = guess.value;
sum = 1;
while ((sum >= 0 ? sum : -sum) > epsilon && rate != oldrate) {
sum = 0;
factor = 1;
for (i = 0; i < cashflows.length; i++) {
factor *= 1 + rate;
if (factor == 0) {
scf.PushOperand(operand, 'e#DIV/0!', 0);
return;
}
sum += cashflows[i] / factor;
}
if (oldsum != null) {
m = (sum - oldsum) / (rate - oldrate);
oldrate = rate;
rate = rate - sum / m;
oldsum = sum;
} else {
oldrate = rate;
rate = 1.1 * rate;
oldsum = sum;
}
tries++;
if (tries >= maxloop) {
scf.PushOperand(operand, 'e#NUM!', 0);
return;
}
}
scf.PushOperand(operand, 'n%', rate);
return;
};
SocialCalc.Formula.FunctionList['IRR'] = [
SocialCalc.Formula.IRRFunction,
-1,
'irr',
'',
'financial',
];
FormulaMut.IoFunctions = function (fname, operand, foperand, sheet, coord) {
var argList = {
BUTTON: [2],
IMAGEBUTTON: [2],
EMAIL: [14, 14, 14, 14],
EMAILIF: [13, 14, 14, 14, 14],
EMAILONEDIT: [14, 14, 14, 14, 14],
EMAILAT: [13, 14, 14, 14, 14],
EMAILONEDITIF: [14, 13, 14, 14, 14, 14],
EMAILATIF: [13, 13, 14, 14, 14, 14],
SUBMIT: [2],
TEXTBOX: [2],
AUTOCOMPLETE: [2, 14],
SELECT: [2, 14, 1, 1],
CHECKBOX: [3],
RADIOBUTTON: [2, 2],
COPYVALUE: [4, 12, 15],
COPYFORMULA: [4, 12, 12],
INSERT: [4, 8, -12, -15],
DELETEIF: [4, 7, 8],
COMMAND: [4, 14],
COMMANDIF: [4, 13, 14],
PANEL: [15, -12],
SPLASH: [12],
STYLE: [6],
};
var i;
var parameter;
var scf = SocialCalc.Formula;
var result = 0;
var resulttype = 'e#VALUE!';
var numargs = foperand.length;
var argdef = argList[fname];
var operand_value = [];
var operand_type = [];
var repeatCount = -1;
var repeatIndex = 0;
var wantedType;
for (i = 1; i <= numargs; i++) {
if (repeatCount != -1) {
wantedType = Math.abs(argdef[repeatIndex + ((i - 1 - repeatIndex) % repeatCount)]);
} else {
if (i > argdef.length) {
scf.FunctionArgsError(fname, operand);
return;
}
wantedType = argdef[i - 1];
if (wantedType < 0) {
repeatCount = argdef.length - (i - 1);
repeatIndex = i - 1;
wantedType = Math.abs(wantedType);
}
}
if (wantedType == 1) {
parameter = scf.OperandAsNumber(sheet, foperand);
} else if (wantedType == 2) {
parameter = scf.OperandAsText(sheet, foperand);
} else if (wantedType == 3) {
parameter = scf.OperandValueAndType(sheet, foperand);
} else {
var parameterType = foperand[foperand.length - 1].type;
var validParameterType = false;
if (
(parameterType.charAt(0) == 'n' && (wantedType & 1) != 0) ||
(parameterType.charAt(0) == 't' && (wantedType & 2) != 0)
) {
validParameterType = true;
parameter = scf.OperandValueAndType(sheet, foperand);
}
if (parameterType == 'coord' && (wantedType & 4) != 0) {
validParameterType = true;
parameter = scf.OperandAsCoord(sheet, foperand);
parameter.value = SocialCalc.Formula.PlainCoord(parameter.value);
}
if (parameterType == 'range' && (wantedType & 8) != 0) {
validParameterType = true;
parameter = scf.OperandAsRange(sheet, foperand);
parameter.value = SocialCalc.Formula.PlainCoord(parameter.value);
}
if (validParameterType == false) {
scf.FunctionArgsError(fname, operand);
return;
}
}
operand_value[i] = parameter.value;
operand_type[i] = parameter.type;
if (parameter.type.charAt(0) == 'e') {
scf.PushOperand(operand, parameter.type, result);
return;
}
}
switch (fname) {
case 'STYLE':
var parameters = sheet.ioParameterList[coord];
if (parameters) {
var css = SocialCalc.Formula.getStandardizedList(sheet, {
value: operand_value[1],
type: operand_type[1],
});
if (css.length > 0) {
parameters.css = css[0];
parameters.cssParameter =
operand_type[1] == 't' ? '"' + operand_value[1] + '"' : operand_value[1];
}
result = '';
resulttype = 'ni';
}
break;
case 'SELECT':
var parameters = sheet.ioParameterList[coord];
var optionSource = SocialCalc.Formula.getStandardizedList(sheet, parameters[1]);
parameters.html = [];
parameters.html[0] = operand_value[4] == true ? 'multiple' : '';
parameters.html[1] = operand_value[3] ? '' + operand_value[3] : '1';
if (optionSource.length > 0) {
var options = '';
var optionRegExp = new RegExp('';
}
return str;
};
SpreadsheetControlSC.SpreadsheetControl.FillFunctionNames = function (cname, ele) {
var i, f;
var scf = SocialCalc.Formula;
ele.length = 0;
f = scf.FunctionClasses[cname];
for (i = 0; i < f.items.length; i++) {
ele.options[i] = new Option(f.items[i], f.items[i]);
if (i == 0) {
ele.options[i].selected = true;
}
}
};
SpreadsheetControlSC.SpreadsheetControl.GetFunctionInfoStr = function (fname) {
var scf = SocialCalc.Formula;
var f = scf.FunctionList[fname];
var scsc = SocialCalc.special_chars;
var str = '' + fname + '(' + scsc(scf.FunctionArgString(fname)) + ')
';
str += scsc(f[3]);
return str;
};
SpreadsheetControlSC.SpreadsheetControl.FunctionClassChosen = function (cname) {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var idp = spreadsheet.idPrefix + 'function';
var scf = SocialCalc.Formula;
SpreadsheetControlSC.SpreadsheetControl.FillFunctionNames(
cname,
document.getElementById(idp + 'name'),
);
SpreadsheetControlSC.SpreadsheetControl.FunctionChosen(scf.FunctionClasses[cname].items[0]);
};
SpreadsheetControlSC.SpreadsheetControl.FunctionChosen = function (fname) {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var idp = spreadsheet.idPrefix + 'function';
document.getElementById(idp + 'desc').innerHTML =
SpreadsheetControlSC.SpreadsheetControl.GetFunctionInfoStr(fname);
};
SpreadsheetControlSC.SpreadsheetControl.HideFunctions = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var ele = document.getElementById(spreadsheet.idPrefix + 'functiondialog');
ele.innerHTML = '';
SocialCalc.DragUnregister(ele);
SocialCalc.KeyboardFocus();
if (ele.parentNode) {
ele.parentNode.removeChild(ele);
}
};
SpreadsheetControlSC.SpreadsheetControl.DoFunctionPaste = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var ele = document.getElementById(spreadsheet.idPrefix + 'functionname');
var mele = document.getElementById(spreadsheet.idPrefix + 'multilinetextarea');
var text = ele.value + '(';
SpreadsheetControlSC.SpreadsheetControl.HideFunctions();
if (mele) {
mele.value += text;
mele.focus();
SocialCalc.CmdGotFocus(mele);
} else {
editor.EditorAddToInput(text, '=');
}
};
SpreadsheetControlSC.SpreadsheetControl.DoMultiline = function () {
var SCLocSS = SocialCalc.LocalizeSubstrings;
var str, ele, text;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var wval = editor.workingvalues;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var idp = spreadsheet.idPrefix + 'multiline';
ele = document.getElementById(idp + 'dialog');
if (ele) return;
switch (editor.state) {
case 'start':
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
editor.RangeRemove();
text = SocialCalc.GetCellContents(editor.context.sheetobj, wval.ecoord);
break;
case 'input':
case 'inputboxdirect':
text = editor.inputBox.GetText();
break;
}
editor.inputBox.element.disabled = true;
text = SocialCalc.special_chars(text);
str =
'' +
'' +
SCLocSS(
' ' +
' ' +
'
' +
'',
);
var main = SocialCalc.document.createElement('div');
main.id = idp + 'dialog';
main.style.position = 'absolute';
var vp = SocialCalc.GetViewportInfo();
var pos = SocialCalc.GetElementPositionWithScroll(spreadsheet.spreadsheetDiv);
main.style.top = vp.height / 3 - pos.top + 'px';
main.style.left = vp.width / 3 - pos.left + 'px';
main.style.zIndex = '100';
main.style.backgroundColor = '#FFF';
main.style.border = '1px solid black';
main.style.width = '400px';
main.innerHTML =
'' +
'| ' +
SCLocSS(' %loc!Multi-line Input Box!') +
' | ' +
' X |
' +
'' +
str +
'
';
SocialCalc.DragRegister(
main.firstChild.firstChild.firstChild,
true,
true,
{
MouseDown: SocialCalc.DragFunctionStart,
MouseMove: SocialCalc.DragFunctionPosition,
MouseUp: SocialCalc.DragFunctionPosition,
Disabled: null,
positionobj: main,
},
spreadsheet.spreadsheetDiv,
);
spreadsheet.spreadsheetDiv.appendChild(main);
ele = document.getElementById(idp + 'textarea');
ele.focus();
SocialCalc.CmdGotFocus(ele);
};
SpreadsheetControlSC.SpreadsheetControl.HideMultiline = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var ele = document.getElementById(spreadsheet.idPrefix + 'multilinedialog');
ele.innerHTML = '';
SocialCalc.DragUnregister(ele);
SocialCalc.KeyboardFocus();
if (ele.parentNode) {
ele.parentNode.removeChild(ele);
}
switch (editor.state) {
case 'start':
editor.inputBox.DisplayCellContents(null);
break;
case 'input':
case 'inputboxdirect':
editor.inputBox.element.disabled = false;
editor.inputBox.Focus();
break;
}
};
SpreadsheetControlSC.SpreadsheetControl.DoMultilineClear = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var ele = document.getElementById(spreadsheet.idPrefix + 'multilinetextarea');
ele.value = '';
ele.focus();
};
SpreadsheetControlSC.SpreadsheetControl.DoMultilinePaste = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var wval = editor.workingvalues;
var ele = document.getElementById(spreadsheet.idPrefix + 'multilinetextarea');
var text = ele.value;
SpreadsheetControlSC.SpreadsheetControl.HideMultiline();
switch (editor.state) {
case 'start':
wval.partialexpr = '';
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
break;
case 'input':
case 'inputboxdirect':
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
break;
}
editor.EditorSaveEdit(text);
};
SpreadsheetControlSC.SpreadsheetControl.DoLink = function () {
var SCLoc = SocialCalc.LocalizeString;
var str, ele, text, cell, setformat, popup;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var wval = editor.workingvalues;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var idp = spreadsheet.idPrefix + 'link';
ele = document.getElementById(idp + 'dialog');
if (ele) return;
switch (editor.state) {
case 'start':
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
editor.RangeRemove();
text = SocialCalc.GetCellContents(editor.context.sheetobj, wval.ecoord);
break;
case 'input':
case 'inputboxdirect':
text = editor.inputBox.GetText();
break;
}
editor.inputBox.element.disabled = true;
if (text.charAt(0) == "'") {
text = text.slice(1);
}
var parts = SocialCalc.ParseCellLinkText(text);
text = SocialCalc.special_chars(text);
cell = spreadsheet.sheet.cells[editor.ecell.coord];
setformat = !cell || !cell.textvalueformat ? ' checked' : '';
popup = parts.newwin ? ' checked' : '';
str =
'' +
'' +
SCLoc('Description') +
'
' +
'
' +
'' +
SCLoc('URL') +
'
' +
'
';
if (SocialCalc.Callbacks.MakePageLink) {
str +=
'' +
SCLoc('Page Name') +
'
' +
'
' +
'' +
SCLoc('Workspace') +
'
' +
'
';
}
str += SocialCalc.LocalizeSubstrings(
' ' +
'%loc!Set to Link format!
' +
' ' +
'%loc!Show in new browser window!' +
'
' +
'' +
' ' +
' ' +
'
' +
'',
);
var main = SocialCalc.document.createElement('div');
main.id = idp + 'dialog';
main.style.position = 'absolute';
var vp = SocialCalc.GetViewportInfo();
var pos = SocialCalc.GetElementPositionWithScroll(spreadsheet.spreadsheetDiv);
main.style.top = vp.height / 3 - pos.top + 'px';
main.style.left = vp.width / 3 - pos.left + 'px';
main.style.zIndex = '100';
main.style.backgroundColor = '#FFF';
main.style.border = '1px solid black';
main.style.width = '400px';
main.innerHTML =
'' +
'| ' +
' ' +
SCLoc('Link Input Box') +
' | ' +
' X |
' +
'' +
str +
'
';
SocialCalc.DragRegister(
main.firstChild.firstChild.firstChild,
true,
true,
{
MouseDown: SocialCalc.DragFunctionStart,
MouseMove: SocialCalc.DragFunctionPosition,
MouseUp: SocialCalc.DragFunctionPosition,
Disabled: null,
positionobj: main,
},
spreadsheet.spreadsheetDiv,
);
spreadsheet.spreadsheetDiv.appendChild(main);
ele = document.getElementById(idp + 'url');
ele.focus();
SocialCalc.CmdGotFocus(ele);
};
SpreadsheetControlSC.SpreadsheetControl.HideLink = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var ele = document.getElementById(spreadsheet.idPrefix + 'linkdialog');
ele.innerHTML = '';
SocialCalc.DragUnregister(ele);
SocialCalc.KeyboardFocus();
if (ele.parentNode) {
ele.parentNode.removeChild(ele);
}
switch (editor.state) {
case 'start':
editor.inputBox.DisplayCellContents(null);
break;
case 'input':
case 'inputboxdirect':
editor.inputBox.element.disabled = false;
editor.inputBox.Focus();
break;
}
};
SpreadsheetControlSC.SpreadsheetControl.DoLinkClear = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
document.getElementById(spreadsheet.idPrefix + 'linkdesc').value = '';
document.getElementById(spreadsheet.idPrefix + 'linkpagename').value = '';
document.getElementById(spreadsheet.idPrefix + 'linkworkspace').value = '';
var ele = document.getElementById(spreadsheet.idPrefix + 'linkurl');
ele.value = '';
ele.focus();
};
SpreadsheetControlSC.SpreadsheetControl.DoLinkPaste = function () {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var wval = editor.workingvalues;
var descele = document.getElementById(spreadsheet.idPrefix + 'linkdesc');
var urlele = document.getElementById(spreadsheet.idPrefix + 'linkurl');
var pagenameele = document.getElementById(spreadsheet.idPrefix + 'linkpagename');
var workspaceele = document.getElementById(spreadsheet.idPrefix + 'linkworkspace');
var formatele = document.getElementById(spreadsheet.idPrefix + 'linkformat');
var popupele = document.getElementById(spreadsheet.idPrefix + 'linkpopup');
var text = '';
var ltsym, gtsym, obsym, cbsym;
if (popupele.checked) {
ltsym = '<<';
gtsym = '>>';
obsym = '[[';
cbsym = ']]';
} else {
ltsym = '<';
gtsym = '>';
obsym = '[';
cbsym = ']';
}
if (pagenameele && pagenameele.value) {
if (workspaceele.value) {
text = descele.value + '{' + workspaceele.value + obsym + pagenameele.value + cbsym + '}';
} else {
text = descele.value + obsym + pagenameele.value + cbsym;
}
} else {
text = descele.value + ltsym + urlele.value + gtsym;
}
SpreadsheetControlSC.SpreadsheetControl.HideLink();
switch (editor.state) {
case 'start':
wval.partialexpr = '';
wval.ecoord = editor.ecell.coord;
wval.erow = editor.ecell.row;
wval.ecol = editor.ecell.col;
break;
case 'input':
case 'inputboxdirect':
editor.inputBox.Blur();
editor.inputBox.ShowInputBox(false);
editor.state = 'start';
break;
}
if (formatele.checked) {
SocialCalc.SpreadsheetControlExecuteCommand(null, 'set %C textvalueformat text-link', '');
}
editor.EditorSaveEdit(text);
};
SpreadsheetControlSC.SpreadsheetControl.DoSum = function () {
var cmd, cell, row, col, sel, cr, foundvalue;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var editor = spreadsheet.editor;
var sheet = editor.context.sheetobj;
if (editor.range.hasrange) {
sel =
SocialCalc.crToCoord(editor.range.left, editor.range.top) +
':' +
SocialCalc.crToCoord(editor.range.right, editor.range.bottom);
cmd =
'set ' +
SocialCalc.crToCoord(editor.range.right, editor.range.bottom + 1) +
' formula sum(' +
sel +
')';
} else {
row = editor.ecell.row - 1;
col = editor.ecell.col;
if (row <= 1) {
cmd = 'set ' + editor.ecell.coord + ' constant e#REF! 0 #REF!';
} else {
foundvalue = false;
while (row > 0) {
cr = SocialCalc.crToCoord(col, row);
cell = sheet.GetAssuredCell(cr);
if (!cell.datatype || cell.datatype == 't') {
if (foundvalue) {
row++;
break;
}
} else {
foundvalue = true;
}
row--;
}
cmd =
'set ' +
editor.ecell.coord +
' formula sum(' +
SocialCalc.crToCoord(col, row) +
':' +
SocialCalc.crToCoord(col, editor.ecell.row - 1) +
')';
}
}
editor.EditorScheduleSheetCommands(cmd, true, false);
};
SpreadsheetControlSC.SpreadsheetControl.FindInSheet = function () {
var searchstatus = $('#searchstatus');
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
if (!this.value.length) {
searchstatus.text('');
spreadsheet.sheet.search_cells = [];
spreadsheet.sheet.selected_search_cell = undefined;
return;
}
var cells = spreadsheet.sheet.cells;
var regex = new RegExp(this.value, 'im');
var cell, cellvalue;
var search_cells = [];
for (var cell_id in cells) {
cell = cells[cell_id];
var cr = SocialCalc.coordToCr(cell_id);
if (
spreadsheet.sheet.rowattribs.hide[cr.row] === 'yes' ||
spreadsheet.sheet.colattribs.hide[SocialCalc.rcColname(cr.col)] === 'yes'
) {
continue;
}
if (cell.datatype === 'c') {
cellvalue = cell.displaystring;
} else {
cellvalue = String(cell.datavalue);
}
if (cellvalue !== undefined && cellvalue.match(regex)) {
search_cells.push(cell_id);
}
}
spreadsheet.sheet.search_cells = search_cells;
if (search_cells.length) {
spreadsheet.sheet.selected_search_cell = 0;
spreadsheet.editor.MoveECell(search_cells[0]);
searchstatus.text('1 of ' + search_cells.length);
} else {
spreadsheet.sheet.selected_search_cell = undefined;
searchstatus.text('No Matches');
}
};
SpreadsheetControlSC.SpreadsheetControl.SearchSheet = function (direction) {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var sheet = spreadsheet.sheet;
var cells = sheet.search_cells;
if (!cells.length) {
return;
}
var selected_cell = sheet.selected_search_cell;
if (selected_cell === (direction === 0 ? 0 : cells.length - 1)) {
selected_cell = direction === 0 ? cells.length - 1 : 0;
} else {
selected_cell += direction === 0 ? -1 : 1;
}
var new_cell = cells[selected_cell];
sheet.selected_search_cell = selected_cell;
spreadsheet.editor.MoveECell(new_cell);
document.getElementById('searchstatus').textContent =
String(selected_cell + 1) + ' of ' + cells.length;
};
SpreadsheetControlSC.SpreadsheetControl.SearchUp = function () {
SpreadsheetControlSC.SpreadsheetControl.SearchSheet(0);
};
SpreadsheetControlSC.SpreadsheetControl.SearchDown = function () {
SpreadsheetControlSC.SpreadsheetControl.SearchSheet(1);
};
SpreadsheetControlSC.SpreadsheetControlSortOnclick = function (s, _t) {
var name, i;
var namelist = [];
var nl = document.getElementById(s.idPrefix + 'sortlist');
SocialCalc.LoadColumnChoosers(s);
s.editor.RangeChangeCallback.sort = SocialCalc.UpdateSortRangeProposal;
for (name in s.sheet.names) {
namelist.push(name);
}
namelist.sort();
nl.length = 0;
nl.options[0] = new Option(SocialCalc.LocalizeString('[select range]'));
nl.options[1] = new Option(SocialCalc.LocalizeString('Sort All'), 'all');
var n_options = nl.options.length;
for (i = 0; i < namelist.length; i++) {
name = namelist[i];
nl.options[i + n_options] = new Option(name, name);
if (name == s.sortrange) {
nl.options[i + n_options].selected = true;
}
}
if (s.sortrange == '') {
nl.options[0].selected = true;
}
SocialCalc.UpdateSortRangeProposal(s.editor);
SocialCalc.KeyboardFocus();
return;
};
SpreadsheetControlSC.SpreadsheetControlSortSave = function (_editor, _setting) {
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
var str, sele, rele;
str = 'sort:' + SocialCalc.encodeForSave(spreadsheet.sortrange) + ':';
sele = document.getElementById(spreadsheet.idPrefix + 'majorsort');
rele = document.getElementById(spreadsheet.idPrefix + 'majorsortup');
str += sele.selectedIndex + (rele.checked ? ':up' : ':down');
sele = document.getElementById(spreadsheet.idPrefix + 'minorsort');
if (sele.selectedIndex > 0) {
rele = document.getElementById(spreadsheet.idPrefix + 'minorsortup');
str += ':' + sele.selectedIndex + (rele.checked ? ':up' : ':down');
} else {
str += '::';
}
sele = document.getElementById(spreadsheet.idPrefix + 'lastsort');
if (sele.selectedIndex > 0) {
rele = document.getElementById(spreadsheet.idPrefix + 'lastsortup');
str += ':' + sele.selectedIndex + (rele.checked ? ':up' : ':down');
} else {
str += '::';
}
return str + '\n';
};
SpreadsheetControlSC.SpreadsheetControlSortLoad = function (_editor, _setting, line, _flags) {
var parts;
var ele;
var sele;
var spreadsheet = SocialCalc.GetSpreadsheetControlObject();
parts = line.split(':');
spreadsheet.sortrange = SocialCalc.decodeFromSave(parts[1]);
ele = document.getElementById(spreadsheet.idPrefix + 'sortbutton');
if (spreadsheet.sortrange) {
ele.value = SocialCalc.LocalizeString('Sort ') + spreadsheet.sortrange;
ele.style.visibility = 'visible';
} else {
ele.style.visibility = 'hidden';
}
SocialCalc.LoadColumnChoosers(spreadsheet);
sele = document.getElementById(spreadsheet.idPrefix + 'majorsort');
sele.selectedIndex = parts[2] - 0;
document.getElementById(spreadsheet.idPrefix + 'majorsort' + parts[3]).checked = true;
sele = document.getElementById(spreadsheet.idPrefix + 'minorsort');
if (parts[4]) {
sele.selectedIndex = parts[4] - 0;
document.getElementById(spreadsheet.idPrefix + 'minorsort' + parts[5]).checked = true;
} else {
sele.selectedIndex = 0;
document.getElementById(spreadsheet.idPrefix + 'minorsortup').checked = true;
}
sele = document.getElementById(spreadsheet.idPrefix + 'lastsort');
if (parts[6]) {
sele.selectedIndex = parts[6] - 0;
document.getElementById(spreadsheet.idPrefix + 'lastsort' + parts[7]).checked = true;
} else {
sele.selectedIndex = 0;
document.getElementById(spreadsheet.idPrefix + 'lastsortup').checked = true;
}
return true;
};
SpreadsheetControlSC.SpreadsheetControlCommentOnclick = function (s, t) {
s.editor.MoveECellCallback.comment = SocialCalc.SpreadsheetControlCommentMoveECell;
SocialCalc.SpreadsheetControlCommentDisplay(s, t);
SocialCalc.KeyboardFocus();
return;
};
SpreadsheetControlSC.SpreadsheetControlCommentDisplay = function (s, _t) {
var c = '';
if (s.editor.ecell && s.editor.ecell.coord && s.sheet.cells[s.editor.ecell.coord]) {
c = s.sheet.cells[s.editor.ecell.coord].comment || '';
}
document.getElementById(s.idPrefix + 'commenttext').value = c;
};
SpreadsheetControlSC.SpreadsheetControlCommentMoveECell = function (_editor) {
SocialCalc.SpreadsheetControlCommentDisplay(
SocialCalc.GetSpreadsheetControlObject(),
'comment',
);
};
SpreadsheetControlSC.SpreadsheetControlCommentSet = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
s.ExecuteCommand(
'set %C comment ' +
SocialCalc.encodeForSave(document.getElementById(s.idPrefix + 'commenttext').value),
);
var cell = SocialCalc.GetEditorCellElement(s.editor, s.editor.ecell.row, s.editor.ecell.col);
if (!s.editor.ECellReadonly()) {
cell.element.title = document.getElementById(s.idPrefix + 'commenttext').value;
s.editor.UpdateCellCSS(cell, s.editor.ecell.row, s.editor.ecell.col);
}
SocialCalc.KeyboardFocus();
};
SpreadsheetControlSC.SpreadsheetControlCommentOnunclick = function (s, _t) {
delete s.editor.MoveECellCallback.comment;
};
SpreadsheetControlSC.SpreadsheetControlNamesOnclick = function (s, _t) {
document.getElementById(s.idPrefix + 'namesname').value = '';
document.getElementById(s.idPrefix + 'namesdesc').value = '';
document.getElementById(s.idPrefix + 'namesvalue').value = '';
s.editor.RangeChangeCallback.names = SocialCalc.SpreadsheetControlNamesRangeChange;
s.editor.MoveECellCallback.names = SocialCalc.SpreadsheetControlNamesRangeChange;
SocialCalc.SpreadsheetControlNamesRangeChange(s.editor);
SocialCalc.SpreadsheetControlNamesFillNameList();
SocialCalc.SpreadsheetControlNamesChangedName();
};
SpreadsheetControlSC.SpreadsheetControlNamesFillNameList = function () {
var SCLoc = SocialCalc.LocalizeString;
var name, i;
var namelist = [];
var s = SocialCalc.GetSpreadsheetControlObject();
var nl = document.getElementById(s.idPrefix + 'nameslist');
var currentname = document
.getElementById(s.idPrefix + 'namesname')
.value.toUpperCase()
.replace(/[^A-Z0-9_.]/g, '');
for (name in s.sheet.names) {
namelist.push(name);
}
namelist.sort();
nl.length = 0;
if (namelist.length > 0) {
nl.options[0] = new Option(SCLoc('[New]'));
} else {
nl.options[0] = new Option(SCLoc('[None]'));
}
for (i = 0; i < namelist.length; i++) {
name = namelist[i];
nl.options[i + 1] = new Option(name, name);
if (name == currentname) {
nl.options[i + 1].selected = true;
}
}
if (currentname == '') {
nl.options[0].selected = true;
}
};
SpreadsheetControlSC.SpreadsheetControlNamesChangedName = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
var nl = document.getElementById(s.idPrefix + 'nameslist');
var name = nl.options[nl.selectedIndex].value;
if (s.sheet.names[name]) {
document.getElementById(s.idPrefix + 'namesname').value = name;
document.getElementById(s.idPrefix + 'namesdesc').value = s.sheet.names[name].desc || '';
document.getElementById(s.idPrefix + 'namesvalue').value =
s.sheet.names[name].definition || '';
} else {
document.getElementById(s.idPrefix + 'namesname').value = '';
document.getElementById(s.idPrefix + 'namesdesc').value = '';
document.getElementById(s.idPrefix + 'namesvalue').value = '';
}
};
SpreadsheetControlSC.SpreadsheetControlNamesRangeChange = function (editor) {
var s = SocialCalc.GetSpreadsheetControlObject();
var ele = document.getElementById(s.idPrefix + 'namesrangeproposal');
if (editor.range.hasrange) {
ele.value =
SocialCalc.crToCoord(editor.range.left, editor.range.top) +
':' +
SocialCalc.crToCoord(editor.range.right, editor.range.bottom);
} else {
ele.value = editor.ecell.coord;
}
};
SpreadsheetControlSC.SpreadsheetControlNamesOnunclick = function (s, _t) {
delete s.editor.RangeChangeCallback.names;
delete s.editor.MoveECellCallback.names;
};
SpreadsheetControlSC.SpreadsheetControlNamesSetValue = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
document.getElementById(s.idPrefix + 'namesvalue').value = document.getElementById(
s.idPrefix + 'namesrangeproposal',
).value;
SocialCalc.KeyboardFocus();
};
SpreadsheetControlSC.SpreadsheetControlNamesSave = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
var name = document.getElementById(s.idPrefix + 'namesname').value;
SocialCalc.SetTab(s.tabs[0].name);
SocialCalc.KeyboardFocus();
if (name != '') {
s.ExecuteCommand(
'name define ' +
name +
' ' +
document.getElementById(s.idPrefix + 'namesvalue').value +
'\n' +
'name desc ' +
name +
' ' +
document.getElementById(s.idPrefix + 'namesdesc').value,
);
}
};
SpreadsheetControlSC.SpreadsheetControlNamesDelete = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
var name = document.getElementById(s.idPrefix + 'namesname').value;
SocialCalc.SetTab(s.tabs[0].name);
SocialCalc.KeyboardFocus();
if (name != '') {
s.ExecuteCommand('name delete ' + name);
}
SocialCalc.KeyboardFocus();
};
SpreadsheetControlSC.SpreadsheetControlClipboardOnclick = function (s, _t) {
s = SocialCalc.GetSpreadsheetControlObject();
var clipele = document.getElementById(s.idPrefix + 'clipboardtext');
document.getElementById(s.idPrefix + 'clipboardformat-tab').checked = true;
try {
clipele.value = SocialCalc.ConvertSaveToOtherFormat(
SpreadsheetControlSC.Clipboard.clipboard,
'tab',
);
} catch (err) {
console.error(err);
}
return;
};
SpreadsheetControlSC.SpreadsheetControlClipboardFormat = function (which) {
var s = SocialCalc.GetSpreadsheetControlObject();
var clipele = document.getElementById(s.idPrefix + 'clipboardtext');
clipele.value = SocialCalc.ConvertSaveToOtherFormat(
SpreadsheetControlSC.Clipboard.clipboard,
which,
);
};
SpreadsheetControlSC.SpreadsheetControlClipboardLoad = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
var savetype = 'tab';
SocialCalc.SetTab(s.tabs[0].name);
SocialCalc.KeyboardFocus();
if (document.getElementById(s.idPrefix + 'clipboardformat-csv').checked) {
savetype = 'csv';
} else if (document.getElementById(s.idPrefix + 'clipboardformat-scsave').checked) {
savetype = 'scsave';
}
s.editor.pastescclipboard = true;
s.editor.EditorScheduleSheetCommands(
'loadclipboard ' +
SocialCalc.encodeForSave(
SocialCalc.ConvertOtherFormatToSave(
document.getElementById(s.idPrefix + 'clipboardtext').value,
savetype,
),
),
true,
false,
);
};
SpreadsheetControlSC.SpreadsheetControlClipboardClear = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
var clipele = document.getElementById(s.idPrefix + 'clipboardtext');
clipele.value = '';
s.editor.EditorScheduleSheetCommands('clearclipboard', true, false);
clipele.focus();
};
SpreadsheetControlSC.SpreadsheetControlClipboardExport = function () {
var s = SocialCalc.GetSpreadsheetControlObject();
if (s.ExportCallback) {
s.ExportCallback(s);
}
SocialCalc.SetTab(s.tabs[0].name);
SocialCalc.KeyboardFocus();
};
SpreadsheetControlSC.SpreadsheetControlSettingsSwitch = function (target) {
SocialCalc.SettingControlReset();
var s = SocialCalc.GetSpreadsheetControlObject();
var sheettable = document.getElementById(s.idPrefix + 'sheetsettingstable');
var celltable = document.getElementById(s.idPrefix + 'cellsettingstable');
var sheettoolbar = document.getElementById(s.idPrefix + 'sheetsettingstoolbar');
var celltoolbar = document.getElementById(s.idPrefix + 'cellsettingstoolbar');
if (target == 'sheet') {
sheettable.style.display = 'block';
celltable.style.display = 'none';
sheettoolbar.style.display = 'block';
celltoolbar.style.display = 'none';
SocialCalc.SettingsControlSetCurrentPanel(s.views.settings.values.sheetspanel);
} else {
sheettable.style.display = 'none';
celltable.style.display = 'block';
sheettoolbar.style.display = 'none';
celltoolbar.style.display = 'block';
SocialCalc.SettingsControlSetCurrentPanel(s.views.settings.values.cellspanel);
}
};
SpreadsheetControlSC.SettingsControlSave = function (target) {
var range, cmdstr;
var s = SocialCalc.GetSpreadsheetControlObject();
var sc = SocialCalc.SettingsControls;
var panelobj = sc.CurrentPanel;
var attribs = SocialCalc.SettingsControlUnloadPanel(panelobj);
SocialCalc.SetTab(s.tabs[0].name);
SocialCalc.KeyboardFocus();
if (target == 'sheet') {
cmdstr = s.sheet.DecodeSheetAttributes(attribs);
} else if (target == 'cell') {
if (s.editor.range.hasrange) {
range =
SocialCalc.crToCoord(s.editor.range.left, s.editor.range.top) +
':' +
SocialCalc.crToCoord(s.editor.range.right, s.editor.range.bottom);
}
cmdstr = s.sheet.DecodeCellAttributes(s.editor.ecell.coord, attribs, range);
} else {
}
if (cmdstr) {
s.editor.EditorScheduleSheetCommands(cmdstr, true, false);
}
};
SpreadsheetControlSC.SpreadsheetControlCreateSpreadsheetSave = function (
spreadsheet,
otherparts,
) {
var result;
var otherpartsstr = '';
var otherpartsnames = '';
var partname, extranl;
if (otherparts) {
for (partname in otherparts) {
if (otherparts[partname].charAt(otherparts[partname].length - 1) != '\n') {
extranl = '\n';
} else {
extranl = '';
}
otherpartsstr +=
'--' +
spreadsheet.multipartBoundary +
'\nContent-type: text/plain; charset=UTF-8\n\n' +
otherparts[partname] +
extranl;
otherpartsnames += 'part:' + partname + '\n';
}
}
result =
'socialcalc:version:1.0\n' +
'MIME-Version: 1.0\nContent-Type: multipart/mixed; boundary=' +
spreadsheet.multipartBoundary +
'\n' +
'--' +
spreadsheet.multipartBoundary +
'\nContent-type: text/plain; charset=UTF-8\n\n' +
'# SocialCalc Spreadsheet Control Save\nversion:1.0\npart:sheet\npart:edit\npart:audit\n' +
otherpartsnames +
'--' +
spreadsheet.multipartBoundary +
'\nContent-type: text/plain; charset=UTF-8\n\n' +
spreadsheet.CreateSheetSave() +
'--' +
spreadsheet.multipartBoundary +
'\nContent-type: text/plain; charset=UTF-8\n\n' +
spreadsheet.editor.SaveEditorSettings() +
'--' +
spreadsheet.multipartBoundary +
'\nContent-type: text/plain; charset=UTF-8\n\n' +
spreadsheet.sheet.CreateAuditString() +
otherpartsstr +
'--' +
spreadsheet.multipartBoundary +
'--\n';
return result;
};
SpreadsheetControlSC.SpreadsheetControlDecodeSpreadsheetSave = function (spreadsheet, str) {
var pos1,
mpregex,
searchinfo,
boundary,
boundaryregex,
blanklineregex,
start,
ending,
lines,
i,
line,
p,
pnum;
var parts = {};
var partlist = [];
pos1 = str.search(/^MIME-Version:\s1\.0/im);
if (pos1 < 0) return parts;
mpregex = /^Content-Type:\s*multipart\/mixed;\s*boundary=(\S+)/gim;
mpregex.lastIndex = pos1;
searchinfo = mpregex.exec(str);
if (!searchinfo || mpregex.lastIndex <= 0) return parts;
boundary = searchinfo[1];
boundaryregex = new RegExp('^--' + boundary + '(?:\r\n|\n)', 'mg');
boundaryregex.lastIndex = mpregex.lastIndex;
searchinfo = boundaryregex.exec(str);
blanklineregex = /(?:\r\n|\n)(?:\r\n|\n)/gm;
blanklineregex.lastIndex = boundaryregex.lastIndex;
searchinfo = blanklineregex.exec(str);
if (!searchinfo) return parts;
start = blanklineregex.lastIndex;
boundaryregex.lastIndex = start;
searchinfo = boundaryregex.exec(str);
if (!searchinfo) return parts;
ending = searchinfo.index;
lines = str.substring(start, ending).split(/\r\n|\n/);
for (i = 0; i < lines.length; i++) {
line = lines[i];
p = line.split(':');
switch (p[0]) {
case 'version':
break;
case 'part':
partlist.push(p[1]);
break;
}
}
for (pnum = 0; pnum < partlist.length; pnum++) {
blanklineregex.lastIndex = ending;
searchinfo = blanklineregex.exec(str);
if (!searchinfo) return parts;
start = blanklineregex.lastIndex;
if (pnum == partlist.length - 1) {
boundaryregex = new RegExp('^--' + boundary + '--$', 'mg');
}
boundaryregex.lastIndex = start;
searchinfo = boundaryregex.exec(str);
if (!searchinfo) return parts;
ending = searchinfo.index;
parts[partlist[pnum]] = {
start,
end: ending,
};
}
return parts;
};
SpreadsheetControlSC.SettingsControls = {
Controls: {},
CurrentPanel: null,
};
SpreadsheetControlSC.SettingsControlSetCurrentPanel = function (panelobj) {
SpreadsheetControlSC.SettingsControls.CurrentPanel = panelobj;
SpreadsheetControlSC.SettingsControls.PopupChangeCallback({ panelobj }, '', null);
};
SpreadsheetControlSC.SettingsControlInitializePanel = function (panelobj) {
var ctrlname, ctrl;
var sc = SocialCalc.SettingsControls;
for (ctrlname in panelobj) {
if (ctrlname == 'name') continue;
ctrl = sc.Controls[panelobj[ctrlname].type];
if (ctrl && ctrl.Initialize) ctrl.Initialize(panelobj, ctrlname);
}
};
SpreadsheetControlSC.SettingsControlLoadPanel = function (panelobj, attribs) {
var ctrlname, ctrl;
var sc = SocialCalc.SettingsControls;
for (ctrlname in panelobj) {
if (ctrlname == 'name') continue;
ctrl = sc.Controls[panelobj[ctrlname].type];
if (ctrl && ctrl.SetValue)
ctrl.SetValue(panelobj, ctrlname, attribs[panelobj[ctrlname].setting]);
}
};
SpreadsheetControlSC.SettingsControlUnloadPanel = function (panelobj) {
var ctrlname, ctrl;
var sc = SocialCalc.SettingsControls;
var attribs = {};
for (ctrlname in panelobj) {
if (ctrlname == 'name') continue;
ctrl = sc.Controls[panelobj[ctrlname].type];
if (ctrl && ctrl.GetValue)
attribs[panelobj[ctrlname].setting] = ctrl.GetValue(panelobj, ctrlname);
}
return attribs;
};
SpreadsheetControlSC.SettingsControls.PopupChangeCallback = function (attribs, _id, _value) {
var sc = SocialCalc.Constants;
var ele = document.getElementById('sample-text');
if (!ele || !attribs || !attribs.panelobj) return;
var idPrefix = SocialCalc.CurrentSpreadsheetControlObject.idPrefix;
var c = attribs.panelobj.name == 'cell' ? 'c' : '';
var v, a, parts, str1, str2;
parts =
sc.defaultCellLayout.match(/^padding.(\S+) (\S+) (\S+) (\S+).vertical.align.(\S+);$/) || [];
var cv = {
color: ['textcolor'],
backgroundColor: ['bgcolor', '#FFF'],
fontSize: ['fontsize', sc.defaultCellFontSize],
fontFamily: ['fontfamily'],
paddingTop: ['padtop', parts[1]],
paddingRight: ['padright', parts[2]],
paddingBottom: ['padbottom', parts[3]],
paddingLeft: ['padleft', parts[4]],
verticalAlign: ['alignvert', parts[5]],
};
for (a in cv) {
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + c + cv[a][0]) || cv[a][1] || '';
ele.style[a] = v;
}
if (c == 'c') {
cv = {
borderTop: 'cbt',
borderRight: 'cbr',
borderBottom: 'cbb',
borderLeft: 'cbl',
};
for (a in cv) {
v = SpreadsheetControlSC.SettingsControls.BorderSideGetValue(attribs.panelobj, cv[a]);
ele.style[a] = v ? v.val || '' : '';
}
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + 'calignhoriz');
ele.style.textAlign = v || 'left';
ele.childNodes[1].style.textAlign = v || 'right';
} else {
ele.style.border = '';
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + 'textalignhoriz');
ele.style.textAlign = v || 'left';
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + 'numberalignhoriz');
ele.childNodes[1].style.textAlign = v || 'right';
}
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + c + 'fontlook');
parts = v ? v.match(/^(\S+) (\S+)$/) || [] : [];
ele.style.fontStyle = parts[1] || '';
ele.style.fontWeight = parts[2] || '';
v = SpreadsheetControlSC.Popup.GetValue(idPrefix + c + 'formatnumber') || 'General';
str1 = SocialCalc.FormatNumber.formatNumberWithFormat(9.8765, v, '');
str2 = SocialCalc.FormatNumber.formatNumberWithFormat(-1234.5, v, '');
if (str2 != '??-???-?? ??:??:??') {
str1 += '
' + str2;
}
ele.childNodes[1].innerHTML = str1;
};
SpreadsheetControlSC.SettingsControls.PopupListSetValue = function (panelobj, ctrlname, value) {
if (!value) {
(function(){})(ctrlname + ' no value');
return;
}
var sp = SocialCalc.Popup;
if (!value.def) {
sp.SetValue(panelobj[ctrlname].id, value.val);
} else {
sp.SetValue(panelobj[ctrlname].id, '');
}
};
SpreadsheetControlSC.SettingsControls.PopupListGetValue = function (panelobj, ctrlname) {
var ctl = panelobj[ctrlname];
if (!ctl) return null;
var value = SpreadsheetControlSC.Popup.GetValue(ctl.id);
if (value) {
return {
def: false,
val: value,
};
} else {
return {
def: true,
val: 0,
};
}
};
SpreadsheetControlSC.SettingsControls.PopupListInitialize = function (panelobj, ctrlname) {
var i, val, pos, otext;
var sc = SocialCalc.SettingsControls;
var initialdata =
panelobj[ctrlname].initialdata || sc.Controls[panelobj[ctrlname].type].InitialData || '';
initialdata = SocialCalc.LocalizeSubstrings(initialdata);
var optionvals = initialdata.split(/\|/);
var options = [];
for (i = 0; i < optionvals.length; i++) {
val = optionvals[i];
pos = val.indexOf(':');
otext = val.substring(0, pos);
if (otext.indexOf('\\') != -1) {
otext = otext.replace(/\\c/g, ':');
otext = otext.replace(/\\b/g, '\\');
}
otext = SocialCalc.special_chars(otext);
if (otext == '[custom]') {
options[i] = {
o: SocialCalc.Constants.s_PopupListCustom,
v: val.substring(pos + 1),
a: { custom: true },
};
} else if (otext == '[cancel]') {
options[i] = {
o: SocialCalc.Constants.s_PopupListCancel,
v: '',
a: { cancel: true },
};
} else if (otext == '[break]') {
options[i] = {
o: '-----',
v: '',
a: { skip: true },
};
} else if (otext == '[newcol]') {
options[i] = {
o: '',
v: '',
a: { newcol: true },
};
} else {
options[i] = {
o: otext,
v: val.substring(pos + 1),
};
}
}
SpreadsheetControlSC.Popup.Create('List', panelobj[ctrlname].id, {});
SpreadsheetControlSC.Popup.Initialize(panelobj[ctrlname].id, {
options,
attribs: {
changedcallback: SpreadsheetControlSC.SettingsControls.PopupChangeCallback,
panelobj,
},
});
};
SpreadsheetControlSC.SettingsControls.PopupListReset = function (_ctrlname) {
SpreadsheetControlSC.Popup.Reset('List');
};
SpreadsheetControlSC.SettingsControls.Controls.PopupList = {
SetValue: SpreadsheetControlSC.SettingsControls.PopupListSetValue,
GetValue: SpreadsheetControlSC.SettingsControls.PopupListGetValue,
Initialize: SpreadsheetControlSC.SettingsControls.PopupListInitialize,
OnReset: SpreadsheetControlSC.SettingsControls.PopupListReset,
ChangedCallback: null,
};
SpreadsheetControlSC.SettingsControls.ColorChooserSetValue = function (
panelobj,
ctrlname,
value,
) {
if (!value) {
(function(){})(ctrlname + ' no value');
return;
}
var sp = SocialCalc.Popup;
if (!value.def) {
sp.SetValue(panelobj[ctrlname].id, value.val);
} else {
sp.SetValue(panelobj[ctrlname].id, '');
}
};
SpreadsheetControlSC.SettingsControls.ColorChooserGetValue = function (panelobj, ctrlname) {
var value = SpreadsheetControlSC.Popup.GetValue(panelobj[ctrlname].id);
if (value) {
return {
def: false,
val: value,
};
} else {
return {
def: true,
val: 0,
};
}
};
SpreadsheetControlSC.SettingsControls.ColorChooserInitialize = function (panelobj, ctrlname) {
SpreadsheetControlSC.Popup.Create('ColorChooser', panelobj[ctrlname].id, {});
SpreadsheetControlSC.Popup.Initialize(panelobj[ctrlname].id, {
attribs: {
title: ' ',
moveable: true,
width: '106px',
changedcallback: SpreadsheetControlSC.SettingsControls.PopupChangeCallback,
panelobj,
},
});
};
SpreadsheetControlSC.SettingsControls.ColorChooserReset = function (_ctrlname) {
SpreadsheetControlSC.Popup.Reset('ColorChooser');
};
SpreadsheetControlSC.SettingsControls.Controls.ColorChooser = {
SetValue: SpreadsheetControlSC.SettingsControls.ColorChooserSetValue,
GetValue: SpreadsheetControlSC.SettingsControls.ColorChooserGetValue,
Initialize: SpreadsheetControlSC.SettingsControls.ColorChooserInitialize,
OnReset: SpreadsheetControlSC.SettingsControls.ColorChooserReset,
ChangedCallback: null,
};
SpreadsheetControlSC.SettingsControls.BorderSideSetValue = function (panelobj, ctrlname, value) {
var ele, idname, parts;
var idstart = panelobj[ctrlname].id;
if (!value) {
(function(){})(ctrlname + ' no value');
return;
}
ele = document.getElementById(idstart + '-onoff-bcb');
if (!ele) return;
if (value.val) {
ele.checked = true;
ele.value = value.val;
parts = value.val.match(/(\S+)\s+(\S+)\s+(\S.+)/);
idname = idstart + '-color';
SpreadsheetControlSC.Popup.SetValue(idname, parts[3]);
SpreadsheetControlSC.Popup.SetDisabled(idname, false);
} else {
ele.checked = false;
ele.value = value.val;
idname = idstart + '-color';
SpreadsheetControlSC.Popup.SetValue(idname, '');
SpreadsheetControlSC.Popup.SetDisabled(idname, true);
}
};
SpreadsheetControlSC.SettingsControls.BorderSideGetValue = function (panelobj, ctrlname) {
var ele, value;
var idstart = panelobj[ctrlname].id;
ele = document.getElementById(idstart + '-onoff-bcb');
if (!ele) return;
if (ele.checked) {
value = SpreadsheetControlSC.Popup.GetValue(idstart + '-color');
value = '1px solid ' + (value || 'rgb(0,0,0)');
return {
def: false,
val: value,
};
} else {
return {
def: false,
val: '',
};
}
};
SpreadsheetControlSC.SettingsControls.BorderSideInitialize = function (panelobj, ctrlname) {
var idstart = panelobj[ctrlname].id;
SpreadsheetControlSC.Popup.Create('ColorChooser', idstart + '-color', {});
SpreadsheetControlSC.Popup.Initialize(idstart + '-color', {
attribs: {
title: ' ',
width: '106px',
moveable: true,
changedcallback: SpreadsheetControlSC.SettingsControls.PopupChangeCallback,
panelobj,
},
});
};
SpreadsheetControlSC.SettingsControlOnchangeBorder = function (ele) {
var sc = SocialCalc.SettingsControls;
var panelobj = sc.CurrentPanel;
var nameparts = ele.id.match(/(^.*-)(\w+)-(\w+)-(\w+)$/);
if (!nameparts) return;
var ctrlname = nameparts[2];
var ctrlidsuffix = nameparts[4];
var ctrltype = panelobj[ctrlname].type;
switch (ctrlidsuffix) {
case 'bcb':
if (ele.checked) {
sc.Controls[ctrltype].SetValue(sc.CurrentPanel, ctrlname, {
def: false,
val: ele.value || '1px solid rgb(0,0,0)',
});
} else {
sc.Controls[ctrltype].SetValue(sc.CurrentPanel, ctrlname, {
def: false,
val: '',
});
}
break;
}
};
SpreadsheetControlSC.SettingsControls.Controls.BorderSide = {
SetValue: SpreadsheetControlSC.SettingsControls.BorderSideSetValue,
GetValue: SpreadsheetControlSC.SettingsControls.BorderSideGetValue,
OnClick: SpreadsheetControlSC.SettingsControls.ColorComboOnClick,
Initialize: SpreadsheetControlSC.SettingsControls.BorderSideInitialize,
InitialData: {
thickness: '1 pixel:1px',
style: 'Solid:solid',
},
ChangedCallback: null,
};
SpreadsheetControlSC.SettingControlReset = function () {
var sc = SocialCalc.SettingsControls;
var ctrlname;
for (ctrlname in sc.Controls) {
if (sc.Controls[ctrlname].OnReset) sc.Controls[ctrlname].OnReset(ctrlname);
}
};
SpreadsheetControlSC.CtrlSEditor = function (whichpart) {
var strtoedit, partname;
if (whichpart.length > 0) {
strtoedit = SocialCalc.special_chars(SocialCalc.OtherSaveParts[whichpart] || '');
} else {
strtoedit = 'Listing of Parts\n';
for (partname in SocialCalc.OtherSaveParts) {
strtoedit += SocialCalc.special_chars(
'\nPart: ' + partname + '\n=====\n' + SocialCalc.OtherSaveParts[partname] + '\n',
);
}
}
var editbox = SocialCalc.document.createElement('div');
editbox.style.cssText =
'position:absolute;z-index:500;width:300px;height:300px;left:100px;top:200px;border:1px solid black;background-color:#EEE;text-align:center;';
editbox.id = 'socialcalc-editbox';
editbox.innerHTML =
whichpart +
'
';
document.body.appendChild(editbox);
var ebta = document.getElementById('socialcalc-editbox-textarea');
ebta.focus();
SocialCalc.CmdGotFocus(ebta);
};
SpreadsheetControlSC.CtrlSEditorDone = function (idprefix, whichpart) {
var edittextarea = document.getElementById(idprefix + '-textarea');
var text = edittextarea.value;
if (whichpart.length > 0) {
if (text.length > 0) {
SocialCalc.OtherSaveParts[whichpart] = text;
} else {
delete SocialCalc.OtherSaveParts[whichpart];
}
}
var editbox = document.getElementById(idprefix);
SocialCalc.KeyboardFocus();
editbox.parentNode.removeChild(editbox);
};
// In-place TypeScript conversion of socialcalcviewer.js (SocialCalc global script).
// Ambient API types live in socialcalcviewer.d.ts (referenced by dist/SocialCalc.d.ts).
// Vite+ strips types with Oxc before UMD concat — no runtime tax.
// Typechecked global-script module (no @ts-nocheck).
//
// SocialCalcViewer
//
/*
// The code module of the SocialCalc package that lets you embed a spreadsheet viewer
// with an optional simple toolbar into a web page.
//
// (c) Copyright 2008, 2009, 2010 Socialtext, Inc.
// All Rights Reserved.
//
*/
// Mutable progressive-init bridges for ambient nested namespaces.
SocialCalc.LocalizeStringList = {};
SocialCalc.CurrentSpreadsheetViewerObject = null;
const SpreadsheetViewerCtor = function (idPrefix) {
var scc = SocialCalc.Constants;
this.parentNode = null;
this.spreadsheetDiv = null;
this.requestedHeight = 0;
this.requestedWidth = 0;
this.requestedSpaceBelow = 0;
this.height = 0;
this.width = 0;
this.viewheight = 0;
this.spreadsheetDiv = null;
this.editorDiv = null;
this.sortrange = '';
this.idPrefix = idPrefix || 'SocialCalc-';
this.imagePrefix = scc.defaultImagePrefix;
this.statuslineheight = scc.SVStatuslineheight;
this.statuslineCSS = scc.SVStatuslineCSS;
this.sheet = new SocialCalc.Sheet();
this.context = new SocialCalc.RenderContext(this.sheet);
if (SocialCalc._app == true || SocialCalc._view == true)
scc.defaultImagePrefix = this.imagePrefix = '../' + this.imagePrefix;
if (SocialCalc._app == true) {
this.context.showGrid = false;
this.context.showRCHeaders = false;
this.context.highlightTypes.range.style = '';
this.context.sheetobj.cells['A1'] = new SocialCalc.Cell('A1');
this.context.sheetobj.cells['A1'].displaystring = 'Loading ... ';
} else {
this.context.showGrid = true;
this.context.showRCHeaders = true;
}
this.editor = new SocialCalc.TableEditor(this.context);
this.editor.noEdit = true;
this.editor.StatusCallback.statusline = {
func: SocialCalc.SpreadsheetViewerStatuslineCallback,
params: {},
};
this.hasStatusLine = true;
this.statuslineHTML =
'';
this.statuslineFull = true;
this.noRecalc = true;
this.repeatingMacroTimer = null;
this.repeatingMacroInterval = 60;
this.repeatingMacroCommands = '';
SocialCalc.CurrentSpreadsheetViewerObject = this;
return;
};
SocialCalc.SpreadsheetViewer = SpreadsheetViewerCtor;
SocialCalc.SpreadsheetViewer.prototype.InitializeSpreadsheetViewer = function (
node,
height,
width,
spacebelow,
) {
return SocialCalc.InitializeSpreadsheetViewer(this, node, height, width, spacebelow);
};
SocialCalc.SpreadsheetViewer.prototype.LoadSave = function (str) {
return SocialCalc.SpreadsheetViewerLoadSave(this, str);
};
SocialCalc.SpreadsheetViewer.prototype.DoOnResize = function () {
return SocialCalc.DoOnResize(this);
};
SocialCalc.SpreadsheetViewer.prototype.SizeSSDiv = function () {
return SocialCalc.SizeSSDiv(this);
};
SocialCalc.SpreadsheetViewer.prototype.DecodeSpreadsheetSave = function (str) {
return SocialCalc.SpreadsheetViewerDecodeSpreadsheetSave(this, str);
};
SocialCalc.SpreadsheetViewer.prototype.ParseSheetSave = function (str) {
return this.sheet.ParseSheetSave(str);
};
SocialCalc.InitializeSpreadsheetViewer = function (spreadsheet, node, height, width, spacebelow) {
var child;
spreadsheet.requestedHeight = height || 0;
spreadsheet.requestedWidth = width || 0;
spreadsheet.requestedSpaceBelow = spacebelow || 0;
var nodeEl = typeof node == 'string' ? document.getElementById(node) : node;
if (nodeEl == null) {
(function(){})('SocialCalc.SpreadsheetControl not given parent node.');
return;
}
spreadsheet.parentNode = nodeEl;
spreadsheet.spreadsheetDiv = SocialCalc.document.createElement('div');
spreadsheet.SizeSSDiv();
for (child = nodeEl.firstChild; child != null; child = nodeEl.firstChild) {
nodeEl.removeChild(child);
}
nodeEl.appendChild(spreadsheet.spreadsheetDiv);
spreadsheet.nonviewheight = spreadsheet.hasStatusLine ? spreadsheet.statuslineheight : 0;
spreadsheet.viewheight = spreadsheet.height - spreadsheet.nonviewheight;
spreadsheet.editorDiv = spreadsheet.editor.CreateTableEditor(
spreadsheet.width,
spreadsheet.viewheight,
);
if (spreadsheet.spreadsheetDiv && spreadsheet.editorDiv) {
spreadsheet.spreadsheetDiv.appendChild(spreadsheet.editorDiv);
}
if (spreadsheet.hasStatusLine) {
spreadsheet.statuslineDiv = SocialCalc.document.createElement('div');
spreadsheet.statuslineDiv.style.cssText = spreadsheet.statuslineCSS;
spreadsheet.statuslineDiv.style.height =
spreadsheet.statuslineheight -
(Number(spreadsheet.statuslineDiv.style.paddingTop.slice(0, -2)) || 0) -
(Number(spreadsheet.statuslineDiv.style.paddingBottom.slice(0, -2)) || 0) +
'px';
spreadsheet.statuslineDiv.id = spreadsheet.idPrefix + 'statusline';
spreadsheet.spreadsheetDiv.appendChild(spreadsheet.statuslineDiv);
spreadsheet.editor.StatusCallback.statusline = {
func: SocialCalc.SpreadsheetViewerStatuslineCallback,
params: { spreadsheetobj: spreadsheet },
};
}
if (SocialCalc._app == true) {
spreadsheet.formDataViewer = new SocialCalc.SpreadsheetViewer('te_FormData-');
spreadsheet.formDataViewer.sheet.statuscallback = null;
SocialCalc.CurrentSpreadsheetViewerObject = spreadsheet;
}
return;
};
SocialCalc.SpreadsheetViewerLoadSave = function (spreadsheet, savestr) {
var rmstr, pos, t, t2;
var parts = spreadsheet.DecodeSpreadsheetSave(savestr);
if (parts) {
if (parts.sheet) {
spreadsheet.sheet.ResetSheet();
spreadsheet.sheet.ParseSheetSave(savestr.substring(parts.sheet.start, parts.sheet.end));
}
if (parts.edit) {
spreadsheet.editor.LoadEditorSettings(savestr.substring(parts.edit.start, parts.edit.end));
}
if (parts.startupmacro) {
spreadsheet.editor.EditorScheduleSheetCommands(
savestr.substring(parts.startupmacro.start, parts.startupmacro.end),
false,
true,
);
}
if (parts.repeatingmacro) {
rmstr = savestr.substring(parts.repeatingmacro.start, parts.repeatingmacro.end);
rmstr = rmstr.replace('\r', '');
pos = rmstr.indexOf('\n');
if (pos > 0) {
t = rmstr.substring(0, pos) - 0;
t2 = t;
spreadsheet.repeatingMacroInterval = t;
spreadsheet.repeatingMacroCommands = rmstr.substring(pos + 1);
if (t2 > 0) {
spreadsheet.repeatingMacroTimer = window.setTimeout(
SocialCalc.SpreadsheetViewerDoRepeatingMacro,
spreadsheet.repeatingMacroInterval * 1e3,
);
}
}
}
}
if (spreadsheet.editor.context.sheetobj.attribs.recalc == 'off' || spreadsheet.noRecalc) {
spreadsheet.editor.ScheduleRender();
} else {
spreadsheet.editor.EditorScheduleSheetCommands('recalc');
}
};
SocialCalc.SpreadsheetViewerDoRepeatingMacro = function () {
var spreadsheet = SocialCalc.GetSpreadsheetViewerObject();
var editor = spreadsheet.editor;
spreadsheet.repeatingMacroTimer = null;
SocialCalc.SheetCommandInfo.CmdExtensionCallbacks.repeatmacro = {
func: SocialCalc.SpreadsheetViewerRepeatMacroCommand,
data: null,
};
editor.EditorScheduleSheetCommands(spreadsheet.repeatingMacroCommands);
};
SocialCalc.SpreadsheetViewerRepeatMacroCommand = function (name, data, sheet, cmd, _saveundo) {
var spreadsheet = SocialCalc.GetSpreadsheetViewerObject();
var rest = cmd.RestOfString();
var t = rest - 0;
if (!(t > 0)) t = spreadsheet.repeatingMacroInterval;
spreadsheet.repeatingMacroInterval = t;
spreadsheet.repeatingMacroTimer = window.setTimeout(
SocialCalc.SpreadsheetViewerDoRepeatingMacro,
spreadsheet.repeatingMacroInterval * 1e3,
);
};
SocialCalc.SpreadsheetViewerStopRepeatingMacro = function () {
var spreadsheet = SocialCalc.GetSpreadsheetViewerObject();
if (spreadsheet.repeatingMacroTimer) {
window.clearTimeout(spreadsheet.repeatingMacroTimer);
spreadsheet.repeatingMacroTimer = null;
}
};
SocialCalc.SpreadsheetViewerDoButtonCmd = function (e, buttoninfo, bobj) {
var obj = bobj.element;
var which = bobj.functionobj.command;
var spreadsheet = SocialCalc.GetSpreadsheetViewerObject();
var editor = spreadsheet.editor;
switch (which) {
case 'recalc':
editor.EditorScheduleSheetCommands('recalc');
break;
default:
break;
}
if (obj && obj.blur) obj.blur();
SocialCalc.KeyboardFocus();
};
SocialCalc.LocalizeString = function (str) {
var cstr = SocialCalc.LocalizeStringList[str];
if (!cstr) {
cstr =
SocialCalc.Constants[
's_loc_' + str.toLowerCase().replace(/\s/g, '_').replace(/\W/g, 'X')
] || str;
SocialCalc.LocalizeStringList[str] = cstr;
}
return cstr;
};
SocialCalc.LocalizeSubstrings = function (str) {
var SCLoc = SocialCalc.LocalizeString;
return str.replace(/%(loc|ssc)!(.*?)!/g, function (a, t, c) {
if (t == 'ssc') {
return SocialCalc.Constants[c] || (function(){})('Missing constant: ' + c);
} else {
return SCLoc(c);
}
});
};
SocialCalc.GetSpreadsheetViewerObject = function () {
var csvo = SocialCalc.CurrentSpreadsheetViewerObject;
if (csvo) return csvo;
throw 'No current SpreadsheetViewer object.';
};
function SocialCalc_DoOnResize_Viewer(spreadsheet) {
var v;
var vname;
var views = spreadsheet.views || {};
var needresize = spreadsheet.SizeSSDiv();
if (!needresize) return;
for (vname in views) {
v = views[vname].element;
v.style.width = spreadsheet.width + 'px';
v.style.height = spreadsheet.height - spreadsheet.nonviewheight + 'px';
}
if (SocialCalc._app) return;
spreadsheet.editor.ResizeTableEditor(
spreadsheet.width,
spreadsheet.height - spreadsheet.nonviewheight,
);
}
function SocialCalc_SizeSSDiv_Viewer(spreadsheet) {
var sizes;
var pos;
var resized, nodestyle, newval;
var fudgefactorX = 10;
var fudgefactorY = 10;
resized = false;
if (!spreadsheet.parentNode || !spreadsheet.spreadsheetDiv) {
return false;
}
sizes = SocialCalc.GetViewportInfo();
const basePos = SocialCalc.GetElementPosition(spreadsheet.parentNode);
pos = {
left: basePos.left,
top: basePos.top,
right: 0,
bottom: 0,
};
nodestyle = spreadsheet.parentNode.style;
if (nodestyle.marginTop) {
pos.top += Number(nodestyle.marginTop.slice(0, -2)) || 0;
}
if (nodestyle.marginBottom) {
pos.bottom += Number(nodestyle.marginBottom.slice(0, -2)) || 0;
}
if (nodestyle.marginLeft) {
pos.left += Number(nodestyle.marginLeft.slice(0, -2)) || 0;
}
if (nodestyle.marginRight) {
pos.right += Number(nodestyle.marginRight.slice(0, -2)) || 0;
}
newval =
spreadsheet.requestedHeight ||
sizes.height - (pos.top + pos.bottom + fudgefactorY) - (spreadsheet.requestedSpaceBelow || 0);
if (spreadsheet.height != newval) {
spreadsheet.height = newval;
spreadsheet.spreadsheetDiv.style.height = newval + 'px';
resized = true;
}
newval =
spreadsheet.requestedWidth || sizes.width - (pos.left + pos.right + fudgefactorX) || 700;
if (spreadsheet.width != newval) {
spreadsheet.width = newval;
spreadsheet.spreadsheetDiv.style.width = newval + 'px';
resized = true;
}
spreadsheet.spreadsheetDiv.style.position = 'relative';
return resized;
}
SocialCalc.DoOnResize = SocialCalc_DoOnResize_Viewer;
SocialCalc.SizeSSDiv = SocialCalc_SizeSSDiv_Viewer;
SocialCalc.SpreadsheetViewerStatuslineCallback = function (editor, status, arg, params) {
var spreadsheet = params.spreadsheetobj;
var slstr = '';
if (spreadsheet && spreadsheet.statuslineDiv) {
if (spreadsheet.statuslineFull) {
slstr = editor.GetStatuslineString(status, arg, params);
} else {
slstr = editor.ecell ? editor.ecell.coord : '';
}
slstr = spreadsheet.statuslineHTML.replace(/\{status\}/, slstr);
spreadsheet.statuslineDiv.innerHTML = slstr;
}
switch (status) {
case 'cmdendnorender':
case 'calcfinished':
case 'doneposcalc':
break;
default:
break;
}
};
SocialCalc.CmdGotFocus = function (obj) {
SocialCalc.Keyboard.passThru = obj;
};
SocialCalc.SpreadsheetViewerCreateSheetHTML = function (spreadsheet) {
var context, div, ele;
var result = '';
context = new SocialCalc.RenderContext(spreadsheet.sheet);
div = SocialCalc.document.createElement('div');
ele = context.RenderSheet(null, { type: 'html' });
div.appendChild(ele);
result = div.innerHTML;
return result;
};
SocialCalc.SpreadsheetViewerDecodeSpreadsheetSave = function (spreadsheet, str) {
var pos1,
mpregex,
searchinfo,
boundary,
boundaryregex,
blanklineregex,
start,
ending,
lines,
i,
p,
pnum,
line;
var parts = {};
var partlist = [];
var hasreturnonly = /[^\n]\r[^\n]/;
if (hasreturnonly.test(str)) {
str = str.replace(/([^\n])\r([^\n])/g, '$1\r\n$2');
}
pos1 = str.search(/^MIME-Version:\s1\.0/im);
if (pos1 < 0) return parts;
mpregex = /^Content-Type:\s*multipart\/mixed;\s*boundary=(\S+)/gim;
mpregex.lastIndex = pos1;
searchinfo = mpregex.exec(str);
if (!searchinfo || mpregex.lastIndex <= 0) return parts;
boundary = searchinfo[1];
boundaryregex = new RegExp('^--' + boundary + '(?:\r\n|\n)', 'mg');
boundaryregex.lastIndex = mpregex.lastIndex;
searchinfo = boundaryregex.exec(str);
blanklineregex = /(?:\r\n|\n)(?:\r\n|\n)/gm;
blanklineregex.lastIndex = boundaryregex.lastIndex;
searchinfo = blanklineregex.exec(str);
if (!searchinfo) return parts;
start = blanklineregex.lastIndex;
boundaryregex.lastIndex = start;
searchinfo = boundaryregex.exec(str);
if (!searchinfo) return parts;
ending = searchinfo.index;
lines = str.substring(start, ending).split(/\r\n|\n/);
for (i = 0; i < lines.length; i++) {
line = lines[i];
p = line.split(':');
switch (p[0]) {
case 'version':
break;
case 'part':
partlist.push(p[1]);
break;
}
}
for (pnum = 0; pnum < partlist.length; pnum++) {
blanklineregex.lastIndex = ending;
searchinfo = blanklineregex.exec(str);
if (!searchinfo) return parts;
start = blanklineregex.lastIndex;
if (pnum == partlist.length - 1) {
boundaryregex = new RegExp('^--' + boundary + '--$', 'mg');
}
boundaryregex.lastIndex = start;
searchinfo = boundaryregex.exec(str);
if (!searchinfo) return parts;
ending = searchinfo.index;
parts[partlist[pnum]] = {
start,
end: ending,
};
}
return parts;
};
// Closing half of a UMD IIFE. Inlined in build.ts — not a standalone module.
// Leading `;` defuses an ASI trap: the preceding file may end with a
// function expression and no trailing semicolon, so a bare `(` would be
// parsed as a call applied to that function expression.
(function () {
// DOM-free safety net. Full implementations live in
// socialcalctableeditor.ts / socialcalcspreadsheetcontrol.ts and touch
// `document`. Each wrapper checks at call time so tests that install a
// DOM shim *after* bundle load still reach the real methods — the old
// load-time replacement permanently stomped them once the bundle had
// been loaded in a non-DOM context.
var fallbacks = {
GetEditorCellElement: function () {},
ReplaceCell: function () {},
EditorRenderSheet: function () {},
SpreadsheetControlSortSave: function () {
return '';
},
SpreadsheetControlStatuslineCallback: function () {},
DoPositionCalculations: function (editor) {
SocialCalc.EditorSheetStatusCallback(null, 'doneposcalc', null, editor);
},
};
for (var name in fallbacks) {
if (!Object.prototype.hasOwnProperty.call(fallbacks, name)) continue;
(function (name, fallback) {
var real = SocialCalc[name];
SocialCalc[name] = function () {
var fn = typeof document !== 'undefined' && real ? real : fallback;
return fn.apply(this, arguments);
};
})(name, fallbacks[name]);
}
})();
// Just return a value to define the module export.
return SocialCalc;
});
SocialCalc = module.exports;
}).call(host);
SocialCalc.document = SocialCalc.document || {};
SocialCalc.document.createElement = function (tag) { return new ShimNode(tag); };
return SocialCalc;
}