Merge branch 'jg_sci_350_formulas' of https://github.com/jbargu/scinote-web into jbargu-jg_sci_350_formulas

This commit is contained in:
zmagod 2016-09-16 09:28:19 +02:00
commit b9b466cd8e
19 changed files with 22973 additions and 115 deletions

View file

@ -12,6 +12,7 @@ function initHandsOnTables(root) {
rowHeaders: true,
colHeaders: true,
fillHandle: false,
formulas: true,
cells: function (row, col, prop) {
var cellProperties = {};
@ -181,29 +182,6 @@ function expandResult(result) {
renderTable($(result).find("div.step-result-hot-table"));
}
initHandsOnTables($(document));
initResultCommentTabAjax();
expandAllResults();
initTutorial();
applyCollapseLinkCallBack();
initCommentOptions("ul.content-comments");
initEditComments("#results");
initDeleteComments("#results");
$(function () {
$("#results-collapse-btn").click(function () {
$('.result .panel-collapse').collapse('hide');
$(document).find("span.collapse-result-icon").each(function() {
$(this).addClass("glyphicon-collapse-down");
$(this).removeClass("glyphicon-collapse-up");
});
});
$("#results-expand-btn").click(expandAllResults);
});
function renderTable(table) {
$(table).handsontable("render");
// Yet another dirty hack to solve HandsOnTable problems
@ -358,6 +336,28 @@ function processResult(ev, resultTypeEnum, editMode, forS3) {
// This checks if the ctarget param exist in the
// rendered url and opens the comment tab
$(document).ready(function(){
initHandsOnTables($(document));
initResultCommentTabAjax();
expandAllResults();
initTutorial();
applyCollapseLinkCallBack();
initCommentOptions("ul.content-comments");
initEditComments("#results");
initDeleteComments("#results");
$(function () {
$("#results-collapse-btn").click(function () {
$('.result .panel-collapse').collapse('hide');
$(document).find("span.collapse-result-icon").each(function() {
$(this).addClass("glyphicon-collapse-down");
$(this).removeClass("glyphicon-collapse-up");
});
});
$("#results-expand-btn").click(expandAllResults);
});
if( getParam('ctarget') ){
var target = "#"+ getParam('ctarget');
$(target).find('a.comment-tab-link').click();

View file

@ -291,6 +291,7 @@ function initHandsOnTable(root) {
rowHeaders: true,
colHeaders: true,
fillHandle: false,
formulas: true,
cells: function (row, col, prop) {
var cellProperties = {};
@ -338,6 +339,7 @@ function initEditableHandsOnTable(root) {
rowHeaders: true,
colHeaders: true,
contextMenu: true,
formulas: true,
preventOverflow: 'horizontal'
});
@ -648,18 +650,27 @@ function expandStep(step) {
});
}
// On init
initCallBacks();
initHandsOnTable($(document));
expandAllSteps();
setupAssetsLoading();
function renderTable(table) {
$(table).handsontable("render");
// Yet another dirty hack to solve HandsOnTable problems
if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) {
$(table).find(".ht_master .wtHolder").css("height", "100%");
}
}
// Init comments edit/delete
initCommentOptions("ul.content-comments");
initEditComments("#steps");
initDeleteComments("#steps");
$(document).ready(function() {
// On init
initCallBacks();
initHandsOnTable($(document));
expandAllSteps();
setupAssetsLoading();
$(function () {
// Init comments edit/delete
initCommentOptions("ul.content-comments");
initEditComments("#steps");
initDeleteComments("#steps");
$(function () {
$("[data-action='collapse-steps']").click(function () {
$('.step .panel-collapse').collapse('hide');
@ -670,12 +681,5 @@ $(function () {
});
$("[data-action='expand-steps']").click(expandAllSteps);
});
function renderTable(table) {
$(table).handsontable("render");
// Yet another dirty hack to solve HandsOnTable problems
if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) {
$(table).find(".ht_master .wtHolder").css("height", "100%");
}
}
});
})

View file

@ -43,7 +43,8 @@ function initializeHandsonTable(el) {
colHeaders: headers,
columnSorting: true,
editor: false,
copyPaste: false
copyPaste: false,
formulas: true
});
el.handsontable("getInstance").loadData(data);
el.handsontable("getInstance").sort(3, order);
@ -61,7 +62,8 @@ function initializeHandsonTable(el) {
rowHeaders: true,
colHeaders: true,
editor: false,
copyPaste: false
copyPaste: false,
formulas: true
});
el.handsontable("getInstance").loadData(data);
}
@ -1191,17 +1193,29 @@ function showTutorial() {
return tutorialProjectId == currentProjectId;
}
/**
$(document).ready(function() {
/**
* ACTUAL CODE
*/
initializeReportElements($(REPORT_CONTENT));
initializeReportElements($(REPORT_CONTENT));
initializeGlobalReportSort();
initializePrintPopup();
initializeSaveToPdf();
initializeSaveReport();
initializeAddContentsModal();
initializeSidebarNavigation();
initializeUnsavedWorkDialog();
initializeTutorial();
initializeReportSidebartruncation();
initializeGlobalReportSort();
initializePrintPopup();
initializeSaveToPdf();
initializeSaveReport();
initializeAddContentsModal();
initializeSidebarNavigation();
initializeUnsavedWorkDialog();
initializeTutorial();
$(".report-nav-link").each( function(){
truncateLongString( $(this), 30);
});
})
$(document).change(function(){
setTimeout(function(){
$(".report-nav-link").each( function(){
truncateLongString( $(this), 30);
});
}, 1000);
});

View file

@ -17,6 +17,7 @@ function initEditableHandsOnTable(root) {
rowHeaders: true,
colHeaders: true,
contextMenu: true,
formulas: true,
preventOverflow: 'horizontal'
});
});

View file

@ -54,3 +54,16 @@
<%= javascript_include_tag "results/result_texts" %>
<%= javascript_include_tag "results/result_tables" %>
<%= javascript_include_tag "results/result_assets" %>
<!-- Libraries for formulas -->
<%= javascript_include_tag "lodash" %>
<%= javascript_include_tag "numeral" %>
<%= javascript_include_tag "numeric" %>
<%= javascript_include_tag "md5" %>
<%= javascript_include_tag "jstat" %>
<%= javascript_include_tag "formula" %>
<%= javascript_include_tag "parser" %>
<%= javascript_include_tag "ruleJS" %>
<%= javascript_include_tag "handsontable.formula" %>
<%= javascript_include_tag "big.min" %>
<%= stylesheet_link_tag "handsontable.formula" %>

View file

@ -31,3 +31,16 @@
<% end %>
<%= javascript_include_tag "protocols/steps" %>
<!-- Libraries for formulas -->
<%= javascript_include_tag "lodash" %>
<%= javascript_include_tag "numeral" %>
<%= javascript_include_tag "numeric" %>
<%= javascript_include_tag "md5" %>
<%= javascript_include_tag "jstat" %>
<%= javascript_include_tag "formula" %>
<%= javascript_include_tag "parser" %>
<%= javascript_include_tag "ruleJS" %>
<%= javascript_include_tag "handsontable.formula" %>
<%= javascript_include_tag "big.min" %>
<%= stylesheet_link_tag "handsontable.formula" %>

View file

@ -75,3 +75,16 @@
<%= javascript_include_tag "handsontable.full.min" %>
<%= javascript_include_tag("reports/new") %>
<!-- Libraries for formulas -->
<%= javascript_include_tag "lodash" %>
<%= javascript_include_tag "numeral" %>
<%= javascript_include_tag "numeric" %>
<%= javascript_include_tag "md5" %>
<%= javascript_include_tag "jstat" %>
<%= javascript_include_tag "formula" %>
<%= javascript_include_tag "parser" %>
<%= javascript_include_tag "ruleJS" %>
<%= javascript_include_tag "handsontable.formula" %>
<%= javascript_include_tag "big.min" %>
<%= stylesheet_link_tag "handsontable.formula" %>

View file

