Can you use tooltips on other Dojo wijits such as ValidationTextBoxes? - tooltip

(Follows on from Can you define tooltips in Dojo wijit template?)
I'd like to be able to popup some help text if a user hovers or keeps the focus on a Dojo wijit for some time. I know that these wijits come with some prompt behaviours such as when they are empty or on validation errors, but I'd like to be able to prompt regardless of the content of the control. For example:
<input name="tooltipTesting"
data-dojo-attach-point="tooltipMe"
data-dojo-type="dijit.form.ValidationTextBox"
data-dojo-props="placeHolder:'Type Something',
required:true,
value: '${blah}'" />
<div data-dojo-type="dijit.Tooltip" data-dojo-props="connectId:'tooltipMe'">
Got to love hovering over links. Sometimes you a get a free tooltip.
</div>
Programmatic definition of the tooltips works for plain HTML elements like anchors, but nothing I do appears to associate a tooltip with other Dojo controls. Advice?

You can programatically connect the widget to the tooltip using
tooltip.addTarget(widget.domNode);

dijit.Tooltip connects to the DOM node(s), not to Dijit Widgets (i.e. javascript objects), but you can always use widget's reference to its root DOM node accessible via widget.domNode.
There is also a problem with your markup: dojo-dojo-attach-point does not assign an id to the widget (you reference from the Tooltip via connectedId). Define id property <input id="tooltipMe"> to do so, then the ValidationTextBox itself and also the root DOM node of the ValidationTextBox will have the same id. Note that you cannot use hardcoded IDs in the widget templates.

Related

How to add a toolTip to a valuePicker

