diff --git a/inst/htmlwidgets/plotly.js b/inst/htmlwidgets/plotly.js index d637157815..6dc46fbb40 100644 --- a/inst/htmlwidgets/plotly.js +++ b/inst/htmlwidgets/plotly.js @@ -1,2 +1,2 @@ -!function i(r,o,n){function a(e,t){if(!o[e]){if(!r[e]){var l="function"==typeof require&&require;if(!t&&l)return l(e,!0);if(s)return s(e,!0);throw(l=new Error("Cannot find module '"+e+"'")).code="MODULE_NOT_FOUND",l}l=o[e]={exports:{}},r[e][0].call(l.exports,function(t){return a(r[e][1][t]||t)},l,l.exports,i,r,o,n)}return o[e].exports}for(var s="function"==typeof require&&require,t=0;t"),d.legendgroup=d.legendgroup||p.join("
"),d._originalIndex=l,d._newIndex=this.gd._fullData.length+g.length,d._isCrosstalkTrace=!0,g.push(d))}if(0"),g.legendgroup=g.legendgroup||p.join("
"),g._originalIndex=l,g._newIndex=this.gd._fullData.length+d.length,g._isCrosstalkTrace=!0,d.push(g))}if(0 0) {\n var ev = JSON.stringify(event);\n for (var i = 0; i < selectionHistory.length; i++) {\n var sel = JSON.stringify(selectionHistory[i]);\n if (sel == ev) {\n return;\n }\n }\n }\n \n // accumulate history for persistent selection\n if (!x.highlight.persistent) {\n selectionHistory = [event];\n } else {\n selectionHistory.push(event);\n }\n crosstalk.var(\"plotlySelectionHistory\").set(selectionHistory);\n \n // do the actual updating of traces, frames, and the selectize widget\n traceManager.updateSelection(set, e.value);\n // https://github.com/selectize/selectize.js/blob/master/docs/api.md#methods_items\n if (x.selectize) {\n if (!x.highlight.persistent || e.value === null) {\n selectize.clear(true);\n }\n selectize.addItems(e.value, true);\n selectize.close();\n }\n }\n selection.on(\"change\", selectionChange);\n \n // Set a crosstalk variable selection value, triggering an update\n var turnOn = function(e) {\n if (e) {\n var selectedKeys = pointsToKeys(e.points);\n // Keys are group names, values are array of selected keys from group.\n for (var set in selectedKeys) {\n if (selectedKeys.hasOwnProperty(set)) {\n selection.set(selectedKeys[set].value, {sender: el});\n }\n }\n }\n };\n if (x.highlight.debounce > 0) {\n turnOn = debounce(turnOn, x.highlight.debounce);\n }\n graphDiv.on(x.highlight.on, turnOn);\n \n graphDiv.on(x.highlight.off, function turnOff(e) {\n // remove any visual clues\n removeBrush(el);\n // remove any selection history\n crosstalk.var(\"plotlySelectionHistory\").set(null);\n // trigger the actual removal of selection traces\n selection.set(null, {sender: el});\n });\n \n // register a callback for selectize so that there is bi-directional\n // communication between the widget and direct manipulation events\n if (x.selectize) {\n var selectizeID = Object.keys(x.selectize)[i];\n var items = x.selectize[selectizeID].items;\n var first = [{value: \"\", label: \"(All)\"}];\n var opts = {\n options: first.concat(items),\n searchField: \"label\",\n valueField: \"value\",\n labelField: \"label\",\n maxItems: 50\n };\n var select = $(\"#\" + selectizeID).find(\"select\")[0];\n var selectize = $(select).selectize(opts)[0].selectize;\n // NOTE: this callback is triggered when *directly* altering \n // dropdown items\n selectize.on(\"change\", function() {\n var currentItems = traceManager.groupSelections[set] || [];\n if (!x.highlight.persistent) {\n removeBrush(el);\n for (var i = 0; i < currentItems.length; i++) {\n selectize.removeItem(currentItems[i], true);\n }\n }\n var newItems = selectize.items.filter(function(idx) { \n return currentItems.indexOf(idx) < 0;\n });\n if (newItems.length > 0) {\n traceManager.updateSelection(set, newItems);\n } else {\n // Item has been removed...\n // TODO: this logic won't work for dynamically changing palette \n traceManager.updateSelection(set, null);\n traceManager.updateSelection(set, selectize.items);\n }\n });\n }\n } // end of selectionChange\n } // end of renderValue\n}\n\n/**\n * @param graphDiv The Plotly graph div\n * @param highlight An object with options for updating selection(s)\n */\nfunction TraceManager(graphDiv, highlight) {\n // The Plotly graph div\n this.gd = graphDiv;\n\n // Preserve the original data.\n // TODO: try using Lib.extendFlat() as done in \n // https://github.com/plotly/plotly.js/pull/1136 \n this.origData = JSON.parse(JSON.stringify(graphDiv.data));\n \n // avoid doing this over and over\n this.origOpacity = [];\n for (var i = 0; i < this.origData.length; i++) {\n this.origOpacity[i] = this.origData[i].opacity === 0 ? 0 : (this.origData[i].opacity || 1);\n }\n\n // key: group name, value: null or array of keys representing the\n // most recently received selection for that group.\n this.groupSelections = {};\n \n // selection parameters (e.g., transient versus persistent selection)\n this.highlight = highlight;\n}\n\nTraceManager.prototype.close = function() {\n // TODO: Unhook all event handlers\n};\n\nTraceManager.prototype.updateFilter = function(group, keys) {\n\n if (typeof(keys) === \"undefined\" || keys === null) {\n \n this.gd.data = JSON.parse(JSON.stringify(this.origData));\n \n } else {\n \n var traces = [];\n for (var i = 0; i < this.origData.length; i++) {\n var trace = this.origData[i];\n if (!trace.key || trace.set !== group) {\n continue;\n }\n var matchFunc = getMatchFunc(trace);\n var matches = matchFunc(trace.key, keys);\n \n if (matches.length > 0) {\n if (!trace._isSimpleKey) {\n // subsetArrayAttrs doesn't mutate trace (it makes a modified clone)\n trace = subsetArrayAttrs(trace, matches);\n }\n traces.push(trace);\n }\n }\n }\n \n this.gd.data = traces;\n Plotly.redraw(this.gd);\n \n // NOTE: we purposely do _not_ restore selection(s), since on filter,\n // axis likely will update, changing the pixel -> data mapping, leading \n // to a likely mismatch in the brush outline and highlighted marks\n \n};\n\nTraceManager.prototype.updateSelection = function(group, keys) {\n \n if (keys !== null && !Array.isArray(keys)) {\n throw new Error(\"Invalid keys argument; null or array expected\");\n }\n \n // if selection has been cleared, or if this is transient\n // selection, delete the \"selection traces\"\n var nNewTraces = this.gd.data.length - this.origData.length;\n if (keys === null || !this.highlight.persistent && nNewTraces > 0) {\n var tracesToRemove = [];\n for (var i = 0; i < this.gd.data.length; i++) {\n if (this.gd.data[i]._isCrosstalkTrace) tracesToRemove.push(i);\n }\n Plotly.deleteTraces(this.gd, tracesToRemove);\n this.groupSelections[group] = keys;\n } else {\n // add to the groupSelection, rather than overwriting it\n // TODO: can this be removed?\n this.groupSelections[group] = this.groupSelections[group] || [];\n for (var i = 0; i < keys.length; i++) {\n var k = keys[i];\n if (this.groupSelections[group].indexOf(k) < 0) {\n this.groupSelections[group].push(k);\n }\n }\n }\n \n if (keys === null) {\n \n Plotly.restyle(this.gd, {\"opacity\": this.origOpacity});\n \n } else if (keys.length >= 1) {\n \n // placeholder for new \"selection traces\"\n var traces = [];\n // this variable is set in R/highlight.R\n var selectionColour = crosstalk.group(group).var(\"plotlySelectionColour\").get() || \n this.highlight.color[0];\n\n for (var i = 0; i < this.origData.length; i++) {\n // TODO: try using Lib.extendFlat() as done in \n // https://github.com/plotly/plotly.js/pull/1136 \n var trace = JSON.parse(JSON.stringify(this.gd.data[i]));\n if (!trace.key || trace.set !== group) {\n continue;\n }\n // Get sorted array of matching indices in trace.key\n var matchFunc = getMatchFunc(trace);\n var matches = matchFunc(trace.key, keys);\n \n if (matches.length > 0) {\n // If this is a \"simple\" key, that means select the entire trace\n if (!trace._isSimpleKey) {\n trace = subsetArrayAttrs(trace, matches);\n }\n // reach into the full trace object so we can properly reflect the \n // selection attributes in every view\n var d = this.gd._fullData[i];\n \n /* \n / Recursively inherit selection attributes from various sources, \n / in order of preference:\n / (1) official plotly.js selected attribute\n / (2) highlight(selected = attrs_selected(...))\n */\n // TODO: it would be neat to have a dropdown to dynamically specify these!\n $.extend(true, trace, this.highlight.selected);\n \n // if it is defined, override color with the \"dynamic brush color\"\"\n if (d.marker) {\n trace.marker = trace.marker || {};\n trace.marker.color = selectionColour || trace.marker.color || d.marker.color;\n }\n if (d.line) {\n trace.line = trace.line || {};\n trace.line.color = selectionColour || trace.line.color || d.line.color;\n }\n if (d.textfont) {\n trace.textfont = trace.textfont || {};\n trace.textfont.color = selectionColour || trace.textfont.color || d.textfont.color;\n }\n if (d.fillcolor) {\n // TODO: should selectionColour inherit alpha from the existing fillcolor?\n trace.fillcolor = selectionColour || trace.fillcolor || d.fillcolor;\n }\n // attach a sensible name/legendgroup\n trace.name = trace.name || keys.join(\"
\");\n trace.legendgroup = trace.legendgroup || keys.join(\"
\");\n \n // keep track of mapping between this new trace and the trace it targets\n // (necessary for updating frames to reflect the selection traces)\n trace._originalIndex = i;\n trace._newIndex = this.gd._fullData.length + traces.length;\n trace._isCrosstalkTrace = true;\n traces.push(trace);\n }\n }\n \n if (traces.length > 0) {\n \n Plotly.addTraces(this.gd, traces).then(function(gd) {\n // incrementally add selection traces to frames\n // (this is heavily inspired by Plotly.Plots.modifyFrames() \n // in src/plots/plots.js)\n var _hash = gd._transitionData._frameHash;\n var _frames = gd._transitionData._frames || [];\n \n for (var i = 0; i < _frames.length; i++) {\n \n // add to _frames[i].traces *if* this frame references selected trace(s)\n var newIndices = [];\n for (var j = 0; j < traces.length; j++) {\n var tr = traces[j];\n if (_frames[i].traces.indexOf(tr._originalIndex) > -1) {\n newIndices.push(tr._newIndex);\n _frames[i].traces.push(tr._newIndex);\n }\n }\n \n // nothing to do...\n if (newIndices.length === 0) {\n continue;\n }\n \n var ctr = 0;\n var nFrameTraces = _frames[i].data.length;\n \n for (var j = 0; j < nFrameTraces; j++) {\n var frameTrace = _frames[i].data[j];\n if (!frameTrace.key || frameTrace.set !== group) {\n continue;\n }\n \n var matchFunc = getMatchFunc(frameTrace);\n var matches = matchFunc(frameTrace.key, keys);\n \n if (matches.length > 0) {\n if (!trace._isSimpleKey) {\n frameTrace = subsetArrayAttrs(frameTrace, matches);\n }\n var d = gd._fullData[newIndices[ctr]];\n if (d.marker) {\n frameTrace.marker = d.marker;\n }\n if (d.line) {\n frameTrace.line = d.line;\n }\n if (d.textfont) {\n frameTrace.textfont = d.textfont;\n }\n ctr = ctr + 1;\n _frames[i].data.push(frameTrace);\n }\n }\n \n // update gd._transitionData._frameHash\n _hash[_frames[i].name] = _frames[i];\n }\n \n });\n \n // dim traces that have a set matching the set of selection sets\n var tracesToDim = [],\n opacities = [],\n sets = Object.keys(this.groupSelections),\n n = this.origData.length;\n \n for (var i = 0; i < n; i++) {\n var opacity = this.origOpacity[i] || 1;\n // have we already dimmed this trace? Or is this even worth doing?\n if (opacity !== this.gd._fullData[i].opacity || this.highlight.opacityDim === 1) {\n continue;\n }\n // is this set an element of the set of selection sets?\n var matches = findMatches(sets, [this.gd.data[i].set]);\n if (matches.length) {\n tracesToDim.push(i);\n opacities.push(opacity * this.highlight.opacityDim);\n }\n }\n \n if (tracesToDim.length > 0) {\n Plotly.restyle(this.gd, {\"opacity\": opacities}, tracesToDim);\n // turn off the selected/unselected API\n Plotly.restyle(this.gd, {\"selectedpoints\": null});\n }\n \n }\n \n }\n};\n\n/* \nNote: in all of these match functions, we assume needleSet (i.e. the selected keys)\nis a 1D (or flat) array. The real difference is the meaning of haystack.\nfindMatches() does the usual thing you'd expect for \nlinked brushing on a scatterplot matrix. findSimpleMatches() returns a match iff \nhaystack is a subset of the needleSet. findNestedMatches() returns \n*/\n\nfunction getMatchFunc(trace) {\n return (trace._isNestedKey) ? findNestedMatches : \n (trace._isSimpleKey) ? findSimpleMatches : findMatches;\n}\n\n// find matches for \"flat\" keys\nfunction findMatches(haystack, needleSet) {\n var matches = [];\n haystack.forEach(function(obj, i) {\n if (obj === null || needleSet.indexOf(obj) >= 0) {\n matches.push(i);\n }\n });\n return matches;\n}\n\n// find matches for \"simple\" keys\nfunction findSimpleMatches(haystack, needleSet) {\n var match = haystack.every(function(val) {\n return val === null || needleSet.indexOf(val) >= 0;\n });\n // yes, this doesn't make much sense other than conforming \n // to the output type of the other match functions\n return (match) ? [0] : []\n}\n\n// find matches for a \"nested\" haystack (2D arrays)\nfunction findNestedMatches(haystack, needleSet) {\n var matches = [];\n for (var i = 0; i < haystack.length; i++) {\n var hay = haystack[i];\n var match = hay.every(function(val) { \n return val === null || needleSet.indexOf(val) >= 0; \n });\n if (match) {\n matches.push(i);\n }\n }\n return matches;\n}\n\nfunction isPlainObject(obj) {\n return (\n Object.prototype.toString.call(obj) === '[object Object]' &&\n Object.getPrototypeOf(obj) === Object.prototype\n );\n}\n\nfunction subsetArrayAttrs(obj, indices) {\n var newObj = {};\n Object.keys(obj).forEach(function(k) {\n var val = obj[k];\n\n if (k.charAt(0) === \"_\") {\n newObj[k] = val;\n } else if (k === \"transforms\" && Array.isArray(val)) {\n newObj[k] = val.map(function(transform) {\n return subsetArrayAttrs(transform, indices);\n });\n } else if (k === \"colorscale\" && Array.isArray(val)) {\n newObj[k] = val;\n } else if (isPlainObject(val)) {\n newObj[k] = subsetArrayAttrs(val, indices);\n } else if (Array.isArray(val)) {\n newObj[k] = subsetArray(val, indices);\n } else {\n newObj[k] = val;\n }\n });\n return newObj;\n}\n\nfunction subsetArray(arr, indices) {\n var result = [];\n for (var i = 0; i < indices.length; i++) {\n result.push(arr[indices[i]]);\n }\n return result;\n}\n\n// Convenience function for removing plotly's brush \nfunction removeBrush(el) {\n var outlines = el.querySelectorAll(\".select-outline\");\n for (var i = 0; i < outlines.length; i++) {\n outlines[i].remove();\n }\n}\n\n\n// https://davidwalsh.name/javascript-debounce-function\n\n// Returns a function, that, as long as it continues to be invoked, will not\n// be triggered. The function will be called after it stops being called for\n// N milliseconds. If `immediate` is passed, trigger the function on the\n// leading edge, instead of the trailing.\nfunction debounce(func, wait, immediate) {\n\tvar timeout;\n\treturn function() {\n\t\tvar context = this, args = arguments;\n\t\tvar later = function() {\n\t\t\ttimeout = null;\n\t\t\tif (!immediate) func.apply(context, args);\n\t\t};\n\t\tvar callNow = immediate && !timeout;\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\t\tif (callNow) func.apply(context, args);\n\t};\n};\n\nmodule.exports = widgetDefinition"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","theSrc/scripts/plotly.js","theSrc/scripts/widgetdefinition.js"],"names":["r","e","n","t","o","i","f","c","require","u","a","Error","code","p","exports","call","length","1","module","_widgetdefinition","HTMLWidgets","widget","_widgetdefinition2","default","widgetDefinition","name","type","initialize","el","width","height","resize","instance","autosize","Plotly","relayout","renderValue","x","lay","layout","crosstalk","var","set","highlight","window","PLOTLYENV","BASE_URL","base_url","persistent","onmousemove","event","shiftKey","persistentShift","graphDiv","document","getElementById","id","setAttribute","addPostRenderHandler","modebars","querySelectorAll","style","zIndex","selectize","dynamic","plotly","pickerDiv","flex","createElement","class","pickerInput","placeholder","pickerLabel","for","innerHTML","appendChild","ids","Object","keys","container","label","group","selectDiv","select","multiple","parentElement","insertBefore","picker","$","colors","color","opts","value","showColour","palette","allowedCols","join","colourpicker","changeDelay","grps","ctGroups","on","eventDataWithKey","eventData","undefined","hasOwnProperty","points","map","pt","obj","curveNumber","pointNumber","y","z","customdata","attrsToAttach","trace","data","_isSimpleKey","key","attr","Array","isArray","pointNumbers","idx","purge","plot","then","shinyMode","Shiny","addCustomMessageHandler","msg","gd","method","args","concat","apply","react","mapboxIDs","_fullLayout","_subplots","mapbox","_fitBounds","_subplot","fitBounds","bounds","options","eventClearMap","eventDataFunctionMap","legendEventData","d","legendgroup","legendgrps","traces","push","setInputValue","plotly_deselect","plotly_unhover","plotly_doubleclick","evt","input","source","priority","plotly_click","plotly_sunburstclick","plotly_hover","plotly_selected","plotly_selecting","plotly_brushed","range","lassoPoints","plotly_brushing","plotly_legendclick","plotly_legenddoubleclick","plotly_clickannotation","fullAnnotation","shinyEvents","eventDataPreProcessor","JSON","stringify","traceManager","TraceManager","allSets","curveIdx","newSet","indexOf","selection","SelectionHandle","FilterHandle","removeBrush","updateFilter","prototype","diff","this","filter","oldValue","selectionHistory","get","receiverID","plotlySelectionColour","ev","updateSelection","clear","addItems","close","selectizeID","turnOn","selectedKeys","keysBySet","keyFlat","ptNum","_isNestedKey","pointsToKeys","sender","debounce","func","wait","immediate","timeout","context","arguments","callNow","clearTimeout","setTimeout","off","items","searchField","valueField","labelField","maxItems","find","currentItems","groupSelections","removeItem","newItems","origData","parse","origOpacity","opacity","getMatchFunc","findNestedMatches","findSimpleMatches","findMatches","haystack","needleSet","matches","forEach","every","val","subsetArrayAttrs","indices","newObj","k","charAt","transform","toString","getPrototypeOf","arr","result","subsetArray","outlines","remove","matchFunc","redraw","nNewTraces","tracesToRemove","_isCrosstalkTrace","deleteTraces","restyle","selectionColour","_fullData","extend","selected","marker","line","textfont","fillcolor","_originalIndex","_newIndex","addTraces","_hash","_transitionData","_frameHash","_frames","newIndices","j","tr","ctr","nFrameTraces","frameTrace","tracesToDim","opacities","sets","opacityDim","selectedpoints"],"mappings":"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","file":"plotly.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i 0) {\n var ev = JSON.stringify(event);\n for (var i = 0; i < selectionHistory.length; i++) {\n var sel = JSON.stringify(selectionHistory[i]);\n if (sel == ev) {\n return;\n }\n }\n }\n \n // accumulate history for persistent selection\n if (!x.highlight.persistent) {\n selectionHistory = [event];\n } else {\n selectionHistory.push(event);\n }\n crosstalk.var(\"plotlySelectionHistory\").set(selectionHistory);\n \n // do the actual updating of traces, frames, and the selectize widget\n traceManager.updateSelection(set, e.value);\n // https://github.com/selectize/selectize.js/blob/master/docs/api.md#methods_items\n if (x.selectize) {\n if (!x.highlight.persistent || e.value === null) {\n selectize.clear(true);\n }\n selectize.addItems(e.value, true);\n selectize.close();\n }\n }\n selection.on(\"change\", selectionChange);\n \n // Set a crosstalk variable selection value, triggering an update\n var turnOn = function(e) {\n if (e) {\n var selectedKeys = pointsToKeys(e.points);\n // Keys are group names, values are array of selected keys from group.\n for (var set in selectedKeys) {\n if (selectedKeys.hasOwnProperty(set)) {\n selection.set(selectedKeys[set].value, {sender: el});\n }\n }\n }\n };\n if (x.highlight.debounce > 0) {\n turnOn = debounce(turnOn, x.highlight.debounce);\n }\n graphDiv.on(x.highlight.on, turnOn);\n \n graphDiv.on(x.highlight.off, function turnOff(e) {\n // remove any visual clues\n removeBrush(el);\n // remove any selection history\n crosstalk.var(\"plotlySelectionHistory\").set(null);\n // trigger the actual removal of selection traces\n selection.set(null, {sender: el});\n });\n \n // register a callback for selectize so that there is bi-directional\n // communication between the widget and direct manipulation events\n if (x.selectize) {\n var selectizeID = Object.keys(x.selectize)[i];\n var items = x.selectize[selectizeID].items;\n var first = [{value: \"\", label: \"(All)\"}];\n var opts = {\n options: first.concat(items),\n searchField: \"label\",\n valueField: \"value\",\n labelField: \"label\",\n maxItems: 50\n };\n var select = $(\"#\" + selectizeID).find(\"select\")[0];\n var selectize = $(select).selectize(opts)[0].selectize;\n // NOTE: this callback is triggered when *directly* altering \n // dropdown items\n selectize.on(\"change\", function() {\n var currentItems = traceManager.groupSelections[set] || [];\n if (!x.highlight.persistent) {\n removeBrush(el);\n for (var i = 0; i < currentItems.length; i++) {\n selectize.removeItem(currentItems[i], true);\n }\n }\n var newItems = selectize.items.filter(function(idx) { \n return currentItems.indexOf(idx) < 0;\n });\n if (newItems.length > 0) {\n traceManager.updateSelection(set, newItems);\n } else {\n // Item has been removed...\n // TODO: this logic won't work for dynamically changing palette \n traceManager.updateSelection(set, null);\n traceManager.updateSelection(set, selectize.items);\n }\n });\n }\n } // end of selectionChange\n\n graphDiv.on(\"plotly_afterplot\", function() {\n // Used by Displayr to determine when widget is ready to be snapshot for testing\n graphDiv.setAttribute(\"rhtmlwidget-status\", \"ready\");\n });\n } // end of renderValue\n}\n\n/**\n * @param graphDiv The Plotly graph div\n * @param highlight An object with options for updating selection(s)\n */\nfunction TraceManager(graphDiv, highlight) {\n // The Plotly graph div\n this.gd = graphDiv;\n\n // Preserve the original data.\n // TODO: try using Lib.extendFlat() as done in \n // https://github.com/plotly/plotly.js/pull/1136 \n this.origData = JSON.parse(JSON.stringify(graphDiv.data));\n \n // avoid doing this over and over\n this.origOpacity = [];\n for (var i = 0; i < this.origData.length; i++) {\n this.origOpacity[i] = this.origData[i].opacity === 0 ? 0 : (this.origData[i].opacity || 1);\n }\n\n // key: group name, value: null or array of keys representing the\n // most recently received selection for that group.\n this.groupSelections = {};\n \n // selection parameters (e.g., transient versus persistent selection)\n this.highlight = highlight;\n}\n\nTraceManager.prototype.close = function() {\n // TODO: Unhook all event handlers\n};\n\nTraceManager.prototype.updateFilter = function(group, keys) {\n\n if (typeof(keys) === \"undefined\" || keys === null) {\n \n this.gd.data = JSON.parse(JSON.stringify(this.origData));\n \n } else {\n \n var traces = [];\n for (var i = 0; i < this.origData.length; i++) {\n var trace = this.origData[i];\n if (!trace.key || trace.set !== group) {\n continue;\n }\n var matchFunc = getMatchFunc(trace);\n var matches = matchFunc(trace.key, keys);\n \n if (matches.length > 0) {\n if (!trace._isSimpleKey) {\n // subsetArrayAttrs doesn't mutate trace (it makes a modified clone)\n trace = subsetArrayAttrs(trace, matches);\n }\n traces.push(trace);\n }\n }\n }\n \n this.gd.data = traces;\n Plotly.redraw(this.gd);\n \n // NOTE: we purposely do _not_ restore selection(s), since on filter,\n // axis likely will update, changing the pixel -> data mapping, leading \n // to a likely mismatch in the brush outline and highlighted marks\n \n};\n\nTraceManager.prototype.updateSelection = function(group, keys) {\n \n if (keys !== null && !Array.isArray(keys)) {\n throw new Error(\"Invalid keys argument; null or array expected\");\n }\n \n // if selection has been cleared, or if this is transient\n // selection, delete the \"selection traces\"\n var nNewTraces = this.gd.data.length - this.origData.length;\n if (keys === null || !this.highlight.persistent && nNewTraces > 0) {\n var tracesToRemove = [];\n for (var i = 0; i < this.gd.data.length; i++) {\n if (this.gd.data[i]._isCrosstalkTrace) tracesToRemove.push(i);\n }\n Plotly.deleteTraces(this.gd, tracesToRemove);\n this.groupSelections[group] = keys;\n } else {\n // add to the groupSelection, rather than overwriting it\n // TODO: can this be removed?\n this.groupSelections[group] = this.groupSelections[group] || [];\n for (var i = 0; i < keys.length; i++) {\n var k = keys[i];\n if (this.groupSelections[group].indexOf(k) < 0) {\n this.groupSelections[group].push(k);\n }\n }\n }\n \n if (keys === null) {\n \n Plotly.restyle(this.gd, {\"opacity\": this.origOpacity});\n \n } else if (keys.length >= 1) {\n \n // placeholder for new \"selection traces\"\n var traces = [];\n // this variable is set in R/highlight.R\n var selectionColour = crosstalk.group(group).var(\"plotlySelectionColour\").get() || \n this.highlight.color[0];\n\n for (var i = 0; i < this.origData.length; i++) {\n // TODO: try using Lib.extendFlat() as done in \n // https://github.com/plotly/plotly.js/pull/1136 \n var trace = JSON.parse(JSON.stringify(this.gd.data[i]));\n if (!trace.key || trace.set !== group) {\n continue;\n }\n // Get sorted array of matching indices in trace.key\n var matchFunc = getMatchFunc(trace);\n var matches = matchFunc(trace.key, keys);\n \n if (matches.length > 0) {\n // If this is a \"simple\" key, that means select the entire trace\n if (!trace._isSimpleKey) {\n trace = subsetArrayAttrs(trace, matches);\n }\n // reach into the full trace object so we can properly reflect the \n // selection attributes in every view\n var d = this.gd._fullData[i];\n \n /* \n / Recursively inherit selection attributes from various sources, \n / in order of preference:\n / (1) official plotly.js selected attribute\n / (2) highlight(selected = attrs_selected(...))\n */\n // TODO: it would be neat to have a dropdown to dynamically specify these!\n $.extend(true, trace, this.highlight.selected);\n \n // if it is defined, override color with the \"dynamic brush color\"\"\n if (d.marker) {\n trace.marker = trace.marker || {};\n trace.marker.color = selectionColour || trace.marker.color || d.marker.color;\n }\n if (d.line) {\n trace.line = trace.line || {};\n trace.line.color = selectionColour || trace.line.color || d.line.color;\n }\n if (d.textfont) {\n trace.textfont = trace.textfont || {};\n trace.textfont.color = selectionColour || trace.textfont.color || d.textfont.color;\n }\n if (d.fillcolor) {\n // TODO: should selectionColour inherit alpha from the existing fillcolor?\n trace.fillcolor = selectionColour || trace.fillcolor || d.fillcolor;\n }\n // attach a sensible name/legendgroup\n trace.name = trace.name || keys.join(\"
\");\n trace.legendgroup = trace.legendgroup || keys.join(\"
\");\n \n // keep track of mapping between this new trace and the trace it targets\n // (necessary for updating frames to reflect the selection traces)\n trace._originalIndex = i;\n trace._newIndex = this.gd._fullData.length + traces.length;\n trace._isCrosstalkTrace = true;\n traces.push(trace);\n }\n }\n \n if (traces.length > 0) {\n \n Plotly.addTraces(this.gd, traces).then(function(gd) {\n // incrementally add selection traces to frames\n // (this is heavily inspired by Plotly.Plots.modifyFrames() \n // in src/plots/plots.js)\n var _hash = gd._transitionData._frameHash;\n var _frames = gd._transitionData._frames || [];\n \n for (var i = 0; i < _frames.length; i++) {\n \n // add to _frames[i].traces *if* this frame references selected trace(s)\n var newIndices = [];\n for (var j = 0; j < traces.length; j++) {\n var tr = traces[j];\n if (_frames[i].traces.indexOf(tr._originalIndex) > -1) {\n newIndices.push(tr._newIndex);\n _frames[i].traces.push(tr._newIndex);\n }\n }\n \n // nothing to do...\n if (newIndices.length === 0) {\n continue;\n }\n \n var ctr = 0;\n var nFrameTraces = _frames[i].data.length;\n \n for (var j = 0; j < nFrameTraces; j++) {\n var frameTrace = _frames[i].data[j];\n if (!frameTrace.key || frameTrace.set !== group) {\n continue;\n }\n \n var matchFunc = getMatchFunc(frameTrace);\n var matches = matchFunc(frameTrace.key, keys);\n \n if (matches.length > 0) {\n if (!trace._isSimpleKey) {\n frameTrace = subsetArrayAttrs(frameTrace, matches);\n }\n var d = gd._fullData[newIndices[ctr]];\n if (d.marker) {\n frameTrace.marker = d.marker;\n }\n if (d.line) {\n frameTrace.line = d.line;\n }\n if (d.textfont) {\n frameTrace.textfont = d.textfont;\n }\n ctr = ctr + 1;\n _frames[i].data.push(frameTrace);\n }\n }\n \n // update gd._transitionData._frameHash\n _hash[_frames[i].name] = _frames[i];\n }\n \n });\n \n // dim traces that have a set matching the set of selection sets\n var tracesToDim = [],\n opacities = [],\n sets = Object.keys(this.groupSelections),\n n = this.origData.length;\n \n for (var i = 0; i < n; i++) {\n var opacity = this.origOpacity[i] || 1;\n // have we already dimmed this trace? Or is this even worth doing?\n if (opacity !== this.gd._fullData[i].opacity || this.highlight.opacityDim === 1) {\n continue;\n }\n // is this set an element of the set of selection sets?\n var matches = findMatches(sets, [this.gd.data[i].set]);\n if (matches.length) {\n tracesToDim.push(i);\n opacities.push(opacity * this.highlight.opacityDim);\n }\n }\n \n if (tracesToDim.length > 0) {\n Plotly.restyle(this.gd, {\"opacity\": opacities}, tracesToDim);\n // turn off the selected/unselected API\n Plotly.restyle(this.gd, {\"selectedpoints\": null});\n }\n \n }\n \n }\n};\n\n/* \nNote: in all of these match functions, we assume needleSet (i.e. the selected keys)\nis a 1D (or flat) array. The real difference is the meaning of haystack.\nfindMatches() does the usual thing you'd expect for \nlinked brushing on a scatterplot matrix. findSimpleMatches() returns a match iff \nhaystack is a subset of the needleSet. findNestedMatches() returns \n*/\n\nfunction getMatchFunc(trace) {\n return (trace._isNestedKey) ? findNestedMatches : \n (trace._isSimpleKey) ? findSimpleMatches : findMatches;\n}\n\n// find matches for \"flat\" keys\nfunction findMatches(haystack, needleSet) {\n var matches = [];\n haystack.forEach(function(obj, i) {\n if (obj === null || needleSet.indexOf(obj) >= 0) {\n matches.push(i);\n }\n });\n return matches;\n}\n\n// find matches for \"simple\" keys\nfunction findSimpleMatches(haystack, needleSet) {\n var match = haystack.every(function(val) {\n return val === null || needleSet.indexOf(val) >= 0;\n });\n // yes, this doesn't make much sense other than conforming \n // to the output type of the other match functions\n return (match) ? [0] : []\n}\n\n// find matches for a \"nested\" haystack (2D arrays)\nfunction findNestedMatches(haystack, needleSet) {\n var matches = [];\n for (var i = 0; i < haystack.length; i++) {\n var hay = haystack[i];\n var match = hay.every(function(val) { \n return val === null || needleSet.indexOf(val) >= 0; \n });\n if (match) {\n matches.push(i);\n }\n }\n return matches;\n}\n\nfunction isPlainObject(obj) {\n return (\n Object.prototype.toString.call(obj) === '[object Object]' &&\n Object.getPrototypeOf(obj) === Object.prototype\n );\n}\n\nfunction subsetArrayAttrs(obj, indices) {\n var newObj = {};\n Object.keys(obj).forEach(function(k) {\n var val = obj[k];\n\n if (k.charAt(0) === \"_\") {\n newObj[k] = val;\n } else if (k === \"transforms\" && Array.isArray(val)) {\n newObj[k] = val.map(function(transform) {\n return subsetArrayAttrs(transform, indices);\n });\n } else if (k === \"colorscale\" && Array.isArray(val)) {\n newObj[k] = val;\n } else if (isPlainObject(val)) {\n newObj[k] = subsetArrayAttrs(val, indices);\n } else if (Array.isArray(val)) {\n newObj[k] = subsetArray(val, indices);\n } else {\n newObj[k] = val;\n }\n });\n return newObj;\n}\n\nfunction subsetArray(arr, indices) {\n var result = [];\n for (var i = 0; i < indices.length; i++) {\n result.push(arr[indices[i]]);\n }\n return result;\n}\n\n// Convenience function for removing plotly's brush \nfunction removeBrush(el) {\n var outlines = el.querySelectorAll(\".select-outline\");\n for (var i = 0; i < outlines.length; i++) {\n outlines[i].remove();\n }\n}\n\n\n// https://davidwalsh.name/javascript-debounce-function\n\n// Returns a function, that, as long as it continues to be invoked, will not\n// be triggered. The function will be called after it stops being called for\n// N milliseconds. If `immediate` is passed, trigger the function on the\n// leading edge, instead of the trailing.\nfunction debounce(func, wait, immediate) {\n\tvar timeout;\n\treturn function() {\n\t\tvar context = this, args = arguments;\n\t\tvar later = function() {\n\t\t\ttimeout = null;\n\t\t\tif (!immediate) func.apply(context, args);\n\t\t};\n\t\tvar callNow = immediate && !timeout;\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\t\tif (callNow) func.apply(context, args);\n\t};\n};\n\nmodule.exports = widgetDefinition"]} \ No newline at end of file diff --git a/theSrc/scripts/widgetdefinition.js b/theSrc/scripts/widgetdefinition.js index 8f25d2fd78..87a2d88d7e 100644 --- a/theSrc/scripts/widgetdefinition.js +++ b/theSrc/scripts/widgetdefinition.js @@ -58,6 +58,9 @@ const widgetDefinition = { } var graphDiv = document.getElementById(el.id); + + // Used by Displayr to determine when widget is ready to be snapshot for testing + graphDiv.setAttribute("rhtmlwidget-status", "loading"); // TODO: move the control panel injection strategy inside here... HTMLWidgets.addPostRenderHandler(function() { @@ -551,6 +554,11 @@ const widgetDefinition = { }); } } // end of selectionChange + + graphDiv.on("plotly_afterplot", function() { + // Used by Displayr to determine when widget is ready to be snapshot for testing + graphDiv.setAttribute("rhtmlwidget-status", "ready"); + }); } // end of renderValue }