@ -7,55 +7,68 @@ Rails.application.config.assets.version = '1.0'
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w( underscore.js )
Rails.application.config.assets.precompile += %w( jsPlumb-2.0.4-min.js )
Rails.application.config.assets.precompile += %w( jsnetworkx.js )
Rails.application.config.assets.precompile += %w( handsontable.full.min.js )
Rails.application.config.assets.precompile += %w( users/settings/preferences.js )
Rails.application.config.assets.precompile += %w( users/settings/organizations.js )
Rails.application.config.assets.precompile += %w( users/settings/organizations/add_user_modal.js )
Rails.application.config.assets.precompile += %w( users/settings/organization.js )
Rails.application.config.assets.precompile += %w( my_modules/activities.js )
Rails.application.config.assets.precompile += %w( my_modules/protocols.js )
Rails.application.config.assets.precompile += %w( my_modules/protocols/protocol_status_bar.js )
Rails.application.config.assets.precompile += %w( my_modules/results.js )
Rails.application.config.assets.precompile += %w( results/result_tables.js )
Rails.application.config.assets.precompile += %w( results/result_assets.js )
Rails.application.config.assets.precompile += %w( results/result_texts.js )
Rails.application.config.assets.precompile += %w( users/registrations/edit.js )
Rails.application.config.assets.precompile += %w( jquery-ui/draggable.js )
Rails.application.config.assets.precompile += %w( jquery-ui/droppable.js )
Rails.application.config.assets.precompile += %w( jquery.ui.touch-punch.min.js )
Rails.application.config.assets.precompile += %w( bootstrap-colorselector.js )
Rails.application.config.assets.precompile += %w( eventPause-min.js )
Rails.application.config.assets.precompile += %w( sidebar.js )
Rails.application.config.assets.precompile += %w( samples/samples.js )
Rails.application.config.assets.precompile += %w( samples/sample_datatable.js )
Rails.application.config.assets.precompile += %w( projects/index.js )
Rails.application.config.assets.precompile += %w( samples/samples_importer.js )
Rails.application.config.assets.precompile += %w( projects/canvas.js )
Rails.application.config.assets.precompile += %w( experiments/dropdown_actions.js )
Rails.application.config.assets.precompile += %w( reports/index.js )
Rails.application.config.assets.precompile += %w( reports/new.js )
Rails.application.config.assets.precompile += %w( protocols/index.js )
Rails.application.config.assets.precompile += %w( protocols/header.js )
Rails.application.config.assets.precompile += %w( protocols/steps.js )
Rails.application.config.assets.precompile += %w( protocols/edit.js )
Rails.application.config.assets.precompile += %w( protocols/import_export/eln_table.js )
Rails.application.config.assets.precompile += %w( protocols/import_export/import.js )
Rails.application.config.assets.precompile += %w( protocols/import_export/export.js )
Rails.application.config.assets.precompile += %w( datatables.js )
Rails.application.config.assets.precompile += %w( search/index.js )
Rails.application.config.assets.precompile += %w( navigation.js )
Rails.application.config.assets.precompile += %w( datatables.css )
Rails.application.config.assets.precompile += %w( my_modules.js )
Rails.application.config.assets.precompile += %w( direct-upload.js )
Rails.application.config.assets.precompile += %w( canvas-to-blob.min.js )
Rails.application.config.assets.precompile += %w( Sortable.min.js )
Rails.application.config.assets.precompile += %w( reports_pdf.css )
Rails.application.config.assets.precompile += %w( jszip.min.js )
Rails.application.config.assets.precompile += %w( assets.js )
Rails.application.config.assets.precompile += %w( comments.js )
Rails.application.config.assets.precompile += %w( projects/show.js )
Rails.application.config.assets.precompile += %w( projects/introdutory_popup.js )
# application.js application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w(underscore.js)
Rails.application.config.assets.precompile += %w(jsPlumb-2.0.4-min.js)
Rails.application.config.assets.precompile += %w(jsnetworkx.js)
Rails.application.config.assets.precompile += %w(handsontable.full.min.js)
Rails.application.config.assets.precompile += %w(users/settings/preferences.js)
Rails.application.config.assets.precompile += %w(users/settings/organizations.js)
Rails.application.config.assets.precompile += %w(users/settings/organizations/add_user_modal.js)
Rails.application.config.assets.precompile += %w(users/settings/organization.js)
Rails.application.config.assets.precompile += %w(my_modules/activities.js)
Rails.application.config.assets.precompile += %w(my_modules/protocols.js)
Rails.application.config.assets.precompile += %w(my_modules/protocols/protocol_status_bar.js)
Rails.application.config.assets.precompile += %w(my_modules/results.js)
Rails.application.config.assets.precompile += %w(results/result_tables.js)
Rails.application.config.assets.precompile += %w(results/result_assets.js)
Rails.application.config.assets.precompile += %w(results/result_texts.js)
Rails.application.config.assets.precompile += %w(users/registrations/edit.js)
Rails.application.config.assets.precompile += %w(jquery-ui/draggable.js)
Rails.application.config.assets.precompile += %w(jquery-ui/droppable.js)
Rails.application.config.assets.precompile += %w(jquery.ui.touch-punch.min.js)
Rails.application.config.assets.precompile += %w(bootstrap-colorselector.js)
Rails.application.config.assets.precompile += %w(eventPause-min.js)
Rails.application.config.assets.precompile += %w(sidebar.js)
Rails.application.config.assets.precompile += %w(samples/samples.js)
Rails.application.config.assets.precompile += %w(samples/sample_datatable.js)
Rails.application.config.assets.precompile += %w(projects/index.js)
Rails.application.config.assets.precompile += %w(samples/samples_importer.js)
Rails.application.config.assets.precompile += %w(projects/canvas.js)
Rails.application.config.assets.precompile += %w(experiments/dropdown_actions.js)
Rails.application.config.assets.precompile += %w(reports/index.js)
Rails.application.config.assets.precompile += %w(reports/new.js)
Rails.application.config.assets.precompile += %w(protocols/index.js)
Rails.application.config.assets.precompile += %w(protocols/header.js)
Rails.application.config.assets.precompile += %w(protocols/steps.js)
Rails.application.config.assets.precompile += %w(protocols/edit.js)
Rails.application.config.assets.precompile += %w(protocols/import_export/eln_table.js)
Rails.application.config.assets.precompile += %w(protocols/import_export/import.js)
Rails.application.config.assets.precompile += %w(protocols/import_export/export.js)
Rails.application.config.assets.precompile += %w(datatables.js)
Rails.application.config.assets.precompile += %w(search/index.js)
Rails.application.config.assets.precompile += %w(navigation.js)
Rails.application.config.assets.precompile += %w(datatables.css)
Rails.application.config.assets.precompile += %w(my_modules.js)
Rails.application.config.assets.precompile += %w(direct-upload.js)
Rails.application.config.assets.precompile += %w(canvas-to-blob.min.js)
Rails.application.config.assets.precompile += %w(Sortable.min.js)
Rails.application.config.assets.precompile += %w(reports_pdf.css)
Rails.application.config.assets.precompile += %w(jszip.min.js)
Rails.application.config.assets.precompile += %w(assets.js)
Rails.application.config.assets.precompile += %w(comments.js)
Rails.application.config.assets.precompile += %w(projects/show.js)
Rails.application.config.assets.precompile += %w(projects/introdutory_popup.js)
# Libraries needed for Handsontable formulas
Rails.application.config.assets.precompile += %w(lodash.js)
Rails.application.config.assets.precompile += %w(numeral.js)
Rails.application.config.assets.precompile += %w(numeric.js)
Rails.application.config.assets.precompile += %w(md5.js)
Rails.application.config.assets.precompile += %w(jstat.js)
Rails.application.config.assets.precompile += %w(formula.js)
Rails.application.config.assets.precompile += %w(parser.js)
Rails.application.config.assets.precompile += %w(ruleJS.js)
Rails.application.config.assets.precompile += %w(handsontable.formula.js)
Rails.application.config.assets.precompile += %w(handsontable.formula.css)
Rails.application.config.assets.precompile += %w(big.min.js)

1
vendor/assets/javascripts/big.min.js vendored Normal file

File diff suppressed because one or more lines are too long