I have an Ext Lib valuePicker on an XPage and then have added an Ext Lib toolTip to the Xpage and specified the id of the valuePicker in the for property of the toolTip (it shows up in the list of controls to aim the toolTip at, but when I hover over the valuePicker nothing happens. I have several toolTips on the page aiming at radio buttons and edit boxes and they all work correctly so my process is correct. I aim the toolTip that I want for the valuePicker to an edit control and I get the correct tip displaying.
The valuePicker "loses" it id during rendering (look at rendered page's source code) so it is not possible to address valuePicker's id in tooltip.
A workaround is to put a <span> with an id around the valuePicker and to address this id in tooltip.
<span
id="valuePickerTooltip">
<xe:valuePicker
id="valuePicker"
...>
<xe:this.dataProvider>
...
</xe:this.dataProvider>
</xe:valuePicker>
</span>
<xe:tooltip
id="tooltip1"
for="valuePickerTooltip"
label="this is the tooltip">
</xe:tooltip>
perhaps you can compute the "for" property for the xe:tooltip to use getClientId("valuePickerTooltip").
Without having this tested, I'm pretty sure the "valuePickerTooltip" id will be converted to a client ID at runtime, that means it gets a prefix. With getClientId() you can get the runtime ID for a control.

Hiding Shield ASP.NET MVC charts using JS function

I am using Shield ASP.NET MVC charts on a page. I need the charts to initially show data for my visitors, and I need to provide the user the possibility to hide the charts by clicking on the corresponding button(s). For this purpose I use the following function:
<script>
function HideChart() {
document.getElementById("DataSpot").innerHTML = "";
}
</script>
And I am placing the charts as follows:
<p id="DataSpot">
#(Html.ShieldChart()
.Name("chart")
.PrimaryHeader(header => header.Text("Profile Hits"))
.Export(false)
.AxisX(axisX => axisX
………..
)
</p>
<button onclick="HideChart()">Hide Chart</button>
The problem is, that when I click on the button, nothing happens.
#user2492467,
Do you need to hide the chart or do you need to wipe out its content? If just hiding the chart, the approach suggested by Chris would work just fine. However, if you need to irrevocably wipe out the chart from the page altogether, then clearing its content is not enough. Only removing the rendered chart markup would open the door for memory leaks, as references to the DOM nodes may remain in the chart javascript component.
A better approach would be to find the javascript component instance and call its .destroy() method. This will ensure the component is fully destroyed and no memory is leaked:
$("#DataSpot").swidget().destroy();
Note that you still need to give your chart a name using the MVC wrapper's .Name("DataSpot") method just like Ed suggests. This will give your chart's HTML element an ID that you can use with jQuery to find the chart instance.
The .swidget() method is a standard jQuery extension method added by the Shield UI javascript framework. It returns the javascript component instance associated with the element matched by the jQuery selector. This is how you find the chart instance.
How about:
<script>
function HideChart() {
document.getElementById('DataSpot').style.display='none';
}
</script>
You should also update your button:
<button type="button" onclick="HideChart()" value="Hide Chart" />
Actually there is something happening, obviously not the thing that you need. This is because you need to wipe out the rendered chart by referencing its container.
The element is fine and if you put some text in your function and execute it you will see that it will appear on the appropriate spot. However to hide the chart you need to use it’s name. In other words the following statement:
document.getElementById("DataSpot").innerHTML = "";
should be changed to
document.getElementById("chart").innerHTML = "";
or you may rename the chart to
.Name("DataSpot ")
and remove the P element in both cases since it makes no use.

MobiScroll Select Preset

The mobiscroll documentation states
This preset enhances a regular HTML select to select the values with a scroller. The original select is hidden, and a dummy input is visible instead. The value of the select is maintained by the preset.
The sample HTML code they provide uses inline styling to hide the original select element
<select name="City" id="select" style="display:none">
However, when I do this and setup the mobiscroll replacement to appear inline
$('#select').scroller({preset:'select',theme:'default',display:'inline',mode:'scroller',inputClass: 'i-
txt'});
I find that although the scroller appears I still end up with what looks like an input element above it. This does not happen in their demo code but there I note that what they do is something like this
<div id="select_cont" style="display: none;">
<select name="City" id="select">
but that simply hides everything including the mobiscroll replacement. Looking under the covers I found that calling
$('#select').scroller({preset:'select',theme:'default',display:'inline',mode:'scroller',inputClass: 'i-
txt'});
introduces a dummy input element into the DOM.
<input id='cities_dummy'...
I can get the dummy to hide itself by issuing a
$('#cities_dummy').css('display','none')
immediately after creating the scroller. However, I cannot understand why things are working differently in the demo code. I have noted that they are using jQuery Mobile v 1.1.1 whilst I am using the very latest version.
Perhaps this issue is related to versions? Or is there something else at play here? I'd much appreciate any help.
I figured it out. It is all down to the
inputClass:i-txt
bit in the scroller options settings. In the demo code they are probably playing with this class via script depending on the value of the display property in the options object. The point is this - in order to get the original select to disappear when the scroller display is set to "inline" you must define i-txt (or whatever input class you use) as
.i-txt{display:none}

Integrating Django-dynamic-formsets with JQuery Mobile's Radio Buttons

I am using Django and the django-dynamic-formset plugin to generate a JQuery Mobile (JQM) site. I have nested forms that allow the user to click a "Add" link to another line to the form. This works great without JQM, but when JQM is used to style the form widgets the radio button labels do not trigger the correct radio button.
I have put up a static example of the behaviour, based on the generated HTML. Click the "Add" link, then try choosing a severity for the added item. The "for" attributes of the labels appear to update correctly, so I do not know what I'm doing wrong.
The django-dynamic-formset guide provides me with a way to call a JavaScript function after the user clicks the "Add" button, but I do not know if there's a JQM method I should be calling that will fix the issue. When I use JQM's enhanceWithin function it triggers a page load, which submits my form to Django, which I don't want at that point because the form won't validate yet.
Edit: I uploaded a much better example to the same URL.
After enough caffeine and peanut M&M's I have figured it out.
Reason for Failure: The django-dynamic-formset (DDF) plugin duplicates the form you give it. But the form is cloned as-is, which already includes all the JQuery Mobile (JQM) processing. This causes JQM to ignore it and makes the radio buttons misbehave.
The Solution: The DDF plugin allows you to specify what form to clone by its formTemplate parameter. JQM allows you to disable automatic mobile-enhancement of certain elements. Create an un-enhanced version of your form, and pass that to DDF as your formTemplate.
More Details:
I put this coded into my HTML head, before the reference to JQM:
<script>
$(document).bind('mobileinit',function(){
$.mobile.ignoreContentEnabled = true; // required for using the natural forms
});
</script>
And included this style to hide my "natural" form:
<style>
.natural-form { visibility: hidden; display: none; }
</style>
In the Django code I added a <div class='natural-form> and put a dummy version of my form in it (being sure to surround it another <div> with a unique ID for reference later). In my initialization of DDF I give it the unique ID as the parameter to formTemplate.
I was told on another forum I would have to hack DDF and JQM to get this to work. I am impressed at the design of both of these libraries - flexible enough that a newbie to JQuery can stick all the pieces in the right places and get something out of it.

Can you define tooltips in Dojo wijit template?

I've been trying to get a Dojo (1.6) dijit.Tooltip to work when defined in a wijit template.
So, if I have wijit template that includes the following:
<a data-dojo-attach-point="tooltipMe" href="" onclick="return false;">
Show a Tooltip
</a>
<div data-dojo-type="dijit.Tooltip" data-dojo-props="connectId:'tooltipMe'">
Got to love hovering over links. Sometimes you a get a free tooltip
</div>
I can see the link of course, but nothing happens when I hover. Scouting round the newsgroups it seems there might be a problem with defining tooltips in wijit templates, but it's not mentioned in the Dojo docs.
Is it possible to define tooltips inline like this? Or am I just doing something wrong, it seems like the obvious place to do it.
If not, is there an accepted approach for creating and linking tooltips to DOM nodes defined in wijit templates?
Tooltips connectId property has to be the id of a DOM node. data-dojo-attach-point is not an id, it just creates a reference in the instantiated widget.
So in your case you need to assign an id to the a-node and use the same id in connectId. To avoid id clashes when creating multiple instances of your widget you can use the ${id} variable substitution to ensure that all ids are unique:
Your code should look something like this:
<a id="${id}_link" data-dojo-attach-point="tooltipMe" href="" onclick="return false;">
Show a Tooltip
</a>
<div data-dojo-type="dijit.Tooltip" data-dojo-props="connectId:'${id}_link'">
Got to love hovering over links. Sometimes you a get a free tooltip
</div>
I've had problems doing it this way before. I used script to create them on my page after I had done some other work, maybe something like this will help you out if you use it in the template postCreate method.
var span = dojo.query('.hasEntry span').forEach(function(node, index, nodelist)
{
new dijit.Tooltip({
connectId:node,
position:"above",
label: toolTipLabel
});
});
Responding to an old thread here, but just wanted to share a solution for people looking to use tooltips without IDs on their custom widget elements. It's not as pretty as just using tooltip, but it works. It uses the "dijit/popup" and "dijit/TooltipDialog" modules.
this.editTooltipDialog = new TooltipDialog({
content: "<p>I love tooltips</p>",
onMouseLeave: function(){
popup.close(this.editTooltipDialog);
}
});
on(this.targetDiv, 'mouseover', lang.hitch(this, function(){
popup.open({
popup: this.editTooltipDialog,
around: this.targetDiv
});
}));
I tried to replicate the issue in jsFiddle: http://jsfiddle.net/phusick/EcLLb/.
I found out that dijit.Tooltip widget from the template is instantized, but it does not connect mouse events, presumably because DOM node it attempts to connect to does not exist yet (i.e. has not been added to document DOM tree).
To prove the aforementioned I tried to connect the tooltip in widget's postCreate method, when all DOM building is done and it worked:
postCreate: function() {
this.inherited(arguments);
this.tooltip1.set("connectId", this.tooltipMe); // w/o this the tooltip won't show
}
So you can instantize tooltips via a template markup and then just connect then to DOM nodes in postCreate method.

Resources