function ExpressionPreviewDialog(title, cellIndex, rowIndices, values, expression, onDone) { this._onDone = onDone; var self = this; var frame = DialogSystem.createDialog(); frame.width("700px"); var header = $('
').addClass("dialog-header").text(title).appendTo(frame); var body = $('
').addClass("dialog-body").appendTo(frame); var footer = $('
').addClass("dialog-footer").appendTo(frame); var html = $(ExpressionPreviewDialog.generateWidgetHtml()).appendTo(body); this._elmts = DOM.bind(html); $('').html("  OK  ").click(function() { DialogSystem.dismissUntil(self._level - 1); self._onDone(self._previewWidget.getExpression(true)); }).appendTo(footer); $('').text("Cancel").click(function() { DialogSystem.dismissUntil(self._level - 1); }).appendTo(footer); this._level = DialogSystem.showDialog(frame); this._previewWidget = new ExpressionPreviewDialog.Widget( this._elmts, cellIndex, rowIndices, values, expression ); } ExpressionPreviewDialog.generateWidgetHtml = function() { var html = DOM.loadHTML("core", "scripts/dialogs/expression-preview-dialog.html"); var languageOptions = []; for (var prefix in theProject.scripting) { if (theProject.scripting.hasOwnProperty(prefix)) { var info = theProject.scripting[prefix]; languageOptions.push(''); } } return html.replace("$LANGUAGE_OPTIONS$", languageOptions.join("")); }; ExpressionPreviewDialog.Widget = function( elmts, cellIndex, rowIndices, values, expression ) { var language = "grel"; if (!(expression)) { language = $.cookie("scripting.lang"); if (language == "gel") { // backward compatible language = "grel"; } if (!(language) || !(language.toLowerCase() in theProject.scripting)) { language = "grel"; } this.expression = theProject.scripting[language].defaultExpression; } else { this.expression = expression; var colon = expression.indexOf(":"); if (colon > 0) { var l = expression.substring(0, colon); if (l.toLowerCase() in theProject.scripting) { this.expression = expression.substring(colon + 1); language = l; } } } this._elmts = elmts; this._cellIndex = cellIndex; this._rowIndices = rowIndices; this._values = values; this._results = null; this._timerID = null; $("#expression-preview-tabs").tabs(); $("#expression-preview-tabs-history").css("display", ""); $("#expression-preview-tabs-help").css("display", ""); this._elmts.expressionPreviewLanguageSelect[0].value = language; this._elmts.expressionPreviewLanguageSelect.bind("change", function() { $.cookie("scripting.lang", this.value); self.update(); }); var self = this; this._elmts.expressionPreviewTextarea .attr("value", this.expression) .keyup(function(){ self._scheduleUpdate(); }) .select() .focus(); this.update(); this._renderExpressionHistoryTab(); this._renderHelpTab(); }; ExpressionPreviewDialog.Widget.prototype.getExpression = function(commit) { var s = $.trim(this.expression || ""); if (!s.length) { return null; } s = this._getLanguage() + ":" + s; if (commit) { $.post( "/command/core/log-expression?" + $.param({ project: theProject.id, expression: s }), null, function(data) { }, "json" ); } return s; }; ExpressionPreviewDialog.Widget.prototype._getLanguage = function() { return this._elmts.expressionPreviewLanguageSelect[0].value; }; ExpressionPreviewDialog.Widget.prototype._renderHelpTab = function() { var self = this; $.getJSON( "/command/core/get-expression-language-info", null, function(data) { self._renderHelp(data); }, "json" ); }; ExpressionPreviewDialog.Widget.prototype._renderHelp = function(data) { var elmt = this._elmts.expressionPreviewHelpTabBody.empty(); $('

').text("Variables").appendTo(elmt); var varTable = $('
').appendTo(elmt)[0]; var vars = [ { name: "cell", description: "The current cell. It has a few fields: 'value' and 'recon'." }, { name: "value", description: "The current cell's value. This is a shortcut for 'cell.value'." }, { name: "row", description: "The current row. It has 4 fields: 'flagged', 'starred', 'index', and 'cells'." }, { name: "cells", description: "The cells of the current row. This is a shortcut for 'row.cells'. " + "A particular cell can be retrieved with 'cells.' if the is a single word, " + "or with 'cells[\"\"] otherwise." }, { name: "rowIndex", description: "The current row's index. This is a shortcut for 'row.index'." } ]; for (var i = 0; i < vars.length; i++) { var variable = vars[i]; var tr = varTable.insertRow(varTable.rows.length); $(tr.insertCell(0)).addClass("expression-preview-doc-item-title").text(variable.name); $(tr.insertCell(1)).addClass("expression-preview-doc-item-desc").text(variable.description); } var renderEntry = function(table, name, entry) { var tr0 = table.insertRow(table.rows.length); var tr1 = table.insertRow(table.rows.length); var tr2 = table.insertRow(table.rows.length); $(tr0.insertCell(0)).addClass("expression-preview-doc-item-title").text(name); $(tr0.insertCell(1)).addClass("expression-preview-doc-item-params").text("(" + entry.params + ")"); $(tr1.insertCell(0)); $(tr1.insertCell(1)).addClass("expression-preview-doc-item-returns").text("returns: " + entry.returns); $(tr2.insertCell(0)); $(tr2.insertCell(1)).addClass("expression-preview-doc-item-desc").text(entry.description); }; var renderEntries = function(table, map) { var names = []; for (var n in map) { if (map.hasOwnProperty(n)) { names.push(n); } } names.sort(); for (var i = 0; i < names.length; i++) { var name = names[i]; renderEntry(table, name, map[name]); } }; $('

').text("Functions").appendTo(elmt); var functionTable = $('
').appendTo(elmt)[0]; renderEntries(functionTable, data.functions); $('

').text("Controls").appendTo(elmt); var controlTable = $('
').appendTo(elmt)[0]; renderEntries(controlTable, data.controls); }; ExpressionPreviewDialog.Widget.prototype._renderExpressionHistoryTab = function() { var self = this; $.getJSON( "/command/core/get-expression-history?" + $.param({ project: theProject.id }), null, function(data) { self._renderExpressionHistory(data); }, "json" ); }; ExpressionPreviewDialog.Widget.prototype._renderExpressionHistory = function(data) { var self = this; var elmt = this._elmts.expressionPreviewHistoryContainer.empty(); var table = $( '' + '' + '
FromExpression
' ).appendTo(elmt)[0]; var renderEntry = function(entry) { var tr = table.insertRow(table.rows.length); var o = Scripting.parse(entry.code); $('Reuse').appendTo(tr.insertCell(0)).click(function() { self._elmts.expressionPreviewTextarea[0].value = o.expression; self._elmts.expressionPreviewLanguageSelect[0].value = o.language; $("#expression-preview-tabs").tabs('option', 'selected', 0); self._elmts.expressionPreviewTextarea.select().focus(); self.update(); }); $(tr.insertCell(1)).html(entry.global ? "Other projects" : "This project"); $(tr.insertCell(2)).text(o.language + ":"); $(tr.insertCell(3)).text(o.expression); }; for (var i = 0; i < data.expressions.length; i++) { var entry = data.expressions[i]; renderEntry(entry); } }; ExpressionPreviewDialog.Widget.prototype._scheduleUpdate = function() { if (this._timerID !== null) { window.clearTimeout(this._timerID); } var self = this; this._timerID = window.setTimeout(function() { self.update(); }, 300); }; ExpressionPreviewDialog.Widget.prototype.update = function() { var self = this; var expression = this.expression = $.trim(this._elmts.expressionPreviewTextarea[0].value); var params = { project: theProject.id, expression: this._getLanguage() + ":" + expression, cellIndex: this._cellIndex }; this._prepareUpdate(params); $.post( "/command/core/preview-expression?" + $.param(params), { rowIndices: JSON.stringify(this._rowIndices) }, function(data) { if (data.code != "error") { self._results = data.results; } else { self._results = null; } self._renderPreview(expression, data); }, "json" ); }; ExpressionPreviewDialog.Widget.prototype._prepareUpdate = function(params) { }; ExpressionPreviewDialog.Widget.prototype._renderPreview = function(expression, data) { var container = this._elmts.expressionPreviewPreviewContainer.empty(); var table = $('
').appendTo(container)[0]; var tr = table.insertRow(0); $(tr.insertCell(0)).addClass("expression-preview-heading").text("row"); $(tr.insertCell(1)).addClass("expression-preview-heading").text("value"); $(tr.insertCell(2)).addClass("expression-preview-heading").text(expression); var renderValue = function(td, v) { if (v !== null && v !== undefined) { if ($.isPlainObject(v)) { $('').addClass("expression-preview-special-value").text("Error: " + v.message).appendTo(td); } else { td.text(v); } } else { $('null').addClass("expression-preview-special-value").appendTo(td); } }; if (this._results !== null) { this._elmts.expressionPreviewErrorContainer.empty().text("No syntax error."); } else { var message = (data.type == "parser") ? data.message : "Internal error"; this._elmts.expressionPreviewErrorContainer.empty().text(message); } for (var i = 0; i < this._values.length; i++) { var tr = table.insertRow(table.rows.length); $(tr.insertCell(0)).attr("width", "1%").html((this._rowIndices[i] + 1) + "."); renderValue($(tr.insertCell(1)).addClass("expression-preview-value"), this._values[i]); var tdValue = $(tr.insertCell(2)).addClass("expression-preview-value"); if (this._results !== null) { var v = this._results[i]; renderValue(tdValue, v); } } };