5830
vendor/assets/javascripts/formula.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,418 @@
(function(Handsontable) {
'use strict';
function HandsontableFormula() {
var isFormula = function(value) {
if (value) {
if (value[0] === '=') {
return true;
}
}
return false;
};
var formulaRenderer = function(instance, TD, row, col, prop, value, cellProperties) {
if (instance.formulasEnabled && isFormula(value)) {
// translate coordinates into cellId
var cellId = instance.plugin.utils.translateCellCoords({
row: row,
col: col
}),
prevFormula = null,
formula = null,
needUpdate = false,
error, result;
if (!cellId) {
return;
}
// get cell data
var item = instance.plugin.matrix.getItem(cellId);
if (item) {
needUpdate = !! item.needUpdate;
if (item.error) {
prevFormula = item.formula;
error = item.error;
if (needUpdate) {
error = null;
}
}
}
// check if typed formula or cell value should be recalculated
if ((value && value[0] === '=') || needUpdate) {
formula = value.substr(1).toUpperCase();
if (!error || formula !== prevFormula) {
var currentItem = item;
if (!currentItem) {
// define item to rulesJS matrix if not exists
item = {
id: cellId,
formula: formula
};
// add item to matrix
currentItem = instance.plugin.matrix.addItem(item);
}
// parse formula
var newValue = instance.plugin.parse(formula, {
row: row,
col: col,
id: cellId
});
// check if update needed
needUpdate = (newValue.error === '#NEED_UPDATE');
// update item value and error
instance.plugin.matrix.updateItem(currentItem, {
formula: formula,
value: newValue.result,
error: newValue.error,
needUpdate: needUpdate
});
error = newValue.error;
result = newValue.result;
// update cell value in hot
value = error || result;
}
}
if (error) {
// clear cell value
if (!value) {
// reset error
error = null;
} else {
// show error
value = error;
}
}
}
// apply changes
if (cellProperties.type === 'numeric') {
numericCell.renderer.apply(this, [instance, TD, row, col, prop, value, cellProperties]);
} else {
textCell.renderer.apply(this, [instance, TD, row, col, prop, value, cellProperties]);
}
};
var afterChange = function(changes, source) {
var instance = this;
if (!instance.formulasEnabled) {
return;
}
if (source === 'edit' || source === 'undo' || source === 'autofill') {
var rerender = false;
changes.forEach(function(item) {
var row = item[0],
col = item[1],
prevValue = item[2],
value = item[3];
var cellId = instance.plugin.utils.translateCellCoords({
row: row,
col: col
});
// if changed value, all references cells should be recalculated
if (value[0] !== '=' || prevValue !== value) {
instance.plugin.matrix.removeItem(cellId);
// get referenced cells
var deps = instance.plugin.matrix.getDependencies(cellId);
// update cells
deps.forEach(function(itemId) {
instance.plugin.matrix.updateItem(itemId, {
needUpdate: true
});
});
rerender = true;
}
});
if (rerender) {
instance.render();
}
}
};
var beforeAutofillInsidePopulate = function(index, direction, data, deltas, iterators, selected) {
var instance = this;
var r = index.row,
c = index.col,
value = data[r][c],
delta = 0,
rlength = data.length, // rows
clength = data ? data[0].length : 0; //cols
if (value[0] === '=') { // formula
if (['down', 'up'].indexOf(direction) !== -1) {
delta = rlength * iterators.row;
} else if (['right', 'left'].indexOf(direction) !== -1) {
delta = clength * iterators.col;
}
return {
value: instance.plugin.utils.updateFormula(value, direction, delta),
iterators: iterators
}
} else { // other value
// increment or decrement values for more than 2 selected cells
if (rlength >= 2 || clength >= 2) {
var newValue = instance.plugin.helper.number(value),
ii,
start;
if (instance.plugin.utils.isNumber(newValue)) {
if (['down', 'up'].indexOf(direction) !== -1) {
delta = deltas[0][c];
if (direction === 'down') {
newValue += (delta * rlength * iterators.row);
} else {
ii = (selected.row - r) % rlength;
start = ii > 0 ? rlength - ii : 0;
newValue = instance.plugin.helper.number(data[start][c]);
newValue += (delta * rlength * iterators.row);
// last element in array -> decrement iterator
// iterator cannot be less than 1
if (iterators.row > 1 && (start + 1) === rlength) {
iterators.row--;
}
}
} else if (['right', 'left'].indexOf(direction) !== -1) {
delta = deltas[r][0];
if (direction === 'right') {
newValue += (delta * clength * iterators.col);
} else {
ii = (selected.col - c) % clength;
start = ii > 0 ? clength - ii : 0;
newValue = instance.plugin.helper.number(data[r][start]);
newValue += (delta * clength * (iterators.col || 1));
// last element in array -> decrement iterator
// iterator cannot be less than 1
if (iterators.col > 1 && (start + 1) === clength) {
iterators.col--;
}
}
}
return {
value: newValue,
iterators: iterators
}
}
}
}
return {
value: value,
iterators: iterators
};
};
var afterCreateRow = function(row, amount, auto) {
if (auto) {
return;
}
var instance = this;
var selectedRow = instance.plugin.utils.isArray(instance.getSelected()) ? instance.getSelected()[0] : undefined;
if (instance.plugin.utils.isUndefined(selectedRow)) {
return;
}
var direction = (selectedRow >= row) ? 'before' : 'after',
items = instance.plugin.matrix.getRefItemsToRow(row),
counter = 1,
changes = [];
items.forEach(function(id) {
var item = instance.plugin.matrix.getItem(id),
formula = instance.plugin.utils.changeFormula(item.formula, 1, {
row: row
}), // update formula if needed
newId = id;
if (formula !== item.formula) { // formula updated
// change row index and get new coordinates
if ((direction === 'before' && selectedRow <= item.row) || (direction === 'after' && selectedRow < item.row)) {
newId = instance.plugin.utils.changeRowIndex(id, counter);
}
var cellCoords = instance.plugin.utils.cellCoords(newId);
if (newId !== id) {
// remove current item from matrix
instance.plugin.matrix.removeItem(id);
}
// set updated formula in new cell
changes.push([cellCoords.row, cellCoords.col, '=' + formula]);
}
});
if (items) {
instance.plugin.matrix.removeItemsBelowRow(row);
}
if (changes) {
instance.setDataAtCell(changes);
}
};
var afterCreateCol = function(col) {
var instance = this;
var selectedCol = instance.plugin.utils.isArray(instance.getSelected()) ? instance.getSelected()[1] : undefined;
if (instance.plugin.utils.isUndefined(selectedCol)) {
return;
}
var items = instance.plugin.matrix.getRefItemsToColumn(col),
counter = 1,
direction = (selectedCol >= col) ? 'before' : 'after',
changes = [];
items.forEach(function(id) {
var item = instance.plugin.matrix.getItem(id),
formula = instance.plugin.utils.changeFormula(item.formula, 1, {
col: col
}), // update formula if needed
newId = id;
if (formula !== item.formula) { // formula updated
// change col index and get new coordinates
if ((direction === 'before' && selectedCol <= item.col) || (direction === 'after' && selectedCol < item.col)) {
newId = instance.plugin.utils.changeColIndex(id, counter);
}
var cellCoords = instance.plugin.utils.cellCoords(newId);
if (newId !== id) {
// remove current item from matrix if id changed
instance.plugin.matrix.removeItem(id);
}
// set updated formula in new cell
changes.push([cellCoords.row, cellCoords.col, '=' + formula]);
}
});
if (items) {
instance.plugin.matrix.removeItemsBelowCol(col);
}
if (changes) {
instance.setDataAtCell(changes);
}
};
var formulaCell = {
renderer: formulaRenderer,
editor: Handsontable.editors.TextEditor,
dataType: 'formula'
};
var textCell = {
renderer: Handsontable.renderers.TextRenderer,
editor: Handsontable.editors.TextEditor
};
var numericCell = {
renderer: Handsontable.renderers.NumericRenderer,
editor: Handsontable.editors.NumericEditor
};
this.init = function() {
var instance = this;
instance.formulasEnabled = !! instance.getSettings().formulas;
if (instance.formulasEnabled) {
var custom = {
cellValue: instance.getDataAtCell
};
instance.plugin = new ruleJS();
instance.plugin.init();
instance.plugin.custom = custom;
Handsontable.cellTypes['formula'] = formulaCell;
Handsontable.TextCell.renderer = formulaRenderer;
Handsontable.NumericCell.renderer = formulaRenderer;
instance.addHook('afterChange', afterChange);
instance.addHook('beforeAutofillInsidePopulate', beforeAutofillInsidePopulate);
instance.addHook('afterCreateRow', afterCreateRow);
instance.addHook('afterCreateCol', afterCreateCol);
} else {
instance.removeHook('afterChange', afterChange);
instance.removeHook('beforeAutofillInsidePopulate', beforeAutofillInsidePopulate);
instance.removeHook('afterCreateRow', afterCreateRow);
instance.removeHook('afterCreateCol', afterCreateCol);
}
};
}
var htFormula = new HandsontableFormula();
Handsontable.hooks.add('beforeInit', htFormula.init);
Handsontable.hooks.add('afterUpdateSettings', function() {
htFormula.init.call(this, 'afterUpdateSettings')
});
})(Handsontable);

3251
vendor/assets/javascripts/jstat.js vendored Normal file

File diff suppressed because it is too large Load diff

6789
vendor/assets/javascripts/lodash.js vendored Normal file

File diff suppressed because it is too large Load diff

274
vendor/assets/javascripts/md5.js vendored Normal file
View file

@ -0,0 +1,274 @@
/*
* JavaScript MD5 1.0.1
* https://github.com/blueimp/JavaScript-MD5
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/MIT
*
* Based on
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*jslint bitwise: true */
/*global unescape, define */
(function ($) {
'use strict';
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t) {
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
}
function md5_ff(a, b, c, d, x, s, t) {
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t) {
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t) {
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t) {
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len) {
/* append padding */
x[len >> 5] |= 0x80 << (len % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var i, olda, oldb, oldc, oldd,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
for (i = 0; i < x.length; i += 16) {
olda = a;
oldb = b;
oldc = c;
oldd = d;
a = md5_ff(a, b, c, d, x[i], 7, -680876936);
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i], 20, -373897302);
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
d = md5_hh(d, a, b, c, x[i], 11, -358537222);
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i], 6, -198630844);
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return [a, b, c, d];
}
/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input) {
var i,
output = '';
for (i = 0; i < input.length * 32; i += 8) {
output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
}
return output;
}
/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input) {
var i,
output = [];
output[(input.length >> 2) - 1] = undefined;
for (i = 0; i < output.length; i += 1) {
output[i] = 0;
}
for (i = 0; i < input.length * 8; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
}
return output;
}
/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s) {
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}
/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data) {
var i,
bkey = rstr2binl(key),
ipad = [],
opad = [],
hash;
ipad[15] = opad[15] = undefined;
if (bkey.length > 16) {
bkey = binl_md5(bkey, key.length * 8);
}
for (i = 0; i < 16; i += 1) {
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}
/*
* Convert a raw string to a hex string
*/
function rstr2hex(input) {
var hex_tab = '0123456789abcdef',
output = '',
x,
i;
for (i = 0; i < input.length; i += 1) {
x = input.charCodeAt(i);
output += hex_tab.charAt((x >>> 4) & 0x0F) +
hex_tab.charAt(x & 0x0F);
}
return output;
}
/*
* Encode a string as utf-8
*/
function str2rstr_utf8(input) {
return unescape(encodeURIComponent(input));
}
/*
* Take string arguments and return either raw or hex encoded strings
*/
function raw_md5(s) {
return rstr_md5(str2rstr_utf8(s));
}
function hex_md5(s) {
return rstr2hex(raw_md5(s));
}
function raw_hmac_md5(k, d) {
return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
}
function hex_hmac_md5(k, d) {
return rstr2hex(raw_hmac_md5(k, d));
}
function md5(string, key, raw) {
if (!key) {
if (!raw) {
return hex_md5(string);
}
return raw_md5(string);
}
if (!raw) {
return hex_hmac_md5(key, string);
}
return raw_hmac_md5(key, string);
}
if (typeof define === 'function' && define.amd) {
define(function () {
return md5;
});
} else {
$.md5 = md5;
}
}(this));

