diff --git a/projects/google/liveSS/files/New Text Document.txt b/projects/google/liveSS/files/New Text Document.txt deleted file mode 100644 index e69de29..0000000 diff --git a/projects/google/liveSS/js/descriptions_builders.js b/projects/google/liveSS/js/descriptions_builders.js new file mode 100644 index 0000000..3316acf --- /dev/null +++ b/projects/google/liveSS/js/descriptions_builders.js @@ -0,0 +1,504 @@ +/** + * Updated: 2019-04-12 + */ + + +/** Descriptions **/ + +function RangeDescription(value, row, column, desc) { + /* + * arguments: [value[, row[, column[, desc]]]] + * + * value -> any type + * row -> integer (>0) + * column -> integer (>0) + * desc -> object containing full range description to override default settings + * + */ + + var tag = 'range', + sheetName = '', + row = (row && typeof row == 'number') ? row : 1, + column = (column && typeof column == 'number') ? column : 1, + height = 1, width = 1, + mustMerge = true, // options: true, false, 'vertically', 'across' + wrapStrategy = SpreadsheetApp.WrapStrategy.CLIP, + numberFormat = '@', + background = '#efefef', + validation = null, + value = (value) ? value : '', + protection = false, // options: true, false, 'warning' + unprotected = false; + + if (desc) { + if (isPropDefined(desc, 'tag')) tag = desc.tag; + if (desc.hasOwnProperty('sheetName') && typeof desc.sheetName == 'string') sheetName = desc.sheetName; + if (desc.hasOwnProperty('row') && typeof desc.row == 'number') row = desc.row; + if (desc.hasOwnProperty('column') && typeof desc.column == 'number') column = desc.column; + if (desc.hasOwnProperty('height') && typeof desc.height == 'number') height = desc.height; + if (desc.hasOwnProperty('width') && typeof desc.width == 'number') width = desc.width; + if (isPropDefined(desc, 'mustMerge')) mustMerge = desc.mustMerge; + if (isPropDefined(desc, 'wrapStrategy')) wrapStrategy = desc.wrapStrategy; + if (isPropDefined(desc, 'numberFormat')) numberFormat = desc.numberFormat; + if (isPropDefined(desc, 'background')) background = desc.background; + if (isPropDefined(desc, 'validation')) validation = desc.validation; + if (isPropDefined(desc, 'value')) value = desc.value; + + if (isPropDefined(desc, 'protection')) protection = desc.protection; + if (isPropDefined(desc, 'unprotected')) unprotected = desc.unprotected; + } + + function Border() { + + var top = null, left = null, bottom = null, right = null, + vertical = null, horizontal = null, + color = null, style = null; + + if (desc && isPropDefined(desc, 'border')) { + var border = desc.border; + if (isPropDefined(border, 'top')) top = border.top; + if (isPropDefined(border, 'left')) left = border.left; + if (isPropDefined(border, 'bottom')) bottom = border.bottom; + if (isPropDefined(border, 'right')) right = border.right; + if (isPropDefined(border, 'vertical')) vertical = border.vertical; + if (isPropDefined(border, 'horizontal')) horizontal = border.horizontal; + if (isPropDefined(border, 'color')) color = border.color; + if (isPropDefined(border, 'style')) style = border.style; + } + + this.top = top; + this.left = left; + this.bottom = bottom; + this.right = right; + this.vertical = vertical; + this.horizontal = horizontal; + this.color = color; + this.style = style; + + } + + function Alignment() { + + var vertical = 'middle', horizontal = 'center'; + + if (desc && isPropDefined(desc, 'alignment')) { + var alignment = desc.alignment; + if (isPropDefined(alignment, 'vertical')) vertical = alignment.vertical; + if (isPropDefined(alignment, 'horizontal')) horizontal = alignment.horizontal; + } + + this.vertical = vertical; + this.horizontal = horizontal; + + } + + function Font() { + + var family = 'Inconsolata', + color = null, + size = 10, + weight = 'normal', + style = 'normal', + line = 'none'; + + if (desc && isPropDefined(desc, 'font')) { + var font = desc.font; + if (isPropDefined(font, 'family')) family = font.family; + if (isPropDefined(font, 'color')) color = font.color; + if (isPropDefined(font, 'size')) size = font.size; + if (isPropDefined(font, 'weight')) weight = font.weight; + if (isPropDefined(font, 'style')) style = font.style; + if (isPropDefined(font, 'line')) line = font.line; + } + + this.family = family; + this.color = color; + this.size = size; + this.weight = weight; + this.style = style; + this.line = line; + + } + + function Indent() { + + var left = 0, right = 0; + + if (desc && isPropDefined(desc, 'indent')) { + var indent = desc.indent; + if (isPropDefined(indent, 'left')) left = indent.left; + if (isPropDefined(indent, 'right')) right = indent.right; + } + + this.left = left; + this.right = right; + + } + + // Meta + this.tag = tag; + + // Range + this.sheetName = sheetName; + this.row = row; + this.column = column; + this.height = height; + this.width = width; + this.mustMerge = mustMerge; + + // Appearance + this.wrapStrategy = wrapStrategy; + this.numberFormat = numberFormat; + this.background = background; + this.border = new Border; + this.alignment = new Alignment; + this.font = new Font; + this.indent = new Indent; + + // Data + this.validation = validation; + this.value = value; + + // Protection + this.protection = protection; + this.unprotected = unprotected; + +} + +function SheetDescription(height, width, sheetName) { + /* + * arguments: [height[, width[, sheetName]]] + * + * height -> integer (>0) || array of integers(>0) representing different row heights + * width -> integer (>0) || array of integers(>0) representing different column widths + * sheetName -> string + * + */ + + if (!height) height = 1; + if (!width) width = 1; + + var rowHeight = 21, columnWidth = 100; + + if (Array.isArray(height)) { + if (height.every(function(n) { return typeof n == 'number'; })) { + rowHeight = height; + height = height.length; + } + } + + if (Array.isArray(width)) { + if (width.every(function(n) { return typeof n == 'number'; })) { + columnWidth = width; + width = width.length; + } + } + + this.sheetName = (sheetName && typeof sheetName == 'string') ? sheetName : ''; + + // Dimensions + this.height = height; + this.width = width; + this.rowHeight = rowHeight; + this.columnWidth = columnWidth; + this.frozenRows = 0; + this.frozenColumns = 0; + + // Body + this.range = new RangeDescription(undefined, undefined, undefined, sheetName); + this.range.height = height; + this.range.width = width; + this.range.mustMerge = false; + this.hasGridlines = false; + + // Protection + this.protection = false; + /* must be either false or object (may be ommitted or deleted) + * object: { + * warning = boolean + * unprotected = array of unprotected ranges + * } + */ + +} + + +/** Builders **/ + +function buildRange(desc) { + /* + * arguments: desc + * + * desc -> object containing full range description + * + */ + + var ss = SpreadsheetApp.getActive(), + sheet = (desc.sheetName) ? ss.getSheetByName(desc.sheetName) : ss.getActiveSheet(), + range = sheet.getRange(desc.row, desc.column, desc.height, desc.width), + cell = sheet.getRange(desc.row, desc.column); + + var value = desc.value; + if (value && typeof value == 'string') { + var left = desc.indent.left, + right = desc.indent.right; + if (left || right) { + polyfills__String_repeat(); + var lI = (left) ? ' '.repeat(left) : '', + rI = (right) ? ' '.repeat(right) : ''; + value = lI + value + rI; + } + } + + if (desc.mustMerge) { + switch (desc.mustMerge) { + case 'vertically': range.mergeVertically(); break; + case 'across': range.mergeAcross(); break; + default: range.merge(); + } + } else range.breakApart(); + + range + .setBorder( + desc.border.top, desc.border.left, + desc.border.bottom, desc.border.right, + desc.border.vertical, desc.border.horizontal, + desc.border.color, desc.border.style + ) + .setWrapStrategy(desc.wrapStrategy) + .setNumberFormat(desc.numberFormat) + .setHorizontalAlignment(desc.alignment.horizontal) + .setVerticalAlignment(desc.alignment.vertical) + .setBackground(desc.background) + .setFontColor(desc.font.color) + .setFontFamily(desc.font.family) + .setFontSize(desc.font.size) + .setFontLine(desc.font.line) + .setFontWeight(desc.font.weight) + .setFontStyle(desc.font.style) + .setDataValidation(desc.validation); + + cell.setValue(value); + +} + +function buildRanges(descArr) { + /* + * arguments: descArr + * + * descArr -> array of objects containing full range descriptions + * + */ + + if (Array.isArray(descArr)) { + for (var i = 0; i < descArr.length; i++) buildRange(descArr[i]); + } + +} + +function buildSheet(desc, rangeArr, isNew) { + /* + * arguments: desc[, rangeArr[, isNew]] + * + * desc -> object containing full sheet description + * rangeArr -> function to run after + * isNew -> boolean (false by default) + */ + + if (!isNew) isNew = false; + + var ss = SpreadsheetApp.getActive(); + var sheet, index, unprotected1 = [], unprotected2 = []; + + var sheetName = (desc.sheetName) ? desc.sheetName : undefined, + height = desc.height, + width = desc.width, + rowHeight = desc.rowHeight, + columnWidth = desc.columnWidth, + frozenRows = desc.frozenRows, + frozenColumns = desc.frozenColumns; + + if (isNew) { + (sheetName) ? ss.insertSheet(sheetName) : ss.insertSheet(); + sheet = ss.getActiveSheet(); + } else { + sheet = (sheetName) ? ss.getSheetByName(sheetName) : ss.getActiveSheet(); + } + + index = sheet.getIndex() - 1; + + shrinkSheet(sheet); + + sheet.setHiddenGridlines(!desc.hasGridlines); + + if (height > 1) sheet.insertRowsAfter(1, height - 1); + if (width > 1) sheet.insertColumnsAfter(1, width - 1); + + if (Array.isArray(rowHeight)) { + for (var r = 0; r < rowHeight.length; r++) { + sheet.setRowHeight(r + 1, rowHeight[r]); + } + } else { + sheet.setRowHeights(1, height, rowHeight); + } + + if (Array.isArray(columnWidth)) { + for (var c = 0; c < columnWidth.length; c++) { + sheet.setColumnWidth(c + 1, columnWidth[c]); + } + } else { + sheet.setColumnWidths(1, width, columnWidth); + } + + if (frozenRows && frozenRows < height) sheet.setFrozenRows(frozenRows); + if (frozenColumns && frozenColumns < width) sheet.setFrozenColumns(frozenColumns); + + if (rangeArr && Array.isArray(rangeArr)) { + + for (var r = 0; r < rangeArr.length; r++) { + var rng = rangeArr[r]; + if (sheetName) rng.sheetName = sheetName; + if (rng.unprotected) { + unprotected1.push(sheet.getRange(rng.row, rng.column, rng.height, rng.width)); + if (unprotected1.length == 1) sheet.setCurrentCell(sheet.getRange(rng.row, rng.column)); + } + } + + buildRanges(rangeArr); + + } + + var protection = ss.getProtections(SpreadsheetApp.ProtectionType.SHEET)[index]; + if (protection) protection.remove(); + + if (desc.hasOwnProperty('protection') && desc.protection) { + + protection = sheet.protect(); + + if (desc.protection.hasOwnProperty('warning') && desc.protection.warning) { + protection.setWarningOnly(true); + } else { + var owner = ss.getOwner(); + protection.addEditor(owner); + protection.removeEditors(protection.getEditors()); + } + + var hasUnprotected = isPropDefined(desc.protection, 'unprotected'); + + if (hasUnprotected || unprotected1.length) { + + if (hasUnprotected && desc.protection.unprotected.length) { + unprotected2 = desc.protection.unprotected; + } + + var unprotected = unprotected1.concat(unprotected2); + + if (unprotected.length) protection.setUnprotectedRanges(unprotected); + + } + + } + +} + +function buildValidation(desc, showArrow, allowInvalid) { + /* + * arguments: desc[, showArrow[, allowInvalid]] + * + * desc -> array of description entities, where index 0 is purpose and others are arguments + * showArrow -> boolean, if true dropdown arrow will appear in dropdown type of validation + * allowInvalid -> boolean, if true will allow validation override + * + */ + + if (desc) { + + var validation = SpreadsheetApp.newDataValidation(), + purpose = desc[0]; + (showArrow == undefined || showArrow == null) ? showArrow = true : showArrow = showArrow; + (allowInvalid == undefined) ? allowInvalid = false : allowInvalid = allowInvalid; + + switch (purpose) { + + // Dates + case 'date': validation.requireDate(); break; + case 'date =': validation = validation.requireDateEqualTo(date(desc[1])); break; + case 'date >': validation = validation.requireDateAfter(date(desc[1])); break; + case 'date >=': validation = validation.requireDateOnOrAfter(date(desc[1])); break; + case 'date <': validation = validation.requireDateBefore(date(desc[1])); break; + case 'date <=': validation = validation.requireDateOnOrBefore(date(desc[1])); break; + case 'date <=>': validation = validation.requireDateBetween(date(desc[1]), date(desc[2])); break; + case 'date <>': validation = validation.requireDateNotBetween(date(desc[1]), date(desc[2])); break; + + // Numbers + case 'number =': validation = validation.requireNumberEqualTo(desc[1]); break; + case 'number !=': validation = validation.requireNumberNotEqualTo(desc[1]); break; + case 'number >': validation = validation.requireNumberGreaterThan(desc[1]); break; + case 'number >=': validation = validation.requireNumberGreaterThanOrEqualTo(desc[1]); break; + case 'number <': validation = validation.requireNumberLessThan(desc[1]); break; + case 'number <=': validation = validation.requireNumberLessThanOrEqualTo(desc[1]); break; + case 'number <=>': validation = validation.requireNumberBetween(desc[1], desc[2]); break; + case 'number <>': validation = validation.requireNumberNotBetween(desc[1], desc[2]); break; + + // Text + case 'text =': validation = requireTextEqualTo(desc[1]); break; + case 'text +': validation = requireTextContallowInvalidns(desc[1]); break; + case 'text -': validation = requireTextDoesNotContallowInvalidn(desc[1]); break; + + // Misc + case 'checkbox': + if (desc[1]) { + if (desc[2]) validation = validation.requireCheckbox(desc[1], desc[2]); + else validation = validation.requireCheckbox(desc[1]); + } else validation = validation.requireCheckbox(); + break; + case 'formula': validation = validation.requireFormulaSatisfied(desc[1]); break; + case 'emallowInvalidl': validation = validation.requireTextIsEmallowInvalidl(); break; + case 'url': validation = validation.requireTextIsUrl(); break; + case 'list': validation = validation.requireValueInList(desc[1], showArrow); break; + case 'range': validation = validation.requireValueInRange(desc[1], showArrow); break; + + } + + validation = validation.setAllowInvalid(allowInvalid).build(); + + return validation; + + } + +} + + +/** Misc **/ + +function shrinkSheet(sheet) { + /* + * arguments: sheet + * + * sheet -> sheet object + * + */ + + var u; + + var maxRows = sheet.getMaxRows(), + maxColumns = sheet.getMaxColumns(), + frozenRows = sheet.getFrozenRows(), + frozenColumns = sheet.getFrozenColumns(); + + if (frozenRows) sheet.setFrozenRows(0); + if (frozenColumns) sheet.setFrozenColumns(0); + if (maxRows > 1) sheet.deleteRows(2, maxRows - 1); + if (maxColumns > 1) sheet.deleteColumns(2, maxColumns - 1); + + desc = new SheetDescription; + sheet.setRowHeight(1, desc.rowHeight); + sheet.setColumnWidth(1, desc.columnWidth); + sheet.setHiddenGridlines(false); + + buildRange(new RangeDescription(u, u, u, { + sheetName: sheet.getName(), + font: { color: new RangeDescription().background } + })); + +} diff --git a/projects/google/liveSS/js/edit-response.js b/projects/google/liveSS/js/edit-response.js new file mode 100644 index 0000000..24df3eb --- /dev/null +++ b/projects/google/liveSS/js/edit-response.js @@ -0,0 +1,16 @@ +/** + * Updated: 2019-04-12 + */ + + +/** Edit Response **/ + +function executeEditResponse(eventDesc) { + /* + * arguments: eventDesc + * + * eventDesc -> Edit Event description object + * + */ + +} diff --git a/projects/google/liveSS/js/events.js b/projects/google/liveSS/js/events.js new file mode 100644 index 0000000..7f09110 --- /dev/null +++ b/projects/google/liveSS/js/events.js @@ -0,0 +1,67 @@ +/** + * Updated: 2019-04-12 + */ + + +/** Edit Event **/ + +function onEdit(e) { + /* + * arguments: e + * + * e -> Edit Event object + * + */ + + var $ = new Edit(e); + + executeEditResponse($); + +} + + +/** Open Event **/ + +function onOpen() { + +} + + +/** Change Event **/ + +function onChange() { + +} + + +/** Misc **/ + +function Edit(evt) { + /* + * arguments: evt + * + * evt -> Edit Event object + * + */ + + var ss = SpreadsheetApp.getActive(), + sheet = ss.getActiveSheet(), + sheetName = activeSheet.getName(), + range = evt.range, + row = range.getRow(), + column = range.getColumn(), + value = range.getValue(), + oldValue = evt.oldValue; + + if (typeof value == 'string') value = value.trim(); + + this.ss = ss; + this.sheet = sheet; + this.sheetName = sheetName; + this.range = range; + this.row = row; + this.column = column; + this.value = value; + this.oldValue = oldValue; + +} diff --git a/projects/google/liveSS/js/form-entities.js b/projects/google/liveSS/js/form-entities.js new file mode 100644 index 0000000..2d2e5c2 --- /dev/null +++ b/projects/google/liveSS/js/form-entities.js @@ -0,0 +1,315 @@ +/** + * Updated: 2019-04-12 + */ + + +/** Form Entities **/ + +function Title_(value, row, column, height, width, horizontalAlignment, omitIndent) { + /* + * arguments: [value[, row[, column[, height[, width[, horizontalAlignment[, omitIndent]]]]]]] + * + * value -> string + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * omitIndent -> boolean, if true indent will not be applied + * + */ + + return new RangeDescription(value, row, column, { + height: (height) ? height : undefined, + width: (width) ? width : undefined, + font: { family: 'Montserrat', size: 12, color: '#434343', weight: 'bold', line: 'underline' }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + indent: (omitIndent) ? undefined : { left: 2, right: 2 }, + }); + +} + +function HeaderMain_(value, row, column, height, width, horizontalAlignment, omitIndent) { + /* + * arguments: [value[, row[, column[, height[, width[, horizontalAlignment[, omitIndent]]]]]]] + * + * value -> string + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * omitIndent -> boolean, if true indent will not be applied + * + */ + + return new RangeDescription(value, row, column, { + height: (height) ? height : undefined, + width: (width) ? width : undefined, + font: { family: 'Roboto', size: 11, color: '#cccccc' }, + background: 'black', + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + indent: (omitIndent) ? undefined : { left: 2, right: 2 }, + }); + +} + +function Header_(value, row, column, height, width, horizontalAlignment, omitIndent) { + /* + * arguments: [value[, row[, column[, height[, width[, horizontalAlignment[, omitIndent]]]]]]] + * + * value -> string + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * omitIndent -> boolean, if true indent will not be applied + * + */ + + return new RangeDescription(value, row, column, { + height: (height) ? height : undefined, + width: (width) ? width : undefined, + font: { family: 'Roboto', size: 10, color: '#434343', style: 'italic' }, + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + indent: (omitIndent) ? undefined : { left: 2, right: 2 }, + }); + +} + +function Label_(value, required, row, column, height, width, omitIndent, applyBorder) { + /* + * arguments: value[, required[, row[, column[, height[, width[, omitIndent[, applyBorder]]]]]]] + * + * value -> string + * required -> boolean, determines if label points at required field + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * omitIndent -> boolean, if true indent will not be applied + * applyBorder -> boolean, if true border will be applied + * + */ + + if (value && typeof value == 'string') { + + var fontColor = '#666666'; + if (required) { + value += ' *'; + fontColor = '#134f5c'; + } + + return new RangeDescription(value, row, column, { + height: (height) ? height : undefined, + width: (width) ? width : undefined, + wrapStrategy: (!height && !width && !applyBorder) ? SpreadsheetApp.WrapStrategy.OVERFLOW : undefined, + alignment: { horizontal: 'right' }, + font: { family: 'Roboto', color: fontColor }, + border: (applyBorder) ? { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + } : undefined, + indent: (omitIndent) ? undefined : { right: 2 }, + }); + + } + +} + +function Cell_(value, row, column, height, width, numberFormat, horizontalAlignment, omitIndent) { + /* + * arguments: [value[, row[, column[, height[, width[, numberFormat[, horizontalAlignment[, omitIndent]]]]]]]] + * + * value -> any type + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * numberFormat -> string reprsenting format pattern + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * omitIndent -> boolean, if true indent will not be applied + * + */ + + return new RangeDescription(value, row, column, { + height: (height) ? height : undefined, + width: (width) ? width : undefined, + numberFormat: (numberFormat) ? numberFormat : undefined, + font: { family: 'Poppins', size: 11 }, + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + indent: (omitIndent) ? undefined : { left: 2, right: 2 }, + }); + +} + +function InputRequired_(value, row, column, height, width, validation, numberFormat, horizontalAlignment, unprotected) { + /* + * arguments: [value [,row[, column[, height[, width[, validation[, numberFormat[, horizontalAlignment[, unprotected]]]]]]]]] + * + * value -> any type + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * validation -> data validation object + * numberFormat -> string reprsenting format pattern + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * unprotected -> boolean, if false the range will be protected along with protected sheet + * + */ + + if (unprotected == undefined) unprotected = true; + + return new RangeDescription(value, row, column, { + tag: 'input', + height: (height) ? height : undefined, + width: (width) ? width : undefined, + numberFormat: (numberFormat) ? numberFormat : undefined, + font: { family: 'Poppins', size: 11, weight: 'bold' }, + background: '#c9daf8', + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + validation: (validation) ? validation : undefined, + unprotected: unprotected, + }); + +} + +function InputOptional_(value, row, column, height, width, validation, numberFormat, horizontalAlignment, unprotected) { + /* + * arguments: [value [,row[, column[, height[, width[, validation[, numberFormat[, horizontalAlignment[, unprotected]]]]]]]]] + * + * value -> any type + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * validation -> data validation object + * numberFormat -> string reprsenting format pattern + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * unprotected -> boolean, if false the range will be protected along with protected sheet + * + */ + + if (unprotected == undefined) unprotected = true; + + return new RangeDescription(value, row, column, { + tag: 'input', + height: (height) ? height : undefined, + width: (width) ? width : undefined, + numberFormat: (numberFormat) ? numberFormat : undefined, + font: { family: 'Poppins', size: 11, weight: 'bold' }, + background: '#d0e0e3', + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + validation: (validation) ? validation : undefined, + unprotected: unprotected, + }); + +} + +function InputAction_(value, row, column, height, width, validation) { + /* + * arguments: [value [,row[, column[, height[, width[, validation]]]]]] + * + * value -> any type + * row -> integer (>0) + * column -> integer (>0) + * height -> integer (>0) + * width -> integer (>0) + * validation -> data validation object + * + */ + + return new RangeDescription(value, row, column, { + tag: 'input', + height: (height) ? height : undefined, + width: (width) ? width : undefined, + font: { family: 'Poppins', color: 'blue', size: 11, weight: 'bold' }, + background: '#d9ead3', + border: { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + }, + validation: (validation) ? validation : undefined, + unprotected: true, + }); + +} + +function Checkbox_(row, column, value, horizontalAlignment, applyBorder, height, width) { + /* + * arguments: [row[, column[, value[, horizontalAlignment[, applyBorder[, height[, width]]]]]]] + * + * row -> integer (>0) + * column -> integer (>0) + * value -> boolean (false by default) + * horizontalAlignment -> selection op string options "left", "right" and "center" to override existing setting + * applyBorder -> boolean, if true border will be applied + * height -> integer (>0) + * width -> integer (>0) + * + */ + + if (value == undefined) value = false; + + return new RangeDescription(value, row, column, { + tag: 'input', + height: (height) ? height : undefined, + width: (width) ? width : undefined, + font: { color: Label_('/').font.color }, + numberFormat: new Formats().auto, + border: (applyBorder) ? { + top: true, + left: true, + bottom: true, + right: true, + color: Title_().font.color, + } : undefined, + alignment: (horizontalAlignment) ? { horizontal: horizontalAlignment } : undefined, + validation: buildValidation(['checkbox']), + unprotected: true, + }); + +} diff --git a/projects/google/liveSS/js/formats_converters.js b/projects/google/liveSS/js/formats_converters.js new file mode 100644 index 0000000..85f303b --- /dev/null +++ b/projects/google/liveSS/js/formats_converters.js @@ -0,0 +1,140 @@ +/** + * Updated: 2019-04-12 + */ + + +/** Formats **/ + +function Formats() { + + this.auto = '0.###############'; + this.text = '@'; + this.date = { + reversed: 'yyyy-mm-dd', + us: 'mm/dd/yyyy', + intl: 'dd.mm.yyyy', + month_short: 'mmm d, yyyy', + month_long: 'mmmm d, yyyy', + }; + this.dollar = { + no_text: [ + '$#,##0.00;;;', + '$#,##0.00;($#,##0.00);;', + '$#,##0.00;($#,##0.00);$0.00;' + ], + text_allowed: [ + '$#,##0.00;;', + '$#,##0.00;($#,##0.00);', + '$#,##0.00;($#,##0.00);$0.00' + ], + }; + +} + + +/** Converters **/ + +function convertLocalDateToEST(params) { + /* + * arguments: [params] + * + * paramas -> string representing time parameters + * + */ + + var date; + + if (params != undefined) date = new Date(params); + else date = new Date; + + return new Date(date.toLocaleString('en-US', { timeZone: 'America/New_York' })); + +} + +function convertDateToString(date, format) { + /* + * arguments: date, format + * + * date -> date object to convert to string + * format -> string as date format representation + * + */ + + var dateStr; + + var yyyy = date.getFullYear(), + yy = date.getYear(), + month = date.getMonth(), + calendarDay = date.getDate(), + weekDay = date.getDay(), + hours = date.getHours(), + minutes = date.getMinutes(), + seconds = date.getSeconds(); + + var ap_ = /\bam\/pm\b/gi, ap = 'AM'; + + if (format.search(ap) > -1 && hours > 12) { + hours = hours - 12; + ap = 'PM'; + } + + var months = { + short: [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ], + long: [ + 'January', 'February', 'March', + 'April', 'May', 'June', + 'July', 'August', 'September', + 'October', 'November', 'December' + ], + }; + + var weekDays = { + short: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + long: [ + 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' + ], + }; + + dateStr = format + .replace(/\byyyy\b/gi, yyyy) + .replace(/\byy\b/gi, yy) + .replace(/\bmmmm\b/gi, months.long[month]) + .replace(/\bmmm\b/gi, months.short[month]) + .replace(/\bmm\b/g, ((month + 1) < 10) ? '0' + (month + 1) : month + 1) + .replace(/\bm\b/gi, month + 1) + .replace(/\bdddd\b/gi, weekDays.long[weekDay]) + .replace(/\bddd\b/gi, weekDays.short[weekDay]) + .replace(/\bdd\b/gi, (calendarDay < 10) ? '0' + calendarDay : calendarDay) + .replace(/\bd\b/gi, calendarDay) + .replace(/\bHH\b/g, (hours < 10) ? '0' + hours : hours) + .replace(/\bMM\b/g, (minutes < 10) ? '0' + minutes : minutes) + .replace(/\bSS\b/g, (seconds < 10) ? '0' + seconds : seconds) + .replace(ap_, ap);; + + return dateStr; + +} + +function convertDateStringReversedToUS(reversedDateStr) { + /* + * arguments: reversedDateStr + * + * reversedDateStr -> string representing date pattern "yyyy-mm-dd" + * + */ + + if ( + reversedDateStr && typeof reversedDateStr == 'string' && + reversedDateStr.length == 10 && + reversedDateStr.search('-') == 4 && + reversedDateStr.lastIndexOf('-') == 7 + ) + { + var d = reversedDateStr.split('-'); + return d[1] + '/' + d[2] + '/' + d[0]; + } + +} diff --git a/projects/google/liveSS/js/simplifiers_polyfills.js b/projects/google/liveSS/js/simplifiers_polyfills.js new file mode 100644 index 0000000..b439b99 --- /dev/null +++ b/projects/google/liveSS/js/simplifiers_polyfills.js @@ -0,0 +1,143 @@ +/** + * Updated: 2019-04-10 + */ + + +/** Simplifiers **/ + +function abc_() { + return [ + , 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' + , 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' + ]; +} + +function col(ltr_num, isUC) { + /* + * arguments: ltr_num[, isUC] + * + * ltr_num -> string of letters (len<=2) || integer (>0,len<=2) + * isUC -> boolean determining if return column must be presented in upper case + * + */ + + var abc = abc_(); + + if (typeof ltr_num == 'string') { + + var colIdx, + ltr = ltr_num.toLowerCase(); + if (ltr.length == 2) colIdx = abc.indexOf(ltr[0]) * 26 + abc.indexOf(ltr[1]); + else colIdx = abc.indexOf(ltr[0]); + return colIdx; + + } else if (typeof ltr_num == 'number') { + + var ltr, num = ltr_num; + if (num > 26) ltr = abc[quotient(num, 26)] + abc[num % 26]; + else ltr = abc[num]; + if (isUC) ltr = ltr.toUpperCase(); + return ltr; + + } + +} + +function quotient(n1, n2) { + /* + * arguments: n1, n2 + * + * n1 -> integer + * n2 -> integer + * + */ + + return (n1 - (n1 % n2)) / n2; + +} + +function clone(source) { + /* + * arguments: source + * + * source -> object to clone + * + */ + + var target = new Object(); + + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + target[prop] = source[prop]; + } + } + + return target; + +} + +function isPropDefined(source, prop) { + /* + * arguments: source, prop + * + * source -> object to test + * prop -> string representing object's property + * + */ + + return source.hasOwnProperty(prop) && source[prop] != undefined; + +} + + +/** Polyfills **/ + +// String + +function polyfills__String_repeat() { + /* + * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat + * + */ + + if (!String.prototype.repeat) { + String.prototype.repeat = function(count) { + 'use strict'; + if (this == null) + throw new TypeError('can\'t convert ' + this + ' to object'); + + var str = '' + this; + // To convert string to integer. + count = +count; + // Check NaN + if (count != count) + count = 0; + + if (count < 0) + throw new RangeError('repeat count must be non-negative'); + + if (count == Infinity) + throw new RangeError('repeat count must be less than infinity'); + + count = Math.floor(count); + if (str.length == 0 || count == 0) + return ''; + + // Ensuring count is a 31-bit integer allows us to heavily optimize the + // main part. But anyway, most current (August 2014) browsers can't handle + // strings 1 << 28 chars or longer, so: + if (str.length * count >= 1 << 28) + throw new RangeError('repeat count must not overflow maximum string size'); + + var maxCount = str.length * count; + count = Math.floor(Math.log(count) / Math.log(2)); + while (count) { + str += str; + count--; + } + str += str.substring(0, maxCount - str.length); + return str; + } + } + +}