jQuery ui tabs select help needed. Can I cancel the action? - javascript

I'm using the following function to update the tabs on a jQuery ui tabs widget.
function updateTheTabs(select, disable) {
var selectIdx = vehicleSelectorControl.tabIndexByName(select);
$tabs.tabs('option', 'disabled', [])
.tabs('option', 'disabled', convertToTabIndices(disable))
.tabs('option', 'collapsible', true)
.tabs('select', selectIdx)
.tabs('option', 'collapsible', false)
.tabs('select', selectIdx);
}
I'm toggling the 'collapsible' option to achieve a desired behavior by the client. I also update the content of the tab on tabSelect. My question is I would only like the first tabSelect to actually trigger the call to the server. The 2nd tabSelect is just meant to show the tab. I realize this is a bit of a hack. Other controls on the page affect the tab states and in a certain case, a tab was already selected so the first call wasn't updating its content, hence I made it collapsible, select it (which is actually de-selecting it), set collapsible to false, then selecting the tab (this triggers the update properly). Anyways the client likes the current behavior except that I can see the server is being called twice. I tried breaking the chain in to two pieces and setting a boolean variable in between then checking it when deciding to update the tabs. I didn't quite get the behavior I wanted. Can anyone point me in the right direction here? Again, I don't want to call the server if it's not necessary. I would like a solution that doesn't require changing the 'updateTheTabs' function. Thanks so much for any advice or tips.
Cheers,
~ck in San Diego

I'm not sure I got what you wanted to do, but to the sentence "...except that I can see the server is being called twice", I take that you want to cache the content of the tab.
You may try to set the cache option to true when you initiate the tabs:
$tabs.tabs({cache: true});

It might be easiest to just use a global to keep track of whether or not the tab has been loaded. Then in beforeLoad, check if the tabs has been loaded. If not, load it, otherwise just show it. In example code below, be sure to change 'my-tab' to match the title in the html, i.e. My Tab
var tabLoaded = false;
$("#tabs").tabs({
beforeLoad: function(event, ui) {
if($(ui.panel).attr('id') == 'my-tab' && tabLoaded) {
event.preventDefault();
}
});

Related

How to synchronize toggle selections across pages with JQuery Mobile?

I have a need to have a multi-page html, with each page containing an identical toggle. When the user changes a toggle on one page, all the toggles on the other pages should change (or at least change on loading the other pages).
I've created a Fiddle to illustrate a simple scenario, with a two page example and identical toggles on each page. I'd LIKE to be able to change the toggle on page 2 by toggling the toggle on page 1
http://jsfiddle.net/vSr99/
I've tried a number of methods, and yes have included a refresh after attempting to manipulate with javascript, but have not even come close, no doubt due to my programatically challenged nature :-/
If anyone can suggest a simple solution I'd much appreciate it!
Thx
try setting a global attribute when the button is clicked and store this on $('html') like so:
$('html'). attr('toggleIs',true);
then you can check for this on pagebforeshow and add the toggled state to the buttons on all new pages being pulled into view depending on the button state.
EDIT
Here is a jsfiddle (ignore the first alert);
Here is the html:
$(document).on('change', '.your_select', function(){
// set
if( $(this).find('option:selected').val() == "on" ){
$('html').data('toggle', 'on');
} else {
$('html').data('toggle', 'off');
}
});
$(document).on('pagebeforeshow', '.ui-page', function(){
var that = $(this).find('.your_select');
// clear
that.find('option').removeAttr('selected');
// reset
if($('html').data('toggle') == "on" ){
alert("should be on")
that.find('select option[value="on"]').attr('selected', 'selected')
} else {
alert("should be off")
that.find('option[value="off"]').attr('selected', 'selected')
}
// refresh slider
...
});
please note:
took me a while to see you where using jquery 1.6.4, so my on-bindings didn't work. If you want to keep, you need to use live for the bindings to also capture pages being pulled in.
I gave a class to all sliders, to set them together
I cannot get the JQM slider('refresh') to work on the slider or any parent element... you will have to figure that out by yourself, but the synchronizing is working :-)

How to modify jQuery mobile history Back Button behavior