679
vendor/assets/javascripts/numeral.js vendored Normal file
View file

@ -0,0 +1,679 @@
/*!
* numeral.js
* version : 1.5.3
* author : Adam Draper
* license : MIT
* http://adamwdraper.github.com/Numeral-js/
*/
(function () {
/************************************
Constants
************************************/
var numeral,
VERSION = '1.5.3',
// internal storage for language config files
languages = {},
currentLanguage = 'en',
zeroFormat = null,
defaultFormat = '0,0',
// check for nodeJS
hasModule = (typeof module !== 'undefined' && module.exports);
/************************************
Constructors
************************************/
// Numeral prototype object
function Numeral (number) {
this._value = number;
}
/**
* Implementation of toFixed() that treats floats more like decimals
*
* Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
* problems for accounting- and finance-related software.
*/
function toFixed (value, precision, roundingFunction, optionals) {
var power = Math.pow(10, precision),
optionalsRegExp,
output;
//roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round);
// Multiply up by precision, round accurately, then divide and use native toFixed():
output = (roundingFunction(value * power) / power).toFixed(precision);
if (optionals) {
optionalsRegExp = new RegExp('0{1,' + optionals + '}$');
output = output.replace(optionalsRegExp, '');
}
return output;
}
/************************************
Formatting
************************************/
// determine what type of formatting we need to do
function formatNumeral (n, format, roundingFunction) {
var output;
// figure out what kind of format we are dealing with
if (format.indexOf('$') > -1) { // currency!!!!!
output = formatCurrency(n, format, roundingFunction);
} else if (format.indexOf('%') > -1) { // percentage
output = formatPercentage(n, format, roundingFunction);
} else if (format.indexOf(':') > -1) { // time
output = formatTime(n, format);
} else { // plain ol' numbers or bytes
output = formatNumber(n._value, format, roundingFunction);
}
// return string
return output;
}
// revert to number
function unformatNumeral (n, string) {
var stringOriginal = string,
thousandRegExp,
millionRegExp,
billionRegExp,
trillionRegExp,
suffixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
bytesMultiplier = false,
power;
if (string.indexOf(':') > -1) {
n._value = unformatTime(string);
} else {
if (string === zeroFormat) {
n._value = 0;
} else {
if (languages[currentLanguage].delimiters.decimal !== '.') {
string = string.replace(/\./g,'').replace(languages[currentLanguage].delimiters.decimal, '.');
}
// see if abbreviations are there so that we can multiply to the correct number
thousandRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
millionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
billionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
trillionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
// see if bytes are there so that we can multiply to the correct number
for (power = 0; power <= suffixes.length; power++) {
bytesMultiplier = (string.indexOf(suffixes[power]) > -1) ? Math.pow(1024, power + 1) : false;
if (bytesMultiplier) {
break;
}
}
// do some math to create our number
n._value = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * (((string.split('-').length + Math.min(string.split('(').length-1, string.split(')').length-1)) % 2)? 1: -1) * Number(string.replace(/[^0-9\.]+/g, ''));
// round if we are talking about bytes
n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value;
}
}
return n._value;
}
function formatCurrency (n, format, roundingFunction) {
var symbolIndex = format.indexOf('$'),
openParenIndex = format.indexOf('('),
minusSignIndex = format.indexOf('-'),
space = '',
spliceIndex,
output;
// check for space before or after currency
if (format.indexOf(' $') > -1) {
space = ' ';
format = format.replace(' $', '');
} else if (format.indexOf('$ ') > -1) {
space = ' ';
format = format.replace('$ ', '');
} else {
format = format.replace('$', '');
}
// format the number
output = formatNumber(n._value, format, roundingFunction);
// position the symbol
if (symbolIndex <= 1) {
if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
output = output.split('');
spliceIndex = 1;
if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex){
// the symbol appears before the "(" or "-"
spliceIndex = 0;
}
output.splice(spliceIndex, 0, languages[currentLanguage].currency.symbol + space);
output = output.join('');
} else {
output = languages[currentLanguage].currency.symbol + space + output;
}
} else {
if (output.indexOf(')') > -1) {
output = output.split('');
output.splice(-1, 0, space + languages[currentLanguage].currency.symbol);
output = output.join('');
} else {
output = output + space + languages[currentLanguage].currency.symbol;
}
}
return output;
}
function formatPercentage (n, format, roundingFunction) {
var space = '',
output,
value = n._value * 100;
// check for space before %
if (format.indexOf(' %') > -1) {
space = ' ';
format = format.replace(' %', '');
} else {
format = format.replace('%', '');
}
output = formatNumber(value, format, roundingFunction);
if (output.indexOf(')') > -1 ) {
output = output.split('');
output.splice(-1, 0, space + '%');
output = output.join('');
} else {
output = output + space + '%';
}
return output;
}
function formatTime (n) {
var hours = Math.floor(n._value/60/60),
minutes = Math.floor((n._value - (hours * 60 * 60))/60),
seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60));
return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds);
}
function unformatTime (string) {
var timeArray = string.split(':'),
seconds = 0;
// turn hours and minutes into seconds and add them all up
if (timeArray.length === 3) {
// hours
seconds = seconds + (Number(timeArray[0]) * 60 * 60);
// minutes
seconds = seconds + (Number(timeArray[1]) * 60);
// seconds
seconds = seconds + Number(timeArray[2]);
} else if (timeArray.length === 2) {
// minutes
seconds = seconds + (Number(timeArray[0]) * 60);
// seconds
seconds = seconds + Number(timeArray[1]);
}
return Number(seconds);
}
function formatNumber (value, format, roundingFunction) {
var negP = false,
signed = false,
optDec = false,
abbr = '',
abbrK = false, // force abbreviation to thousands
abbrM = false, // force abbreviation to millions
abbrB = false, // force abbreviation to billions
abbrT = false, // force abbreviation to trillions
abbrForce = false, // force abbreviation
bytes = '',
ord = '',
abs = Math.abs(value),
suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
min,
max,
power,
w,
precision,
thousands,
d = '',
neg = false;
// check if number is zero and a custom zero format has been set
if (value === 0 && zeroFormat !== null) {
return zeroFormat;
} else {
// see if we should use parentheses for negative number or if we should prefix with a sign
// if both are present we default to parentheses
if (format.indexOf('(') > -1) {
negP = true;
format = format.slice(1, -1);
} else if (format.indexOf('+') > -1) {
signed = true;
format = format.replace(/\+/g, '');
}
// see if abbreviation is wanted
if (format.indexOf('a') > -1) {
// check if abbreviation is specified
abbrK = format.indexOf('aK') >= 0;
abbrM = format.indexOf('aM') >= 0;
abbrB = format.indexOf('aB') >= 0;
abbrT = format.indexOf('aT') >= 0;
abbrForce = abbrK || abbrM || abbrB || abbrT;
// check for space before abbreviation
if (format.indexOf(' a') > -1) {
abbr = ' ';
format = format.replace(' a', '');
} else {
format = format.replace('a', '');
}
if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) {
// trillion
abbr = abbr + languages[currentLanguage].abbreviations.trillion;
value = value / Math.pow(10, 12);
} else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) {
// billion
abbr = abbr + languages[currentLanguage].abbreviations.billion;
value = value / Math.pow(10, 9);
} else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) {
// million
abbr = abbr + languages[currentLanguage].abbreviations.million;
value = value / Math.pow(10, 6);
} else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) {
// thousand
abbr = abbr + languages[currentLanguage].abbreviations.thousand;
value = value / Math.pow(10, 3);
}
}
// see if we are formatting bytes
if (format.indexOf('b') > -1) {
// check for space before
if (format.indexOf(' b') > -1) {
bytes = ' ';
format = format.replace(' b', '');
} else {
format = format.replace('b', '');
}
for (power = 0; power <= suffixes.length; power++) {
min = Math.pow(1024, power);
max = Math.pow(1024, power+1);
if (value >= min && value < max) {
bytes = bytes + suffixes[power];
if (min > 0) {
value = value / min;
}
break;
}
}
}
// see if ordinal is wanted
if (format.indexOf('o') > -1) {
// check for space before
if (format.indexOf(' o') > -1) {
ord = ' ';
format = format.replace(' o', '');
} else {
format = format.replace('o', '');
}
ord = ord + languages[currentLanguage].ordinal(value);
}
if (format.indexOf('[.]') > -1) {
optDec = true;
format = format.replace('[.]', '.');
}
w = value.toString().split('.')[0];
precision = format.split('.')[1];
thousands = format.indexOf(',');
if (precision) {
if (precision.indexOf('[') > -1) {
precision = precision.replace(']', '');
precision = precision.split('[');
d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length);
} else {
d = toFixed(value, precision.length, roundingFunction);
}
w = d.split('.')[0];
if (d.split('.')[1].length) {
d = languages[currentLanguage].delimiters.decimal + d.split('.')[1];
} else {
d = '';
}
if (optDec && Number(d.slice(1)) === 0) {
d = '';
}
} else {
w = toFixed(value, null, roundingFunction);
}
// format number
if (w.indexOf('-') > -1) {
w = w.slice(1);
neg = true;
}
if (thousands > -1) {
w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[currentLanguage].delimiters.thousands);
}
if (format.indexOf('.') === 0) {
w = '';
}
return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + ((!neg && signed) ? '+' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : '');
}
}
/************************************
Top Level Functions
************************************/
numeral = function (input) {
if (numeral.isNumeral(input)) {
input = input.value();
} else if (input === 0 || typeof input === 'undefined') {
input = 0;
} else if (!Number(input)) {
input = numeral.fn.unformat(input);
}
return new Numeral(Number(input));
};
// version number
numeral.version = VERSION;
// compare numeral object
numeral.isNumeral = function (obj) {
return obj instanceof Numeral;
};
// This function will load languages and then set the global language. If
// no arguments are passed in, it will simply return the current global
// language key.
numeral.language = function (key, values) {
if (!key) {
return currentLanguage;
}
if (key && !values) {
if(!languages[key]) {
throw new Error('Unknown language : ' + key);
}
currentLanguage = key;
}
if (values || !languages[key]) {
loadLanguage(key, values);
}
return numeral;
};
// This function provides access to the loaded language data. If
// no arguments are passed in, it will simply return the current
// global language object.
numeral.languageData = function (key) {
if (!key) {
return languages[currentLanguage];
}
if (!languages[key]) {
throw new Error('Unknown language : ' + key);
}
return languages[key];
};
numeral.language('en', {
delimiters: {
thousands: ',',
decimal: '.'
},
abbreviations: {
thousand: 'k',
million: 'm',
billion: 'b',
trillion: 't'
},
ordinal: function (number) {
var b = number % 10;
return (~~ (number % 100 / 10) === 1) ? 'th' :
(b === 1) ? 'st' :
(b === 2) ? 'nd' :
(b === 3) ? 'rd' : 'th';
},
currency: {
symbol: '$'
}
});
numeral.zeroFormat = function (format) {
zeroFormat = typeof(format) === 'string' ? format : null;
};
numeral.defaultFormat = function (format) {
defaultFormat = typeof(format) === 'string' ? format : '0.0';
};
/************************************
Helpers
************************************/
function loadLanguage(key, values) {
languages[key] = values;
}
/************************************
Floating-point helpers
************************************/
// The floating-point helper functions and implementation
// borrows heavily from sinful.js: http://guipn.github.io/sinful.js/
/**
* Array.prototype.reduce for browsers that don't support it
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Compatibility
*/
if ('function' !== typeof Array.prototype.reduce) {
Array.prototype.reduce = function (callback, opt_initialValue) {
'use strict';
if (null === this || 'undefined' === typeof this) {
// At the moment all modern browsers, that support strict mode, have
// native implementation of Array.prototype.reduce. For instance, IE8
// does not support strict mode, so this check is actually useless.
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function');
}
var index,
value,
length = this.length >>> 0,
isValueSet = false;
if (1 < arguments.length) {
value = opt_initialValue;
isValueSet = true;
}
for (index = 0; length > index; ++index) {
if (this.hasOwnProperty(index)) {
if (isValueSet) {
value = callback(value, this[index], index, this);
} else {
value = this[index];
isValueSet = true;
}
}
}
if (!isValueSet) {
throw new TypeError('Reduce of empty array with no initial value');
}
return value;
};
}
/**
* Computes the multiplier necessary to make x >= 1,
* effectively eliminating miscalculations caused by
* finite precision.
*/
function multiplier(x) {
var parts = x.toString().split('.');
if (parts.length < 2) {
return 1;
}
return Math.pow(10, parts[1].length);
}
/**
* Given a variable number of arguments, returns the maximum
* multiplier that must be used to normalize an operation involving
* all of them.
*/
function correctionFactor() {
var args = Array.prototype.slice.call(arguments);
return args.reduce(function (prev, next) {
var mp = multiplier(prev),
mn = multiplier(next);
return mp > mn ? mp : mn;
}, -Infinity);
}
/************************************
Numeral Prototype
************************************/
numeral.fn = Numeral.prototype = {
clone : function () {
return numeral(this);
},
format : function (inputString, roundingFunction) {
return formatNumeral(this,
inputString ? inputString : defaultFormat,
(roundingFunction !== undefined) ? roundingFunction : Math.round
);
},
unformat : function (inputString) {
if (Object.prototype.toString.call(inputString) === '[object Number]') {
return inputString;
}
return unformatNumeral(this, inputString ? inputString : defaultFormat);
},
value : function () {
return this._value;
},
valueOf : function () {
return this._value;
},
set : function (value) {
this._value = Number(value);
return this;
},
add : function (value) {
var corrFactor = correctionFactor.call(null, this._value, value);
function cback(accum, curr, currI, O) {
return accum + corrFactor * curr;
}
this._value = [this._value, value].reduce(cback, 0) / corrFactor;
return this;
},
subtract : function (value) {
var corrFactor = correctionFactor.call(null, this._value, value);
function cback(accum, curr, currI, O) {
return accum - corrFactor * curr;
}
this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor;
return this;
},
multiply : function (value) {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) * (curr * corrFactor) /
(corrFactor * corrFactor);
}
this._value = [this._value, value].reduce(cback, 1);
return this;
},
divide : function (value) {
function cback(accum, curr, currI, O) {
var corrFactor = correctionFactor(accum, curr);
return (accum * corrFactor) / (curr * corrFactor);
}
this._value = [this._value, value].reduce(cback);
return this;
},
difference : function (value) {
return Math.abs(numeral(this._value).subtract(value).value());
}
};
/************************************
Exposing Numeral
************************************/
// CommonJS module is defined
if (hasModule) {
module.exports = numeral;
}
/*global ender:false */
if (typeof ender === 'undefined') {
// here, `this` means `window` in the browser, or `global` on the server
// add `numeral` as a global object via a string identifier,
// for Closure Compiler 'advanced' mode
this['numeral'] = numeral;
}
/*global define:false */
if (typeof define === 'function' && define.amd) {
define([], function () {
return numeral;
});
}
}).call(this);

