I am trying to convert a JQuery Mobile app over to Backbone. I am using the HTML5/Backbone/Jquery Mobile template that comes with Netbeans. Everything is going fine except 'pageshow' event is not firing when backbone renders the page. The original is a multi page template. The backbone version is identical except the page is delivered dynamically.
The page contains a canvas that I use to display a Jqplot chart. Page renders fine but the chart is never created because 'pageshow' event which creates the chart never happens.
I have the pageshow script at the bottom of the body.
<!-- Draw chart -->
<script>
$('#page2').on('pageshow', function() {
console.log("Pageshow triggered");
$.jqplot('chart1', [[3,7,9,1,4,6,8,2,5]], {
axesDefaults: {
labelRenderer: $.jqplot.CanvasAxisLabelRenderer
},
axes: {
xaxis: {
label: " ",
pad: 0
},
yaxis: {
label: " ",
pad: 0
}
}
}).replot({clear: true, resetAxes:true});
});
</script>
Hope you can help.
Paul
Related
I'm loading in a report and displaying it with jquery-ui in tab format. The report is returned by an ajax call in json, and a function is formatting it into HTML. Example code below:
<div id="reportdiv">
</div>
<script>
function displayreport(objectid)
{
$( "#reportdiv" ).hide();
$( "#reportdiv" ).html("");
$.ajax({
type: "GET",
headers: { 'authtoken': getToken() },
url:'/reportservice/v1/report/'+objectid.id,
success: function(data){
if(data == null)
{
alert("That report does not exist.");
}
else
{
var retHTML = dataToTabHTML(data.config);
$("#reportdiv").html(retHTML).fadeIn(500);
$(function() {
tabs = $( "#reportdiv" ).tabs();
tabs.find( ".ui-tabs-nav" ).sortable({
axis: "x",
stop: function() {
tabs.tabs( "refresh" );
}
});
});
}
}
});
}
</script>
This works fine the first time displayreport is called. However, if the user enters another value and runs displayreport again, the "tabs" format is completely lost (the tabs are displayed as links above my sections, and clicking on a link takes you to that section further down the page).
I figured completely re-setting the reportdiv html at the beginning of the function would bring me back to original state and allow it to work normally every time. Any suggestions?
After more testing, found that destroy was the way to go. If I've set up tabs already, run the destroy, otherwise, skip the destroy (http://jsfiddle.net/scmxyras/1/) :
if(tabs!=undefined)$( "#reportdiv" ).tabs("destroy");
Context
I have a small Ember app, which, amongst other things, displays a number of connected users and, when hovering an element of the page, their names as a list.
All in all, it works quite well. The applications pulls data from a REST endpoint every two minutes, as the backend didn't allow for pushing data.
The contents of the tooltip are computed in the Controller, with a function that basically concatenate strings in various ways according to the context. Then it's bound to a data attribute of the <img> the tooltip is created on. When the View is ready and didInsertElement is fired, the tooltip is generated (if needs be) based on this data-bindattr value.
Question
When new data is pulled from the backend, everything is updated accordingly, except the tooltip content. (When browsing the page's DOM, the data-bindattr value is updated too.)
What could cause the tooltip to not refresh? Is it a case of JQuery-UI not calculating it again?
Some code
Refreshing code in the app's controller:
Monitor.ApplicationController = Ember.ArrayController.extend({
itemController: 'process',
sortProperties: ['name'],
sortAscending: true,
intervalId: undefined,
startRefreshing: function() {
var self = this;
if (self.get('intervalId')) {
return;
}
self.set( 'intervalId', setInterval(function() {
self.store.find('process');
}, 120000 ));
}
});
View: Process.hbs
<div {{bind-attr class=":inline inactive:inactive"}}>
<img {{bind-attr src=icon}} {{bind-attr data-caption=contentText}} class="caption" />
<div class="counter">{{nbUsers}}</div>
</div>
View: ProcessView
Monitor.ProcessView = Ember.View.extend({
// (...) Various stuff.
didInsertElement: function() {
this.updateTooltip();
},
updateTooltip: function() {
console.log('Inside updateTooltip!');
if (!this.$()) {return;}
if (this.get('controller').get('inactive')) {
this.$().tooltip({items: '.caption', disabled: true});
return;
}
this.$().tooltip({
items: '.caption',
tooltipClass: 'tooltip',
content: function() {
return $(this).data('caption');
},
position: {
my: 'left+15px center',
at: 'right center',
collision: 'flip'
},
show: false,
hide: false
});
}.observes('controller.inactive', 'controller.contentText')
});
Controller: ProcessController
Monitor.ProcessController = Ember.ObjectController.extend({
contentText: function() {
var tooltipContent = '';
this.get('containers').forEach(function(container) {
// Do a lot of things to tooltipContent involving:
// container.get('name')
// container.get('text')
// container.get('size')
// container.get('nbUsers')
// The data-bindattr value refreshes correctly so I cut this out for readability.
return tooltipContent;
}.property('name', 'containers.#each')
});
Edit 1:
Replaced 'containers.#each' by 'contentText' in the observer and added logging.
Here's what I think is happening:
Your tooltip library isn't observing the data-caption attribute. Meaning, when you update the attribute, you have to explicitly tell the library to update the tooltip as well. So although your attribute is updating just fine, the tooltip library isn't actually watching for those updates.
This can be remedied by calling updateTooltip, which you do, in didInsertElement. However, didInsertElement only fires once, when the element is first inserted. It's not called when the content changes.
Those two things combined are, I think, causing your problem. I think that all you need to do is have updateTooltip also observe the controller.contextText property. Then it should be called when the text updates.
So it turns out my codes declares and initialize a tooltip, but once it's done, you can't change the content the same way. Plus it adds unneeded computing anyway.
Thanks to #GJK's answer and that question, I found out what was happening. Turns out you need to set the content of the tooltip to refresh it, not recreate it.
Here is the working code for Ember integration:
Monitor.ProcessView = Ember.View.extend({
// Other stuff
didInsertElement: function() {
this.initTooltip();
},
initTooltip: function() {
if (!this.$()) {return;}
if (this.get('controller').get('inactive')) {
this.$().tooltip({items: '.caption', disabled: true});
return;
}
this.$().tooltip({
items: '.caption',
tooltipClass: 'tooltip',
content: function() {
return $(this).data('caption');
},
position: {
my: 'left+15px center',
at: 'right center',
collision: 'flip'
},
show: false,
hide: false
});
},
updateTooltip: function() {
if (!this.$()) {return;}
if (this.get('controller').get('inactive')) {
this.$().tooltip({items: '.caption', disabled: true});
return;
}
content = this.get('controller').get('contentText');
this.$().tooltip("option", "content", content);
}.observes('controller.contentText')
});
As an added bonus, you can avoid using the data attribute as a buffer now, although I'm not sure why.
I have a jQuery UI Dialog that is displayed when there are form errors.
Heres the code:
function alert_field_errors (errors)
{
$('<div></div>').dialog({
modal: true,
title: "Error",
open: function () {
$(this).html('The following are required:<br /><br />'+errors+'<br />Please complete these in order to continue.');
},
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
}
the errors variable would contain something like First Name<br />Last Name<br />Email Address<br />
It works great, except for the fact that it is not centered. It seems to be positioning itself before the content is loaded, so that when it is displayed, the bottom margin of the dialog is closer to the bottom of the window compared to the top margin of the dialog.
I tried using the position option, but nothing seems to work.
Any help would be greatly appreciated.
Heres how I fixed it:
I created an empty div on the page with the id of error-dialog and gave it css display: none;.
Then I changed my code to this:
$('#error-dialog').html('The following are required:<br /><br /><i>'+$errors+'</i><br />Please complete these in order to continue.');
$('#error-dialog').dialog({
modal: true,
title: "Error",
buttons: {
Ok: function () {
$(this).dialog("close");
}
}
});
Now it is populating the dialog with content before display it, therefore allowing it to center itself properly.
So I have a jQuery UI dialog with some buttons inside (full example here => http://jsfiddle.net/VLr5G/3/):
<div id="test">
<button>Btn 1</button>
<button>Btn 2</button>
<button>Btn 3</button>
</div>
What I want to do is force the focus on the "Close" button - I have tried applying the following code when the dialog opens:
open: function() {
$(this).parents('.ui-dialog-buttonpane button:eq(0)').focus();
}
Unfortunately the focus always keeps getting on the first button inside the dialog. Is this a bug, or am I missing something ?
Thanks a lot in advance for your help !
UPDATE
Okay so the answer from Stanley works fine with my first example... But try to change the version of jQuery UI => http://jsfiddle.net/VLr5G/10/
From what I could find so far, it worked until jQuery UI 1.10.0.
You are not getting the close button correctly.
You should do this instead:
$(document).ready(function() {
$('#test').dialog({
buttons: {
'Close': function() {$(this).dialog('close');}
},
open: function() {
$(this).parent().find('.ui-dialog-buttonpane button:eq(0)').focus();
}
});
});
Working jsfiddle: http://jsfiddle.net/GG7EP/2/
UPDATE
To make it work with jQuery 1.10.0 or above, call the button's focus function in focus event
$(document).ready(function() {
$('#test').dialog({
buttons: {
'Close': function() {$(this).dialog('close');}
},
focus: function() {
$(this).parent().find('.ui-dialog-buttonpane button:eq(0)').focus();
}
});
});
JsFiddle: http://jsfiddle.net/V3P4t/
I have a div:
<div id="mproEmailAccountPopUp"></div>
I declare a Dialog
var popupdiv = $( '#mproEmailAccountPopUp' );
popupdiv.dialog({
width: 650,
autoOpen: false,
modal: false
});
I then get some html form stuff (this works fine) from a server and update the dialog content:
function ShowEdit(accountId) {
$.ajax({
type: "POST",
async: false,
url: "<%=EmailHandler %>?action=GetEmailAccountEdit",
data: { accountId: accountId },
success: function (result) {
alert("Success GetEmailAccountEdit");
popupdiv.html(result);
popupdiv.dialog("open");
//popupdiv.dialog( "moveToTop" )
}
});
}
This works beautifully the first time, but if you press the close button, and then recall the function. The dialog is updated with the new html, but you can't type in ANY of the text boxes. I have narrowed it down to the modal overlay (as it works with modal:false). The z-index seems to be 1 less than the modal form, and I have even deleted (via firebug) the modal overlay div, but I can still not edit the text boxes.
If I turn modal:false then it works fine, modal:true is causing these problems.
As you can see, i have tried the "moveToTop" method, no effect.
I have also tried destroying the popup, and reinitialising it entirely from within the ShowEdit function.
Anyone have any clue about what I can do to fix this?