I'll start this off with I have researched a bit, but no solution that solves what seems like it should be a simple JQM modification.
I have a wine review webapp that has the following view user flow:
http://5buckchuck.com/
Wine type > Wine list > Wine Details > Wine review (redirect via django backto ) > Wine Details updated from review
What I want to happen is when the user presses the back button it should go back to the wine list. What currently happens is the the Wine Detail view is reloaded. It takes pressing back three times to get back to the Wine List. :-(
My thoughts to solve this were two:
Splice the last 3 items from the history stack, if the last items in the history stack was Wine Review. I had a hard time trying to introspect the last history object to get the pageURL. I have a feeling that this solution is a bit too fragile though.
var last_hist = $.mobile.urlHistory.getActive();
last_hist.data.pageURL;
The second thought was to override the back button behavior so that the back button from the Wine Detail view would always go back to the Wine list view
$('div#wine_detail').live('pageshow',function(event, ui){
$("a.ui-btn-left").bind("click", function(){
location.replace("/wines/{{wine.wine_type}}/#");
});
});
There is probably a better way to do this, but I'm a bit out of ideas.
Update:
So I continue to hack on this with somewhat negligible results. On thing I have found was this is what I basically need to work: window.history.go(-3)
from the console it does exactly what I need.
So I tried binding it the the back button like such:
$('div#wine_detail').live('pageshow',function(event, ui){
var last = $.mobile.urlHistory.stack.length - 1;
var last_url = $.mobile.urlHistory.stack[last].url;
var review_url = /review/g;
if (last_url.match(review_url) )
{
$('div#wine_detail a.ui-btn-left').bind( 'click', function( ) {
console.log("click should be bound and going back in time...")
window.history.go(-2);
});
}
else
{
console.log('err nope its: ' + last_url);
}
});
No dice, something interupts the transaction...
I'd prefer not to splice/pop/push with the urlHistory. How about redirect on pagebeforechange like so:
$(document).on("pagebeforechange", function (e, data) {
var overrideToPage;
// some for-loop to go through the urlHistory TOP>DOWN
for (var i = $.mobile.urlHistory.activeIndex - 1; i >= 0; i--) {
// this checks if # = your target id. You probably need to adapt this;
if ($.mobile.urlHistory.stack[i].url = $('#yourPageId').attr('id')) {
// save and break
overrideToPage = $.mobile.urlHistory.stack[i].url;
break;
}
// set new Page
data.toPage = overrideToPage;
}
});
This captures your back button changePage call and redirects to the page you want. You could also just set data.toPage = winelist directly of course.
I'm only doing this with #internal pages, but it shoudn't be so hard to set this up with winelist.html etc.
For more info, check the event page in the JQM docs
Why not have a back button in the header section of your page? Something like this:
<div data-role="header">
<a data-direction="reverse" data-role="button" href="#winelist" data-icon="back">Back</a>
<h1>Wine Detail</h1>
</div><!-- /header -->
I wrestled with this recently as well. After thinking about it, I realized I could rewrite my JQM application to use Pop Up "windows" for those pages that I didn't want in my history. This ended up being an easier and cleaner fix than mucking around with browser history.
Now users can intuitively use the browser back button, and I don't have to code application back buttons.
The only thing you have to ensure is that the popups don't themselves make it into the browser history, so make sure to set the "history" option to false like so:
$('#some_popup').popup( { history: false } );
Okay so the solution was close to the update I posted. The issue with the previous solution was that there were to many things bind-ed to the "Back" button. While my new bind action may have been working sometimes, the other actions would take place too, I tried unbind() but still no worky.
My solution is a bit of smoke and mirrors. I check to see if the the previous page was the review page and then if so, I swap out the old back button for my new faux button with the history back step like so:
$('div#wine_detail').live('pageshow',function(event, ui){
var last = $.mobile.urlHistory.stack.length - 1;
var last_url = $.mobile.urlHistory.stack[last].url;
var review_url = /review/g;
if (last_url.match(review_url) )
{
$('a.ui-btn-left').replaceWith('<span class="ui-btn-inner ui-btn-corner-all"><span class="ui-btn-text">Back</span><span class="ui-icon ui-icon-arrow-l ui-icon-shadow"></span></span>');
$('#time_machine').bind( 'click', function( ) {
console.log("click should be bound and going back in time...")
window.history.go(-3);
});
}
else
{
console.log('err nope its: ' + last_url);
}
It looks exactly the same, and no one is the wiser. it could probably be improved by using the the jQm method pagebeforeshow so user could never see the swap. Hope this helps someone.
If you have the situation that you want the close button refer to an arbitrary (not the last) page, you could also change first to the target page and open the dialog afterwards. Therefore the close button at the dialog will open the target page.
// First: change to the target page
$.mobile.changePage('#target_page');
Afterwards open the dialog like this.
// Second: change to the dialog
window.setTimeout(
// for some reason you have to wrap it in a timeout
function(){
$.mobile.changePage('#dialog');
},
1
);
Now you can open the dialog and the close button will open #target_page.
Advantages:
solution works for single dialogs rather than removing all close buttons from all dialogs
seamless integration on a single point of code
history manipulation is not needed
I have seen similar issues before when using jquery mobile and it is addressed in the documentation. When setting up your Javascript "at the beginning of your page" use pageinit instead of ready or maybe in your case pageshow. I think this will address your issue without having to workaround the history queue.

Prevent an exception with jQuery UI Tabs

I am adding some custom tabs to a jquery ui tab control.
$("#tabs").tabs("add","#tabContent0","CLICK ME TO CHANGE PAGE",0);
$('a[href="#tabContent0"]').attr("href","javascript:window.location='http://www.google.co.uk';");
Yes this is a bit of a hack, but it is exactly what i need and provide a nice way to give links back to previous parent pages.
jquery throws the following exception: "jQuery UI Tabs: Mismatching fragment identifier."
This is thrown on the line which appears to attempt to make the tab container visible in jquery ui (exact line wont help as is minified and custom build from official site).
Obviously im just redirecting but jquery has additional code to select the tab (which doesnt exist). In internet explorer, if the user has script errors enabled they will see the exception be thrown just before the window location changes, which I just cant have happen.
I cant put try catch around this code because it is the code inside jquery ui that throws the exception.
Is there anyway I can prevent this exception being thrown or achive the same thing but a different way without having to modified jquery ui ?
Edit: I am now wondering if there is a way to override the on click event hook placed on the element by jquery .. its definitely doing something there i cant see.
Edit: I have to log off now but I have made some progress, if someone can just help me get the right URL, using this code it prevents the exception, but redirects me to "http://myurl/undefined"
$('#tabs').bind('tabsselect', function(event, ui) {
if(ui.index<2) //ignore this will change to get current tab count -1 (so the end tab is left as it is
{
window.location=$('#'+ui.tab).attr("href"); //attr href is undefined, how do i use ui.tab properly to get the right url
return false;
}
});
It works OK for me in Chrome and IE8.
I also tried this code and it worked:
$("#tabs").tabs("add","#tabContent0","CLICK ME TO CHANGE PAGE",0);
$('a[href="#tabContent0"]').click(function() {
document.location='http://www.google.co.uk/';
});
Instead of changing href attribute, I add a handler on the click event of the new tab. This will make the tab to be switched and then the location changed.
From the jQuery UI docs:
$('#example').tabs({
select: function(event, ui) {
var url = $.data(ui.tab, 'load.tabs');
if( url ) {
location.href = url;
return false;
}
return true;
}
});
Though, jQuery's tabs, uh, method, ought to support passing in a selector for the tabs and panels so you could just make things links, instead of having to kick against the pricks.

Click count possible with javascript?

Let's say, in website, I want to display the notice message block whenever people click any of the link at my website more than x number of times. Is that possible to count with javascript and display the notice message block ? And can we count the refresh times also ? Or can it be only done with server side language like php ? Please kindly suggest. Thank you.
With Regards,
To do something when any link is clicked is best done with JQuery's live:
Description: Attach a handler to the
event for all elements which match the
current selector, now and in the
future.
$('a').live('click', function() {
// Live handler called.
});
Even if you add more links in run time, this will take care of it.
For counting refreshes I would do it with ajax calls on window.load event, or if you want to use new tech - store it locally with Html5. :-)
You can do that on the client. However, this will be limited to the browser. The simplest will be to store this information in cookies on the client. For instance with jQuery you could simply intercept clicks like that:
$("a").click(function() {
var clickedUrl = $(this).attr('href');
// Here you update the cookie for the count of clicks for that A URL
});
I would either count page refreshes serverside or probably call an ajax function to update the count when the page loads.
If you want to count clicks you may need to bind an event to each link and then for each indivisual button store the number of clicks in global variables...
You could register each click event on the document by using:
$(document).click(function()
{
// Check the number in the cookie and add another
// click to the cookie
});
Then you could use the jQuery cookie plugin to store that value and check it each time there is a click (in the function above).
here's the cookie plugin: https://github.com/carhartl/jquery-cookie
I threw together a quick example. If you're not worried about doing this from page to page then you don't need cookies, just store it in a variable:
http://www.webdesignandseo.net/jquery/clickcount/

ASP.NET/jQuery Post-Back, but not when using browser's "Back" button

I'm working on an ASP.NET Web Project with some AJAX magic. As my GridView's data needs up to 15 seconds to be gathered, I send the page to the client and fire an asynchronous update of an UpdatePanel via jQuery/JScript (see below).
This works well, so far. Now I'd like to skip this step when the user navigates to the next page (e.g. record detail view) and comes back via the "Back" button. Is there a way to get his, and what's the most elegant one?
This one does not work (hasDonePostBack's value isn't kept by the browser):
var hasDonePostBack = false;
function fRefreshAsyncOnce(id, param) {
$(document).ready(function() {
if (!hasDonePostBack) {
__doPostBack(id, param);
hasDonePostBack = true;
}
});
}
Any help would be great!
The reason why this is important: Regetting the data takes another 15 seconds. Moreover, the grid is working with controls and more client script (e.g. checkboxes that can be checked, CSS classes that are toggled, etc.), and all this should be the same after returning.
Cheers,
Matthias
You may want to look at the history point feature; you may be able to take advantage of that for this feature: http://msdn.microsoft.com/en-us/library/cc488548.aspx
However, that is the nature of the beast when triggering client-side operations... the other option is allowing the user to cancel the postback (or try to interpret a way to cancel it yourself) using this technique: http://msdn.microsoft.com/en-us/library/bb398789.aspx

Categories

Resources