3263
vendor/assets/javascripts/numeric.js vendored Normal file

File diff suppressed because it is too large Load diff

961
vendor/assets/javascripts/parser.js vendored Normal file
View file

@ -0,0 +1,961 @@
/* parser generated by jison 0.4.15 */
/*
Returns a Parser object of the following structure:
Parser: {
yy: {}
}
Parser.prototype: {
yy: {},
trace: function(),
symbols_: {associative list: name ==> number},
terminals_: {associative list: number ==> name},
productions_: [...],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$),
table: [...],
defaultActions: {...},
parseError: function(str, hash),
parse: function(input),
lexer: {
EOF: 1,
parseError: function(str, hash),
setInput: function(input),
input: function(),
unput: function(str),
more: function(),
less: function(n),
pastInput: function(),
upcomingInput: function(),
showPosition: function(),
test_match: function(regex_match_array, rule_index),
next: function(),
lex: function(),
begin: function(condition),
popState: function(),
_currentRules: function(),
topState: function(),
pushState: function(condition),
options: {
ranges: boolean (optional: true ==> token location info will include a .range[] member)
flex: boolean (optional: true ==> flex-like lexing behaviour where the rules are tested exhaustively to find the longest match)
backtrack_lexer: boolean (optional: true ==> lexer regexes are tested in order and for each matching regex the action code is invoked; the lexer terminates the scan when a token is returned by the action code)
},
performAction: function(yy, yy_, $avoiding_name_collisions, YY_START),
rules: [...],
conditions: {associative list: name ==> set},
}
}
token location info (@$, _$, etc.): {
first_line: n,
last_line: n,
first_column: n,
last_column: n,
range: [start_number, end_number] (where the numbers are indexes into the input string, regular zero-based)
}
the parseError function receives a 'hash' object with these members for lexer and parser errors: {
text: (matched text)
token: (the produced terminal token, if any)
line: (yylineno)
}
while parser (grammar) errors will also provide these members, i.e. parser errors deliver a superset of attributes: {
loc: (yylloc)
expected: (string describing the set of expected tokens)
recoverable: (boolean: TRUE when the parser has a error recovery rule available for this particular error)
}
*/
var Parser = (function(){
var o=function(k,v,o,l){for(o=o||{},l=k.length;l--;o[k[l]]=v);return o},$V0=[1,4],$V1=[1,5],$V2=[1,7],$V3=[1,10],$V4=[1,8],$V5=[1,9],$V6=[1,11],$V7=[1,16],$V8=[1,17],$V9=[1,14],$Va=[1,15],$Vb=[1,18],$Vc=[1,20],$Vd=[1,21],$Ve=[1,22],$Vf=[1,23],$Vg=[1,24],$Vh=[1,25],$Vi=[1,26],$Vj=[1,27],$Vk=[1,28],$Vl=[1,29],$Vm=[5,11,12,13,15,16,17,18,19,20,21,22,30,31],$Vn=[5,11,12,13,15,16,17,18,19,20,21,22,30,31,33],$Vo=[1,38],$Vp=[5,11,12,13,15,16,17,18,19,20,21,22,30,31,35],$Vq=[5,12,13,15,16,17,18,19,30,31],$Vr=[5,12,15,16,17,18,30,31],$Vs=[5,12,13,15,16,17,18,19,20,21,30,31],$Vt=[15,30,31],$Vu=[5,11,12,13,15,16,17,18,19,20,21,22,30,31,32,36];
var parser = {trace: function trace() { },
yy: {},
symbols_: {"error":2,"expressions":3,"expression":4,"EOF":5,"variableSequence":6,"TIME_AMPM":7,"TIME_24":8,"number":9,"STRING":10,"&":11,"=":12,"+":13,"(":14,")":15,"<":16,">":17,"NOT":18,"-":19,"*":20,"/":21,"^":22,"FUNCTION":23,"expseq":24,"cell":25,"FIXEDCELL":26,":":27,"CELL":28,"ARRAY":29,";":30,",":31,"VARIABLE":32,"DECIMAL":33,"NUMBER":34,"%":35,"#":36,"!":37,"$accept":0,"$end":1},
terminals_: {5:"EOF",7:"TIME_AMPM",8:"TIME_24",10:"STRING",11:"&",12:"=",13:"+",14:"(",15:")",16:"<",17:">",18:"NOT",19:"-",20:"*",21:"/",22:"^",23:"FUNCTION",26:"FIXEDCELL",27:":",28:"CELL",29:"ARRAY",30:";",31:",",32:"VARIABLE",33:"DECIMAL",34:"NUMBER",35:"%",36:"#",37:"!"},
productions_: [0,[3,2],[4,1],[4,1],[4,1],[4,1],[4,1],[4,3],[4,3],[4,3],[4,3],[4,4],[4,4],[4,4],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,2],[4,2],[4,3],[4,4],[4,1],[4,1],[4,2],[25,1],[25,3],[25,1],[25,3],[24,1],[24,1],[24,3],[24,3],[6,1],[6,3],[9,1],[9,3],[9,2],[2,3],[2,4]],
performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate /* action[1] */, $$ /* vstack */, _$ /* lstack */) {
/* this == yyval */
var $0 = $$.length - 1;
switch (yystate) {
case 1:
return $$[$0-1];
break;
case 2:
this.$ = yy.handler.helper.callVariable.call(this, $$[$0]);
break;
case 3:
this.$ = yy.handler.time.call(yy.obj, $$[$0], true);
break;
case 4:
this.$ = yy.handler.time.call(yy.obj, $$[$0]);
break;
case 5:
this.$ = yy.handler.helper.number($$[$0]);
break;
case 6:
this.$ = yy.handler.helper.string($$[$0]);
break;
case 7:
this.$ = yy.handler.helper.specialMatch('&', $$[$0-2], $$[$0]);
break;
case 8:
this.$ = yy.handler.helper.logicMatch('=', $$[$0-2], $$[$0]);
break;
case 9:
this.$ = yy.handler.helper.mathMatch('+', $$[$0-2], $$[$0]);
break;
case 10:
this.$ = yy.handler.helper.number($$[$0-1]);
break;
case 11:
this.$ = yy.handler.helper.logicMatch('<=', $$[$0-3], $$[$0]);
break;
case 12:
this.$ = yy.handler.helper.logicMatch('>=', $$[$0-3], $$[$0]);
break;
case 13:
this.$ = yy.handler.helper.logicMatch('<>', $$[$0-3], $$[$0]);
break;
case 14:
this.$ = yy.handler.helper.logicMatch('NOT', $$[$0-2], $$[$0]);
break;
case 15:
this.$ = yy.handler.helper.logicMatch('>', $$[$0-2], $$[$0]);
break;
case 16:
this.$ = yy.handler.helper.logicMatch('<', $$[$0-2], $$[$0]);
break;
case 17:
this.$ = yy.handler.helper.mathMatch('-', $$[$0-2], $$[$0]);
break;
case 18:
this.$ = yy.handler.helper.mathMatch('*', $$[$0-2], $$[$0]);
break;
case 19:
this.$ = yy.handler.helper.mathMatch('/', $$[$0-2], $$[$0]);
break;
case 20:
this.$ = yy.handler.helper.mathMatch('^', $$[$0-2], $$[$0]);
break;
case 21:
var n1 = yy.handler.helper.numberInverted($$[$0]);
this.$ = n1;
if (isNaN(this.$)) {
this.$ = 0;
}
break;
case 22:
var n1 = yy.handler.helper.number($$[$0]);
this.$ = n1;
if (isNaN(this.$)) {
this.$ = 0;
}
break;
case 23:
this.$ = yy.handler.helper.callFunction.call(this, $$[$0-2], '');
break;
case 24:
this.$ = yy.handler.helper.callFunction.call(this, $$[$0-3], $$[$0-1]);
break;
case 28:
this.$ = yy.handler.helper.fixedCellValue.call(yy.obj, $$[$0]);
break;
case 29:
this.$ = yy.handler.helper.fixedCellRangeValue.call(yy.obj, $$[$0-2], $$[$0]);
break;
case 30:
this.$ = yy.handler.helper.cellValue.call(yy.obj, $$[$0]);
break;
case 31:
this.$ = yy.handler.helper.cellRangeValue.call(yy.obj, $$[$0-2], $$[$0]);
break;
case 32:
if (yy.handler.utils.isArray($$[$0])) {
this.$ = $$[$0];
} else {
this.$ = [$$[$0]];
}
break;
case 33:
var result = [],
arr = eval("[" + yytext + "]");
arr.forEach(function (item) {
result.push(item);
});
this.$ = result;
break;
case 34: case 35:
$$[$0-2].push($$[$0]);
this.$ = $$[$0-2];
break;
case 36:
this.$ = [$$[$0]];
break;
case 37:
this.$ = (yy.handler.utils.isArray($$[$0-2]) ? $$[$0-2] : [$$[$0-2]]);
this.$.push($$[$0]);
break;
case 38:
this.$ = $$[$0];
break;
case 39:
this.$ = ($$[$0-2] + '.' + $$[$0]) * 1;
break;
case 40:
this.$ = $$[$0-1] * 0.01;
break;
case 41: case 42:
this.$ = $$[$0-2] + $$[$0-1] + $$[$0];
break;
}
},
table: [{2:13,3:1,4:2,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{1:[3]},{5:[1,19],11:$Vc,12:$Vd,13:$Ve,16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl},o($Vm,[2,2],{33:[1,30]}),o($Vm,[2,3]),o($Vm,[2,4]),o($Vm,[2,5],{35:[1,31]}),o($Vm,[2,6]),{2:13,4:32,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:33,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:34,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{14:[1,35]},o($Vm,[2,25]),o($Vm,[2,26],{2:36,32:[1,37],36:$Vb}),o($Vn,[2,36],{36:$Vo}),o($Vp,[2,38],{33:[1,39]}),o($Vm,[2,28],{27:[1,40]}),o($Vm,[2,30],{27:[1,41]}),{32:[1,42]},{1:[2,1]},{2:13,4:43,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:44,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:45,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:48,6:3,7:$V0,8:$V1,9:6,10:$V2,12:[1,46],13:$V3,14:$V4,17:[1,47],19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:50,6:3,7:$V0,8:$V1,9:6,10:$V2,12:[1,49],13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:51,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:52,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:53,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:54,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:55,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{32:[1,56]},o($Vp,[2,40]),{11:$Vc,12:$Vd,13:$Ve,15:[1,57],16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl},o($Vq,[2,21],{11:$Vc,20:$Vj,21:$Vk,22:$Vl}),o($Vq,[2,22],{11:$Vc,20:$Vj,21:$Vk,22:$Vl}),{2:13,4:60,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,15:[1,58],19:$V5,23:$V6,24:59,25:12,26:$V7,28:$V8,29:[1,61],32:$V9,34:$Va,36:$Vb},o($Vm,[2,27]),{36:$Vo},{32:[1,62]},{34:[1,63]},{26:[1,64]},{28:[1,65]},{37:[1,66]},o($Vm,[2,7]),o([5,12,15,30,31],[2,8],{11:$Vc,13:$Ve,16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vq,[2,9],{11:$Vc,20:$Vj,21:$Vk,22:$Vl}),{2:13,4:67,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:68,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},o($Vr,[2,16],{11:$Vc,13:$Ve,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),{2:13,4:69,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},o($Vr,[2,15],{11:$Vc,13:$Ve,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o([5,12,15,18,30,31],[2,14],{11:$Vc,13:$Ve,16:$Vf,17:$Vg,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vq,[2,17],{11:$Vc,20:$Vj,21:$Vk,22:$Vl}),o($Vs,[2,18],{11:$Vc,22:$Vl}),o($Vs,[2,19],{11:$Vc,22:$Vl}),o([5,12,13,15,16,17,18,19,20,21,22,30,31],[2,20],{11:$Vc}),o($Vn,[2,37]),o($Vm,[2,10]),o($Vm,[2,23]),{15:[1,70],30:[1,71],31:[1,72]},o($Vt,[2,32],{11:$Vc,12:$Vd,13:$Ve,16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vt,[2,33]),{37:[1,73]},o($Vp,[2,39]),o($Vm,[2,29]),o($Vm,[2,31]),o($Vu,[2,41]),o($Vr,[2,11],{11:$Vc,13:$Ve,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vr,[2,13],{11:$Vc,13:$Ve,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vr,[2,12],{11:$Vc,13:$Ve,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vm,[2,24]),{2:13,4:74,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},{2:13,4:75,6:3,7:$V0,8:$V1,9:6,10:$V2,13:$V3,14:$V4,19:$V5,23:$V6,25:12,26:$V7,28:$V8,32:$V9,34:$Va,36:$Vb},o($Vu,[2,42]),o($Vt,[2,34],{11:$Vc,12:$Vd,13:$Ve,16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl}),o($Vt,[2,35],{11:$Vc,12:$Vd,13:$Ve,16:$Vf,17:$Vg,18:$Vh,19:$Vi,20:$Vj,21:$Vk,22:$Vl})],
defaultActions: {19:[2,1]},
parseError: function parseError(str, hash) {
if (hash.recoverable) {
this.trace(str);
} else {
throw new Error(str);
}
},
parse: function parse(input) {
var self = this,
stack = [0],
tstack = [], // token stack
vstack = [null], // semantic value stack
lstack = [], // location stack
table = this.table,
yytext = '',
yylineno = 0,
yyleng = 0,
recovering = 0,
TERROR = 2,
EOF = 1;
var args = lstack.slice.call(arguments, 1);
//this.reductionCount = this.shiftCount = 0;
var lexer = Object.create(this.lexer);
var sharedState = { yy: {} };
// copy state
for (var k in this.yy) {
if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
sharedState.yy[k] = this.yy[k];
}
}
lexer.setInput(input, sharedState.yy);
sharedState.yy.lexer = lexer;
sharedState.yy.parser = this;
if (typeof lexer.yylloc == 'undefined') {
lexer.yylloc = {};
}
var yyloc = lexer.yylloc;
lstack.push(yyloc);
var ranges = lexer.options && lexer.options.ranges;
if (typeof sharedState.yy.parseError === 'function') {
this.parseError = sharedState.yy.parseError;
} else {
this.parseError = Object.getPrototypeOf(this).parseError;
}
function popStack (n) {
stack.length = stack.length - 2 * n;
vstack.length = vstack.length - n;
lstack.length = lstack.length - n;
}
_token_stack:
function lex() {
var token;
token = lexer.lex() || EOF;
// if token isn't its numeric value, convert
if (typeof token !== 'number') {
token = self.symbols_[token] || token;
}
return token;
}
var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected;
while (true) {
// retreive state number from top of stack
state = stack[stack.length - 1];
// use default actions if available
if (this.defaultActions[state]) {
action = this.defaultActions[state];
} else {
if (symbol === null || typeof symbol == 'undefined') {
symbol = lex();
}
// read action for current state and first input
action = table[state] && table[state][symbol];
}
_handle_error:
// handle parse error
if (typeof action === 'undefined' || !action.length || !action[0]) {
var error_rule_depth;
var errStr = '';
// Return the rule stack depth where the nearest error rule can be found.
// Return FALSE when no error recovery rule was found.
function locateNearestErrorRecoveryRule(state) {
var stack_probe = stack.length - 1;
var depth = 0;
// try to recover from error
for(;;) {
// check for error recovery rule in this state
if ((TERROR.toString()) in table[state]) {
return depth;
}
if (state === 0 || stack_probe < 2) {
return false; // No suitable error recovery rule available.
}
stack_probe -= 2; // popStack(1): [symbol, action]
state = stack[stack_probe];
++depth;
}
}
if (!recovering) {
// first see if there's any chance at hitting an error recovery rule:
error_rule_depth = locateNearestErrorRecoveryRule(state);
// Report error
expected = [];
for (p in table[state]) {
if (this.terminals_[p] && p > TERROR) {
expected.push("'"+this.terminals_[p]+"'");
}
}
if (lexer.showPosition) {
errStr = 'Parse error on line '+(yylineno+1)+":\n"+lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + (this.terminals_[symbol] || symbol)+ "'";
} else {
errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
(symbol == EOF ? "end of input" :
("'"+(this.terminals_[symbol] || symbol)+"'"));
}
this.parseError(errStr, {
text: lexer.match,
token: this.terminals_[symbol] || symbol,
line: lexer.yylineno,
loc: yyloc,
expected: expected,
recoverable: (error_rule_depth !== false)
});
} else if (preErrorSymbol !== EOF) {
error_rule_depth = locateNearestErrorRecoveryRule(state);
}
// just recovered from another error
if (recovering == 3) {
if (symbol === EOF || preErrorSymbol === EOF) {
throw new Error(errStr || 'Parsing halted while starting to recover from another error.');
}
// discard current lookahead and grab another
yyleng = lexer.yyleng;
yytext = lexer.yytext;
yylineno = lexer.yylineno;
yyloc = lexer.yylloc;
symbol = lex();
}
// try to recover from error
if (error_rule_depth === false) {
throw new Error(errStr || 'Parsing halted. No suitable error recovery rule available.');
}
popStack(error_rule_depth);
preErrorSymbol = (symbol == TERROR ? null : symbol); // save the lookahead token
symbol = TERROR; // insert generic error symbol as new lookahead
state = stack[stack.length-1];
action = table[state] && table[state][TERROR];
recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
}
// this shouldn't happen, unless resolve defaults are off
if (action[0] instanceof Array && action.length > 1) {
throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
}
switch (action[0]) {
case 1: // shift
//this.shiftCount++;
stack.push(symbol);
vstack.push(lexer.yytext);
lstack.push(lexer.yylloc);
stack.push(action[1]); // push state
symbol = null;
if (!preErrorSymbol) { // normal execution/no error
yyleng = lexer.yyleng;
yytext = lexer.yytext;
yylineno = lexer.yylineno;
yyloc = lexer.yylloc;
if (recovering > 0) {
recovering--;
}
} else {
// error just occurred, resume old lookahead f/ before error
symbol = preErrorSymbol;
preErrorSymbol = null;
}
break;
case 2:
// reduce
//this.reductionCount++;
len = this.productions_[action[1]][1];
// perform semantic action
yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
// default location, uses first token for firsts, last for lasts
yyval._$ = {
first_line: lstack[lstack.length-(len||1)].first_line,
last_line: lstack[lstack.length-1].last_line,
first_column: lstack[lstack.length-(len||1)].first_column,
last_column: lstack[lstack.length-1].last_column
};
if (ranges) {
yyval._$.range = [lstack[lstack.length-(len||1)].range[0], lstack[lstack.length-1].range[1]];
}
r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
if (typeof r !== 'undefined') {
return r;
}
// pop off stack
if (len) {
stack = stack.slice(0,-1*len*2);
vstack = vstack.slice(0, -1*len);
lstack = lstack.slice(0, -1*len);
}
stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
vstack.push(yyval.$);
lstack.push(yyval._$);
// goto new state = table[STATE][NONTERMINAL]
newState = table[stack[stack.length-2]][stack[stack.length-1]];
stack.push(newState);
break;
case 3:
// accept
return true;
}
}
return true;
}};
/* generated by jison-lex 0.3.4 */
var lexer = (function(){
var lexer = ({
EOF:1,
parseError:function parseError(str, hash) {
if (this.yy.parser) {
this.yy.parser.parseError(str, hash);
} else {
throw new Error(str);
}
},
// resets the lexer, sets new input
setInput:function (input, yy) {
this.yy = yy || this.yy || {};
this._input = input;
this._more = this._backtrack = this.done = false;
this.yylineno = this.yyleng = 0;
this.yytext = this.matched = this.match = '';
this.conditionStack = ['INITIAL'];
this.yylloc = {
first_line: 1,
first_column: 0,
last_line: 1,
last_column: 0
};
if (this.options.ranges) {
this.yylloc.range = [0,0];
}
this.offset = 0;
return this;
},
// consumes and returns one char from the input
input:function () {
var ch = this._input[0];
this.yytext += ch;
this.yyleng++;
this.offset++;
this.match += ch;
this.matched += ch;
var lines = ch.match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno++;
this.yylloc.last_line++;
} else {
this.yylloc.last_column++;
}
if (this.options.ranges) {
this.yylloc.range[1]++;
}
this._input = this._input.slice(1);
return ch;
},
// unshifts one char (or a string) into the input
unput:function (ch) {
var len = ch.length;
var lines = ch.split(/(?:\r\n?|\n)/g);
this._input = ch + this._input;
this.yytext = this.yytext.substr(0, this.yytext.length - len);
//this.yyleng -= len;
this.offset -= len;
var oldLines = this.match.split(/(?:\r\n?|\n)/g);
this.match = this.match.substr(0, this.match.length - 1);
this.matched = this.matched.substr(0, this.matched.length - 1);
if (lines.length - 1) {
this.yylineno -= lines.length - 1;
}
var r = this.yylloc.range;
this.yylloc = {
first_line: this.yylloc.first_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.first_column,
last_column: lines ?
(lines.length === oldLines.length ? this.yylloc.first_column : 0)
+ oldLines[oldLines.length - lines.length].length - lines[0].length :
this.yylloc.first_column - len
};
if (this.options.ranges) {
this.yylloc.range = [r[0], r[0] + this.yyleng - len];
}
this.yyleng = this.yytext.length;
return this;
},
// When called from action, caches matched text and appends it on next action
more:function () {
this._more = true;
return this;
},
// When called from action, signals the lexer that this rule fails to match the input, so the next matching rule (regex) should be tested instead.
reject:function () {
if (this.options.backtrack_lexer) {
this._backtrack = true;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
return this;
},
// retain first n characters of the match
less:function (n) {
this.unput(this.match.slice(n));
},
// displays already matched input, i.e. for error messages
pastInput:function () {
var past = this.matched.substr(0, this.matched.length - this.match.length);
return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
},
// displays upcoming input, i.e. for error messages
upcomingInput:function () {
var next = this.match;
if (next.length < 20) {
next += this._input.substr(0, 20-next.length);
}
return (next.substr(0,20) + (next.length > 20 ? '...' : '')).replace(/\n/g, "");
},
// displays the character position where the lexing error occurred, i.e. for error messages
showPosition:function () {
var pre = this.pastInput();
var c = new Array(pre.length + 1).join("-");
return pre + this.upcomingInput() + "\n" + c + "^";
},
// test the lexed token: return FALSE when not a match, otherwise return token
test_match:function (match, indexed_rule) {
var token,
lines,
backup;
if (this.options.backtrack_lexer) {
// save context
backup = {
yylineno: this.yylineno,
yylloc: {
first_line: this.yylloc.first_line,
last_line: this.last_line,
first_column: this.yylloc.first_column,
last_column: this.yylloc.last_column
},
yytext: this.yytext,
match: this.match,
matches: this.matches,
matched: this.matched,
yyleng: this.yyleng,
offset: this.offset,
_more: this._more,
_input: this._input,
yy: this.yy,
conditionStack: this.conditionStack.slice(0),
done: this.done
};
if (this.options.ranges) {
backup.yylloc.range = this.yylloc.range.slice(0);
}
}
lines = match[0].match(/(?:\r\n?|\n).*/g);
if (lines) {
this.yylineno += lines.length;
}
this.yylloc = {
first_line: this.yylloc.last_line,
last_line: this.yylineno + 1,
first_column: this.yylloc.last_column,
last_column: lines ?
lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length :
this.yylloc.last_column + match[0].length
};
this.yytext += match[0];
this.match += match[0];
this.matches = match;
this.yyleng = this.yytext.length;
if (this.options.ranges) {
this.yylloc.range = [this.offset, this.offset += this.yyleng];
}
this._more = false;
this._backtrack = false;
this._input = this._input.slice(match[0].length);
this.matched += match[0];
token = this.performAction.call(this, this.yy, this, indexed_rule, this.conditionStack[this.conditionStack.length - 1]);
if (this.done && this._input) {
this.done = false;
}
if (token) {
return token;
} else if (this._backtrack) {
// recover context
for (var k in backup) {
this[k] = backup[k];
}
return false; // rule action called reject() implying the next rule should be tested instead.
}
return false;
},
// return next match in input
next:function () {
if (this.done) {
return this.EOF;
}
if (!this._input) {
this.done = true;
}
var token,
match,
tempMatch,
index;
if (!this._more) {
this.yytext = '';
this.match = '';
}
var rules = this._currentRules();
for (var i = 0; i < rules.length; i++) {
tempMatch = this._input.match(this.rules[rules[i]]);
if (tempMatch && (!match || tempMatch[0].length > match[0].length)) {
match = tempMatch;
index = i;
if (this.options.backtrack_lexer) {
token = this.test_match(tempMatch, rules[i]);
if (token !== false) {
return token;
} else if (this._backtrack) {
match = false;
continue; // rule action called reject() implying a rule MISmatch.
} else {
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
} else if (!this.options.flex) {
break;
}
}
}
if (match) {
token = this.test_match(match, rules[index]);
if (token !== false) {
return token;
}
// else: this is a lexer rule which consumes input without producing a token (e.g. whitespace)
return false;
}
if (this._input === "") {
return this.EOF;
} else {
return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), {
text: "",
token: null,
line: this.yylineno
});
}
},
// return next match that has a token
lex:function lex() {
var r = this.next();
if (r) {
return r;
} else {
return this.lex();
}
},
// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
begin:function begin(condition) {
this.conditionStack.push(condition);
},
// pop the previously active lexer condition state off the condition stack
popState:function popState() {
var n = this.conditionStack.length - 1;
if (n > 0) {
return this.conditionStack.pop();
} else {
return this.conditionStack[0];
}
},
// produce the lexer rule set which is active for the currently active lexer condition state
_currentRules:function _currentRules() {
if (this.conditionStack.length && this.conditionStack[this.conditionStack.length - 1]) {
return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules;
} else {
return this.conditions["INITIAL"].rules;
}
},
// return the currently active lexer condition state; when an index argument is provided it produces the N-th previous condition state, if available
topState:function topState(n) {
n = this.conditionStack.length - 1 - Math.abs(n || 0);
if (n >= 0) {
return this.conditionStack[n];
} else {
return "INITIAL";
}
},
// alias for begin(condition)
pushState:function pushState(condition) {
this.begin(condition);
},
// return the number of states currently on the stack
stateStackSize:function stateStackSize() {
return this.conditionStack.length;
},
options: {},
performAction: function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
var YYSTATE=YY_START;
switch($avoiding_name_collisions) {
case 0:/* skip whitespace */
break;
case 1:return 10;
break;
case 2:return 10;
break;
case 3:return 23;
break;
case 4:return 7;
break;
case 5:return 8;
break;
case 6:return 26;
break;
case 7:return 26;
break;
case 8:return 26;
break;
case 9:return 28;
break;
case 10:return 23;
break;
case 11:return 32;
break;
case 12:return 32;
break;
case 13:return 34;
break;
case 14:return 29;
break;
case 15:/* skip whitespace */
break;
case 16:return 11;
break;
case 17:return ' ';
break;
case 18:return 33;
break;
case 19:return 27;
break;
case 20:return 30;
break;
case 21:return 31;
break;
case 22:return 20;
break;
case 23:return 21;
break;
case 24:return 19;
break;
case 25:return 13;
break;
case 26:return 22;
break;
case 27:return 14;
break;
case 28:return 15;
break;
case 29:return 17;
break;
case 30:return 16;
break;
case 31:return 18;
break;
case 32:return '"';
break;
case 33:return "'";
break;
case 34:return "!";
break;
case 35:return 12;
break;
case 36:return 35;
break;
case 37:return 36;
break;
case 38:return 5;
break;
}
},
rules: [/^(?:\s+)/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+(?=[(]))/,/^(?:([0]?[1-9]|1[0-2])[:][0-5][0-9]([:][0-5][0-9])?[ ]?(AM|am|aM|Am|PM|pm|pM|Pm))/,/^(?:([0]?[0-9]|1[0-9]|2[0-3])[:][0-5][0-9]([:][0-5][0-9])?)/,/^(?:\$[A-Za-z]+\$[0-9]+)/,/^(?:\$[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+\$[0-9]+)/,/^(?:[A-Za-z]+[0-9]+)/,/^(?:[A-Za-z]+(?=[(]))/,/^(?:[A-Za-z]{1,}[A-Za-z_0-9]+)/,/^(?:[A-Za-z_]+)/,/^(?:[0-9]+)/,/^(?:\[(.*)?\])/,/^(?:\$)/,/^(?:&)/,/^(?: )/,/^(?:[.])/,/^(?::)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\/)/,/^(?:-)/,/^(?:\+)/,/^(?:\^)/,/^(?:\()/,/^(?:\))/,/^(?:>)/,/^(?:<)/,/^(?:NOT\b)/,/^(?:")/,/^(?:')/,/^(?:!)/,/^(?:=)/,/^(?:%)/,/^(?:[#])/,/^(?:$)/,/(?:([0-9]+(\.[0-9]+)?)+(E|e)((-|\+)?[0-9]+))/],
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38, 39],"inclusive":true}}
});
return lexer;
})();
parser.lexer = lexer;
function Parser () {
this.yy = {};
}
Parser.prototype = parser;parser.Parser = Parser;
return new Parser;
})();

1314
vendor/assets/javascripts/ruleJS.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
td.formula {
background-color: yellow;
}
td.formula-error {
background-color: red;
}