In a jQuery Mobile application, I'm using Ajax to load a page with dynamic content. Now, I want to add a "reload" button to that page.
Consider index.html:
<div data-role="page" id="home">
<div data-role="header"><h1>Home</h1></div>
<div data-role="content">Time</div>
</div>
And time.php:
<div data-role="page" data-add-back-btn="true" id="time">
<div data-role="header"><h1>Time</h1></div>
<div data-role="content">
<p><?= date(DATE_RFC822)?></p>
Reload
</div>
</div>
I can now navigate back and forth between the "home" and "time" pages, and the time will be updated when arriving on the "time" page, but I would like the "Reload" button to reload the "time" page. That is: it should do an Ajax request for time.php, and recreate the "time" page from the response (and meanwhile show the "page loading" indicator).
How can I do that?
After looking at the code of changePage and loadPage I came up with a simpler solution:
$('.reload').live('click', function(e) {
$.mobile.changePage($.mobile.activePage.jqmData('url'), {
reloadPage: true,
changeHash: false,
transition: 'none'
});
e.preventDefault();
});
Note that JQM will still transition between the old version of the page and the new version; it is best not to use a transition that has a stronge sense of direction (like 'slide').
The preventDefault does not seem strictly necessary, but I added it for good measure.
This does not seem to be possible when using the hijax-style links. You can however use a multi-page HTML document and load the dynamic page content yourself in the pagebeforechange event.
So in index.html, I already add the "time" page with empty content:
<div data-role="page" id="home">
<div data-role="header"><h1>Home</h1></div>
<div data-role="content">Time</div>
</div>
<div data-role="page" data-add-back-btn="true" id="time">
<div data-role="header">
<h1>Time</h1>
Reload
</div>
<div data-role="content"></div>
</div>
Next, I intercept the pagebeforechange event: in case of the "time" page, we will load the page content from URL time.php.
$(document).bind('pagebeforechange', function(e, data) {
if(typeof data.toPage == 'string') {
var u = $.mobile.path.parseUrl(data.toPage);
if(u.hash == "#time") {
loadPageContent($('#time'), 'time.php', data.options);
e.preventDefault();
}
}
});
Since I want to wait for the Ajax request to come back before changing the page, I prevent the page change; loadPageContent will have to do this.
I can do a similar loadPageContent for the "Reload" button:
$(document).ready(function() {
$('#time .reload').bind('click', function(e) {
loadPageContent($('#time'), 'time.php', undefined, $(e.target).closest(".ui-btn"));
});
});
This is the code of loadPageContent:
function loadPageContent(page, url, options, button) {
if(typeof button != "undefined")
button.addClass($.mobile.activeBtnClass);
$.mobile.showPageLoadingMsg($.mobile.loadingMessageTheme, $.mobile.loadingMessage, $.mobile.loadingMessageTextVisible);
var content = page.children(':jqmData(role=content)');
content.load(url, function(response, status, xhr) {
if(status == "success") {
page.page();
content.trigger('create');
$.mobile.hidePageLoadingMsg();
if(typeof button != "undefined")
button.removeClass($.mobile.activeBtnClass);
$.mobile.changePage(page, options);
} else {
$.mobile.hidePageLoadingMsg();
$.mobile.showPageLoadingMsg($.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true);
setTimeout(function() {
$.mobile.hidePageLoadingMsg();
if(typeof button != "undefined")
button.removeClass($.mobile.activeBtnClass);
}, 1000);
}
});
}
This is already quite an elaborate version: it will display the page loading message, and it will display an error message for 1s when the request fails. At the end of a successful request, it will enhance the content with the create trigger, and it will do the page change. If the reload button is passed along, it will mark this button as active while the operation is in progress.
Related
This is probably a simple question, but how can I replace the thing I am dragging with html from an ajax call?
So, if the draggable items are just 'text' items (as below in the html snippet), and when I drag the thing I use a 'image' via the helper method, how can I 'on drop' not use either of them but insert the html as returned from a ajax call.
Where do I make the call (btw, using the 'input-type' value to the ajax call to get the correct html)?
How to I prevent the default 'dragged item' from being inserted? I.e. I don't want the div put in or the helper method image....
Do I need to add like a droppable or do I do this in the sortable on like the received event (kind of works, can't remove image but from help method)??? (I have been trying both, and whilst the ajax call worked and I get the data etc, given that I don't know how to prevent the default stuff being dropped I am not sure 'what' I am replacing with the 'result' from the call...)
$("#desktoplayout").sortable({
receive: function (event, ui) {
$(this).append('<div>html from ajax call</div>'); // kind of works... but the image from the 'helper method' on the 'draggable' is still there.
}
}); // A sortable list of stuff into which things are dragged.
var input-type;
$("#draggableItems .item").draggable({
connectToSortable: "#desktoplayout",
helper: function (event) {
return "<div class='item'><img src='/Images/Header.png' /></div>";
},
start: function (event, ui) {
input-type = $(this).find('.preview').data("input-type");
},
drag: function(e, t) {
},
stop: function(e, t) {
}
});
and
<div id="draggableItems">
<div class="item">
<div class="preview" data-input-type="1">
TEXT
</div>
</div>
</div>
Update
This seems to do what I wanted... is calling remove on the helper the correct way of doing this?
receive: function(event, ui) {
ui.helper.remove();
var $this = $(this);
$.get("somewhere", function(data) {
// Note: presume more logic here.....
$($this).append(data);
});
}
Here is a working example of one solution:
https://jsfiddle.net/Twisty/zh9szubf/
HTML
<div id="draggableItems">
<div class="item">
<div class="preview" data-input-type="1">
TEXT
</div>
</div>
</div>
<ul id="desktoplayout">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
</ul>
JQuery
$(function() {
$("#desktoplayout").sortable({
receive: function(event, ui) {
var newItem;
$.post("/echo/html/", {
html: "<li class='newItem'>From Ajax</li>"
}, function(data) {
ui.helper.replaceWith(data);
});
}
});
var inputType;
$("#draggableItems .item").draggable({
connectToSortable: "#desktoplayout",
helper: function (event) {
return "<div class='item'><img src='/Images/Header.png' /></div>";
},
start: function(event, ui) {
inputType = ui.helper.find('.preview').data("input-type");
}
});
});
This will work with $.get() too, but for the example, it had to be $.post(). Basically, whatever you want top be the result, That code should be in the ui.helper.replaceWith() section.
I would like to do the following:
1. tab-1 is selected when page load at first time
2. After clicking tab-2, form is submitted and page need to stay on the tab-2
I have tested two code snippets. However, both of them have errors (see at below):
<form id="target">
<ul>
<li>Tab-1</li>
<li>Tab-2</li>
<li>Tab-3</li>
</ul>
<div id="tabs-1">
</div>
<div id="tabs-2">
</div>
<div id="tabs-3">
</div>
</form>
code 1-
It works with point2 and doesn't work with point 1
<script>
$(function() {
var $tabs = $('#tabs').tabs();
$tabs.tabs( "option", "selected", 1 );
$('#tabs-B').click(function() {
$('#target').submit();
});
});
</script>
code 2-
It works with point1, but form doesn't submit after clicking tab-2
var $tabs = $('#tabs').tabs();
$('#tabs-B').click(function() {
$('#target').submit(function() {
$tabs.tabs( "option", "selected", 1 );
});
});
use the [select][1] method
$( "#tabs" ).tabs({
select: function(event, ui) {
var data = $("#from1").serialize();
console.log(data);
// submit the for via ajax here
/*$.post("/path",{data:data},function(){
//clear the form fields or what ever you want to do
});*/
}
});
http://jsfiddle.net/5RMxZ/16/
I wrote like there: http://jqueryui.com/demos/tabs/#...follow_a_tab.27s_URL_instead_of_loading_its_content_via_ajax
<script type="text/javascript">
$(function(){
$("#tabs").tabs({
select: function(event, ui) {
var url = $.data(ui.tab, 'load.tabs');
if( url ) {
location.href = url;
return false;
}
return true;
}
});
});
</script>
<div id="tabs">
<ul>
<li>
Home
</li>
<li>
About
</li>
</ul>
</div>
Tabs are created, but initial list (div, ul, li) is visible as well. Another problem: when I hover over tab, I see URL kind of /default.htm#ui-tabs-1, /default.htm#ui-tabs-2 etc. But I want to see URL "/default.htm" over the 1st tab and URL "/about.htm" over the 2nd tab.
What could I do to solve my problem?
UPDATE
In version 1.9 there is powerful widget "menu".
You are miss interpreting the jQuery UI Tabs.
This Tabs are for having content hide/show and if using ajax pull the page info and show it on demand.
if you want those tabs to act as a menu ... then you need a menu, not the jQuery UI Tabs.
If your idea if to use this tabs but to fetch the /about.htm as a new content, then you can use the ajax example
http://jqueryui.com/demos/tabs/#ajax
keep in mind that it will fetch the entire content, so the /about.htm page should not have <html> neither <body> tags
I don't want to encourage you to do this, but the solution is currently available on jQuery UI's website: http://jqueryui.com/demos/tabs/#...follow_a_tab.27s_URL_instead_of_loading_its_content_via_ajax
You may extend it a bit to follow only certain URLs:
select: function(e, ui)
{
var tab = $(ui.tab);
var url = $.data(ui.tab, 'load.tabs');
if(url && tab.attr('data-ajax') == 'false')
{
location.href = url;
return false;
}
return true;
}
Then, when defining tabs:
<li>...</li>
I would like to prevent the default behaviour of a click on a link. I tried the return false; also javascript:void(0); in the href attribute but it doesn’t seem to work. It works fine in Firefox, but not in Chrome and IE.
I have a single tab that loads via AJAX the content which is a simple link.
<script type="text/javascript">
$(function() {
$("#tabs").tabs({
ajaxOptions: {
error: function(xhr, status, index, anchor) {
$(anchor.hash).html("Couldn't load this tab. We'll try to fix this as soon as possible. If this wouldn't be a demo.");
},
success: function() {
alert('hello');
$('#lk').click(function(event) {
alert('Click Me');
event.preventDefault();
return false;
});
}
},
load: function(event, ui) {
$('a', ui.panel).click(function(event) {
$(ui.panel).load(this.href);
event.preventDefault();
return false;
});
}
});
});
</script>
<body>
<div id="tabs">
<ul>
<li>Link</li>
</ul>
</div>
</body>
The content of linkChild.htm is
Click Me
So basically when the tab content is loaded with success, a click event is attached to the link “lk”. When I click on the link, the alert is displayed but then link disappears. I check the HTML and the element is actually removed from the DOM.
$('#selector').click(function(event) {
event.preventDefault();
});
The event object is passed to your click handler by default - you have to have something there to receive it. Once you have the event, you can use jQuery's .preventDefault() method to cancel the link's behavior.
Edit:
Here's the fragment of your code, corrected:
$('a', ui.panel).click(function(event) {
$(ui.panel).load(this.href);
event.preventDefault();
return false;
});
Notice the addition of the word 'event' when creating the anon function (or you could use just e, or anything else - the name is unimportant, the fact there's a var there is.
I'm trying to use jQuery UI's .tabs() to obtain content via AJAX, but the default behavior is to grab the entire page's content. How would I obtain content from a specific #id and/or multiple #id's?
I have a feeling I will need to use the load: event (http://docs.jquery.com/UI/Tabs#event-load), but I need an assist figuring this out.
Example:
The Page with the tabs that is getting and displaying the tabbed content. I have placed #content after the first #the_tabs link to retrieve in an attempt to obtain that specific region of the content, but the entire page is still loaded.
<div id="tabs">
<div id="tabs_display">
</div>
<ul id="the_tabs">
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
</ul>
</div><!-- /#tabs -->
The page being retrieved by the previous markup:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Remote HTML Page Example</title>
</head>
<body>
<div id="content">
I want this content
</div>
<div id="other_stuff">
Not this content
</div>
</body>
</html>
the JS (for setup purposes):
$(document).ready(function(){
/* Tabs
--------------------*/
$(function() {
var $tabs = $('#tabs').tabs({
});
});
});
In Jquery-UI 1.9, "ajaxOptions" is depreciated; so instead the code below worked for me:
(ref: http://jqueryui.com/upgrade-guide/1.9/#deprecated-ajaxoptions-and-cache-options-added-beforeload-event)
$(function() {
$( "#the_tabs" ).tabs({
beforeLoad: function( event, ui ) {
ui.ajaxSettings.dataType = 'html';
ui.ajaxSettings.dataFilter = function(data) {
return $(data).filter("#content").html();
};
}
});
});
$(document).ready(function(){
/* Tabs
--------------------*/
var $tabs = $('#the_tabs').tabs({
ajaxOptions: {
dataFilter: function(data, type){
return $(data).filter("#content").html();
}
}
});
});
Solution props to Supavisah in #jquery on irc.freenode.net
I have had luck using .find, rather than .filter. Like this:
$(document).ready(function(){
$('#the_tabs').tabs({
ajaxOptions: {
cache : true,
dataFilter: function(data){
return $(data).find('#content');
},
}
});
});