Comments (33)
here was my naive unskilled attempt timelyportfolio@8ee84fd. I will be happy to submit a pull, but fear my incompetence will cause widespread damage :)
from htmlwidgets.
Consider these lines from a very basic widget. spin.js
does not allow configuration ex-post like knob
anywhere I can see, so I am forced to remove the nodes and rerender with each change. If I could access the already rendered spinner, then I could just change config.
from htmlwidgets.
You can return an arbitrary value from initialize which will then be passed
to you as the last parameter of both resize and renderValue. This is
basically a mechanism for per-widget instance data that you can access from
rendering. See my jjallaire/networkD3 package for an example (there I
return the D3 force layout as the instance data)
Does that help?
On Friday, August 8, 2014, timelyportfolio [email protected] wrote:
Consider these lines
https://github.com/timelyportfolio/htmlwidgets_spin/blob/master/inst/htmlwidgets/spin.js#L4-L13
from a very basic widget. spin.js does not allow configuration ex-post
like knob anywhere I can see, so I am forced to remove the nodes and
rerender with each change. If I could access the already rendered spinner,
then I could just change config.—
Reply to this email directly or view it on GitHub
#19 (comment).
from htmlwidgets.
Not sure it helps in this case, but very good to know. Going to bang my head on keyboard, and I will report back.
from htmlwidgets.
@jjallaire I think @timelyportfolio is looking for a mechanism that will allow him to manipulate the widget directly using javascript, outside of renderValue
. I have some use cases for this too. For example, the datamaps
js library allows users to define their own plugins. But for the plugin to be activated, it needs to be added to a map instance that was created. Now without access to the map
object returned by renderValue
, I will not be able to do this.
Note that this feature is more for intermediate-to-advanced users who are going to write javascript to customize widget outputs further.
from htmlwidgets.
Yes, in a static context so outside of a shiny context, a way to access whatever we created. I will try to assemble a list of potential uses, but this spin.js
to stop()
is one and in terms of a port of rCharts dimple we will need this for users to configure after creation/render. As far as I now there is no way using spin.js
or dimple
to get these created objects.
from htmlwidgets.
Is there an issue, design flaw, or problem adding this to HTMLWidgets.widgets[...] especially in the static context as I have done in the example?
from htmlwidgets.
I would just attach the object to the element itself using an expando property:
renderValue: function(el, data ) {
var spin = new Spinner(data);
// do stuff with spin
el.spinner = spin; // Attach spinner to element for future use
}
Then later:
var spin = document.getElementById("whatever").spinner;
from htmlwidgets.
That is neat @jcheng5. But since widget id's are randomly generated, how would one know what element to access?
from htmlwidgets.
also, might be a good idea to use consistent property name such as returnWidget
from htmlwidgets.
You can get the widget element however you want--by CSS class, dynamically in an event handler, whatever. It really depends on what the scenario is. For example, if you want to stop the spinner on click:
$(document).on("click", ".spinner", function(e) {
var spin = e.target.spinner;
spin.stop();
});
from htmlwidgets.
but say we have three ajax calls each represented by a spinner, how would we know which pairs with which? I guess we could just pass an identifier in config
or data
.
from htmlwidgets.
Maybe I'm not understanding something. How would having access to the return value of renderValue help you with that problem either?
from htmlwidgets.
if in markdown I create a widget and then subsequently create another widget that I would like to bind to the other widget, how might I accomplish that? It seems I need a known identifier and the return value.
from htmlwidgets.
I'm still not exactly sure we're on the same page, but: If you had two spinners:
var spinners = $(".spinner");
var spinner1 = spinners[0].returnValue; // or .spinner or whatever
var spinner2 = spinners[1].returnValue;
I have to run to a lunch meeting but will be happy to continue this discussion later. Although at this point I wonder if a vchat on Monday might be more productive?
from htmlwidgets.
@jcheng5 I think a vchat would be good.
from htmlwidgets.
My Monday is pretty open, anytime during business hours in the Pacific time zone.
from htmlwidgets.
OK I think I understand what you guys are talking about now--not the widget author, but the user of the widget library wanting to customize the widget further? In that case, I think we certainly need to allow the user to provide the widget's ID, right? (with the default being a randomly generated one, of course)
from htmlwidgets.
@jcheng5 Exactly. Either to do some post rendering manipulation, or say to trigger a link between two widgets.
from htmlwidgets.
For reference, id
is currently set here in htmlwidgets
.
I consider charts a very limited subset of htmlwidgets
, but as an example with rCharts
, I was able to accomplish in one of 2 ways:
1 - Set an id as a parameter in the rCharts configuration; see lines where dom
was set in a similar random strategy in initialize
2 - Use afterScript
with mustache/whisker to do {{chartId}}
. However this does not work as well with multiple widgets, but allows the user a last chance to manipulate, configure, set event handling, etc.
Then to possibly make this idea more tangible, I would love to remake this tags
-built website ( code and site ) with all htmlwidgets.
from htmlwidgets.
A simple test would be
#now do an example with a knob talking to a spin
library(htmltools)
library(htmlwidgets)
#devtools::install_github("timelyportfolio/htmlwidgets_spin")
library(spin)
library(knob)
h <- tags$html(
tags$div(id = "spin1", style = "width:25%;height:150px;display:inline-block"
,tags$h3("Spin To Adjust")
,spin(position = "relative", width = "100px", height = "100px")
)
,tags$div(id = "spin2", style = "width:25%;height:150px;display:inline-block"
,tags$h3("Spin Not To Adjust")
,spin(position = "relative", width = "100px", height = "100px")
)
,tags$div(
tags$h3("Adjust # of Lines")
,knob('Knob Talks to Spin', 14, 0, 20, angleArc = 250, angleOffset = -125,
fgColor = "#66CC66",
)
)
,tags$script(
"
//override knob render value
//since no way currently to do #! js code !# or use JSONfn
HTMLWidgets.widgets[1].renderValue = function(el,data){
/*var knobData = $('script[data-for = ' + $('.knob')[0].id + ']')
var dataObj = JSON.parse(knobData.text());
*/
data.change = function (v) {
$('.spin')[0].spin.opts.lines = v;
HTMLWidgets.widgets[0].renderValue(
$('.spin')[0], $('.spin')[0].spin.opts
)
}
//knobData.text(JSON.stringify(data));
$('.knob').trigger('configure',data);
$('.knob').val(data.value).trigger('change');
};
"
)
)
html_print(h)
from htmlwidgets.
changed the code above to actually accomplish the objective but this has the unfortunate effect of overriding renderValue
on all the knobs
from htmlwidgets.
After inspecting the code more closely, it appears we can addEventListener("DOMContentLoaded', function(){ do something after widget render})
as in
#now do an example with a knob talking to a spin
library(htmltools)
library(htmlwidgets)
library(spin)
library(knob)
h <- tags$html(
tags$div(id = "spin1", style = "width:25%;height:150px;display:inline-block"
,tags$h3("Spin To Adjust")
,spin(position = "relative", width = "100px", height = "100px")
)
,tags$div(id = "spin2", style = "width:25%;height:150px;display:inline-block"
,tags$h3("Spin Not To Adjust")
,spin(position = "relative", width = "100px", height = "100px")
)
,tags$div(
tags$h3("Adjust # of Lines")
,knob('Knob Talks to Spin', 14, 0, 20, angleArc = 250, angleOffset = -125,
fgColor = "#66CC66",
)
)
,tags$div(
tags$h3("Do Nothing")
,knob('Knob Talks to Spin', 14, 0, 20, angleArc = 250, angleOffset = -125,
fgColor = "#66CC66",
)
)
,tags$script(
"
document.addEventListener('DOMContentLoaded',function (){
$('.knob:first').trigger('configure', {
'change': function (v) {
$('.spin')[0].spin.opts.lines = v;
HTMLWidgets.widgets[0].renderValue(
$('.spin')[0], $('.spin')[0].spin.opts
)
}
});
}
)
"
)
)
html_print(h)
from htmlwidgets.
@timelyportfolio That snippet works, but, ugh... it's so fragile. To support this properly it seems like we would want to:
- Allow the user to (optionally) specify the widget ID
- Provide an easy way for code to run after all the widgets have been loaded
- Make it easy to pass new values to be rendered from JS to individual widgets (like
HTMLWidgets.renderValue(el, data)
and have htmlwidgets figure out the right binding to use); we can do this by attaching the binding to the element at the time it is bound
Does that sound right to everyone?
from htmlwidgets.
I think the elementId
argument and the ability to store instance values on the DOM element should close this issue. I will wait till @timelyportfolio can test this with the examples he has been playing with.
from htmlwidgets.
Not optimal, but I think it works for now. Unfortunately, I don't have any better ideas. I think this insight will come as I do this over and over with different widgets. I am satisfied for now that we can do some amazing things.
from htmlwidgets.
@jcheng5 Wouldn't it be nice to have a function like knobInput
for shiny which can be used as an input controller for a shiny app like for instance the ipod wheel: http://anthonyterrien.com/knob/? Do you think this is even feasible?
This is probably not the right place for these kind of suggestions/questions. Let me know where I can do this in the future please.
from htmlwidgets.
@JT85 input widgets are something that we will be thinking about in the future. Currently, the focus is on output html widgets.
from htmlwidgets.
@JT85 It's quite straightforward to do this today without help from htmlwidgets--see this article.
For htmlwidgets, input widgets are less of a win than output widgets, because the main advantage htmlwidgets gives you is to author a widget once and use it in static HTML pages, static R Markdown documents, RStudio Viewer, and Shiny. For input widgets, it doesn't make much sense to have an input widget in any of those contexts but Shiny (unless the widget user is going to write some javascript, in which case, it's not that clear why you'd need an R wrapper in the first place).
I'm not saying htmlwidgets wouldn't be helpful at all for input widgets--just that it'd be far, far less helpful than it is for output widgets.
from htmlwidgets.
I think we can close this, right? Because we have onRender
and onStaticRenderComplete
?
from htmlwidgets.
Would agree can close this. Was a fun discussion.
from htmlwidgets.
didn't mean to close, I'll let y'all decide. Pushed the wrong button.
from htmlwidgets.
going to close since no other comments or objections
from htmlwidgets.
Related Issues (20)
- Pandoc 2.19 has deprecated --self-contained HOT 1
- Move rmarkdown back to Suggests
- Binding resize method is never called. HOT 3
- Change between versions 1.5.4 and 1.6.0: Plotly output in nested tables is not showing HOT 1
- Use system2 to avoid shell injection HOT 5
- What's the License? HOT 1
- S3 generic/method consistency
- Accessibility support HOT 5
- `shouldEval()` probably shouldn't recurse over list-like structures that aren't actually lists
- JSON conversion is not consistent
- 1.6.2 from tags lies about its version HOT 3
- Release htmlwidgets 1.6.3
- Call "JS function" Incompatibility with other package (reactable) HOT 6
- Release htmlwidgets 1.6.4
- htmlwidgets 1.6.3 breaks sortable v0.5.0 bucket and rank lists HOT 2
- How to pass information into the ellipsis argument of the widget's custom HTML function?
- R not installing package HOT 1
- Add support for Observable Plot? HOT 5
- No Shiny reactivity HOT 1
- Sum of value showing NaN in summarywidget HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from htmlwidgets.