diff --git a/js/freeboard+plugins.js b/js/freeboard+plugins.js index cf3bf1e..40af892 100644 --- a/js/freeboard+plugins.js +++ b/js/freeboard+plugins.js @@ -1332,7 +1332,10 @@ PluginEditor = function(jsEditor, valueEditor) ValueEditor = function(theFreeboardModel) { - var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\].)?$"); + var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\]\\[\")?(.*)$"); + + var _autocompleteOptions = []; + var _autocompleteReplacementString; function _resizeValueEditor(element) { @@ -1343,6 +1346,126 @@ ValueEditor = function(theFreeboardModel) $(element).css({height: newHeight + "px"}); } + function _autocompleteFromDatasource(inputString, datasources) + { + var match = _veDatasourceRegex.exec(inputString); + + var options = []; + var replacementString; + + if(match) + { + if(match[1] == "") // List all datasources + { + _.each(datasources, function(datasource) + { + options.push({value: datasource.name(), follow_char: "\"][\""}); + }); + } + else if(match[1] != "" && _.isUndefined(match[2])) // List partial datasources + { + replacementString = match[1]; + + _.each(datasources, function(datasource) + { + var dsName = datasource.name(); + + if(dsName != replacementString && dsName.indexOf(replacementString) == 0) + { + options.push({value: dsName, follow_char: "\"][\""}); + } + }); + } + else + { + var datasource = _.find(datasources, function(datasource) + { + return (datasource.name() === match[1]); + }); + + if(!_.isUndefined(datasource)) + { + var dataPath = ""; + + if(!_.isUndefined(match[2])) + { + dataPath = match[2] + match[3]; + } + + var dataPathItems = dataPath.split("\"][\""); + dataPath = "data"; + + for(var index = 1; index < dataPathItems.length - 1; index++) + { + if(dataPathItems[index] != "") + { + dataPathItem = "[\"" + dataPathItems[index] + "\"]"; + dataPath = dataPath + dataPathItem; + } + } + + var lastPathObject = _.last(dataPathItems); + + // If the last character is a ", then ignore it + if(lastPathObject.charAt(lastPathObject.length - 1) == "\"") + { + lastPathObject = lastPathObject.replace(/\[\"?$/, ""); + dataPath = dataPath + "[\"" + lastPathObject + "\"]"; + } + + var dataValue = datasource.getDataRepresentation(dataPath); + + if(_.isArray(dataValue)) + { + for(var index = 0; index < dataValue.length; index++) + { + var followChar = "\"]"; + + if(_.isObject(dataValue[index])) + { + followChar = followChar + "\"][\""; + } + else if(_.isArray(dataValue[index])) + { + followChar = followChar + "\"]["; + } + + options.push({value: index, follow_char: followChar}); + } + } + else if(_.isObject(dataValue)) + { + replacementString = lastPathObject; + + if(_.keys(dataValue).indexOf(replacementString) == -1) + { + _.each(dataValue, function(value, name) + { + if(name != lastPathObject && name.indexOf(lastPathObject) == 0) + { + var followChar = "\"]"; + + if(_.isArray(value)) + { + followChar = "\"]["; + } + else if(_.isObject(value)) + { + followChar = "\"][\""; + } + + options.push({value: name, follow_char: followChar}); + } + }); + } + } + } + } + } + _autocompleteOptions = options; + _autocompleteReplacementString = replacementString; + } + function createValueEditor(element) { var dropdown = null; @@ -1360,121 +1483,9 @@ ValueEditor = function(theFreeboardModel) var inputString = $(element).val().substring(0, $(element).getCaretPosition()); inputString = inputString.replace(String.fromCharCode(160), " "); // Weird issue where the textarea box was putting in ASCII (non breaking space) for spaces. - var match = _veDatasourceRegex.exec(inputString); + _autocompleteFromDatasource(inputString, theFreeboardModel.datasources()); - var options = []; - var replacementString; - - if(match) - { - if(match[1] == "") // List all datasources - { - _.each(theFreeboardModel.datasources(), function(datasource) - { - options.push({value: datasource.name(), follow_char: "\"]."}); - }); - } - else if(match[1] != "" && _.isUndefined(match[2])) // List partial datasources - { - replacementString = match[1]; - - _.each(theFreeboardModel.datasources(), function(datasource) - { - var dsName = datasource.name(); - - if(dsName != replacementString && dsName.indexOf(replacementString) == 0) - { - options.push({value: dsName, follow_char: "\"]."}); - } - }); - } - else - { - var datasource = _.find(theFreeboardModel.datasources(), function(datasource) - { - return (datasource.name() === match[1]); - }); - - if(!_.isUndefined(datasource)) - { - var dataPath = ""; - - if(!_.isUndefined(match[2])) - { - dataPath = match[2]; - } - - var dataPathItems = dataPath.split("."); - dataPath = "data"; - - for(var index = 1; index < dataPathItems.length - 1; index++) - { - if(dataPathItems[index] != "") - { - dataPath = dataPath + "." + dataPathItems[index]; - } - } - - var lastPathObject = _.last(dataPathItems); - - // If the last character is a [, then ignore it - if(lastPathObject.charAt(lastPathObject.length - 1) == "[") - { - lastPathObject = lastPathObject.replace(/\[+$/, ""); - dataPath = dataPath + "." + lastPathObject; - } - - var dataValue = datasource.getDataRepresentation(dataPath); - - if(_.isArray(dataValue)) - { - for(var index = 0; index < dataValue.length; index++) - { - var followChar = "]"; - - if(_.isObject(dataValue[index])) - { - followChar = followChar + "."; - } - else if(_.isArray(dataValue[index])) - { - followChar = followChar + "["; - } - - options.push({value: index, follow_char: followChar}); - } - } - else if(_.isObject(dataValue)) - { - replacementString = lastPathObject; - - if(_.keys(dataValue).indexOf(replacementString) == -1) - { - _.each(dataValue, function(value, name) - { - if(name != lastPathObject && name.indexOf(lastPathObject) == 0) - { - var followChar = undefined; - - if(_.isArray(value)) - { - followChar = "["; - } - else if(_.isObject(value)) - { - followChar = "."; - } - - options.push({value: name, follow_char: followChar}); - } - }); - } - } - } - } - } - - if(options.length > 0) + if(_autocompleteOptions.length > 0) { if(!dropdown) { @@ -1489,7 +1500,7 @@ ValueEditor = function(theFreeboardModel) var currentIndex = 0; - _.each(options, function(option) + _.each(_autocompleteOptions, function(option) { var li = $('
  • ' + option.value + '
  • ').appendTo(dropdown).mouseenter(function() { @@ -1507,13 +1518,13 @@ ValueEditor = function(theFreeboardModel) optionValue = optionValue + option.follow_char; } - if(!_.isUndefined(replacementString)) + if(!_.isUndefined(_autocompleteReplacementString)) { - var replacementIndex = inputString.lastIndexOf(replacementString); + var replacementIndex = inputString.lastIndexOf(_autocompleteReplacementString); if(replacementIndex != -1) { - $(element).replaceTextAt(replacementIndex, replacementIndex + replacementString.length, optionValue); + $(element).replaceTextAt(replacementIndex, replacementIndex + _autocompleteReplacementString.length, optionValue); } } else diff --git a/js/freeboard+plugins.min.js b/js/freeboard+plugins.min.js index 85b6971..45c8d19 100644 --- a/js/freeboard+plugins.min.js +++ b/js/freeboard+plugins.min.js @@ -1,2 +1,2 @@ -function DialogBox(e,t,n,i,a){function s(){o.fadeOut(200,function(){$(this).remove()})}var o=$(''),r=$('');r.append('

    '+t+"

    "),$("
    ").appendTo(r).append(e);var d=$("").appendTo(r);n&&$(''+n+"").appendTo(d).click(function(){var e=!1;_.isFunction(a)&&(e=a()),e||s()}),i&&$(''+i+"").appendTo(d).click(function(){s()}),o.append(r),$("body").append(o),o.fadeIn(200)}function FreeboardModel(e,t,n){var i=this,a=1;this.version=0,this.isEditing=ko.observable(!1),this.allow_edit=ko.observable(!1),this.allow_edit.subscribe(function(e){e?$("#main-header").show():$("#main-header").hide()}),this.header_image=ko.observable(),this.plugins=ko.observableArray(),this.datasources=ko.observableArray(),this.panes=ko.observableArray(),this.datasourceData={},this.processDatasourceUpdate=function(e,t){var n=e.name();i.datasourceData[n]=t,_.each(i.panes(),function(e){_.each(e.widgets(),function(e){e.processDatasourceUpdate(n)})})},this._datasourceTypes=ko.observable(),this.datasourceTypes=ko.computed({read:function(){i._datasourceTypes();var t=[];return _.each(e,function(e){var n=e.type_name,i=n;_.isUndefined(e.display_name)||(i=e.display_name),t.push({name:n,display_name:i})}),t}}),this._widgetTypes=ko.observable(),this.widgetTypes=ko.computed({read:function(){i._widgetTypes();var e=[];return _.each(t,function(t){var n=t.type_name,i=n;_.isUndefined(t.display_name)||(i=t.display_name),e.push({name:n,display_name:i})}),e}}),this.addPluginSource=function(e){e&&-1==i.plugins.indexOf(e)&&i.plugins.push(e)},this.serialize=function(){var e=[];_.each(i.panes(),function(t){e.push(t.serialize())});var t=[];return _.each(i.datasources(),function(e){t.push(e.serialize())}),{version:a,header_image:i.header_image(),allow_edit:i.allow_edit(),plugins:i.plugins(),panes:e,datasources:t}},this.deserialize=function(n,a){function s(){_.isUndefined(n.allow_edit)?i.allow_edit(!0):i.allow_edit(n.allow_edit),i.version=n.version||0,i.header_image(n.header_image),_.each(n.datasources,function(t){var n=new DatasourceModel(i,e);n.deserialize(t),i.addDatasource(n)});var s=_.sortBy(n.panes,function(e){return freeboard._getPositionForScreenSize(e).row});_.each(s,function(e){var n=new PaneModel(i,t);n.deserialize(e),i.panes.push(n)}),i.allow_edit()&&0==i.panes().length&&i.setEditing(!0),_.isFunction(a)&&a()}i.clearDashboard(),_.each(n.plugins,function(e){i.addPluginSource(e)}),_.isArray(n.plugins)&&n.plugins.length>0?head.js(n.plugins,function(){s()}):s()},this.clearDashboard=function(){freeboard._removeAllWidgets(),_.each(i.datasources(),function(e){e.dispose()}),_.each(i.panes(),function(e){e.dispose()}),i.plugins.removeAll(),i.datasources.removeAll(),i.panes.removeAll()},this.loadDashboard=function(e,t){n.showLoadingIndicator(!0),i.deserialize(e,function(){n.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("dashboard_loaded")})},this.loadDashboardFromLocalFile=function(){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var e=document.createElement("input");e.type="file",$(e).on("change",function(e){var t=e.target.files;if(t&&t.length>0){var n=t[0],a=new FileReader;a.addEventListener("load",function(e){var t=e.target,n=JSON.parse(t.result);i.loadDashboard(n),i.setEditing(!1)}),a.readAsText(n)}}),$(e).trigger("click")}else alert("Unable to load a file in this browser.")},this.saveDashboard=function(){var e="application/octet-stream",t=document.createElement("a"),n=new Blob([JSON.stringify(i.serialize())],{type:e});document.body.appendChild(t),t.href=window.URL.createObjectURL(n),t.download="dashboard.json",t.target="_self",t.click()},this.addDatasource=function(e){i.datasources.push(e)},this.deleteDatasource=function(e){delete i.datasourceData[e.name()],e.dispose(),i.datasources.remove(e)},this.createPane=function(){var e=new PaneModel(i,t);i.addPane(e)},this.addPane=function(e){i.panes.push(e)},this.deletePane=function(e){e.dispose(),i.panes.remove(e)},this.deleteWidget=function(e){ko.utils.arrayForEach(i.panes(),function(t){t.widgets.remove(e)}),e.dispose()},this.setEditing=function(e,t){if(i.allow_edit()||!e){i.isEditing(e),_.isUndefined(t)&&(t=!0);var a=t?250:0,s=$("#admin-bar").outerHeight();e?($("#toggle-header-icon").addClass("icon-chevron-up").removeClass("icon-wrench"),$(".gridster .gs_w").css({cursor:"pointer"}),$("#main-header").animate({top:"0px"},a),$("#board-content").animate({top:s+20+"px"},a),$("#main-header").data().shown=!0,n.attachWidgetEditIcons($(".sub-section")),freeboard._enableGrid()):($("#toggle-header-icon").addClass("icon-wrench").removeClass("icon-chevron-up"),$(".gridster .gs_w").css({cursor:"default"}),$("#main-header").animate({top:"-"+s+"px"},a),$("#board-content").animate({top:"20"},a),$("#main-header").data().shown=!1,$(".sub-section").unbind(),freeboard._disableGrid()),n.showPaneEditIcons(e,t)}},this.toggleEditing=function(){var e=!i.isEditing();i.setEditing(e)}}function FreeboardUI(){function e(e){e?a.fadeOut(0).appendTo("body").fadeIn(500):a.fadeOut(500).remove()}function t(e,t){_.isUndefined(t)&&(t=!0);var n=t?250:0;e?$(".pane-tools").fadeIn(n):$(".pane-tools").fadeOut(n)}function n(e){$(e).hover(function(){i(this,!0)},function(){i(this,!1)})}function i(e,t){t?$(e).find(".sub-section-tools").fadeIn(250):$(e).find(".sub-section-tools").fadeOut(250)}var a=$('
    ');return{showLoadingIndicator:function(t){e(t)},showPaneEditIcons:function(e,n){t(e,n)},attachWidgetEditIcons:function(e){n(e)}}}function PaneModel(e,t){var n=this;this.title=ko.observable(),this.width=ko.observable(1),this.row={},this.col={},this.col_width=ko.observable(1),this.widgets=ko.observableArray(),this.addWidget=function(e){this.widgets.push(e)},this.widgetCanMoveUp=function(e){return n.widgets.indexOf(e)>=1},this.widgetCanMoveDown=function(e){var t=n.widgets.indexOf(e);return n.widgets().length-1>t},this.moveWidgetUp=function(e){if(n.widgetCanMoveUp(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t-1,2,i[t],i[t-1])}},this.moveWidgetDown=function(e){if(n.widgetCanMoveDown(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t,2,i[t+1],i[t])}},this.getCalculatedHeight=function(){var e=_.reduce(n.widgets(),function(e,t){return e+t.height()},0);e*=6,e+=3,e*=10;var t=Math.ceil((e+20)/30);return Math.max(4,t)},this.serialize=function(){var e=[];return _.each(n.widgets(),function(t){e.push(t.serialize())}),{title:n.title(),width:n.width(),row:n.row,col:n.col,col_width:n.col_width(),widgets:e}},this.deserialize=function(i){n.title(i.title),n.width(i.width),n.row=i.row,n.col=i.col,n.col_width(i.col_width||1),_.each(i.widgets,function(i){var a=new WidgetModel(e,t);a.deserialize(i),n.widgets.push(a)})},this.dispose=function(){_.each(n.widgets(),function(e){e.dispose()})}}function WidgetModel(e,t){function n(){_.isUndefined(i.widgetInstance)||(_.isFunction(i.widgetInstance.onDispose)&&i.widgetInstance.onDispose(),i.widgetInstance=void 0)}var i=this;this.datasourceRefreshNotifications={},this.calculatedSettingScripts={},this.title=ko.observable(),this.fillSize=ko.observable(!1),this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.fillSize(s.fill_size===!0),i.widgetInstance=e,i.shouldRender(!0),i._heightUpdate.valueHasMutated()})}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onSettingsChanged)&&i.widgetInstance.onSettingsChanged(e),i.updateCalculatedSettings(),i._heightUpdate.valueHasMutated()}),this.processDatasourceUpdate=function(e){var t=i.datasourceRefreshNotifications[e];_.isArray(t)&&_.each(t,function(e){i.processCalculatedSetting(e)})},this.callValueFunction=function(t){return t.call(void 0,e.datasourceData)},this.processCalculatedSetting=function(e){if(_.isFunction(i.calculatedSettingScripts[e])){var t=void 0;try{t=i.callValueFunction(i.calculatedSettingScripts[e])}catch(n){var a=i.settings()[e];n instanceof ReferenceError&&/^\w+$/.test(a)&&(t=a)}if(!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onCalculatedValueChanged)&&!_.isUndefined(t))try{i.widgetInstance.onCalculatedValueChanged(e,t)}catch(n){console.log(""+n)}}},this.updateCalculatedSettings=function(){if(i.datasourceRefreshNotifications={},i.calculatedSettingScripts={},!_.isUndefined(i.type())){var e=t[i.type()].settings,n=RegExp("datasources.([\\w_-]+)|datasources\\[['\"]([^'\"]+)","g"),a=i.settings();_.each(e,function(e){if("calculated"==e.type){var t=a[e.name];if(!_.isUndefined(t)){1>=(t.match(/;/g)||[]).length&&-1==t.indexOf("return")&&(t="return "+t);var s;try{s=Function("datasources",t)}catch(o){var r=a[e.name].replace(/"/g,'\\"').replace(/[\r\n]/g," \\\n");s=Function("datasources",'return "'+r+'";')}i.calculatedSettingScripts[e.name]=s,i.processCalculatedSetting(e.name);for(var d;d=n.exec(t);){var l=d[1]||d[2],c=i.datasourceRefreshNotifications[l];_.isUndefined(c)&&(c=[],i.datasourceRefreshNotifications[l]=c),c.push(e.name)}}}})}},this._heightUpdate=ko.observable(),this.height=ko.computed({read:function(){return i._heightUpdate(),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.getHeight)?i.widgetInstance.getHeight():1}}),this.shouldRender=ko.observable(!1),this.render=function(e){i.shouldRender(!1),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.render)&&(i.widgetInstance.render(e),i.updateCalculatedSettings())},this.dispose=function(){},this.serialize=function(){return{title:i.title(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.title(e.title),i.settings(e.settings),i.type(e.type)}}DatasourceModel=function(e,t){function n(){_.isUndefined(i.datasourceInstance)||(_.isFunction(i.datasourceInstance.onDispose)&&i.datasourceInstance.onDispose(),i.datasourceInstance=void 0)}var i=this;this.name=ko.observable(),this.latestData=ko.observable(),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.onSettingsChanged)&&i.datasourceInstance.onSettingsChanged(e)}),this.updateCallback=function(t){e.processDatasourceUpdate(i,t),i.latestData(t);var n=new Date;i.last_updated(n.toLocaleTimeString())},this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.datasourceInstance=e,e.updateNow()},i.updateCallback)}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.last_updated=ko.observable("never"),this.last_error=ko.observable(),this.serialize=function(){return{name:i.name(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.settings(e.settings),i.name(e.name),i.type(e.type)},this.getDataRepresentation=function(e){var t=Function("data","return "+e+";");return t.call(void 0,i.latestData())},this.updateNow=function(){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.updateNow)&&i.datasourceInstance.updateNow()},this.dispose=function(){n()}},DeveloperConsole=function(e){function t(){function t(e){var t=$(""),i=$(''),a=$(''),s=$('
  • ').click(function(){n=_.without(n,a),t.remove()});n.push(a),e&&a.val(e),i.append(s),o.append(t.append($("").append(a)).append($('').append(i)))}var n=[],i=$("
    "),a=$('
    ADD
    '),s=$('
    ');s.append($('Plugin Script URL'));var o=$("");s.append(o),i.append($("

    Here you can add references to other scripts to load datasource or widget plugins.

    ")).append(s).append(a).append('

    To learn how to build plugins for freeboard, please visit http://freeboard.github.io/freeboard/docs/plugin_example.html

    '),_.each(e.plugins(),function(e){t(e)}),a.click(function(){t()}),new DialogBox(i,"Developer Console","OK",null,function(){_.each(e.plugins(),function(e){$('script[src^="'+e+'"]').remove()}),e.plugins.removeAll(),_.each(n,function(t){var n=t.val();n&&n.length>0&&(e.addPluginSource(n),head.js(n+"?"+Date.now()))})})}return{showDeveloperConsole:function(){t()}}},JSEditor=function(){function e(e){n=e}function t(e,t){head.js(n+"css/codemirror.css",n+"css/codemirror-ambiance.css",n+"js/codemirror.js",function(){var n='// Example: Convert temp from C to F and truncate to 2 decimal places.\n// return (datasources["MyDatasource"].sensor.tempInF * 1.8 + 32).toFixed(2);';e||(e=n);var i=$('
    '),a=$('
    '),s=$(''),o=$('
    This javascript will be re-evaluated any time a datasource referenced here is updated, and the value you return will be displayed in the widget. You can assume this javascript is wrapped in a function of the form function(datasources) where datasources is a collection of javascript objects (keyed by their name) corresponding to the most current data in a datasource.
    ');i.append([o,a,s]),$("body").append(i);var r=CodeMirror(a.get(0),{value:e,mode:"javascript",theme:"ambiance",indentUnit:4,lineNumbers:!0,matchBrackets:!0,autoCloseBrackets:!0}),d=$('Close').click(function(){if(t){var e=r.getValue();e===n&&(e=""),t(e),i.remove()}});s.append(d)})}var n="";return{displayJSEditor:function(e,n){t(e,n)},setAssetRoot:function(){e(_assetRoot)}}},PluginEditor=function(e,t){function n(e,t){var n=$('
    ').html(t);$("#setting-value-container-"+e).append(n)}function i(){$("#setting-row-instance-name").length?$("#setting-row-instance-name").nextAll().remove():$("#setting-row-plugin-types").nextAll().remove()}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function s(s,o,r,d,l){function c(e,t){var n=$('
    ').appendTo(h);return n.append('
    "),$('
    ').appendTo(n)}function u(n){_.each(n,function(n){function i(){f.settings[n.name].length>0?u.show():u.hide()}function a(e){var t=$("").appendTo(h),a={};_.isArray(f.settings[n.name])||(f.settings[n.name]=[]),f.settings[n.name].push(a),_.each(n.settings,function(n){var i=$("").appendTo(t),s="";_.isUndefined(e[n.name])||(s=e[n.name]),a[n.name]=s,$('').appendTo(i).val(s).change(function(){a[n.name]=$(this).val()})}),t.append($('').append($('').append($("
  • ").append($('').click(function(){var e=f.settings[n.name].indexOf(a);-1!=e&&(f.settings[n.name].splice(e,1),t.remove(),i())}))))),r.scrollTop(r[0].scrollHeight),i()}!_.isUndefined(n.default_value)&&_.isUndefined(d[n.name])&&(d[n.name]=n.default_value);var s=n.name;_.isUndefined(n.display_name)||(s=n.display_name);var o=c(n.name,s);switch(n.type){case"array":var r=$('
    ').appendTo(o),l=$('
    ').appendTo(r),u=$("").hide().appendTo(l),p=$("").appendTo(u),h=$("").appendTo(l),g=[];_.each(n.settings,function(e){var t=e.name;_.isUndefined(e.display_name)||(t=e.display_name),$(""+t+"").appendTo(p)}),n.name in d&&(g=d[n.name]),$('
    ADD
    ').appendTo(o).click(function(){var e={};_.each(n.settings,function(t){e[t.name]=""}),a(e)}),_.each(g,function(e){a(e)});break;case"boolean":f.settings[n.name]=d[n.name];var m=$('
    ').appendTo(o),v=$('').prependTo(m).change(function(){f.settings[n.name]=this.checked});n.name in d&&v.prop("checked",d[n.name]);break;case"option":var y=d[n.name],v=$("").appendTo($('
    ').appendTo(o)).change(function(){f.settings[n.name]=$(this).val()});_.each(n.options,function(e){var t,n;_.isObject(e)?(t=e.name,n=e.value):t=e,_.isUndefined(n)&&(n=t),_.isUndefined(y)&&(y=n),$("").text(t).attr("value",n).appendTo(v)}),f.settings[n.name]=y,n.name in d&&v.val(d[n.name]);break;default:if(f.settings[n.name]=d[n.name],"calculated"==n.type){var v=$("").appendTo(o).change(function(){f.settings[n.name]=$(this).val()});n.name in d&&v.val(d[n.name]),t.createValueEditor(v);var w=$(''),b=$('
  • ').mousedown(function(e){e.preventDefault(),$(v).focus(),$(v).insertAtCaret('datasources["'),$(v).trigger("freeboard-eval")}),x=$('
  • ').mousedown(function(t){t.preventDefault(),e.displayJSEditor(v.val(),function(e){v.val(e),v.change()})});$(o).append(w.append([b,x]))}else{var v=$('').appendTo(o).change(function(){f.settings[n.name]="number"==n.type?Number($(this).val()):$(this).val()});n.name in d&&v.val(d[n.name])}}_.isUndefined(n.suffix)||o.append($('
    '+n.suffix+"
    ")),_.isUndefined(n.description)||o.append($('
    '+n.description+"
    "))})}var p,f={type:r,settings:{}},h=$("
    "),g=$('
    ').hide();h.append(g),new DialogBox(h,s,"Save","Cancel",function(){$(".validation-error").remove();for(var e=0;p.settings.length>e;e++){var t=p.settings[e];if(t.required&&(_.isUndefined(f.settings[t.name])||""==f.settings[t.name]))return n(t.name,"This is required."),!0;if("number"==t.type&&!a(f.settings[t.name]))return n(t.name,"Must be a number."),!0}_.isFunction(l)&&l(f)});var m,v=_.keys(o);if(v.length>1){var y=c("plugin-types","Type");m=$("").appendTo($('
    ').appendTo(y)),m.append($("").attr("value","undefined")),_.each(o,function(e){m.append($("").text(e.display_name).attr("value",e.type_name))}),m.change(function(){f.type=$(this).val(),f.settings={},i(),p=o[m.val()],_.isUndefined(p)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#setting-row-instance-name").show(),p.description&&p.description.length>0?g.html(p.description).show():g.hide(),$("#dialog-ok").show(),u(p.settings))})}else 1==v.length&&(p=o[v[0]],u(p.settings));m&&(_.isUndefined(r)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#dialog-ok").show(),m.val(r).trigger("change")))}return{createPluginEditor:function(e,t,n,i,a,o){s(e,t,n,i,a,o)}}},ValueEditor=function(e){function t(e){var t=($(e).val().match(/\n/g)||[]).length,n=Math.min(200,20*(t+1));$(e).css({height:n+"px"})}function n(n){var a=null,s=0;$(n).addClass("calculated-value-input").bind("keyup mouseup freeboard-eval",function(t){if(a&&"keyup"==t.type&&(38==t.keyCode||40==t.keyCode||13==t.keyCode))return t.preventDefault(),void 0;var o=$(n).val().substring(0,$(n).getCaretPosition());o=o.replace(String.fromCharCode(160)," ");var r,d=i.exec(o),l=[];if(d)if(""==d[1])_.each(e.datasources(),function(e){l.push({value:e.name(),follow_char:'"].'})});else if(""!=d[1]&&_.isUndefined(d[2]))r=d[1],_.each(e.datasources(),function(e){var t=e.name();t!=r&&0==t.indexOf(r)&&l.push({value:t,follow_char:'"].'})});else{var c=_.find(e.datasources(),function(e){return e.name()===d[1]});if(!_.isUndefined(c)){var u="";_.isUndefined(d[2])||(u=d[2]);var p=u.split(".");u="data";for(var f=1;p.length-1>f;f++)""!=p[f]&&(u=u+"."+p[f]);var h=_.last(p);"["==h.charAt(h.length-1)&&(h=h.replace(/\[+$/,""),u=u+"."+h);var g=c.getDataRepresentation(u);if(_.isArray(g))for(var f=0;g.length>f;f++){var m="]";_.isObject(g[f])?m+=".":_.isArray(g[f])&&(m+="["),l.push({value:f,follow_char:m})}else _.isObject(g)&&(r=h,-1==_.keys(g).indexOf(r)&&_.each(g,function(e,t){if(t!=h&&0==t.indexOf(h)){var n=void 0;_.isArray(e)?n="[":_.isObject(e)&&(n="."),l.push({value:t,follow_char:n})}}))}}if(l.length>0){a||(a=$('').insertAfter(n).width($(n).outerWidth()-2).css("left",$(n).position().left).css("top",$(n).position().top+$(n).outerHeight()-1)),a.empty(),a.scrollTop(0);var v=!0;s=0;var y=0;_.each(l,function(e){var t=$("
  • "+e.value+"
  • ").appendTo(a).mouseenter(function(){$(this).trigger("freeboard-select")}).mousedown(function(e){$(this).trigger("freeboard-insertValue"),e.preventDefault()}).data("freeboard-optionIndex",y).data("freeboard-optionValue",e.value).bind("freeboard-insertValue",function(){var t=e.value;if(_.isUndefined(e.follow_char)||(t+=e.follow_char),_.isUndefined(r))$(n).insertAtCaret(t);else{var i=o.lastIndexOf(r);-1!=i&&$(n).replaceTextAt(i,i+r.length,t)}$(n).triggerHandler("mouseup")}).bind("freeboard-select",function(){$(this).parent().find("li.selected").removeClass("selected"),$(this).addClass("selected"),s=$(this).data("freeboard-optionIndex")});v&&($(t).addClass("selected"),v=!1),y++})}else $(n).next("ul#value-selector").remove(),a=null,s=-1}).focus(function(){t(n)}).focusout(function(){$(n).css({height:""}),$(n).next("ul#value-selector").remove(),a=null,s=-1}).bind("keydown",function(e){if(a)if(38==e.keyCode||40==e.keyCode){e.preventDefault();var t=$(a).find("li");38==e.keyCode?s--:40==e.keyCode&&s++,0>s?s=t.size()-1:s>=t.size()&&(s=0);var n=$(t).eq(s);n.trigger("freeboard-select"),$(a).scrollTop($(n).position().top)}else 13==e.keyCode&&(e.preventDefault(),-1!=s&&$(a).find("li").eq(s).trigger("freeboard-insertValue"))})}var i=RegExp('.*datasources\\["([^"]*)("\\].)?$');return{createValueEditor:function(e){n(e)}}},function(e){function t(){var e=document.createElement("p"),t=!1;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=!0},!1);else{if(!e.attachEvent)return!1;e.attachEvent("onDOMAttrModified",function(){t=!0})}return e.setAttribute("id","target"),t}function n(t,n){if(t){var i=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){i.style||(i.style={});var a=n.attributeName.split(".");n.attributeName=a[0],n.oldValue=i.style[a[1]],n.newValue=a[1]+":"+this.prop("style")[e.camelCase(a[1])],i.style[a[1]]=n.newValue}else n.oldValue=i[n.attributeName],n.newValue=this.attr(n.attributeName),i[n.attributeName]=n.newValue;this.data("attr-old-value",i)}}var i=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(a){var s={trackValues:!1,callback:e.noop};if("function"==typeof a?s.callback=a:e.extend(s,a),s.trackValues&&e(this).each(function(t,n){for(var i,a={},t=0,s=n.attributes,o=s.length;o>t;t++)i=s.item(t),a[i.nodeName]=i.value;e(this).data("attr-old-value",a)}),i){var o={subtree:!1,attributes:!0,attributeOldValue:s.trackValues},r=new i(function(t){t.forEach(function(t){var n=t.target;s.trackValues&&(t.newValue=e(n).attr(t.attributeName)),s.callback.call(n,t)})});return this.each(function(){r.observe(this,o)})}return t()?this.on("DOMAttrModified",function(e){e.originalEvent&&(e=e.originalEvent),e.attributeName=e.attrName,e.oldValue=e.prevValue,s.callback.call(this,e)}):"onpropertychange"in document.body?this.on("propertychange",function(t){t.attributeName=window.event.propertyName,n.call(e(this),s.trackValues,t),s.callback.call(this,t)}):this}}(jQuery),function(e){e.eventEmitter={_JQInit:function(){this._JQ=e(this)},emit:function(e,t){!this._JQ&&this._JQInit(),this._JQ.trigger(e,t)},once:function(e,t){!this._JQ&&this._JQInit(),this._JQ.one(e,t)},on:function(e,t){!this._JQ&&this._JQInit(),this._JQ.bind(e,t)},off:function(e,t){!this._JQ&&this._JQInit(),this._JQ.unbind(e,t)}}}(jQuery);var freeboard=function(){function e(e){var t=a.$el;t.find("> li").unbind().removeData(),$(".gridster").css("width",""),a.generate_grid_and_stylesheet(),e&&t.find("> li").each(function(){var e=this,t=ko.dataFor(e),i=n(t);$(e).attr("data-row",i.row).attr("data-col",i.col)}),a.init(),$(".gridster").css("width",300*a.cols+20*a.cols)}function t(e,t,n){var i=a.cols;_.isUndefined(t)||(e.row[i]=t),_.isUndefined(n)||(e.col[i]=n)}function n(e,t){var n=_.isUndefined(t)?a.cols:t;if(_.isNumber(e.row)&&_.isNumber(e.col)){var i={};i[n]=e.row,e.row=i,i={},i[n]=e.col,e.col=i}var s=1,o=1e3;for(var r in e.col){if(r==n)return{row:e.row[r],col:e.col[r]};if(e.col[r]>n)s=n;else{var d=n-r;o>d&&(s=r,o=d)}}return s in e.col&&s in e.row?{row:e.row[s],col:e.col[s]}:{row:1,col:s}}function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null==n?"":decodeURIComponent(n[1].replace(/\+/g," "))}var a,s=10,o=300,r={},d={},l=new FreeboardUI,c=new FreeboardModel(r,d,l),u=new JSEditor,p=new ValueEditor(c),f=new PluginEditor(u,p),h=new DeveloperConsole(c),g={values:{"font-family":'"HelveticaNeue-UltraLight", "Helvetica Neue Ultra Light", "Helvetica Neue", sans-serif',color:"#d3d4d4","font-weight":100}};return ko.bindingHandlers.pluginEditor={init:function(e,t,n,i){var a=ko.unwrap(t()),s={},o=void 0,u="";"datasource"==a.type?(s=r,u="Datasource"):"widget"==a.type?(s=d,u="Widget"):"pane"==a.type&&(u="Pane"),$(e).click(function(){if("delete"==a.operation){var t=$("

    Are you sure you want to delete this "+u+"?

    ");new DialogBox(t,"Confirm Delete","Yes","No",function(){"datasource"==a.type?c.deleteDatasource(i):"widget"==a.type?c.deleteWidget(i):"pane"==a.type&&c.deletePane(i)})}else{var n=void 0;"datasource"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings(),o.name=i.name()):"widget"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings()):"pane"==a.type&&(o={},"edit"==a.operation&&(o.title=i.title(),o.col_width=i.col_width()),s={settings:{settings:[{name:"title",display_name:"Title",type:"text"},{name:"col_width",display_name:"Columns",type:"number",default_value:1,required:!0}]}}),f.createPluginEditor(u,s,n,o,function(t){if("add"==a.operation){if("datasource"==a.type){var n=new DatasourceModel(c,r);c.addDatasource(n),n.name(t.settings.name),delete t.settings.name,n.settings(t.settings),n.type(t.type)}else if("widget"==a.type){var n=new WidgetModel(c,d);n.settings(t.settings),n.type(t.type),i.widgets.push(n),l.attachWidgetEditIcons(e)}}else"edit"==a.operation&&("pane"==a.type?(i.title(t.settings.title),i.col_width(t.settings.col_width)):("datasource"==a.type&&(i.name(t.settings.name),delete t.settings.name),i.type(t.type),i.settings(t.settings)))})}})}},ko.virtualElements.allowedBindings.datasourceTypeSettings=!0,ko.bindingHandlers.datasourceTypeSettings={update:function(e,t,n,i,a){processPluginSettings(e,t,n,i,a)}},ko.bindingHandlers.grid={init:function(t){a=$(t).gridster({widget_margins:[s,s],widget_base_dimensions:[o,10],resize:{enabled:!0,axes:"x"}}).data("gridster"),e(!1),a.disable()}},ko.bindingHandlers.pane={init:function(e,i,s,o,r){c.isEditing()&&$(e).css({cursor:"pointer"});var d=n(o),u=d.col,p=d.row,f=Number(o.width()),h=Number(o.getCalculatedHeight());a.add_widget(e,f,h,u,p),r.$root.isEditing()&&l.showPaneEditIcons(!0),t(o,p,u),$(e).attrchange({trackValues:!0,callback:function(e){"data-row"==e.attributeName?t(o,Number(e.newValue),void 0):"data-col"==e.attributeName&&t(o,void 0,Number(e.newValue))}})},update:function(e,t,n,i){-1==c.panes.indexOf(i)&&a.remove_widget(e);var s=i.getCalculatedHeight();(s!=Number($(e).attr("data-sizey"))||i.col_width()!=Number($(e).attr("data-sizex")))&&a.resize_widget($(e),i.col_width(),s,function(){a.set_dom_grid_height()})}},ko.bindingHandlers.widget={init:function(e){c.isEditing()&&l.attachWidgetEditIcons($(e).parent())},update:function(e,t,n,i){i.shouldRender()&&($(e).empty(),i.render(e))}},$(function(){function t(){e(!0)}l.showLoadingIndicator(!0);var n;$(window).resize(function(){clearTimeout(n),n=setTimeout(t,500)})}),{initialize:function(e,t){ko.applyBindings(c);var n=i("load");""!=n?$.ajax({url:n,success:function(e){c.loadDashboard(e),_.isFunction(t)&&t()}}):(c.allow_edit(e),c.setEditing(e),l.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("initialized"))},newDashboard:function(){c.loadDashboard({allow_edit:!0})},loadDashboard:function(e,t){c.loadDashboard(e,t)},serialize:function(){return c.serialize()},setEditing:function(e,t){c.setEditing(e,t)},isEditing:function(){return c.isEditing()},loadDatasourcePlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),e.settings.unshift({name:"name",display_name:"Name",type:"text",required:!0}),c.addPluginSource(e.source),r[e.type_name]=e,c._datasourceTypes.valueHasMutated()},resize:function(){e(!0)},loadWidgetPlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),c.addPluginSource(e.source),d[e.type_name]=e,c._widgetTypes.valueHasMutated()},setAssetRoot:function(e){u.setAssetRoot(e)},addStyle:function(e,t){var n,i=document;"object"==typeof i.styleSheets&&(i.styleSheets.length&&(n=i.styleSheets[i.styleSheets.length-1]),i.styleSheets.length&&(i.createStyleSheet?n=i.createStyleSheet():(i.getElementsByTagName("head")[0].appendChild(i.createElement("style")),n=i.styleSheets[i.styleSheets.length-1])),n.addRule?n.addRule(e,t):n.insertRule(e+"{"+t+"}",n.cssRules.length))},showLoadingIndicator:function(e){l.showLoadingIndicator(e)},showDialog:function(e,t,n,i,a){new DialogBox(e,t,n,i,a)},getDatasourceSettings:function(e){var t=c.datasources(),n=_.find(t,function(t){return t.name()===e});return n?n.settings():null},setDatasourceSettings:function(e,t){var n=c.datasources(),i=_.find(n,function(t){return t.name()===e});if(!i)return console.log("Datasource not found"),void 0;var a=_.defaults(t,i.settings());i.settings(a)},getStyleString:function(e){var t="";return _.each(g[e],function(e,n){t=t+n+":"+e+";"}),t},getStyleObject:function(e){return g[e]},showDeveloperConsole:function(){h.showDeveloperConsole()},_removeAllWidgets:function(){a.remove_all_widgets()},_disableGrid:function(){a.disable()},_enableGrid:function(){a.enable()},_getPositionForScreenSize:function(e){return n(e)}}}();$.extend(freeboard,jQuery.eventEmitter),function(){var e=function(e,t){function n(e){a&&clearInterval(a),a=setInterval(function(){i.updateNow()},e)}var i=this,a=null,s=e;n(1e3*s.refresh),this.updateNow=function(){$.ajax({url:s.url,dataType:s.is_jsonp?"JSONP":"JSON",beforeSend:function(e){try{_.each(s.headers,function(t){var n=t.name,i=t.value;_.isUndefined(n)||_.isUndefined(i)||e.setRequestHeader(n,i)})}catch(t){}},success:function(e){t(e)},error:function(){}})},this.onDispose=function(){clearInterval(a),a=null},this.onSettingsChanged=function(e){s=e,n(1e3*s.refresh)}};freeboard.loadDatasourcePlugin({type_name:"JSON",settings:[{name:"url",display_name:"URL",type:"text"},{name:"refresh",display_name:"Refresh Every",type:"number",suffix:"seconds",default_value:5},{name:"is_jsonp",display_name:"Is JSONP",type:"boolean"},{name:"headers",display_name:"Headers",type:"array",settings:[{name:"name",display_name:"Name",type:"text"},{name:"value",display_name:"Value",type:"text"}]}],newInstance:function(t,n,i){n(new e(t,i)) +function DialogBox(e,t,n,i,a){function s(){o.fadeOut(200,function(){$(this).remove()})}var o=$(''),r=$('');r.append('

    '+t+"

    "),$("
    ").appendTo(r).append(e);var d=$("").appendTo(r);n&&$(''+n+"").appendTo(d).click(function(){var e=!1;_.isFunction(a)&&(e=a()),e||s()}),i&&$(''+i+"").appendTo(d).click(function(){s()}),o.append(r),$("body").append(o),o.fadeIn(200)}function FreeboardModel(e,t,n){var i=this,a=1;this.version=0,this.isEditing=ko.observable(!1),this.allow_edit=ko.observable(!1),this.allow_edit.subscribe(function(e){e?$("#main-header").show():$("#main-header").hide()}),this.header_image=ko.observable(),this.plugins=ko.observableArray(),this.datasources=ko.observableArray(),this.panes=ko.observableArray(),this.datasourceData={},this.processDatasourceUpdate=function(e,t){var n=e.name();i.datasourceData[n]=t,_.each(i.panes(),function(e){_.each(e.widgets(),function(e){e.processDatasourceUpdate(n)})})},this._datasourceTypes=ko.observable(),this.datasourceTypes=ko.computed({read:function(){i._datasourceTypes();var t=[];return _.each(e,function(e){var n=e.type_name,i=n;_.isUndefined(e.display_name)||(i=e.display_name),t.push({name:n,display_name:i})}),t}}),this._widgetTypes=ko.observable(),this.widgetTypes=ko.computed({read:function(){i._widgetTypes();var e=[];return _.each(t,function(t){var n=t.type_name,i=n;_.isUndefined(t.display_name)||(i=t.display_name),e.push({name:n,display_name:i})}),e}}),this.addPluginSource=function(e){e&&-1==i.plugins.indexOf(e)&&i.plugins.push(e)},this.serialize=function(){var e=[];_.each(i.panes(),function(t){e.push(t.serialize())});var t=[];return _.each(i.datasources(),function(e){t.push(e.serialize())}),{version:a,header_image:i.header_image(),allow_edit:i.allow_edit(),plugins:i.plugins(),panes:e,datasources:t}},this.deserialize=function(n,a){function s(){_.isUndefined(n.allow_edit)?i.allow_edit(!0):i.allow_edit(n.allow_edit),i.version=n.version||0,i.header_image(n.header_image),_.each(n.datasources,function(t){var n=new DatasourceModel(i,e);n.deserialize(t),i.addDatasource(n)});var s=_.sortBy(n.panes,function(e){return freeboard._getPositionForScreenSize(e).row});_.each(s,function(e){var n=new PaneModel(i,t);n.deserialize(e),i.panes.push(n)}),i.allow_edit()&&0==i.panes().length&&i.setEditing(!0),_.isFunction(a)&&a()}i.clearDashboard(),_.each(n.plugins,function(e){i.addPluginSource(e)}),_.isArray(n.plugins)&&n.plugins.length>0?head.js(n.plugins,function(){s()}):s()},this.clearDashboard=function(){freeboard._removeAllWidgets(),_.each(i.datasources(),function(e){e.dispose()}),_.each(i.panes(),function(e){e.dispose()}),i.plugins.removeAll(),i.datasources.removeAll(),i.panes.removeAll()},this.loadDashboard=function(e,t){n.showLoadingIndicator(!0),i.deserialize(e,function(){n.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("dashboard_loaded")})},this.loadDashboardFromLocalFile=function(){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var e=document.createElement("input");e.type="file",$(e).on("change",function(e){var t=e.target.files;if(t&&t.length>0){var n=t[0],a=new FileReader;a.addEventListener("load",function(e){var t=e.target,n=JSON.parse(t.result);i.loadDashboard(n),i.setEditing(!1)}),a.readAsText(n)}}),$(e).trigger("click")}else alert("Unable to load a file in this browser.")},this.saveDashboard=function(){var e="application/octet-stream",t=document.createElement("a"),n=new Blob([JSON.stringify(i.serialize())],{type:e});document.body.appendChild(t),t.href=window.URL.createObjectURL(n),t.download="dashboard.json",t.target="_self",t.click()},this.addDatasource=function(e){i.datasources.push(e)},this.deleteDatasource=function(e){delete i.datasourceData[e.name()],e.dispose(),i.datasources.remove(e)},this.createPane=function(){var e=new PaneModel(i,t);i.addPane(e)},this.addPane=function(e){i.panes.push(e)},this.deletePane=function(e){e.dispose(),i.panes.remove(e)},this.deleteWidget=function(e){ko.utils.arrayForEach(i.panes(),function(t){t.widgets.remove(e)}),e.dispose()},this.setEditing=function(e,t){if(i.allow_edit()||!e){i.isEditing(e),_.isUndefined(t)&&(t=!0);var a=t?250:0,s=$("#admin-bar").outerHeight();e?($("#toggle-header-icon").addClass("icon-chevron-up").removeClass("icon-wrench"),$(".gridster .gs_w").css({cursor:"pointer"}),$("#main-header").animate({top:"0px"},a),$("#board-content").animate({top:s+20+"px"},a),$("#main-header").data().shown=!0,n.attachWidgetEditIcons($(".sub-section")),freeboard._enableGrid()):($("#toggle-header-icon").addClass("icon-wrench").removeClass("icon-chevron-up"),$(".gridster .gs_w").css({cursor:"default"}),$("#main-header").animate({top:"-"+s+"px"},a),$("#board-content").animate({top:"20"},a),$("#main-header").data().shown=!1,$(".sub-section").unbind(),freeboard._disableGrid()),n.showPaneEditIcons(e,t)}},this.toggleEditing=function(){var e=!i.isEditing();i.setEditing(e)}}function FreeboardUI(){function e(e){e?a.fadeOut(0).appendTo("body").fadeIn(500):a.fadeOut(500).remove()}function t(e,t){_.isUndefined(t)&&(t=!0);var n=t?250:0;e?$(".pane-tools").fadeIn(n):$(".pane-tools").fadeOut(n)}function n(e){$(e).hover(function(){i(this,!0)},function(){i(this,!1)})}function i(e,t){t?$(e).find(".sub-section-tools").fadeIn(250):$(e).find(".sub-section-tools").fadeOut(250)}var a=$('
    ');return{showLoadingIndicator:function(t){e(t)},showPaneEditIcons:function(e,n){t(e,n)},attachWidgetEditIcons:function(e){n(e)}}}function PaneModel(e,t){var n=this;this.title=ko.observable(),this.width=ko.observable(1),this.row={},this.col={},this.col_width=ko.observable(1),this.widgets=ko.observableArray(),this.addWidget=function(e){this.widgets.push(e)},this.widgetCanMoveUp=function(e){return n.widgets.indexOf(e)>=1},this.widgetCanMoveDown=function(e){var t=n.widgets.indexOf(e);return n.widgets().length-1>t},this.moveWidgetUp=function(e){if(n.widgetCanMoveUp(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t-1,2,i[t],i[t-1])}},this.moveWidgetDown=function(e){if(n.widgetCanMoveDown(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t,2,i[t+1],i[t])}},this.getCalculatedHeight=function(){var e=_.reduce(n.widgets(),function(e,t){return e+t.height()},0);e*=6,e+=3,e*=10;var t=Math.ceil((e+20)/30);return Math.max(4,t)},this.serialize=function(){var e=[];return _.each(n.widgets(),function(t){e.push(t.serialize())}),{title:n.title(),width:n.width(),row:n.row,col:n.col,col_width:n.col_width(),widgets:e}},this.deserialize=function(i){n.title(i.title),n.width(i.width),n.row=i.row,n.col=i.col,n.col_width(i.col_width||1),_.each(i.widgets,function(i){var a=new WidgetModel(e,t);a.deserialize(i),n.widgets.push(a)})},this.dispose=function(){_.each(n.widgets(),function(e){e.dispose()})}}function WidgetModel(e,t){function n(){_.isUndefined(i.widgetInstance)||(_.isFunction(i.widgetInstance.onDispose)&&i.widgetInstance.onDispose(),i.widgetInstance=void 0)}var i=this;this.datasourceRefreshNotifications={},this.calculatedSettingScripts={},this.title=ko.observable(),this.fillSize=ko.observable(!1),this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.fillSize(s.fill_size===!0),i.widgetInstance=e,i.shouldRender(!0),i._heightUpdate.valueHasMutated()})}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onSettingsChanged)&&i.widgetInstance.onSettingsChanged(e),i.updateCalculatedSettings(),i._heightUpdate.valueHasMutated()}),this.processDatasourceUpdate=function(e){var t=i.datasourceRefreshNotifications[e];_.isArray(t)&&_.each(t,function(e){i.processCalculatedSetting(e)})},this.callValueFunction=function(t){return t.call(void 0,e.datasourceData)},this.processCalculatedSetting=function(e){if(_.isFunction(i.calculatedSettingScripts[e])){var t=void 0;try{t=i.callValueFunction(i.calculatedSettingScripts[e])}catch(n){var a=i.settings()[e];n instanceof ReferenceError&&/^\w+$/.test(a)&&(t=a)}if(!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onCalculatedValueChanged)&&!_.isUndefined(t))try{i.widgetInstance.onCalculatedValueChanged(e,t)}catch(n){console.log(""+n)}}},this.updateCalculatedSettings=function(){if(i.datasourceRefreshNotifications={},i.calculatedSettingScripts={},!_.isUndefined(i.type())){var e=t[i.type()].settings,n=RegExp("datasources.([\\w_-]+)|datasources\\[['\"]([^'\"]+)","g"),a=i.settings();_.each(e,function(e){if("calculated"==e.type){var t=a[e.name];if(!_.isUndefined(t)){1>=(t.match(/;/g)||[]).length&&-1==t.indexOf("return")&&(t="return "+t);var s;try{s=Function("datasources",t)}catch(o){var r=a[e.name].replace(/"/g,'\\"').replace(/[\r\n]/g," \\\n");s=Function("datasources",'return "'+r+'";')}i.calculatedSettingScripts[e.name]=s,i.processCalculatedSetting(e.name);for(var d;d=n.exec(t);){var l=d[1]||d[2],c=i.datasourceRefreshNotifications[l];_.isUndefined(c)&&(c=[],i.datasourceRefreshNotifications[l]=c),c.push(e.name)}}}})}},this._heightUpdate=ko.observable(),this.height=ko.computed({read:function(){return i._heightUpdate(),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.getHeight)?i.widgetInstance.getHeight():1}}),this.shouldRender=ko.observable(!1),this.render=function(e){i.shouldRender(!1),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.render)&&(i.widgetInstance.render(e),i.updateCalculatedSettings())},this.dispose=function(){},this.serialize=function(){return{title:i.title(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.title(e.title),i.settings(e.settings),i.type(e.type)}}DatasourceModel=function(e,t){function n(){_.isUndefined(i.datasourceInstance)||(_.isFunction(i.datasourceInstance.onDispose)&&i.datasourceInstance.onDispose(),i.datasourceInstance=void 0)}var i=this;this.name=ko.observable(),this.latestData=ko.observable(),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.onSettingsChanged)&&i.datasourceInstance.onSettingsChanged(e)}),this.updateCallback=function(t){e.processDatasourceUpdate(i,t),i.latestData(t);var n=new Date;i.last_updated(n.toLocaleTimeString())},this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.datasourceInstance=e,e.updateNow()},i.updateCallback)}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.last_updated=ko.observable("never"),this.last_error=ko.observable(),this.serialize=function(){return{name:i.name(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.settings(e.settings),i.name(e.name),i.type(e.type)},this.getDataRepresentation=function(e){var t=Function("data","return "+e+";");return t.call(void 0,i.latestData())},this.updateNow=function(){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.updateNow)&&i.datasourceInstance.updateNow()},this.dispose=function(){n()}},DeveloperConsole=function(e){function t(){function t(e){var t=$(""),i=$(''),a=$(''),s=$('
  • ').click(function(){n=_.without(n,a),t.remove()});n.push(a),e&&a.val(e),i.append(s),o.append(t.append($("").append(a)).append($('').append(i)))}var n=[],i=$("
    "),a=$('
    ADD
    '),s=$('
    ');s.append($('Plugin Script URL'));var o=$("");s.append(o),i.append($("

    Here you can add references to other scripts to load datasource or widget plugins.

    ")).append(s).append(a).append('

    To learn how to build plugins for freeboard, please visit http://freeboard.github.io/freeboard/docs/plugin_example.html

    '),_.each(e.plugins(),function(e){t(e)}),a.click(function(){t()}),new DialogBox(i,"Developer Console","OK",null,function(){_.each(e.plugins(),function(e){$('script[src^="'+e+'"]').remove()}),e.plugins.removeAll(),_.each(n,function(t){var n=t.val();n&&n.length>0&&(e.addPluginSource(n),head.js(n+"?"+Date.now()))})})}return{showDeveloperConsole:function(){t()}}},JSEditor=function(){function e(e){n=e}function t(e,t){head.js(n+"css/codemirror.css",n+"css/codemirror-ambiance.css",n+"js/codemirror.js",function(){var n='// Example: Convert temp from C to F and truncate to 2 decimal places.\n// return (datasources["MyDatasource"].sensor.tempInF * 1.8 + 32).toFixed(2);';e||(e=n);var i=$('
    '),a=$('
    '),s=$(''),o=$('
    This javascript will be re-evaluated any time a datasource referenced here is updated, and the value you return will be displayed in the widget. You can assume this javascript is wrapped in a function of the form function(datasources) where datasources is a collection of javascript objects (keyed by their name) corresponding to the most current data in a datasource.
    ');i.append([o,a,s]),$("body").append(i);var r=CodeMirror(a.get(0),{value:e,mode:"javascript",theme:"ambiance",indentUnit:4,lineNumbers:!0,matchBrackets:!0,autoCloseBrackets:!0}),d=$('Close').click(function(){if(t){var e=r.getValue();e===n&&(e=""),t(e),i.remove()}});s.append(d)})}var n="";return{displayJSEditor:function(e,n){t(e,n)},setAssetRoot:function(){e(_assetRoot)}}},PluginEditor=function(e,t){function n(e,t){var n=$('
    ').html(t);$("#setting-value-container-"+e).append(n)}function i(){$("#setting-row-instance-name").length?$("#setting-row-instance-name").nextAll().remove():$("#setting-row-plugin-types").nextAll().remove()}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function s(s,o,r,d,l){function c(e,t){var n=$('
    ').appendTo(h);return n.append('
    "),$('
    ').appendTo(n)}function u(n){_.each(n,function(n){function i(){f.settings[n.name].length>0?u.show():u.hide()}function a(e){var t=$("").appendTo(h),a={};_.isArray(f.settings[n.name])||(f.settings[n.name]=[]),f.settings[n.name].push(a),_.each(n.settings,function(n){var i=$("").appendTo(t),s="";_.isUndefined(e[n.name])||(s=e[n.name]),a[n.name]=s,$('').appendTo(i).val(s).change(function(){a[n.name]=$(this).val()})}),t.append($('').append($('').append($("
  • ").append($('').click(function(){var e=f.settings[n.name].indexOf(a);-1!=e&&(f.settings[n.name].splice(e,1),t.remove(),i())}))))),r.scrollTop(r[0].scrollHeight),i()}!_.isUndefined(n.default_value)&&_.isUndefined(d[n.name])&&(d[n.name]=n.default_value);var s=n.name;_.isUndefined(n.display_name)||(s=n.display_name);var o=c(n.name,s);switch(n.type){case"array":var r=$('
    ').appendTo(o),l=$('
    ').appendTo(r),u=$("").hide().appendTo(l),p=$("").appendTo(u),h=$("").appendTo(l),g=[];_.each(n.settings,function(e){var t=e.name;_.isUndefined(e.display_name)||(t=e.display_name),$(""+t+"").appendTo(p)}),n.name in d&&(g=d[n.name]),$('
    ADD
    ').appendTo(o).click(function(){var e={};_.each(n.settings,function(t){e[t.name]=""}),a(e)}),_.each(g,function(e){a(e)});break;case"boolean":f.settings[n.name]=d[n.name];var m=$('
    ').appendTo(o),v=$('').prependTo(m).change(function(){f.settings[n.name]=this.checked});n.name in d&&v.prop("checked",d[n.name]);break;case"option":var y=d[n.name],v=$("").appendTo($('
    ').appendTo(o)).change(function(){f.settings[n.name]=$(this).val()});_.each(n.options,function(e){var t,n;_.isObject(e)?(t=e.name,n=e.value):t=e,_.isUndefined(n)&&(n=t),_.isUndefined(y)&&(y=n),$("").text(t).attr("value",n).appendTo(v)}),f.settings[n.name]=y,n.name in d&&v.val(d[n.name]);break;default:if(f.settings[n.name]=d[n.name],"calculated"==n.type){var v=$("").appendTo(o).change(function(){f.settings[n.name]=$(this).val()});n.name in d&&v.val(d[n.name]),t.createValueEditor(v);var w=$(''),b=$('
  • ').mousedown(function(e){e.preventDefault(),$(v).focus(),$(v).insertAtCaret('datasources["'),$(v).trigger("freeboard-eval")}),x=$('
  • ').mousedown(function(t){t.preventDefault(),e.displayJSEditor(v.val(),function(e){v.val(e),v.change()})});$(o).append(w.append([b,x]))}else{var v=$('').appendTo(o).change(function(){f.settings[n.name]="number"==n.type?Number($(this).val()):$(this).val()});n.name in d&&v.val(d[n.name])}}_.isUndefined(n.suffix)||o.append($('
    '+n.suffix+"
    ")),_.isUndefined(n.description)||o.append($('
    '+n.description+"
    "))})}var p,f={type:r,settings:{}},h=$("
    "),g=$('
    ').hide();h.append(g),new DialogBox(h,s,"Save","Cancel",function(){$(".validation-error").remove();for(var e=0;p.settings.length>e;e++){var t=p.settings[e];if(t.required&&(_.isUndefined(f.settings[t.name])||""==f.settings[t.name]))return n(t.name,"This is required."),!0;if("number"==t.type&&!a(f.settings[t.name]))return n(t.name,"Must be a number."),!0}_.isFunction(l)&&l(f)});var m,v=_.keys(o);if(v.length>1){var y=c("plugin-types","Type");m=$("").appendTo($('
    ').appendTo(y)),m.append($("").attr("value","undefined")),_.each(o,function(e){m.append($("").text(e.display_name).attr("value",e.type_name))}),m.change(function(){f.type=$(this).val(),f.settings={},i(),p=o[m.val()],_.isUndefined(p)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#setting-row-instance-name").show(),p.description&&p.description.length>0?g.html(p.description).show():g.hide(),$("#dialog-ok").show(),u(p.settings))})}else 1==v.length&&(p=o[v[0]],u(p.settings));m&&(_.isUndefined(r)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#dialog-ok").show(),m.val(r).trigger("change")))}return{createPluginEditor:function(e,t,n,i,a,o){s(e,t,n,i,a,o)}}},ValueEditor=function(e){function t(e){var t=($(e).val().match(/\n/g)||[]).length,n=Math.min(200,20*(t+1));$(e).css({height:n+"px"})}function n(e,t){var n,i=s.exec(e),r=[];if(i)if(""==i[1])_.each(t,function(e){r.push({value:e.name(),follow_char:'"]["'})});else if(""!=i[1]&&_.isUndefined(i[2]))n=i[1],_.each(t,function(e){var t=e.name();t!=n&&0==t.indexOf(n)&&r.push({value:t,follow_char:'"]["'})});else{var d=_.find(t,function(e){return e.name()===i[1]});if(!_.isUndefined(d)){var l="";_.isUndefined(i[2])||(l=i[2]+i[3]);var c=l.split('"]["');l="data";for(var u=1;c.length-1>u;u++)""!=c[u]&&(dataPathItem='["'+c[u]+'"]',l+=dataPathItem);var p=_.last(c);'"'==p.charAt(p.length-1)&&(p=p.replace(/\[\"?$/,""),l=l+'["'+p+'"]');var f=d.getDataRepresentation(l);if(_.isArray(f))for(var u=0;f.length>u;u++){var h='"]';_.isObject(f[u])?h+='"]["':_.isArray(f[u])&&(h+='"]['),r.push({value:u,follow_char:h})}else _.isObject(f)&&(n=p,-1==_.keys(f).indexOf(n)&&_.each(f,function(e,t){if(t!=p&&0==t.indexOf(p)){var n='"]';_.isArray(e)?n='"][':_.isObject(e)&&(n='"]["'),r.push({value:t,follow_char:n})}}))}}o=r,a=n}function i(i){var s=null,r=0;$(i).addClass("calculated-value-input").bind("keyup mouseup freeboard-eval",function(t){if(s&&"keyup"==t.type&&(38==t.keyCode||40==t.keyCode||13==t.keyCode))return t.preventDefault(),void 0;var d=$(i).val().substring(0,$(i).getCaretPosition());if(d=d.replace(String.fromCharCode(160)," "),n(d,e.datasources()),o.length>0){s||(s=$('').insertAfter(i).width($(i).outerWidth()-2).css("left",$(i).position().left).css("top",$(i).position().top+$(i).outerHeight()-1)),s.empty(),s.scrollTop(0);var l=!0;r=0;var c=0;_.each(o,function(e){var t=$("
  • "+e.value+"
  • ").appendTo(s).mouseenter(function(){$(this).trigger("freeboard-select")}).mousedown(function(e){$(this).trigger("freeboard-insertValue"),e.preventDefault()}).data("freeboard-optionIndex",c).data("freeboard-optionValue",e.value).bind("freeboard-insertValue",function(){var t=e.value;if(_.isUndefined(e.follow_char)||(t+=e.follow_char),_.isUndefined(a))$(i).insertAtCaret(t);else{var n=d.lastIndexOf(a);-1!=n&&$(i).replaceTextAt(n,n+a.length,t)}$(i).triggerHandler("mouseup")}).bind("freeboard-select",function(){$(this).parent().find("li.selected").removeClass("selected"),$(this).addClass("selected"),r=$(this).data("freeboard-optionIndex")});l&&($(t).addClass("selected"),l=!1),c++})}else $(i).next("ul#value-selector").remove(),s=null,r=-1}).focus(function(){t(i)}).focusout(function(){$(i).css({height:""}),$(i).next("ul#value-selector").remove(),s=null,r=-1}).bind("keydown",function(e){if(s)if(38==e.keyCode||40==e.keyCode){e.preventDefault();var t=$(s).find("li");38==e.keyCode?r--:40==e.keyCode&&r++,0>r?r=t.size()-1:r>=t.size()&&(r=0);var n=$(t).eq(r);n.trigger("freeboard-select"),$(s).scrollTop($(n).position().top)}else 13==e.keyCode&&(e.preventDefault(),-1!=r&&$(s).find("li").eq(r).trigger("freeboard-insertValue"))})}var a,s=RegExp('.*datasources\\["([^"]*)("\\]\\[")?(.*)$'),o=[];return{createValueEditor:function(e){i(e)}}},function(e){function t(){var e=document.createElement("p"),t=!1;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=!0},!1);else{if(!e.attachEvent)return!1;e.attachEvent("onDOMAttrModified",function(){t=!0})}return e.setAttribute("id","target"),t}function n(t,n){if(t){var i=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){i.style||(i.style={});var a=n.attributeName.split(".");n.attributeName=a[0],n.oldValue=i.style[a[1]],n.newValue=a[1]+":"+this.prop("style")[e.camelCase(a[1])],i.style[a[1]]=n.newValue}else n.oldValue=i[n.attributeName],n.newValue=this.attr(n.attributeName),i[n.attributeName]=n.newValue;this.data("attr-old-value",i)}}var i=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(a){var s={trackValues:!1,callback:e.noop};if("function"==typeof a?s.callback=a:e.extend(s,a),s.trackValues&&e(this).each(function(t,n){for(var i,a={},t=0,s=n.attributes,o=s.length;o>t;t++)i=s.item(t),a[i.nodeName]=i.value;e(this).data("attr-old-value",a)}),i){var o={subtree:!1,attributes:!0,attributeOldValue:s.trackValues},r=new i(function(t){t.forEach(function(t){var n=t.target;s.trackValues&&(t.newValue=e(n).attr(t.attributeName)),s.callback.call(n,t)})});return this.each(function(){r.observe(this,o)})}return t()?this.on("DOMAttrModified",function(e){e.originalEvent&&(e=e.originalEvent),e.attributeName=e.attrName,e.oldValue=e.prevValue,s.callback.call(this,e)}):"onpropertychange"in document.body?this.on("propertychange",function(t){t.attributeName=window.event.propertyName,n.call(e(this),s.trackValues,t),s.callback.call(this,t)}):this}}(jQuery),function(e){e.eventEmitter={_JQInit:function(){this._JQ=e(this)},emit:function(e,t){!this._JQ&&this._JQInit(),this._JQ.trigger(e,t)},once:function(e,t){!this._JQ&&this._JQInit(),this._JQ.one(e,t)},on:function(e,t){!this._JQ&&this._JQInit(),this._JQ.bind(e,t)},off:function(e,t){!this._JQ&&this._JQInit(),this._JQ.unbind(e,t)}}}(jQuery);var freeboard=function(){function e(e){var t=a.$el;t.find("> li").unbind().removeData(),$(".gridster").css("width",""),a.generate_grid_and_stylesheet(),e&&t.find("> li").each(function(){var e=this,t=ko.dataFor(e),i=n(t);$(e).attr("data-row",i.row).attr("data-col",i.col)}),a.init(),$(".gridster").css("width",300*a.cols+20*a.cols)}function t(e,t,n){var i=a.cols;_.isUndefined(t)||(e.row[i]=t),_.isUndefined(n)||(e.col[i]=n)}function n(e,t){var n=_.isUndefined(t)?a.cols:t;if(_.isNumber(e.row)&&_.isNumber(e.col)){var i={};i[n]=e.row,e.row=i,i={},i[n]=e.col,e.col=i}var s=1,o=1e3;for(var r in e.col){if(r==n)return{row:e.row[r],col:e.col[r]};if(e.col[r]>n)s=n;else{var d=n-r;o>d&&(s=r,o=d)}}return s in e.col&&s in e.row?{row:e.row[s],col:e.col[s]}:{row:1,col:s}}function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null==n?"":decodeURIComponent(n[1].replace(/\+/g," "))}var a,s=10,o=300,r={},d={},l=new FreeboardUI,c=new FreeboardModel(r,d,l),u=new JSEditor,p=new ValueEditor(c),f=new PluginEditor(u,p),h=new DeveloperConsole(c),g={values:{"font-family":'"HelveticaNeue-UltraLight", "Helvetica Neue Ultra Light", "Helvetica Neue", sans-serif',color:"#d3d4d4","font-weight":100}};return ko.bindingHandlers.pluginEditor={init:function(e,t,n,i){var a=ko.unwrap(t()),s={},o=void 0,u="";"datasource"==a.type?(s=r,u="Datasource"):"widget"==a.type?(s=d,u="Widget"):"pane"==a.type&&(u="Pane"),$(e).click(function(){if("delete"==a.operation){var t=$("

    Are you sure you want to delete this "+u+"?

    ");new DialogBox(t,"Confirm Delete","Yes","No",function(){"datasource"==a.type?c.deleteDatasource(i):"widget"==a.type?c.deleteWidget(i):"pane"==a.type&&c.deletePane(i)})}else{var n=void 0;"datasource"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings(),o.name=i.name()):"widget"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings()):"pane"==a.type&&(o={},"edit"==a.operation&&(o.title=i.title(),o.col_width=i.col_width()),s={settings:{settings:[{name:"title",display_name:"Title",type:"text"},{name:"col_width",display_name:"Columns",type:"number",default_value:1,required:!0}]}}),f.createPluginEditor(u,s,n,o,function(t){if("add"==a.operation){if("datasource"==a.type){var n=new DatasourceModel(c,r);c.addDatasource(n),n.name(t.settings.name),delete t.settings.name,n.settings(t.settings),n.type(t.type)}else if("widget"==a.type){var n=new WidgetModel(c,d);n.settings(t.settings),n.type(t.type),i.widgets.push(n),l.attachWidgetEditIcons(e)}}else"edit"==a.operation&&("pane"==a.type?(i.title(t.settings.title),i.col_width(t.settings.col_width)):("datasource"==a.type&&(i.name(t.settings.name),delete t.settings.name),i.type(t.type),i.settings(t.settings)))})}})}},ko.virtualElements.allowedBindings.datasourceTypeSettings=!0,ko.bindingHandlers.datasourceTypeSettings={update:function(e,t,n,i,a){processPluginSettings(e,t,n,i,a)}},ko.bindingHandlers.grid={init:function(t){a=$(t).gridster({widget_margins:[s,s],widget_base_dimensions:[o,10],resize:{enabled:!0,axes:"x"}}).data("gridster"),e(!1),a.disable()}},ko.bindingHandlers.pane={init:function(e,i,s,o,r){c.isEditing()&&$(e).css({cursor:"pointer"});var d=n(o),u=d.col,p=d.row,f=Number(o.width()),h=Number(o.getCalculatedHeight());a.add_widget(e,f,h,u,p),r.$root.isEditing()&&l.showPaneEditIcons(!0),t(o,p,u),$(e).attrchange({trackValues:!0,callback:function(e){"data-row"==e.attributeName?t(o,Number(e.newValue),void 0):"data-col"==e.attributeName&&t(o,void 0,Number(e.newValue))}})},update:function(e,t,n,i){-1==c.panes.indexOf(i)&&a.remove_widget(e);var s=i.getCalculatedHeight();(s!=Number($(e).attr("data-sizey"))||i.col_width()!=Number($(e).attr("data-sizex")))&&a.resize_widget($(e),i.col_width(),s,function(){a.set_dom_grid_height()})}},ko.bindingHandlers.widget={init:function(e){c.isEditing()&&l.attachWidgetEditIcons($(e).parent())},update:function(e,t,n,i){i.shouldRender()&&($(e).empty(),i.render(e))}},$(function(){function t(){e(!0)}l.showLoadingIndicator(!0);var n;$(window).resize(function(){clearTimeout(n),n=setTimeout(t,500)})}),{initialize:function(e,t){ko.applyBindings(c);var n=i("load");""!=n?$.ajax({url:n,success:function(e){c.loadDashboard(e),_.isFunction(t)&&t()}}):(c.allow_edit(e),c.setEditing(e),l.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("initialized"))},newDashboard:function(){c.loadDashboard({allow_edit:!0})},loadDashboard:function(e,t){c.loadDashboard(e,t)},serialize:function(){return c.serialize()},setEditing:function(e,t){c.setEditing(e,t)},isEditing:function(){return c.isEditing()},loadDatasourcePlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),e.settings.unshift({name:"name",display_name:"Name",type:"text",required:!0}),c.addPluginSource(e.source),r[e.type_name]=e,c._datasourceTypes.valueHasMutated()},resize:function(){e(!0)},loadWidgetPlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),c.addPluginSource(e.source),d[e.type_name]=e,c._widgetTypes.valueHasMutated()},setAssetRoot:function(e){u.setAssetRoot(e)},addStyle:function(e,t){var n,i=document;"object"==typeof i.styleSheets&&(i.styleSheets.length&&(n=i.styleSheets[i.styleSheets.length-1]),i.styleSheets.length&&(i.createStyleSheet?n=i.createStyleSheet():(i.getElementsByTagName("head")[0].appendChild(i.createElement("style")),n=i.styleSheets[i.styleSheets.length-1])),n.addRule?n.addRule(e,t):n.insertRule(e+"{"+t+"}",n.cssRules.length))},showLoadingIndicator:function(e){l.showLoadingIndicator(e)},showDialog:function(e,t,n,i,a){new DialogBox(e,t,n,i,a)},getDatasourceSettings:function(e){var t=c.datasources(),n=_.find(t,function(t){return t.name()===e});return n?n.settings():null},setDatasourceSettings:function(e,t){var n=c.datasources(),i=_.find(n,function(t){return t.name()===e});if(!i)return console.log("Datasource not found"),void 0;var a=_.defaults(t,i.settings());i.settings(a)},getStyleString:function(e){var t="";return _.each(g[e],function(e,n){t=t+n+":"+e+";"}),t},getStyleObject:function(e){return g[e]},showDeveloperConsole:function(){h.showDeveloperConsole()},_removeAllWidgets:function(){a.remove_all_widgets()},_disableGrid:function(){a.disable()},_enableGrid:function(){a.enable()},_getPositionForScreenSize:function(e){return n(e)}}}();$.extend(freeboard,jQuery.eventEmitter),function(){var e=function(e,t){function n(e){a&&clearInterval(a),a=setInterval(function(){i.updateNow()},e)}var i=this,a=null,s=e;n(1e3*s.refresh),this.updateNow=function(){$.ajax({url:s.url,dataType:s.is_jsonp?"JSONP":"JSON",beforeSend:function(e){try{_.each(s.headers,function(t){var n=t.name,i=t.value;_.isUndefined(n)||_.isUndefined(i)||e.setRequestHeader(n,i)})}catch(t){}},success:function(e){t(e)},error:function(){}})},this.onDispose=function(){clearInterval(a),a=null},this.onSettingsChanged=function(e){s=e,n(1e3*s.refresh)}};freeboard.loadDatasourcePlugin({type_name:"JSON",settings:[{name:"url",display_name:"URL",type:"text"},{name:"refresh",display_name:"Refresh Every",type:"number",suffix:"seconds",default_value:5},{name:"is_jsonp",display_name:"Is JSONP",type:"boolean"},{name:"headers",display_name:"Headers",type:"array",settings:[{name:"name",display_name:"Name",type:"text"},{name:"value",display_name:"Value",type:"text"}]}],newInstance:function(t,n,i){n(new e(t,i)) }});var t=function(e,t){function n(e){s&&clearInterval(s),s=setInterval(function(){a.updateNow()},e)}function i(e){return e.replace(/\w\S*/g,function(e){return e.charAt(0).toUpperCase()+e.substr(1).toLowerCase()})}var a=this,s=null,o=e;n(1e3*o.refresh),this.updateNow=function(){$.ajax({url:"http://api.openweathermap.org/data/2.5/weather?q="+encodeURIComponent(o.location)+"&units="+o.units,dataType:"JSONP",success:function(e){var n={place_name:e.name,sunrise:new Date(1e3*e.sys.sunrise).toLocaleTimeString(),sunset:new Date(1e3*e.sys.sunset).toLocaleTimeString(),conditions:i(e.weather[0].description),current_temp:e.main.temp,high_temp:e.main.temp_max,low_temp:e.main.temp_min,pressure:e.main.pressure,humidity:e.main.humidity,wind_speed:e.wind.speed,wind_direction:e.wind.deg};t(n)},error:function(){}})},this.onDispose=function(){clearInterval(s),s=null},this.onSettingsChanged=function(e){o=e,a.updateNow(),n(1e3*o.refresh)}};freeboard.loadDatasourcePlugin({type_name:"openweathermap",display_name:"Open Weather Map API",settings:[{name:"location",display_name:"Location",type:"text",description:"Example: London, UK"},{name:"units",display_name:"Units",type:"option","default":"imperial",options:[{name:"Imperial",value:"imperial"},{name:"Metric",value:"metric"}]},{name:"refresh",display_name:"Refresh Every",type:"number",suffix:"seconds",default_value:5}],newInstance:function(e,n,i){n(new t(e,i))}});var n=function(e,t){function n(e){t(e)}var i=this,a=e;this.updateNow=function(){dweetio.get_latest_dweet_for(a.thing_id,function(e,t){e||n(t[0].content)})},this.onDispose=function(){},this.onSettingsChanged=function(e){dweetio.stop_listening(),a=e,dweetio.listen_for(a.thing_id,function(e){n(e.content)})},i.onSettingsChanged(e)};freeboard.loadDatasourcePlugin({type_name:"dweet_io",display_name:"Dweet.io",external_scripts:["http://dweet.io/client/dweet.io.min.js"],settings:[{name:"thing_id",display_name:"Thing Name",description:"Example: salty-dog-1",type:"text"}],newInstance:function(e,t,i){t(new n(e,i))}});var i=function(e,t){function n(){r.length>0?(r.length>d&&(t(r[d]),d++),d>=r.length&&o.loop&&(d=0),r.length>d&&(a=setTimeout(n,1e3*o.refresh))):t({})}function i(){r=[],d=0,a&&(clearTimeout(a),a=null)}var a,s=this,o=e,r=[],d=0;this.updateNow=function(){i(),$.ajax({url:o.datafile,dataType:o.is_jsonp?"JSONP":"JSON",success:function(e){r=_.isArray(e)?e:[],d=0,n()},error:function(){}})},this.onDispose=function(){i()},this.onSettingsChanged=function(e){o=e,s.updateNow()}};freeboard.loadDatasourcePlugin({type_name:"playback",display_name:"Playback",settings:[{name:"datafile",display_name:"Data File URL",type:"text",description:"A link to a JSON array of data."},{name:"is_jsonp",display_name:"Is JSONP",type:"boolean"},{name:"loop",display_name:"Loop",type:"boolean",description:"Rewind and loop when finished"},{name:"refresh",display_name:"Refresh Every",type:"number",suffix:"seconds",default_value:5}],newInstance:function(e,t,n){t(new i(e,n))}});var a=function(e,t){function n(){a&&(clearTimeout(a),a=null)}function i(){n(),a=setInterval(s.updateNow,1e3*o.refresh)}var a,s=this,o=e;this.updateNow=function(){var e=new Date,n={numeric_value:e.getTime(),full_string_value:e.toLocaleString(),date_string_value:e.toLocaleDateString(),time_string_value:e.toLocaleTimeString(),date_object:e};t(n)},this.onDispose=function(){n()},this.onSettingsChanged=function(e){o=e,i()},i()};freeboard.loadDatasourcePlugin({type_name:"clock",display_name:"Clock",settings:[{name:"refresh",display_name:"Refresh Every",type:"number",suffix:"seconds",default_value:1}],newInstance:function(e,t,n){t(new a(e,n))}})}(),function(){function e(e,t,n,i){if(e!=t)if($.isNumeric(t)&&$.isNumeric(e)){var a=(""+t).split("."),s=0;a.length>1&&(s=a[1].length),a=(""+e).split(".");var o=0;a.length>1&&(o=a[1].length),jQuery({transitionValue:Number(e),precisionValue:o}).animate({transitionValue:Number(t),precisionValue:s},{duration:i,step:function(){$(n).text(this.transitionValue.toFixed(this.precisionValue))},done:function(){$(n).text(t)}})}else $(n).text(t)}function t(e,t){var i=$(e).data().values;i||(i=[]),i.length>=n&&i.shift(),i.push(Number(t)),$(e).data().values=i,$(e).sparkline(i,{type:"line",height:"100%",width:"100%",fillColor:!1,lineColor:"#FF9900",lineWidth:2,spotRadius:3,spotColor:!1,minSpotColor:"#78AB49",maxSpotColor:"#78AB49",highlightSpotColor:"#9D3926",highlightLineColor:"#9D3926"})}var n=100,i=freeboard.getStyleString("values");i+="overflow: hidden;text-overflow: ellipsis;display: inline;",freeboard.addStyle(".text-widget-unit","padding-left: 5px;display:inline;"),freeboard.addStyle(".text-widget-regular-value",i+"font-size:30px;"),freeboard.addStyle(".text-widget-big-value",i+"font-size:75px;"),freeboard.addStyle(".gauge-widget-wrapper","width: 100%;text-align: center;"),freeboard.addStyle(".gauge-widget","width:200px;height:160px;display:inline-block;"),freeboard.addStyle(".sparkline","width:100%;height: 75px;"),freeboard.addStyle(".sparkline-inline","width:50%;float:right;height:30px;"),freeboard.addStyle(".indicator-light","border-radius:50%;width:22px;height:22px;border:2px solid #3d3d3d;margin-top:5px;float:left;background-color:#222;margin-right:10px;"),freeboard.addStyle(".indicator-light.on","background-color:#FFC773;box-shadow: 0px 0px 15px #FF9900;border-color:#FDF1DF;"),freeboard.addStyle(".indicator-text","margin-top:10px;"),freeboard.addStyle("div.pointer-value","position:absolute;height:95px;margin: auto;top: 0px;bottom: 0px;width: 100%;text-align:center;");var a=function(n){var i,a=n,s=$('

    '),o=$("
    "),r=$('
    '),d=$('');this.render=function(e){$(e).append(s).append(o).append(r).append(d)},this.onSettingsChanged=function(e){a=e,s.html(_.isUndefined(e.title)?"":e.title),o.toggleClass("text-widget-regular-value","regular"==e.size).toggleClass("text-widget-big-value","big"==e.size),r.html(_.isUndefined(e.units)?"":e.units),e.sparkline?d.show():(delete d.data().values,d.empty(),d.hide())},this.onCalculatedValueChanged=function(n,s){"value"==n&&(a.animate?e(i,s,o,500):o.text(s),a.sparkline&&t(d,s),i=s)},this.onDispose=function(){},this.getHeight=function(){return"big"==a.size?2:1},this.onSettingsChanged(n)};freeboard.loadWidgetPlugin({type_name:"text_widget",display_name:"Text",external_scripts:["plugins/thirdparty/jquery.sparkline.min.js"],settings:[{name:"title",display_name:"Title",type:"text"},{name:"size",display_name:"Size",type:"option",options:[{name:"Regular",value:"regular"},{name:"Big",value:"big"}]},{name:"value",display_name:"Value",type:"calculated"},{name:"sparkline",display_name:"Include Sparkline",type:"boolean"},{name:"animate",display_name:"Animate Value Changes",type:"boolean",default_value:!0},{name:"units",display_name:"Units",type:"text"}],newInstance:function(e,t){t(new a(e))}});var s=0,o=function(e){function t(){r&&(o.empty(),n=new JustGage({id:i,value:_.isUndefined(d.min_value)?0:d.min_value,min:_.isUndefined(d.min_value)?0:d.min_value,max:_.isUndefined(d.max_value)?0:d.max_value,label:d.units,showInnerShadow:!1,valueFontColor:"#d3d4d4"}))}var n,i="gauge-"+s++,a=$('

    '),o=$('
    '),r=!1,d=e;this.render=function(e){r=!0,$(e).append(a).append($('
    ').append(o)),t()},this.onSettingsChanged=function(e){e.min_value!=d.min_value||e.max_value!=d.max_value||e.units!=d.units?(d=e,t()):d=e,a.html(e.title)},this.onCalculatedValueChanged=function(e,t){_.isUndefined(n)||n.refresh(Number(t))},this.onDispose=function(){},this.getHeight=function(){return 3},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"gauge",display_name:"Gauge",external_scripts:["plugins/thirdparty/raphael.2.1.0.min.js","plugins/thirdparty/justgage.1.0.1.js"],settings:[{name:"title",display_name:"Title",type:"text"},{name:"value",display_name:"Value",type:"calculated"},{name:"units",display_name:"Units",type:"text"},{name:"min_value",display_name:"Minimum",type:"text",default_value:0},{name:"max_value",display_name:"Maximum",type:"text",default_value:100}],newInstance:function(e,t){t(new o(e))}});var r=function(e){var n=$('

    '),i=$('
    ');this.render=function(e){$(e).append(n).append(i)},this.onSettingsChanged=function(e){n.html(_.isUndefined(e.title)?"":e.title)},this.onCalculatedValueChanged=function(e,n){t(i,n)},this.onDispose=function(){},this.getHeight=function(){return 2},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"sparkline",display_name:"Sparkline",external_scripts:["plugins/thirdparty/jquery.sparkline.min.js"],settings:[{name:"title",display_name:"Title",type:"text"},{name:"value",display_name:"Value",type:"calculated"}],newInstance:function(e,t){t(new r(e))}});var d=function(e){function t(e){if(!e||2>e.length)return[];var t=[];t.push(["m",e[0],e[1]]);for(var n=2;e.length>n;n+=2)t.push(["l",e[n],e[n+1]]);return t.push(["z"]),t}var n,i,a,s,o=3,r=0,d=$('
    '),l=$("
    ");this.render=function(e){a=$(e).width(),s=$(e).height();var r=Math.min(a,s)/2-2*o;n=Raphael($(e).get()[0],a,s);var c=n.circle(a/2,s/2,r);c.attr("stroke","#FF9900"),c.attr("stroke-width",o),i=n.path(t([a/2,s/2-r+o,15,20,-30,0])),i.attr("stroke-width",0),i.attr("fill","#fff"),$(e).append($('
    ').append(d).append(l))},this.onSettingsChanged=function(e){l.html(e.units)},this.onCalculatedValueChanged=function(e,t){if("direction"==e){if(!_.isUndefined(i)){i.animate({transform:"r"+t+","+a/2+","+s/2},250,"bounce")}r=t}else"value_text"==e&&d.html(t)},this.onDispose=function(){},this.getHeight=function(){return 4},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"pointer",display_name:"Pointer",external_scripts:["plugins/thirdparty/raphael.2.1.0.min.js"],settings:[{name:"direction",display_name:"Direction",type:"calculated",description:"In degrees"},{name:"value_text",display_name:"Value Text",type:"calculated"},{name:"units",display_name:"Units",type:"text"}],newInstance:function(e,t){t(new d(e))}});var l=function(e){function t(){a&&(clearInterval(a),a=null)}function n(){if(i&&s){var e=s+(-1==s.indexOf("?")?"?":"&")+Date.now();$(i).css({"background-image":"url("+e+")"})}}var i,a,s;this.render=function(e){$(e).css({width:"100%",height:"100%","background-size":"cover","background-position":"center"}),i=e},this.onSettingsChanged=function(e){t(),e.refresh&&e.refresh>0&&(a=setInterval(n,1e3*Number(e.refresh)))},this.onCalculatedValueChanged=function(e,t){"src"==e&&(s=t),n()},this.onDispose=function(){t()},this.getHeight=function(){return 4},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"picture",display_name:"Picture",fill_size:!0,settings:[{name:"src",display_name:"Image URL",type:"calculated"},{type:"number",display_name:"Refresh every",name:"refresh",suffix:"seconds",description:"Leave blank if the image doesn't need to be refreshed"}],newInstance:function(e,t){t(new l(e))}});var c=function(e){function t(){a.toggleClass("on",o),o?i.text(_.isUndefined(s.on_text)?"":s.on_text):i.text(_.isUndefined(s.off_text)?"":s.off_text)}var n=$('

    '),i=$('
    '),a=$('
    '),s=e,o=!1;this.render=function(e){$(e).append(n).append(a).append(i)},this.onSettingsChanged=function(e){s=e,n.html(_.isUndefined(e.title)?"":e.title),t()},this.onCalculatedValueChanged=function(e,n){"value"==e&&(o=Boolean(n)),t()},this.onDispose=function(){},this.getHeight=function(){return 1},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"indicator",display_name:"Indicator Light",settings:[{name:"title",display_name:"Title",type:"text"},{name:"value",display_name:"Value",type:"calculated"},{name:"on_text",display_name:"On Text",type:"calculated"},{name:"off_text",display_name:"Off Text",type:"calculated"}],newInstance:function(e,t){t(new c(e))}}),freeboard.addStyle(".gm-style-cc a","text-shadow:none;");var u=function(e){function t(){if(n&&i&&s.lat&&s.lon){var e=new google.maps.LatLng(s.lat,s.lon);i.setPosition(e),n.panTo(e)}}var n,i,a=e,s={};this.render=function(e){function a(){var a={zoom:13,center:new google.maps.LatLng(37.235,-115.811111),disableDefaultUI:!0,draggable:!1,styles:[{featureType:"water",elementType:"geometry",stylers:[{color:"#2a2a2a"}]},{featureType:"landscape",elementType:"geometry",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"road.highway",elementType:"geometry.fill",stylers:[{color:"#000000"},{lightness:17}]},{featureType:"road.highway",elementType:"geometry.stroke",stylers:[{color:"#000000"},{lightness:29},{weight:.2}]},{featureType:"road.arterial",elementType:"geometry",stylers:[{color:"#000000"},{lightness:18}]},{featureType:"road.local",elementType:"geometry",stylers:[{color:"#000000"},{lightness:16}]},{featureType:"poi",elementType:"geometry",stylers:[{color:"#000000"},{lightness:21}]},{elementType:"labels.text.stroke",stylers:[{visibility:"on"},{color:"#000000"},{lightness:16}]},{elementType:"labels.text.fill",stylers:[{saturation:36},{color:"#000000"},{lightness:40}]},{elementType:"labels.icon",stylers:[{visibility:"off"}]},{featureType:"transit",elementType:"geometry",stylers:[{color:"#000000"},{lightness:19}]},{featureType:"administrative",elementType:"geometry.fill",stylers:[{color:"#000000"},{lightness:20}]},{featureType:"administrative",elementType:"geometry.stroke",stylers:[{color:"#000000"},{lightness:17},{weight:1.2}]}]};n=new google.maps.Map(e,a),google.maps.event.addDomListener(e,"mouseenter",function(e){e.cancelBubble=!0,n.hover||(n.hover=!0,n.setOptions({zoomControl:!0}))}),google.maps.event.addDomListener(e,"mouseleave",function(){n.hover&&(n.setOptions({zoomControl:!1}),n.hover=!1)}),i=new google.maps.Marker({map:n}),t()}window.google&&window.google.maps?a():(window.gmap_initialize=a,head.js("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&callback=gmap_initialize"))},this.onSettingsChanged=function(e){a=e},this.onCalculatedValueChanged=function(e,n){"lat"==e?s.lat=n:"lon"==e&&(s.lon=n),t()},this.onDispose=function(){},this.getHeight=function(){return 4},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"google_map",display_name:"Google Map",fill_size:!0,settings:[{name:"lat",display_name:"Latitude",type:"calculated"},{name:"lon",display_name:"Longitude",type:"calculated"}],newInstance:function(e,t){t(new u(e))}}),freeboard.addStyle(".html-widget","white-space:normal;width:100%;height:100%");var p=function(e){var t=$('
    '),n=e;this.render=function(e){$(e).append(t)},this.onSettingsChanged=function(e){n=e},this.onCalculatedValueChanged=function(e,n){"html"==e&&t.html(n)},this.onDispose=function(){},this.getHeight=function(){return Number(n.height)},this.onSettingsChanged(e)};freeboard.loadWidgetPlugin({type_name:"html",display_name:"HTML",fill_size:!0,settings:[{name:"html",display_name:"HTML",type:"calculated",description:"Can be literal HTML, or javascript that outputs HTML."},{name:"height",display_name:"Height Blocks",type:"number",default_value:4,description:"A height block is around 60 pixels"}],newInstance:function(e,t){t(new p(e))}})}(); \ No newline at end of file diff --git a/js/freeboard.js b/js/freeboard.js index 20a548b..3792b6b 100644 --- a/js/freeboard.js +++ b/js/freeboard.js @@ -1332,7 +1332,10 @@ PluginEditor = function(jsEditor, valueEditor) ValueEditor = function(theFreeboardModel) { - var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\].)?$"); + var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\]\\[\")?(.*)$"); + + var _autocompleteOptions = []; + var _autocompleteReplacementString; function _resizeValueEditor(element) { @@ -1343,6 +1346,126 @@ ValueEditor = function(theFreeboardModel) $(element).css({height: newHeight + "px"}); } + function _autocompleteFromDatasource(inputString, datasources) + { + var match = _veDatasourceRegex.exec(inputString); + + var options = []; + var replacementString; + + if(match) + { + if(match[1] == "") // List all datasources + { + _.each(datasources, function(datasource) + { + options.push({value: datasource.name(), follow_char: "\"][\""}); + }); + } + else if(match[1] != "" && _.isUndefined(match[2])) // List partial datasources + { + replacementString = match[1]; + + _.each(datasources, function(datasource) + { + var dsName = datasource.name(); + + if(dsName != replacementString && dsName.indexOf(replacementString) == 0) + { + options.push({value: dsName, follow_char: "\"][\""}); + } + }); + } + else + { + var datasource = _.find(datasources, function(datasource) + { + return (datasource.name() === match[1]); + }); + + if(!_.isUndefined(datasource)) + { + var dataPath = ""; + + if(!_.isUndefined(match[2])) + { + dataPath = match[2] + match[3]; + } + + var dataPathItems = dataPath.split("\"][\""); + dataPath = "data"; + + for(var index = 1; index < dataPathItems.length - 1; index++) + { + if(dataPathItems[index] != "") + { + dataPathItem = "[\"" + dataPathItems[index] + "\"]"; + dataPath = dataPath + dataPathItem; + } + } + + var lastPathObject = _.last(dataPathItems); + + // If the last character is a ", then ignore it + if(lastPathObject.charAt(lastPathObject.length - 1) == "\"") + { + lastPathObject = lastPathObject.replace(/\[\"?$/, ""); + dataPath = dataPath + "[\"" + lastPathObject + "\"]"; + } + + var dataValue = datasource.getDataRepresentation(dataPath); + + if(_.isArray(dataValue)) + { + for(var index = 0; index < dataValue.length; index++) + { + var followChar = "\"]"; + + if(_.isObject(dataValue[index])) + { + followChar = followChar + "\"][\""; + } + else if(_.isArray(dataValue[index])) + { + followChar = followChar + "\"]["; + } + + options.push({value: index, follow_char: followChar}); + } + } + else if(_.isObject(dataValue)) + { + replacementString = lastPathObject; + + if(_.keys(dataValue).indexOf(replacementString) == -1) + { + _.each(dataValue, function(value, name) + { + if(name != lastPathObject && name.indexOf(lastPathObject) == 0) + { + var followChar = "\"]"; + + if(_.isArray(value)) + { + followChar = "\"]["; + } + else if(_.isObject(value)) + { + followChar = "\"][\""; + } + + options.push({value: name, follow_char: followChar}); + } + }); + } + } + } + } + } + _autocompleteOptions = options; + _autocompleteReplacementString = replacementString; + } + function createValueEditor(element) { var dropdown = null; @@ -1360,121 +1483,9 @@ ValueEditor = function(theFreeboardModel) var inputString = $(element).val().substring(0, $(element).getCaretPosition()); inputString = inputString.replace(String.fromCharCode(160), " "); // Weird issue where the textarea box was putting in ASCII (non breaking space) for spaces. - var match = _veDatasourceRegex.exec(inputString); + _autocompleteFromDatasource(inputString, theFreeboardModel.datasources()); - var options = []; - var replacementString; - - if(match) - { - if(match[1] == "") // List all datasources - { - _.each(theFreeboardModel.datasources(), function(datasource) - { - options.push({value: datasource.name(), follow_char: "\"]."}); - }); - } - else if(match[1] != "" && _.isUndefined(match[2])) // List partial datasources - { - replacementString = match[1]; - - _.each(theFreeboardModel.datasources(), function(datasource) - { - var dsName = datasource.name(); - - if(dsName != replacementString && dsName.indexOf(replacementString) == 0) - { - options.push({value: dsName, follow_char: "\"]."}); - } - }); - } - else - { - var datasource = _.find(theFreeboardModel.datasources(), function(datasource) - { - return (datasource.name() === match[1]); - }); - - if(!_.isUndefined(datasource)) - { - var dataPath = ""; - - if(!_.isUndefined(match[2])) - { - dataPath = match[2]; - } - - var dataPathItems = dataPath.split("."); - dataPath = "data"; - - for(var index = 1; index < dataPathItems.length - 1; index++) - { - if(dataPathItems[index] != "") - { - dataPath = dataPath + "." + dataPathItems[index]; - } - } - - var lastPathObject = _.last(dataPathItems); - - // If the last character is a [, then ignore it - if(lastPathObject.charAt(lastPathObject.length - 1) == "[") - { - lastPathObject = lastPathObject.replace(/\[+$/, ""); - dataPath = dataPath + "." + lastPathObject; - } - - var dataValue = datasource.getDataRepresentation(dataPath); - - if(_.isArray(dataValue)) - { - for(var index = 0; index < dataValue.length; index++) - { - var followChar = "]"; - - if(_.isObject(dataValue[index])) - { - followChar = followChar + "."; - } - else if(_.isArray(dataValue[index])) - { - followChar = followChar + "["; - } - - options.push({value: index, follow_char: followChar}); - } - } - else if(_.isObject(dataValue)) - { - replacementString = lastPathObject; - - if(_.keys(dataValue).indexOf(replacementString) == -1) - { - _.each(dataValue, function(value, name) - { - if(name != lastPathObject && name.indexOf(lastPathObject) == 0) - { - var followChar = undefined; - - if(_.isArray(value)) - { - followChar = "["; - } - else if(_.isObject(value)) - { - followChar = "."; - } - - options.push({value: name, follow_char: followChar}); - } - }); - } - } - } - } - } - - if(options.length > 0) + if(_autocompleteOptions.length > 0) { if(!dropdown) { @@ -1489,7 +1500,7 @@ ValueEditor = function(theFreeboardModel) var currentIndex = 0; - _.each(options, function(option) + _.each(_autocompleteOptions, function(option) { var li = $('
  • ' + option.value + '
  • ').appendTo(dropdown).mouseenter(function() { @@ -1507,13 +1518,13 @@ ValueEditor = function(theFreeboardModel) optionValue = optionValue + option.follow_char; } - if(!_.isUndefined(replacementString)) + if(!_.isUndefined(_autocompleteReplacementString)) { - var replacementIndex = inputString.lastIndexOf(replacementString); + var replacementIndex = inputString.lastIndexOf(_autocompleteReplacementString); if(replacementIndex != -1) { - $(element).replaceTextAt(replacementIndex, replacementIndex + replacementString.length, optionValue); + $(element).replaceTextAt(replacementIndex, replacementIndex + _autocompleteReplacementString.length, optionValue); } } else diff --git a/js/freeboard.min.js b/js/freeboard.min.js index 796f05b..6e77fb4 100644 --- a/js/freeboard.min.js +++ b/js/freeboard.min.js @@ -1 +1 @@ -function DialogBox(e,t,n,i,a){function s(){o.fadeOut(200,function(){$(this).remove()})}var o=$(''),r=$('');r.append('

    '+t+"

    "),$("
    ").appendTo(r).append(e);var d=$("").appendTo(r);n&&$(''+n+"").appendTo(d).click(function(){var e=!1;_.isFunction(a)&&(e=a()),e||s()}),i&&$(''+i+"").appendTo(d).click(function(){s()}),o.append(r),$("body").append(o),o.fadeIn(200)}function FreeboardModel(e,t,n){var i=this,a=1;this.version=0,this.isEditing=ko.observable(!1),this.allow_edit=ko.observable(!1),this.allow_edit.subscribe(function(e){e?$("#main-header").show():$("#main-header").hide()}),this.header_image=ko.observable(),this.plugins=ko.observableArray(),this.datasources=ko.observableArray(),this.panes=ko.observableArray(),this.datasourceData={},this.processDatasourceUpdate=function(e,t){var n=e.name();i.datasourceData[n]=t,_.each(i.panes(),function(e){_.each(e.widgets(),function(e){e.processDatasourceUpdate(n)})})},this._datasourceTypes=ko.observable(),this.datasourceTypes=ko.computed({read:function(){i._datasourceTypes();var t=[];return _.each(e,function(e){var n=e.type_name,i=n;_.isUndefined(e.display_name)||(i=e.display_name),t.push({name:n,display_name:i})}),t}}),this._widgetTypes=ko.observable(),this.widgetTypes=ko.computed({read:function(){i._widgetTypes();var e=[];return _.each(t,function(t){var n=t.type_name,i=n;_.isUndefined(t.display_name)||(i=t.display_name),e.push({name:n,display_name:i})}),e}}),this.addPluginSource=function(e){e&&-1==i.plugins.indexOf(e)&&i.plugins.push(e)},this.serialize=function(){var e=[];_.each(i.panes(),function(t){e.push(t.serialize())});var t=[];return _.each(i.datasources(),function(e){t.push(e.serialize())}),{version:a,header_image:i.header_image(),allow_edit:i.allow_edit(),plugins:i.plugins(),panes:e,datasources:t}},this.deserialize=function(n,a){function s(){_.isUndefined(n.allow_edit)?i.allow_edit(!0):i.allow_edit(n.allow_edit),i.version=n.version||0,i.header_image(n.header_image),_.each(n.datasources,function(t){var n=new DatasourceModel(i,e);n.deserialize(t),i.addDatasource(n)});var s=_.sortBy(n.panes,function(e){return freeboard._getPositionForScreenSize(e).row});_.each(s,function(e){var n=new PaneModel(i,t);n.deserialize(e),i.panes.push(n)}),i.allow_edit()&&0==i.panes().length&&i.setEditing(!0),_.isFunction(a)&&a()}i.clearDashboard(),_.each(n.plugins,function(e){i.addPluginSource(e)}),_.isArray(n.plugins)&&n.plugins.length>0?head.js(n.plugins,function(){s()}):s()},this.clearDashboard=function(){freeboard._removeAllWidgets(),_.each(i.datasources(),function(e){e.dispose()}),_.each(i.panes(),function(e){e.dispose()}),i.plugins.removeAll(),i.datasources.removeAll(),i.panes.removeAll()},this.loadDashboard=function(e,t){n.showLoadingIndicator(!0),i.deserialize(e,function(){n.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("dashboard_loaded")})},this.loadDashboardFromLocalFile=function(){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var e=document.createElement("input");e.type="file",$(e).on("change",function(e){var t=e.target.files;if(t&&t.length>0){var n=t[0],a=new FileReader;a.addEventListener("load",function(e){var t=e.target,n=JSON.parse(t.result);i.loadDashboard(n),i.setEditing(!1)}),a.readAsText(n)}}),$(e).trigger("click")}else alert("Unable to load a file in this browser.")},this.saveDashboard=function(){var e="application/octet-stream",t=document.createElement("a"),n=new Blob([JSON.stringify(i.serialize())],{type:e});document.body.appendChild(t),t.href=window.URL.createObjectURL(n),t.download="dashboard.json",t.target="_self",t.click()},this.addDatasource=function(e){i.datasources.push(e)},this.deleteDatasource=function(e){delete i.datasourceData[e.name()],e.dispose(),i.datasources.remove(e)},this.createPane=function(){var e=new PaneModel(i,t);i.addPane(e)},this.addPane=function(e){i.panes.push(e)},this.deletePane=function(e){e.dispose(),i.panes.remove(e)},this.deleteWidget=function(e){ko.utils.arrayForEach(i.panes(),function(t){t.widgets.remove(e)}),e.dispose()},this.setEditing=function(e,t){if(i.allow_edit()||!e){i.isEditing(e),_.isUndefined(t)&&(t=!0);var a=t?250:0,s=$("#admin-bar").outerHeight();e?($("#toggle-header-icon").addClass("icon-chevron-up").removeClass("icon-wrench"),$(".gridster .gs_w").css({cursor:"pointer"}),$("#main-header").animate({top:"0px"},a),$("#board-content").animate({top:s+20+"px"},a),$("#main-header").data().shown=!0,n.attachWidgetEditIcons($(".sub-section")),freeboard._enableGrid()):($("#toggle-header-icon").addClass("icon-wrench").removeClass("icon-chevron-up"),$(".gridster .gs_w").css({cursor:"default"}),$("#main-header").animate({top:"-"+s+"px"},a),$("#board-content").animate({top:"20"},a),$("#main-header").data().shown=!1,$(".sub-section").unbind(),freeboard._disableGrid()),n.showPaneEditIcons(e,t)}},this.toggleEditing=function(){var e=!i.isEditing();i.setEditing(e)}}function FreeboardUI(){function e(e){e?a.fadeOut(0).appendTo("body").fadeIn(500):a.fadeOut(500).remove()}function t(e,t){_.isUndefined(t)&&(t=!0);var n=t?250:0;e?$(".pane-tools").fadeIn(n):$(".pane-tools").fadeOut(n)}function n(e){$(e).hover(function(){i(this,!0)},function(){i(this,!1)})}function i(e,t){t?$(e).find(".sub-section-tools").fadeIn(250):$(e).find(".sub-section-tools").fadeOut(250)}var a=$('
    ');return{showLoadingIndicator:function(t){e(t)},showPaneEditIcons:function(e,n){t(e,n)},attachWidgetEditIcons:function(e){n(e)}}}function PaneModel(e,t){var n=this;this.title=ko.observable(),this.width=ko.observable(1),this.row={},this.col={},this.col_width=ko.observable(1),this.widgets=ko.observableArray(),this.addWidget=function(e){this.widgets.push(e)},this.widgetCanMoveUp=function(e){return n.widgets.indexOf(e)>=1},this.widgetCanMoveDown=function(e){var t=n.widgets.indexOf(e);return n.widgets().length-1>t},this.moveWidgetUp=function(e){if(n.widgetCanMoveUp(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t-1,2,i[t],i[t-1])}},this.moveWidgetDown=function(e){if(n.widgetCanMoveDown(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t,2,i[t+1],i[t])}},this.getCalculatedHeight=function(){var e=_.reduce(n.widgets(),function(e,t){return e+t.height()},0);e*=6,e+=3,e*=10;var t=Math.ceil((e+20)/30);return Math.max(4,t)},this.serialize=function(){var e=[];return _.each(n.widgets(),function(t){e.push(t.serialize())}),{title:n.title(),width:n.width(),row:n.row,col:n.col,col_width:n.col_width(),widgets:e}},this.deserialize=function(i){n.title(i.title),n.width(i.width),n.row=i.row,n.col=i.col,n.col_width(i.col_width||1),_.each(i.widgets,function(i){var a=new WidgetModel(e,t);a.deserialize(i),n.widgets.push(a)})},this.dispose=function(){_.each(n.widgets(),function(e){e.dispose()})}}function WidgetModel(e,t){function n(){_.isUndefined(i.widgetInstance)||(_.isFunction(i.widgetInstance.onDispose)&&i.widgetInstance.onDispose(),i.widgetInstance=void 0)}var i=this;this.datasourceRefreshNotifications={},this.calculatedSettingScripts={},this.title=ko.observable(),this.fillSize=ko.observable(!1),this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.fillSize(s.fill_size===!0),i.widgetInstance=e,i.shouldRender(!0),i._heightUpdate.valueHasMutated()})}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onSettingsChanged)&&i.widgetInstance.onSettingsChanged(e),i.updateCalculatedSettings(),i._heightUpdate.valueHasMutated()}),this.processDatasourceUpdate=function(e){var t=i.datasourceRefreshNotifications[e];_.isArray(t)&&_.each(t,function(e){i.processCalculatedSetting(e)})},this.callValueFunction=function(t){return t.call(void 0,e.datasourceData)},this.processCalculatedSetting=function(e){if(_.isFunction(i.calculatedSettingScripts[e])){var t=void 0;try{t=i.callValueFunction(i.calculatedSettingScripts[e])}catch(n){var a=i.settings()[e];n instanceof ReferenceError&&/^\w+$/.test(a)&&(t=a)}if(!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onCalculatedValueChanged)&&!_.isUndefined(t))try{i.widgetInstance.onCalculatedValueChanged(e,t)}catch(n){console.log(""+n)}}},this.updateCalculatedSettings=function(){if(i.datasourceRefreshNotifications={},i.calculatedSettingScripts={},!_.isUndefined(i.type())){var e=t[i.type()].settings,n=RegExp("datasources.([\\w_-]+)|datasources\\[['\"]([^'\"]+)","g"),a=i.settings();_.each(e,function(e){if("calculated"==e.type){var t=a[e.name];if(!_.isUndefined(t)){1>=(t.match(/;/g)||[]).length&&-1==t.indexOf("return")&&(t="return "+t);var s;try{s=Function("datasources",t)}catch(o){var r=a[e.name].replace(/"/g,'\\"').replace(/[\r\n]/g," \\\n");s=Function("datasources",'return "'+r+'";')}i.calculatedSettingScripts[e.name]=s,i.processCalculatedSetting(e.name);for(var d;d=n.exec(t);){var c=d[1]||d[2],l=i.datasourceRefreshNotifications[c];_.isUndefined(l)&&(l=[],i.datasourceRefreshNotifications[c]=l),l.push(e.name)}}}})}},this._heightUpdate=ko.observable(),this.height=ko.computed({read:function(){return i._heightUpdate(),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.getHeight)?i.widgetInstance.getHeight():1}}),this.shouldRender=ko.observable(!1),this.render=function(e){i.shouldRender(!1),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.render)&&(i.widgetInstance.render(e),i.updateCalculatedSettings())},this.dispose=function(){},this.serialize=function(){return{title:i.title(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.title(e.title),i.settings(e.settings),i.type(e.type)}}DatasourceModel=function(e,t){function n(){_.isUndefined(i.datasourceInstance)||(_.isFunction(i.datasourceInstance.onDispose)&&i.datasourceInstance.onDispose(),i.datasourceInstance=void 0)}var i=this;this.name=ko.observable(),this.latestData=ko.observable(),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.onSettingsChanged)&&i.datasourceInstance.onSettingsChanged(e)}),this.updateCallback=function(t){e.processDatasourceUpdate(i,t),i.latestData(t);var n=new Date;i.last_updated(n.toLocaleTimeString())},this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.datasourceInstance=e,e.updateNow()},i.updateCallback)}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.last_updated=ko.observable("never"),this.last_error=ko.observable(),this.serialize=function(){return{name:i.name(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.settings(e.settings),i.name(e.name),i.type(e.type)},this.getDataRepresentation=function(e){var t=Function("data","return "+e+";");return t.call(void 0,i.latestData())},this.updateNow=function(){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.updateNow)&&i.datasourceInstance.updateNow()},this.dispose=function(){n()}},DeveloperConsole=function(e){function t(){function t(e){var t=$(""),i=$(''),a=$(''),s=$('
  • ').click(function(){n=_.without(n,a),t.remove()});n.push(a),e&&a.val(e),i.append(s),o.append(t.append($("").append(a)).append($('').append(i)))}var n=[],i=$("
    "),a=$('
    ADD
    '),s=$('
    ');s.append($('Plugin Script URL'));var o=$("");s.append(o),i.append($("

    Here you can add references to other scripts to load datasource or widget plugins.

    ")).append(s).append(a).append('

    To learn how to build plugins for freeboard, please visit http://freeboard.github.io/freeboard/docs/plugin_example.html

    '),_.each(e.plugins(),function(e){t(e)}),a.click(function(){t()}),new DialogBox(i,"Developer Console","OK",null,function(){_.each(e.plugins(),function(e){$('script[src^="'+e+'"]').remove()}),e.plugins.removeAll(),_.each(n,function(t){var n=t.val();n&&n.length>0&&(e.addPluginSource(n),head.js(n+"?"+Date.now()))})})}return{showDeveloperConsole:function(){t()}}},JSEditor=function(){function e(e){n=e}function t(e,t){head.js(n+"css/codemirror.css",n+"css/codemirror-ambiance.css",n+"js/codemirror.js",function(){var n='// Example: Convert temp from C to F and truncate to 2 decimal places.\n// return (datasources["MyDatasource"].sensor.tempInF * 1.8 + 32).toFixed(2);';e||(e=n);var i=$('
    '),a=$('
    '),s=$(''),o=$('
    This javascript will be re-evaluated any time a datasource referenced here is updated, and the value you return will be displayed in the widget. You can assume this javascript is wrapped in a function of the form function(datasources) where datasources is a collection of javascript objects (keyed by their name) corresponding to the most current data in a datasource.
    ');i.append([o,a,s]),$("body").append(i);var r=CodeMirror(a.get(0),{value:e,mode:"javascript",theme:"ambiance",indentUnit:4,lineNumbers:!0,matchBrackets:!0,autoCloseBrackets:!0}),d=$('Close').click(function(){if(t){var e=r.getValue();e===n&&(e=""),t(e),i.remove()}});s.append(d)})}var n="";return{displayJSEditor:function(e,n){t(e,n)},setAssetRoot:function(){e(_assetRoot)}}},PluginEditor=function(e,t){function n(e,t){var n=$('
    ').html(t);$("#setting-value-container-"+e).append(n)}function i(){$("#setting-row-instance-name").length?$("#setting-row-instance-name").nextAll().remove():$("#setting-row-plugin-types").nextAll().remove()}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function s(s,o,r,d,c){function l(e,t){var n=$('
    ').appendTo(h);return n.append('
    "),$('
    ').appendTo(n)}function u(n){_.each(n,function(n){function i(){f.settings[n.name].length>0?u.show():u.hide()}function a(e){var t=$("").appendTo(h),a={};_.isArray(f.settings[n.name])||(f.settings[n.name]=[]),f.settings[n.name].push(a),_.each(n.settings,function(n){var i=$("").appendTo(t),s="";_.isUndefined(e[n.name])||(s=e[n.name]),a[n.name]=s,$('').appendTo(i).val(s).change(function(){a[n.name]=$(this).val()})}),t.append($('').append($('').append($("
  • ").append($('').click(function(){var e=f.settings[n.name].indexOf(a);-1!=e&&(f.settings[n.name].splice(e,1),t.remove(),i())}))))),r.scrollTop(r[0].scrollHeight),i()}!_.isUndefined(n.default_value)&&_.isUndefined(d[n.name])&&(d[n.name]=n.default_value);var s=n.name;_.isUndefined(n.display_name)||(s=n.display_name);var o=l(n.name,s);switch(n.type){case"array":var r=$('
    ').appendTo(o),c=$('
    ').appendTo(r),u=$("").hide().appendTo(c),p=$("").appendTo(u),h=$("").appendTo(c),g=[];_.each(n.settings,function(e){var t=e.name;_.isUndefined(e.display_name)||(t=e.display_name),$(""+t+"").appendTo(p)}),n.name in d&&(g=d[n.name]),$('
    ADD
    ').appendTo(o).click(function(){var e={};_.each(n.settings,function(t){e[t.name]=""}),a(e)}),_.each(g,function(e){a(e)});break;case"boolean":f.settings[n.name]=d[n.name];var v=$('
    ').appendTo(o),m=$('').prependTo(v).change(function(){f.settings[n.name]=this.checked});n.name in d&&m.prop("checked",d[n.name]);break;case"option":var w=d[n.name],m=$("").appendTo($('
    ').appendTo(o)).change(function(){f.settings[n.name]=$(this).val()});_.each(n.options,function(e){var t,n;_.isObject(e)?(t=e.name,n=e.value):t=e,_.isUndefined(n)&&(n=t),_.isUndefined(w)&&(w=n),$("").text(t).attr("value",n).appendTo(m)}),f.settings[n.name]=w,n.name in d&&m.val(d[n.name]);break;default:if(f.settings[n.name]=d[n.name],"calculated"==n.type){var m=$("").appendTo(o).change(function(){f.settings[n.name]=$(this).val()});n.name in d&&m.val(d[n.name]),t.createValueEditor(m);var b=$(''),y=$('
  • ').mousedown(function(e){e.preventDefault(),$(m).focus(),$(m).insertAtCaret('datasources["'),$(m).trigger("freeboard-eval")}),k=$('
  • ').mousedown(function(t){t.preventDefault(),e.displayJSEditor(m.val(),function(e){m.val(e),m.change()})});$(o).append(b.append([y,k]))}else{var m=$('').appendTo(o).change(function(){f.settings[n.name]="number"==n.type?Number($(this).val()):$(this).val()});n.name in d&&m.val(d[n.name])}}_.isUndefined(n.suffix)||o.append($('
    '+n.suffix+"
    ")),_.isUndefined(n.description)||o.append($('
    '+n.description+"
    "))})}var p,f={type:r,settings:{}},h=$("
    "),g=$('
    ').hide();h.append(g),new DialogBox(h,s,"Save","Cancel",function(){$(".validation-error").remove();for(var e=0;p.settings.length>e;e++){var t=p.settings[e];if(t.required&&(_.isUndefined(f.settings[t.name])||""==f.settings[t.name]))return n(t.name,"This is required."),!0;if("number"==t.type&&!a(f.settings[t.name]))return n(t.name,"Must be a number."),!0}_.isFunction(c)&&c(f)});var v,m=_.keys(o);if(m.length>1){var w=l("plugin-types","Type");v=$("").appendTo($('
    ').appendTo(w)),v.append($("").attr("value","undefined")),_.each(o,function(e){v.append($("").text(e.display_name).attr("value",e.type_name))}),v.change(function(){f.type=$(this).val(),f.settings={},i(),p=o[v.val()],_.isUndefined(p)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#setting-row-instance-name").show(),p.description&&p.description.length>0?g.html(p.description).show():g.hide(),$("#dialog-ok").show(),u(p.settings))})}else 1==m.length&&(p=o[m[0]],u(p.settings));v&&(_.isUndefined(r)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#dialog-ok").show(),v.val(r).trigger("change")))}return{createPluginEditor:function(e,t,n,i,a,o){s(e,t,n,i,a,o)}}},ValueEditor=function(e){function t(e){var t=($(e).val().match(/\n/g)||[]).length,n=Math.min(200,20*(t+1));$(e).css({height:n+"px"})}function n(n){var a=null,s=0;$(n).addClass("calculated-value-input").bind("keyup mouseup freeboard-eval",function(t){if(a&&"keyup"==t.type&&(38==t.keyCode||40==t.keyCode||13==t.keyCode))return t.preventDefault(),void 0;var o=$(n).val().substring(0,$(n).getCaretPosition());o=o.replace(String.fromCharCode(160)," ");var r,d=i.exec(o),c=[];if(d)if(""==d[1])_.each(e.datasources(),function(e){c.push({value:e.name(),follow_char:'"].'})});else if(""!=d[1]&&_.isUndefined(d[2]))r=d[1],_.each(e.datasources(),function(e){var t=e.name();t!=r&&0==t.indexOf(r)&&c.push({value:t,follow_char:'"].'})});else{var l=_.find(e.datasources(),function(e){return e.name()===d[1]});if(!_.isUndefined(l)){var u="";_.isUndefined(d[2])||(u=d[2]);var p=u.split(".");u="data";for(var f=1;p.length-1>f;f++)""!=p[f]&&(u=u+"."+p[f]);var h=_.last(p);"["==h.charAt(h.length-1)&&(h=h.replace(/\[+$/,""),u=u+"."+h);var g=l.getDataRepresentation(u);if(_.isArray(g))for(var f=0;g.length>f;f++){var v="]";_.isObject(g[f])?v+=".":_.isArray(g[f])&&(v+="["),c.push({value:f,follow_char:v})}else _.isObject(g)&&(r=h,-1==_.keys(g).indexOf(r)&&_.each(g,function(e,t){if(t!=h&&0==t.indexOf(h)){var n=void 0;_.isArray(e)?n="[":_.isObject(e)&&(n="."),c.push({value:t,follow_char:n})}}))}}if(c.length>0){a||(a=$('').insertAfter(n).width($(n).outerWidth()-2).css("left",$(n).position().left).css("top",$(n).position().top+$(n).outerHeight()-1)),a.empty(),a.scrollTop(0);var m=!0;s=0;var w=0;_.each(c,function(e){var t=$("
  • "+e.value+"
  • ").appendTo(a).mouseenter(function(){$(this).trigger("freeboard-select")}).mousedown(function(e){$(this).trigger("freeboard-insertValue"),e.preventDefault()}).data("freeboard-optionIndex",w).data("freeboard-optionValue",e.value).bind("freeboard-insertValue",function(){var t=e.value;if(_.isUndefined(e.follow_char)||(t+=e.follow_char),_.isUndefined(r))$(n).insertAtCaret(t);else{var i=o.lastIndexOf(r);-1!=i&&$(n).replaceTextAt(i,i+r.length,t)}$(n).triggerHandler("mouseup")}).bind("freeboard-select",function(){$(this).parent().find("li.selected").removeClass("selected"),$(this).addClass("selected"),s=$(this).data("freeboard-optionIndex")});m&&($(t).addClass("selected"),m=!1),w++})}else $(n).next("ul#value-selector").remove(),a=null,s=-1}).focus(function(){t(n)}).focusout(function(){$(n).css({height:""}),$(n).next("ul#value-selector").remove(),a=null,s=-1}).bind("keydown",function(e){if(a)if(38==e.keyCode||40==e.keyCode){e.preventDefault();var t=$(a).find("li");38==e.keyCode?s--:40==e.keyCode&&s++,0>s?s=t.size()-1:s>=t.size()&&(s=0);var n=$(t).eq(s);n.trigger("freeboard-select"),$(a).scrollTop($(n).position().top)}else 13==e.keyCode&&(e.preventDefault(),-1!=s&&$(a).find("li").eq(s).trigger("freeboard-insertValue"))})}var i=RegExp('.*datasources\\["([^"]*)("\\].)?$');return{createValueEditor:function(e){n(e)}}},function(e){function t(){var e=document.createElement("p"),t=!1;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=!0},!1);else{if(!e.attachEvent)return!1;e.attachEvent("onDOMAttrModified",function(){t=!0})}return e.setAttribute("id","target"),t}function n(t,n){if(t){var i=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){i.style||(i.style={});var a=n.attributeName.split(".");n.attributeName=a[0],n.oldValue=i.style[a[1]],n.newValue=a[1]+":"+this.prop("style")[e.camelCase(a[1])],i.style[a[1]]=n.newValue}else n.oldValue=i[n.attributeName],n.newValue=this.attr(n.attributeName),i[n.attributeName]=n.newValue;this.data("attr-old-value",i)}}var i=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(a){var s={trackValues:!1,callback:e.noop};if("function"==typeof a?s.callback=a:e.extend(s,a),s.trackValues&&e(this).each(function(t,n){for(var i,a={},t=0,s=n.attributes,o=s.length;o>t;t++)i=s.item(t),a[i.nodeName]=i.value;e(this).data("attr-old-value",a)}),i){var o={subtree:!1,attributes:!0,attributeOldValue:s.trackValues},r=new i(function(t){t.forEach(function(t){var n=t.target;s.trackValues&&(t.newValue=e(n).attr(t.attributeName)),s.callback.call(n,t)})});return this.each(function(){r.observe(this,o)})}return t()?this.on("DOMAttrModified",function(e){e.originalEvent&&(e=e.originalEvent),e.attributeName=e.attrName,e.oldValue=e.prevValue,s.callback.call(this,e)}):"onpropertychange"in document.body?this.on("propertychange",function(t){t.attributeName=window.event.propertyName,n.call(e(this),s.trackValues,t),s.callback.call(this,t)}):this}}(jQuery),function(e){e.eventEmitter={_JQInit:function(){this._JQ=e(this)},emit:function(e,t){!this._JQ&&this._JQInit(),this._JQ.trigger(e,t)},once:function(e,t){!this._JQ&&this._JQInit(),this._JQ.one(e,t)},on:function(e,t){!this._JQ&&this._JQInit(),this._JQ.bind(e,t)},off:function(e,t){!this._JQ&&this._JQInit(),this._JQ.unbind(e,t)}}}(jQuery);var freeboard=function(){function e(e){var t=a.$el;t.find("> li").unbind().removeData(),$(".gridster").css("width",""),a.generate_grid_and_stylesheet(),e&&t.find("> li").each(function(){var e=this,t=ko.dataFor(e),i=n(t);$(e).attr("data-row",i.row).attr("data-col",i.col)}),a.init(),$(".gridster").css("width",300*a.cols+20*a.cols)}function t(e,t,n){var i=a.cols;_.isUndefined(t)||(e.row[i]=t),_.isUndefined(n)||(e.col[i]=n)}function n(e,t){var n=_.isUndefined(t)?a.cols:t;if(_.isNumber(e.row)&&_.isNumber(e.col)){var i={};i[n]=e.row,e.row=i,i={},i[n]=e.col,e.col=i}var s=1,o=1e3;for(var r in e.col){if(r==n)return{row:e.row[r],col:e.col[r]};if(e.col[r]>n)s=n;else{var d=n-r;o>d&&(s=r,o=d)}}return s in e.col&&s in e.row?{row:e.row[s],col:e.col[s]}:{row:1,col:s}}function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null==n?"":decodeURIComponent(n[1].replace(/\+/g," "))}var a,s=10,o=300,r={},d={},c=new FreeboardUI,l=new FreeboardModel(r,d,c),u=new JSEditor,p=new ValueEditor(l),f=new PluginEditor(u,p),h=new DeveloperConsole(l),g={values:{"font-family":'"HelveticaNeue-UltraLight", "Helvetica Neue Ultra Light", "Helvetica Neue", sans-serif',color:"#d3d4d4","font-weight":100}};return ko.bindingHandlers.pluginEditor={init:function(e,t,n,i){var a=ko.unwrap(t()),s={},o=void 0,u="";"datasource"==a.type?(s=r,u="Datasource"):"widget"==a.type?(s=d,u="Widget"):"pane"==a.type&&(u="Pane"),$(e).click(function(){if("delete"==a.operation){var t=$("

    Are you sure you want to delete this "+u+"?

    ");new DialogBox(t,"Confirm Delete","Yes","No",function(){"datasource"==a.type?l.deleteDatasource(i):"widget"==a.type?l.deleteWidget(i):"pane"==a.type&&l.deletePane(i)})}else{var n=void 0;"datasource"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings(),o.name=i.name()):"widget"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings()):"pane"==a.type&&(o={},"edit"==a.operation&&(o.title=i.title(),o.col_width=i.col_width()),s={settings:{settings:[{name:"title",display_name:"Title",type:"text"},{name:"col_width",display_name:"Columns",type:"number",default_value:1,required:!0}]}}),f.createPluginEditor(u,s,n,o,function(t){if("add"==a.operation){if("datasource"==a.type){var n=new DatasourceModel(l,r);l.addDatasource(n),n.name(t.settings.name),delete t.settings.name,n.settings(t.settings),n.type(t.type)}else if("widget"==a.type){var n=new WidgetModel(l,d);n.settings(t.settings),n.type(t.type),i.widgets.push(n),c.attachWidgetEditIcons(e)}}else"edit"==a.operation&&("pane"==a.type?(i.title(t.settings.title),i.col_width(t.settings.col_width)):("datasource"==a.type&&(i.name(t.settings.name),delete t.settings.name),i.type(t.type),i.settings(t.settings)))})}})}},ko.virtualElements.allowedBindings.datasourceTypeSettings=!0,ko.bindingHandlers.datasourceTypeSettings={update:function(e,t,n,i,a){processPluginSettings(e,t,n,i,a)}},ko.bindingHandlers.grid={init:function(t){a=$(t).gridster({widget_margins:[s,s],widget_base_dimensions:[o,10],resize:{enabled:!0,axes:"x"}}).data("gridster"),e(!1),a.disable()}},ko.bindingHandlers.pane={init:function(e,i,s,o,r){l.isEditing()&&$(e).css({cursor:"pointer"});var d=n(o),u=d.col,p=d.row,f=Number(o.width()),h=Number(o.getCalculatedHeight());a.add_widget(e,f,h,u,p),r.$root.isEditing()&&c.showPaneEditIcons(!0),t(o,p,u),$(e).attrchange({trackValues:!0,callback:function(e){"data-row"==e.attributeName?t(o,Number(e.newValue),void 0):"data-col"==e.attributeName&&t(o,void 0,Number(e.newValue))}})},update:function(e,t,n,i){-1==l.panes.indexOf(i)&&a.remove_widget(e);var s=i.getCalculatedHeight();(s!=Number($(e).attr("data-sizey"))||i.col_width()!=Number($(e).attr("data-sizex")))&&a.resize_widget($(e),i.col_width(),s,function(){a.set_dom_grid_height()})}},ko.bindingHandlers.widget={init:function(e){l.isEditing()&&c.attachWidgetEditIcons($(e).parent())},update:function(e,t,n,i){i.shouldRender()&&($(e).empty(),i.render(e))}},$(function(){function t(){e(!0)}c.showLoadingIndicator(!0);var n;$(window).resize(function(){clearTimeout(n),n=setTimeout(t,500)})}),{initialize:function(e,t){ko.applyBindings(l);var n=i("load");""!=n?$.ajax({url:n,success:function(e){l.loadDashboard(e),_.isFunction(t)&&t()}}):(l.allow_edit(e),l.setEditing(e),c.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("initialized"))},newDashboard:function(){l.loadDashboard({allow_edit:!0})},loadDashboard:function(e,t){l.loadDashboard(e,t)},serialize:function(){return l.serialize()},setEditing:function(e,t){l.setEditing(e,t)},isEditing:function(){return l.isEditing()},loadDatasourcePlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),e.settings.unshift({name:"name",display_name:"Name",type:"text",required:!0}),l.addPluginSource(e.source),r[e.type_name]=e,l._datasourceTypes.valueHasMutated()},resize:function(){e(!0)},loadWidgetPlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),l.addPluginSource(e.source),d[e.type_name]=e,l._widgetTypes.valueHasMutated()},setAssetRoot:function(e){u.setAssetRoot(e)},addStyle:function(e,t){var n,i=document;"object"==typeof i.styleSheets&&(i.styleSheets.length&&(n=i.styleSheets[i.styleSheets.length-1]),i.styleSheets.length&&(i.createStyleSheet?n=i.createStyleSheet():(i.getElementsByTagName("head")[0].appendChild(i.createElement("style")),n=i.styleSheets[i.styleSheets.length-1])),n.addRule?n.addRule(e,t):n.insertRule(e+"{"+t+"}",n.cssRules.length))},showLoadingIndicator:function(e){c.showLoadingIndicator(e)},showDialog:function(e,t,n,i,a){new DialogBox(e,t,n,i,a)},getDatasourceSettings:function(e){var t=l.datasources(),n=_.find(t,function(t){return t.name()===e});return n?n.settings():null},setDatasourceSettings:function(e,t){var n=l.datasources(),i=_.find(n,function(t){return t.name()===e});if(!i)return console.log("Datasource not found"),void 0;var a=_.defaults(t,i.settings());i.settings(a)},getStyleString:function(e){var t="";return _.each(g[e],function(e,n){t=t+n+":"+e+";"}),t},getStyleObject:function(e){return g[e]},showDeveloperConsole:function(){h.showDeveloperConsole()},_removeAllWidgets:function(){a.remove_all_widgets()},_disableGrid:function(){a.disable()},_enableGrid:function(){a.enable()},_getPositionForScreenSize:function(e){return n(e)}}}();$.extend(freeboard,jQuery.eventEmitter); \ No newline at end of file +function DialogBox(e,t,n,i,a){function s(){o.fadeOut(200,function(){$(this).remove()})}var o=$(''),r=$('');r.append('

    '+t+"

    "),$("
    ").appendTo(r).append(e);var d=$("").appendTo(r);n&&$(''+n+"").appendTo(d).click(function(){var e=!1;_.isFunction(a)&&(e=a()),e||s()}),i&&$(''+i+"").appendTo(d).click(function(){s()}),o.append(r),$("body").append(o),o.fadeIn(200)}function FreeboardModel(e,t,n){var i=this,a=1;this.version=0,this.isEditing=ko.observable(!1),this.allow_edit=ko.observable(!1),this.allow_edit.subscribe(function(e){e?$("#main-header").show():$("#main-header").hide()}),this.header_image=ko.observable(),this.plugins=ko.observableArray(),this.datasources=ko.observableArray(),this.panes=ko.observableArray(),this.datasourceData={},this.processDatasourceUpdate=function(e,t){var n=e.name();i.datasourceData[n]=t,_.each(i.panes(),function(e){_.each(e.widgets(),function(e){e.processDatasourceUpdate(n)})})},this._datasourceTypes=ko.observable(),this.datasourceTypes=ko.computed({read:function(){i._datasourceTypes();var t=[];return _.each(e,function(e){var n=e.type_name,i=n;_.isUndefined(e.display_name)||(i=e.display_name),t.push({name:n,display_name:i})}),t}}),this._widgetTypes=ko.observable(),this.widgetTypes=ko.computed({read:function(){i._widgetTypes();var e=[];return _.each(t,function(t){var n=t.type_name,i=n;_.isUndefined(t.display_name)||(i=t.display_name),e.push({name:n,display_name:i})}),e}}),this.addPluginSource=function(e){e&&-1==i.plugins.indexOf(e)&&i.plugins.push(e)},this.serialize=function(){var e=[];_.each(i.panes(),function(t){e.push(t.serialize())});var t=[];return _.each(i.datasources(),function(e){t.push(e.serialize())}),{version:a,header_image:i.header_image(),allow_edit:i.allow_edit(),plugins:i.plugins(),panes:e,datasources:t}},this.deserialize=function(n,a){function s(){_.isUndefined(n.allow_edit)?i.allow_edit(!0):i.allow_edit(n.allow_edit),i.version=n.version||0,i.header_image(n.header_image),_.each(n.datasources,function(t){var n=new DatasourceModel(i,e);n.deserialize(t),i.addDatasource(n)});var s=_.sortBy(n.panes,function(e){return freeboard._getPositionForScreenSize(e).row});_.each(s,function(e){var n=new PaneModel(i,t);n.deserialize(e),i.panes.push(n)}),i.allow_edit()&&0==i.panes().length&&i.setEditing(!0),_.isFunction(a)&&a()}i.clearDashboard(),_.each(n.plugins,function(e){i.addPluginSource(e)}),_.isArray(n.plugins)&&n.plugins.length>0?head.js(n.plugins,function(){s()}):s()},this.clearDashboard=function(){freeboard._removeAllWidgets(),_.each(i.datasources(),function(e){e.dispose()}),_.each(i.panes(),function(e){e.dispose()}),i.plugins.removeAll(),i.datasources.removeAll(),i.panes.removeAll()},this.loadDashboard=function(e,t){n.showLoadingIndicator(!0),i.deserialize(e,function(){n.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("dashboard_loaded")})},this.loadDashboardFromLocalFile=function(){if(window.File&&window.FileReader&&window.FileList&&window.Blob){var e=document.createElement("input");e.type="file",$(e).on("change",function(e){var t=e.target.files;if(t&&t.length>0){var n=t[0],a=new FileReader;a.addEventListener("load",function(e){var t=e.target,n=JSON.parse(t.result);i.loadDashboard(n),i.setEditing(!1)}),a.readAsText(n)}}),$(e).trigger("click")}else alert("Unable to load a file in this browser.")},this.saveDashboard=function(){var e="application/octet-stream",t=document.createElement("a"),n=new Blob([JSON.stringify(i.serialize())],{type:e});document.body.appendChild(t),t.href=window.URL.createObjectURL(n),t.download="dashboard.json",t.target="_self",t.click()},this.addDatasource=function(e){i.datasources.push(e)},this.deleteDatasource=function(e){delete i.datasourceData[e.name()],e.dispose(),i.datasources.remove(e)},this.createPane=function(){var e=new PaneModel(i,t);i.addPane(e)},this.addPane=function(e){i.panes.push(e)},this.deletePane=function(e){e.dispose(),i.panes.remove(e)},this.deleteWidget=function(e){ko.utils.arrayForEach(i.panes(),function(t){t.widgets.remove(e)}),e.dispose()},this.setEditing=function(e,t){if(i.allow_edit()||!e){i.isEditing(e),_.isUndefined(t)&&(t=!0);var a=t?250:0,s=$("#admin-bar").outerHeight();e?($("#toggle-header-icon").addClass("icon-chevron-up").removeClass("icon-wrench"),$(".gridster .gs_w").css({cursor:"pointer"}),$("#main-header").animate({top:"0px"},a),$("#board-content").animate({top:s+20+"px"},a),$("#main-header").data().shown=!0,n.attachWidgetEditIcons($(".sub-section")),freeboard._enableGrid()):($("#toggle-header-icon").addClass("icon-wrench").removeClass("icon-chevron-up"),$(".gridster .gs_w").css({cursor:"default"}),$("#main-header").animate({top:"-"+s+"px"},a),$("#board-content").animate({top:"20"},a),$("#main-header").data().shown=!1,$(".sub-section").unbind(),freeboard._disableGrid()),n.showPaneEditIcons(e,t)}},this.toggleEditing=function(){var e=!i.isEditing();i.setEditing(e)}}function FreeboardUI(){function e(e){e?a.fadeOut(0).appendTo("body").fadeIn(500):a.fadeOut(500).remove()}function t(e,t){_.isUndefined(t)&&(t=!0);var n=t?250:0;e?$(".pane-tools").fadeIn(n):$(".pane-tools").fadeOut(n)}function n(e){$(e).hover(function(){i(this,!0)},function(){i(this,!1)})}function i(e,t){t?$(e).find(".sub-section-tools").fadeIn(250):$(e).find(".sub-section-tools").fadeOut(250)}var a=$('
    ');return{showLoadingIndicator:function(t){e(t)},showPaneEditIcons:function(e,n){t(e,n)},attachWidgetEditIcons:function(e){n(e)}}}function PaneModel(e,t){var n=this;this.title=ko.observable(),this.width=ko.observable(1),this.row={},this.col={},this.col_width=ko.observable(1),this.widgets=ko.observableArray(),this.addWidget=function(e){this.widgets.push(e)},this.widgetCanMoveUp=function(e){return n.widgets.indexOf(e)>=1},this.widgetCanMoveDown=function(e){var t=n.widgets.indexOf(e);return n.widgets().length-1>t},this.moveWidgetUp=function(e){if(n.widgetCanMoveUp(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t-1,2,i[t],i[t-1])}},this.moveWidgetDown=function(e){if(n.widgetCanMoveDown(e)){var t=n.widgets.indexOf(e),i=n.widgets();n.widgets.splice(t,2,i[t+1],i[t])}},this.getCalculatedHeight=function(){var e=_.reduce(n.widgets(),function(e,t){return e+t.height()},0);e*=6,e+=3,e*=10;var t=Math.ceil((e+20)/30);return Math.max(4,t)},this.serialize=function(){var e=[];return _.each(n.widgets(),function(t){e.push(t.serialize())}),{title:n.title(),width:n.width(),row:n.row,col:n.col,col_width:n.col_width(),widgets:e}},this.deserialize=function(i){n.title(i.title),n.width(i.width),n.row=i.row,n.col=i.col,n.col_width(i.col_width||1),_.each(i.widgets,function(i){var a=new WidgetModel(e,t);a.deserialize(i),n.widgets.push(a)})},this.dispose=function(){_.each(n.widgets(),function(e){e.dispose()})}}function WidgetModel(e,t){function n(){_.isUndefined(i.widgetInstance)||(_.isFunction(i.widgetInstance.onDispose)&&i.widgetInstance.onDispose(),i.widgetInstance=void 0)}var i=this;this.datasourceRefreshNotifications={},this.calculatedSettingScripts={},this.title=ko.observable(),this.fillSize=ko.observable(!1),this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.fillSize(s.fill_size===!0),i.widgetInstance=e,i.shouldRender(!0),i._heightUpdate.valueHasMutated()})}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onSettingsChanged)&&i.widgetInstance.onSettingsChanged(e),i.updateCalculatedSettings(),i._heightUpdate.valueHasMutated()}),this.processDatasourceUpdate=function(e){var t=i.datasourceRefreshNotifications[e];_.isArray(t)&&_.each(t,function(e){i.processCalculatedSetting(e)})},this.callValueFunction=function(t){return t.call(void 0,e.datasourceData)},this.processCalculatedSetting=function(e){if(_.isFunction(i.calculatedSettingScripts[e])){var t=void 0;try{t=i.callValueFunction(i.calculatedSettingScripts[e])}catch(n){var a=i.settings()[e];n instanceof ReferenceError&&/^\w+$/.test(a)&&(t=a)}if(!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.onCalculatedValueChanged)&&!_.isUndefined(t))try{i.widgetInstance.onCalculatedValueChanged(e,t)}catch(n){console.log(""+n)}}},this.updateCalculatedSettings=function(){if(i.datasourceRefreshNotifications={},i.calculatedSettingScripts={},!_.isUndefined(i.type())){var e=t[i.type()].settings,n=RegExp("datasources.([\\w_-]+)|datasources\\[['\"]([^'\"]+)","g"),a=i.settings();_.each(e,function(e){if("calculated"==e.type){var t=a[e.name];if(!_.isUndefined(t)){1>=(t.match(/;/g)||[]).length&&-1==t.indexOf("return")&&(t="return "+t);var s;try{s=Function("datasources",t)}catch(o){var r=a[e.name].replace(/"/g,'\\"').replace(/[\r\n]/g," \\\n");s=Function("datasources",'return "'+r+'";')}i.calculatedSettingScripts[e.name]=s,i.processCalculatedSetting(e.name);for(var d;d=n.exec(t);){var c=d[1]||d[2],l=i.datasourceRefreshNotifications[c];_.isUndefined(l)&&(l=[],i.datasourceRefreshNotifications[c]=l),l.push(e.name)}}}})}},this._heightUpdate=ko.observable(),this.height=ko.computed({read:function(){return i._heightUpdate(),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.getHeight)?i.widgetInstance.getHeight():1}}),this.shouldRender=ko.observable(!1),this.render=function(e){i.shouldRender(!1),!_.isUndefined(i.widgetInstance)&&_.isFunction(i.widgetInstance.render)&&(i.widgetInstance.render(e),i.updateCalculatedSettings())},this.dispose=function(){},this.serialize=function(){return{title:i.title(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.title(e.title),i.settings(e.settings),i.type(e.type)}}DatasourceModel=function(e,t){function n(){_.isUndefined(i.datasourceInstance)||(_.isFunction(i.datasourceInstance.onDispose)&&i.datasourceInstance.onDispose(),i.datasourceInstance=void 0)}var i=this;this.name=ko.observable(),this.latestData=ko.observable(),this.settings=ko.observable({}),this.settings.subscribe(function(e){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.onSettingsChanged)&&i.datasourceInstance.onSettingsChanged(e)}),this.updateCallback=function(t){e.processDatasourceUpdate(i,t),i.latestData(t);var n=new Date;i.last_updated(n.toLocaleTimeString())},this.type=ko.observable(),this.type.subscribe(function(e){function a(){s.newInstance(i.settings(),function(e){i.datasourceInstance=e,e.updateNow()},i.updateCallback)}if(n(),e in t&&_.isFunction(t[e].newInstance)){var s=t[e];s.external_scripts?head.js(s.external_scripts.slice(0),a):a()}}),this.last_updated=ko.observable("never"),this.last_error=ko.observable(),this.serialize=function(){return{name:i.name(),type:i.type(),settings:i.settings()}},this.deserialize=function(e){i.settings(e.settings),i.name(e.name),i.type(e.type)},this.getDataRepresentation=function(e){var t=Function("data","return "+e+";");return t.call(void 0,i.latestData())},this.updateNow=function(){!_.isUndefined(i.datasourceInstance)&&_.isFunction(i.datasourceInstance.updateNow)&&i.datasourceInstance.updateNow()},this.dispose=function(){n()}},DeveloperConsole=function(e){function t(){function t(e){var t=$(""),i=$(''),a=$(''),s=$('
  • ').click(function(){n=_.without(n,a),t.remove()});n.push(a),e&&a.val(e),i.append(s),o.append(t.append($("").append(a)).append($('').append(i)))}var n=[],i=$("
    "),a=$('
    ADD
    '),s=$('
    ');s.append($('Plugin Script URL'));var o=$("");s.append(o),i.append($("

    Here you can add references to other scripts to load datasource or widget plugins.

    ")).append(s).append(a).append('

    To learn how to build plugins for freeboard, please visit http://freeboard.github.io/freeboard/docs/plugin_example.html

    '),_.each(e.plugins(),function(e){t(e)}),a.click(function(){t()}),new DialogBox(i,"Developer Console","OK",null,function(){_.each(e.plugins(),function(e){$('script[src^="'+e+'"]').remove()}),e.plugins.removeAll(),_.each(n,function(t){var n=t.val();n&&n.length>0&&(e.addPluginSource(n),head.js(n+"?"+Date.now()))})})}return{showDeveloperConsole:function(){t()}}},JSEditor=function(){function e(e){n=e}function t(e,t){head.js(n+"css/codemirror.css",n+"css/codemirror-ambiance.css",n+"js/codemirror.js",function(){var n='// Example: Convert temp from C to F and truncate to 2 decimal places.\n// return (datasources["MyDatasource"].sensor.tempInF * 1.8 + 32).toFixed(2);';e||(e=n);var i=$('
    '),a=$('
    '),s=$(''),o=$('
    This javascript will be re-evaluated any time a datasource referenced here is updated, and the value you return will be displayed in the widget. You can assume this javascript is wrapped in a function of the form function(datasources) where datasources is a collection of javascript objects (keyed by their name) corresponding to the most current data in a datasource.
    ');i.append([o,a,s]),$("body").append(i);var r=CodeMirror(a.get(0),{value:e,mode:"javascript",theme:"ambiance",indentUnit:4,lineNumbers:!0,matchBrackets:!0,autoCloseBrackets:!0}),d=$('Close').click(function(){if(t){var e=r.getValue();e===n&&(e=""),t(e),i.remove()}});s.append(d)})}var n="";return{displayJSEditor:function(e,n){t(e,n)},setAssetRoot:function(){e(_assetRoot)}}},PluginEditor=function(e,t){function n(e,t){var n=$('
    ').html(t);$("#setting-value-container-"+e).append(n)}function i(){$("#setting-row-instance-name").length?$("#setting-row-instance-name").nextAll().remove():$("#setting-row-plugin-types").nextAll().remove()}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function s(s,o,r,d,c){function l(e,t){var n=$('
    ').appendTo(h);return n.append('
    "),$('
    ').appendTo(n)}function u(n){_.each(n,function(n){function i(){f.settings[n.name].length>0?u.show():u.hide()}function a(e){var t=$("").appendTo(h),a={};_.isArray(f.settings[n.name])||(f.settings[n.name]=[]),f.settings[n.name].push(a),_.each(n.settings,function(n){var i=$("").appendTo(t),s="";_.isUndefined(e[n.name])||(s=e[n.name]),a[n.name]=s,$('').appendTo(i).val(s).change(function(){a[n.name]=$(this).val()})}),t.append($('').append($('').append($("
  • ").append($('').click(function(){var e=f.settings[n.name].indexOf(a);-1!=e&&(f.settings[n.name].splice(e,1),t.remove(),i())}))))),r.scrollTop(r[0].scrollHeight),i()}!_.isUndefined(n.default_value)&&_.isUndefined(d[n.name])&&(d[n.name]=n.default_value);var s=n.name;_.isUndefined(n.display_name)||(s=n.display_name);var o=l(n.name,s);switch(n.type){case"array":var r=$('
    ').appendTo(o),c=$('
    ').appendTo(r),u=$("").hide().appendTo(c),p=$("").appendTo(u),h=$("").appendTo(c),g=[];_.each(n.settings,function(e){var t=e.name;_.isUndefined(e.display_name)||(t=e.display_name),$(""+t+"").appendTo(p)}),n.name in d&&(g=d[n.name]),$('
    ADD
    ').appendTo(o).click(function(){var e={};_.each(n.settings,function(t){e[t.name]=""}),a(e)}),_.each(g,function(e){a(e)});break;case"boolean":f.settings[n.name]=d[n.name];var v=$('
    ').appendTo(o),m=$('').prependTo(v).change(function(){f.settings[n.name]=this.checked});n.name in d&&m.prop("checked",d[n.name]);break;case"option":var w=d[n.name],m=$("").appendTo($('
    ').appendTo(o)).change(function(){f.settings[n.name]=$(this).val()});_.each(n.options,function(e){var t,n;_.isObject(e)?(t=e.name,n=e.value):t=e,_.isUndefined(n)&&(n=t),_.isUndefined(w)&&(w=n),$("").text(t).attr("value",n).appendTo(m)}),f.settings[n.name]=w,n.name in d&&m.val(d[n.name]);break;default:if(f.settings[n.name]=d[n.name],"calculated"==n.type){var m=$("").appendTo(o).change(function(){f.settings[n.name]=$(this).val()});n.name in d&&m.val(d[n.name]),t.createValueEditor(m);var b=$(''),y=$('
  • ').mousedown(function(e){e.preventDefault(),$(m).focus(),$(m).insertAtCaret('datasources["'),$(m).trigger("freeboard-eval")}),k=$('
  • ').mousedown(function(t){t.preventDefault(),e.displayJSEditor(m.val(),function(e){m.val(e),m.change()})});$(o).append(b.append([y,k]))}else{var m=$('').appendTo(o).change(function(){f.settings[n.name]="number"==n.type?Number($(this).val()):$(this).val()});n.name in d&&m.val(d[n.name])}}_.isUndefined(n.suffix)||o.append($('
    '+n.suffix+"
    ")),_.isUndefined(n.description)||o.append($('
    '+n.description+"
    "))})}var p,f={type:r,settings:{}},h=$("
    "),g=$('
    ').hide();h.append(g),new DialogBox(h,s,"Save","Cancel",function(){$(".validation-error").remove();for(var e=0;p.settings.length>e;e++){var t=p.settings[e];if(t.required&&(_.isUndefined(f.settings[t.name])||""==f.settings[t.name]))return n(t.name,"This is required."),!0;if("number"==t.type&&!a(f.settings[t.name]))return n(t.name,"Must be a number."),!0}_.isFunction(c)&&c(f)});var v,m=_.keys(o);if(m.length>1){var w=l("plugin-types","Type");v=$("").appendTo($('
    ').appendTo(w)),v.append($("").attr("value","undefined")),_.each(o,function(e){v.append($("").text(e.display_name).attr("value",e.type_name))}),v.change(function(){f.type=$(this).val(),f.settings={},i(),p=o[v.val()],_.isUndefined(p)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#setting-row-instance-name").show(),p.description&&p.description.length>0?g.html(p.description).show():g.hide(),$("#dialog-ok").show(),u(p.settings))})}else 1==m.length&&(p=o[m[0]],u(p.settings));v&&(_.isUndefined(r)?($("#setting-row-instance-name").hide(),$("#dialog-ok").hide()):($("#dialog-ok").show(),v.val(r).trigger("change")))}return{createPluginEditor:function(e,t,n,i,a,o){s(e,t,n,i,a,o)}}},ValueEditor=function(e){function t(e){var t=($(e).val().match(/\n/g)||[]).length,n=Math.min(200,20*(t+1));$(e).css({height:n+"px"})}function n(e,t){var n,i=s.exec(e),r=[];if(i)if(""==i[1])_.each(t,function(e){r.push({value:e.name(),follow_char:'"]["'})});else if(""!=i[1]&&_.isUndefined(i[2]))n=i[1],_.each(t,function(e){var t=e.name();t!=n&&0==t.indexOf(n)&&r.push({value:t,follow_char:'"]["'})});else{var d=_.find(t,function(e){return e.name()===i[1]});if(!_.isUndefined(d)){var c="";_.isUndefined(i[2])||(c=i[2]+i[3]);var l=c.split('"]["');c="data";for(var u=1;l.length-1>u;u++)""!=l[u]&&(dataPathItem='["'+l[u]+'"]',c+=dataPathItem);var p=_.last(l);'"'==p.charAt(p.length-1)&&(p=p.replace(/\[\"?$/,""),c=c+'["'+p+'"]');var f=d.getDataRepresentation(c);if(_.isArray(f))for(var u=0;f.length>u;u++){var h='"]';_.isObject(f[u])?h+='"]["':_.isArray(f[u])&&(h+='"]['),r.push({value:u,follow_char:h})}else _.isObject(f)&&(n=p,-1==_.keys(f).indexOf(n)&&_.each(f,function(e,t){if(t!=p&&0==t.indexOf(p)){var n='"]';_.isArray(e)?n='"][':_.isObject(e)&&(n='"]["'),r.push({value:t,follow_char:n})}}))}}o=r,a=n}function i(i){var s=null,r=0;$(i).addClass("calculated-value-input").bind("keyup mouseup freeboard-eval",function(t){if(s&&"keyup"==t.type&&(38==t.keyCode||40==t.keyCode||13==t.keyCode))return t.preventDefault(),void 0;var d=$(i).val().substring(0,$(i).getCaretPosition());if(d=d.replace(String.fromCharCode(160)," "),n(d,e.datasources()),o.length>0){s||(s=$('').insertAfter(i).width($(i).outerWidth()-2).css("left",$(i).position().left).css("top",$(i).position().top+$(i).outerHeight()-1)),s.empty(),s.scrollTop(0);var c=!0;r=0;var l=0;_.each(o,function(e){var t=$("
  • "+e.value+"
  • ").appendTo(s).mouseenter(function(){$(this).trigger("freeboard-select")}).mousedown(function(e){$(this).trigger("freeboard-insertValue"),e.preventDefault()}).data("freeboard-optionIndex",l).data("freeboard-optionValue",e.value).bind("freeboard-insertValue",function(){var t=e.value;if(_.isUndefined(e.follow_char)||(t+=e.follow_char),_.isUndefined(a))$(i).insertAtCaret(t);else{var n=d.lastIndexOf(a);-1!=n&&$(i).replaceTextAt(n,n+a.length,t)}$(i).triggerHandler("mouseup")}).bind("freeboard-select",function(){$(this).parent().find("li.selected").removeClass("selected"),$(this).addClass("selected"),r=$(this).data("freeboard-optionIndex")});c&&($(t).addClass("selected"),c=!1),l++})}else $(i).next("ul#value-selector").remove(),s=null,r=-1}).focus(function(){t(i)}).focusout(function(){$(i).css({height:""}),$(i).next("ul#value-selector").remove(),s=null,r=-1}).bind("keydown",function(e){if(s)if(38==e.keyCode||40==e.keyCode){e.preventDefault();var t=$(s).find("li");38==e.keyCode?r--:40==e.keyCode&&r++,0>r?r=t.size()-1:r>=t.size()&&(r=0);var n=$(t).eq(r);n.trigger("freeboard-select"),$(s).scrollTop($(n).position().top)}else 13==e.keyCode&&(e.preventDefault(),-1!=r&&$(s).find("li").eq(r).trigger("freeboard-insertValue"))})}var a,s=RegExp('.*datasources\\["([^"]*)("\\]\\[")?(.*)$'),o=[];return{createValueEditor:function(e){i(e)}}},function(e){function t(){var e=document.createElement("p"),t=!1;if(e.addEventListener)e.addEventListener("DOMAttrModified",function(){t=!0},!1);else{if(!e.attachEvent)return!1;e.attachEvent("onDOMAttrModified",function(){t=!0})}return e.setAttribute("id","target"),t}function n(t,n){if(t){var i=this.data("attr-old-value");if(n.attributeName.indexOf("style")>=0){i.style||(i.style={});var a=n.attributeName.split(".");n.attributeName=a[0],n.oldValue=i.style[a[1]],n.newValue=a[1]+":"+this.prop("style")[e.camelCase(a[1])],i.style[a[1]]=n.newValue}else n.oldValue=i[n.attributeName],n.newValue=this.attr(n.attributeName),i[n.attributeName]=n.newValue;this.data("attr-old-value",i)}}var i=window.MutationObserver||window.WebKitMutationObserver;e.fn.attrchange=function(a){var s={trackValues:!1,callback:e.noop};if("function"==typeof a?s.callback=a:e.extend(s,a),s.trackValues&&e(this).each(function(t,n){for(var i,a={},t=0,s=n.attributes,o=s.length;o>t;t++)i=s.item(t),a[i.nodeName]=i.value;e(this).data("attr-old-value",a)}),i){var o={subtree:!1,attributes:!0,attributeOldValue:s.trackValues},r=new i(function(t){t.forEach(function(t){var n=t.target;s.trackValues&&(t.newValue=e(n).attr(t.attributeName)),s.callback.call(n,t)})});return this.each(function(){r.observe(this,o)})}return t()?this.on("DOMAttrModified",function(e){e.originalEvent&&(e=e.originalEvent),e.attributeName=e.attrName,e.oldValue=e.prevValue,s.callback.call(this,e)}):"onpropertychange"in document.body?this.on("propertychange",function(t){t.attributeName=window.event.propertyName,n.call(e(this),s.trackValues,t),s.callback.call(this,t)}):this}}(jQuery),function(e){e.eventEmitter={_JQInit:function(){this._JQ=e(this)},emit:function(e,t){!this._JQ&&this._JQInit(),this._JQ.trigger(e,t)},once:function(e,t){!this._JQ&&this._JQInit(),this._JQ.one(e,t)},on:function(e,t){!this._JQ&&this._JQInit(),this._JQ.bind(e,t)},off:function(e,t){!this._JQ&&this._JQInit(),this._JQ.unbind(e,t)}}}(jQuery);var freeboard=function(){function e(e){var t=a.$el;t.find("> li").unbind().removeData(),$(".gridster").css("width",""),a.generate_grid_and_stylesheet(),e&&t.find("> li").each(function(){var e=this,t=ko.dataFor(e),i=n(t);$(e).attr("data-row",i.row).attr("data-col",i.col)}),a.init(),$(".gridster").css("width",300*a.cols+20*a.cols)}function t(e,t,n){var i=a.cols;_.isUndefined(t)||(e.row[i]=t),_.isUndefined(n)||(e.col[i]=n)}function n(e,t){var n=_.isUndefined(t)?a.cols:t;if(_.isNumber(e.row)&&_.isNumber(e.col)){var i={};i[n]=e.row,e.row=i,i={},i[n]=e.col,e.col=i}var s=1,o=1e3;for(var r in e.col){if(r==n)return{row:e.row[r],col:e.col[r]};if(e.col[r]>n)s=n;else{var d=n-r;o>d&&(s=r,o=d)}}return s in e.col&&s in e.row?{row:e.row[s],col:e.col[s]}:{row:1,col:s}}function i(e){e=e.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var t=RegExp("[\\?&]"+e+"=([^&#]*)"),n=t.exec(location.search);return null==n?"":decodeURIComponent(n[1].replace(/\+/g," "))}var a,s=10,o=300,r={},d={},c=new FreeboardUI,l=new FreeboardModel(r,d,c),u=new JSEditor,p=new ValueEditor(l),f=new PluginEditor(u,p),h=new DeveloperConsole(l),g={values:{"font-family":'"HelveticaNeue-UltraLight", "Helvetica Neue Ultra Light", "Helvetica Neue", sans-serif',color:"#d3d4d4","font-weight":100}};return ko.bindingHandlers.pluginEditor={init:function(e,t,n,i){var a=ko.unwrap(t()),s={},o=void 0,u="";"datasource"==a.type?(s=r,u="Datasource"):"widget"==a.type?(s=d,u="Widget"):"pane"==a.type&&(u="Pane"),$(e).click(function(){if("delete"==a.operation){var t=$("

    Are you sure you want to delete this "+u+"?

    ");new DialogBox(t,"Confirm Delete","Yes","No",function(){"datasource"==a.type?l.deleteDatasource(i):"widget"==a.type?l.deleteWidget(i):"pane"==a.type&&l.deletePane(i)})}else{var n=void 0;"datasource"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings(),o.name=i.name()):"widget"==a.type?"add"==a.operation?o={}:(n=i.type(),o=i.settings()):"pane"==a.type&&(o={},"edit"==a.operation&&(o.title=i.title(),o.col_width=i.col_width()),s={settings:{settings:[{name:"title",display_name:"Title",type:"text"},{name:"col_width",display_name:"Columns",type:"number",default_value:1,required:!0}]}}),f.createPluginEditor(u,s,n,o,function(t){if("add"==a.operation){if("datasource"==a.type){var n=new DatasourceModel(l,r);l.addDatasource(n),n.name(t.settings.name),delete t.settings.name,n.settings(t.settings),n.type(t.type)}else if("widget"==a.type){var n=new WidgetModel(l,d);n.settings(t.settings),n.type(t.type),i.widgets.push(n),c.attachWidgetEditIcons(e)}}else"edit"==a.operation&&("pane"==a.type?(i.title(t.settings.title),i.col_width(t.settings.col_width)):("datasource"==a.type&&(i.name(t.settings.name),delete t.settings.name),i.type(t.type),i.settings(t.settings)))})}})}},ko.virtualElements.allowedBindings.datasourceTypeSettings=!0,ko.bindingHandlers.datasourceTypeSettings={update:function(e,t,n,i,a){processPluginSettings(e,t,n,i,a)}},ko.bindingHandlers.grid={init:function(t){a=$(t).gridster({widget_margins:[s,s],widget_base_dimensions:[o,10],resize:{enabled:!0,axes:"x"}}).data("gridster"),e(!1),a.disable()}},ko.bindingHandlers.pane={init:function(e,i,s,o,r){l.isEditing()&&$(e).css({cursor:"pointer"});var d=n(o),u=d.col,p=d.row,f=Number(o.width()),h=Number(o.getCalculatedHeight());a.add_widget(e,f,h,u,p),r.$root.isEditing()&&c.showPaneEditIcons(!0),t(o,p,u),$(e).attrchange({trackValues:!0,callback:function(e){"data-row"==e.attributeName?t(o,Number(e.newValue),void 0):"data-col"==e.attributeName&&t(o,void 0,Number(e.newValue))}})},update:function(e,t,n,i){-1==l.panes.indexOf(i)&&a.remove_widget(e);var s=i.getCalculatedHeight();(s!=Number($(e).attr("data-sizey"))||i.col_width()!=Number($(e).attr("data-sizex")))&&a.resize_widget($(e),i.col_width(),s,function(){a.set_dom_grid_height()})}},ko.bindingHandlers.widget={init:function(e){l.isEditing()&&c.attachWidgetEditIcons($(e).parent())},update:function(e,t,n,i){i.shouldRender()&&($(e).empty(),i.render(e))}},$(function(){function t(){e(!0)}c.showLoadingIndicator(!0);var n;$(window).resize(function(){clearTimeout(n),n=setTimeout(t,500)})}),{initialize:function(e,t){ko.applyBindings(l);var n=i("load");""!=n?$.ajax({url:n,success:function(e){l.loadDashboard(e),_.isFunction(t)&&t()}}):(l.allow_edit(e),l.setEditing(e),c.showLoadingIndicator(!1),_.isFunction(t)&&t(),freeboard.emit("initialized"))},newDashboard:function(){l.loadDashboard({allow_edit:!0})},loadDashboard:function(e,t){l.loadDashboard(e,t)},serialize:function(){return l.serialize()},setEditing:function(e,t){l.setEditing(e,t)},isEditing:function(){return l.isEditing()},loadDatasourcePlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),e.settings.unshift({name:"name",display_name:"Name",type:"text",required:!0}),l.addPluginSource(e.source),r[e.type_name]=e,l._datasourceTypes.valueHasMutated()},resize:function(){e(!0)},loadWidgetPlugin:function(e){_.isUndefined(e.display_name)&&(e.display_name=e.type_name),l.addPluginSource(e.source),d[e.type_name]=e,l._widgetTypes.valueHasMutated()},setAssetRoot:function(e){u.setAssetRoot(e)},addStyle:function(e,t){var n,i=document;"object"==typeof i.styleSheets&&(i.styleSheets.length&&(n=i.styleSheets[i.styleSheets.length-1]),i.styleSheets.length&&(i.createStyleSheet?n=i.createStyleSheet():(i.getElementsByTagName("head")[0].appendChild(i.createElement("style")),n=i.styleSheets[i.styleSheets.length-1])),n.addRule?n.addRule(e,t):n.insertRule(e+"{"+t+"}",n.cssRules.length))},showLoadingIndicator:function(e){c.showLoadingIndicator(e)},showDialog:function(e,t,n,i,a){new DialogBox(e,t,n,i,a)},getDatasourceSettings:function(e){var t=l.datasources(),n=_.find(t,function(t){return t.name()===e});return n?n.settings():null},setDatasourceSettings:function(e,t){var n=l.datasources(),i=_.find(n,function(t){return t.name()===e});if(!i)return console.log("Datasource not found"),void 0;var a=_.defaults(t,i.settings());i.settings(a)},getStyleString:function(e){var t="";return _.each(g[e],function(e,n){t=t+n+":"+e+";"}),t},getStyleObject:function(e){return g[e]},showDeveloperConsole:function(){h.showDeveloperConsole()},_removeAllWidgets:function(){a.remove_all_widgets()},_disableGrid:function(){a.disable()},_enableGrid:function(){a.enable()},_getPositionForScreenSize:function(e){return n(e)}}}();$.extend(freeboard,jQuery.eventEmitter); \ No newline at end of file diff --git a/lib/js/freeboard/ValueEditor.js b/lib/js/freeboard/ValueEditor.js index b1b5164..19dc95c 100644 --- a/lib/js/freeboard/ValueEditor.js +++ b/lib/js/freeboard/ValueEditor.js @@ -1,6 +1,6 @@ ValueEditor = function(theFreeboardModel) { - var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\].)?$"); + var _veDatasourceRegex = new RegExp(".*datasources\\[\"([^\"]*)(\"\\]\\[\")?(.*)$"); var _autocompleteOptions = []; var _autocompleteReplacementString; @@ -27,7 +27,7 @@ ValueEditor = function(theFreeboardModel) { _.each(datasources, function(datasource) { - options.push({value: datasource.name(), follow_char: "\"]."}); + options.push({value: datasource.name(), follow_char: "\"][\""}); }); } else if(match[1] != "" && _.isUndefined(match[2])) // List partial datasources @@ -40,7 +40,7 @@ ValueEditor = function(theFreeboardModel) if(dsName != replacementString && dsName.indexOf(replacementString) == 0) { - options.push({value: dsName, follow_char: "\"]."}); + options.push({value: dsName, follow_char: "\"][\""}); } }); } @@ -57,27 +57,28 @@ ValueEditor = function(theFreeboardModel) if(!_.isUndefined(match[2])) { - dataPath = match[2]; + dataPath = match[2] + match[3]; } - var dataPathItems = dataPath.split("."); + var dataPathItems = dataPath.split("\"][\""); dataPath = "data"; for(var index = 1; index < dataPathItems.length - 1; index++) { if(dataPathItems[index] != "") { - dataPath = dataPath + "." + dataPathItems[index]; + dataPathItem = "[\"" + dataPathItems[index] + "\"]"; + dataPath = dataPath + dataPathItem; } } var lastPathObject = _.last(dataPathItems); - // If the last character is a [, then ignore it - if(lastPathObject.charAt(lastPathObject.length - 1) == "[") + // If the last character is a ", then ignore it + if(lastPathObject.charAt(lastPathObject.length - 1) == "\"") { - lastPathObject = lastPathObject.replace(/\[+$/, ""); - dataPath = dataPath + "." + lastPathObject; + lastPathObject = lastPathObject.replace(/\[\"?$/, ""); + dataPath = dataPath + "[\"" + lastPathObject + "\"]"; } var dataValue = datasource.getDataRepresentation(dataPath); @@ -86,15 +87,15 @@ ValueEditor = function(theFreeboardModel) { for(var index = 0; index < dataValue.length; index++) { - var followChar = "]"; + var followChar = "\"]"; if(_.isObject(dataValue[index])) { - followChar = followChar + "."; + followChar = followChar + "\"][\""; } else if(_.isArray(dataValue[index])) { - followChar = followChar + "["; + followChar = followChar + "\"]["; } options.push({value: index, follow_char: followChar}); @@ -110,15 +111,15 @@ ValueEditor = function(theFreeboardModel) { if(name != lastPathObject && name.indexOf(lastPathObject) == 0) { - var followChar = undefined; + var followChar = "\"]"; if(_.isArray(value)) { - followChar = "["; + followChar = "\"]["; } else if(_.isObject(value)) { - followChar = "."; + followChar = "\"][\""; } options.push({value: name, follow_char: followChar});