I need some assistance understanding page navigation in JQuery Mobile. The documentation I've read assumes you are loading data into the DOM, which in this case I am not (not sure why, I took over this code base).
You can see below, I have a page that MVC delivers. When a user selects a link from the ul, it calls as function to set the window.location, rather than loading the page into the DOM.
My question is, is there a more correct way to do this for JQuery Mobile, due to this issue: in each function, $.mobile.loading('show') is called, then the window location is changed. This page is cached on the iPhone with the loading spinner showing, so if the user presses back, it loads this page from the cache, and the loading spinner is still showing. Since the it was loaded from cache, pageinit and pageshow both do NOT get fired.
So two questions
Is there a more correct way to show the loading animation from one page to another, that is not being loaded into the DOM.
If not, is there a work around?
Thanks
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<form id="myform" method="post" action="/Mobile/Device?isSearch=1" data-ajax="false" >
<ul data-role="listview">
<li >
<h2 > Search for a device </h2>
<p> <input type="search" placeholder="Enter a term to filter active devices" name="txtfilter" data-mini="true" id="txtSearch" /> </p>
<input type="hidden" id="lbluserLatitude" name="lbluserLatitude"/>
<input type="hidden" id="lbluserLongitude" name="lbluserLongitude"/>
</li>
<li>
<a id="lnkViolationDevice" onclick="gotoViolationDevices();">
<h2>
Error Devices
</h2>
<p>
Only devices with Policy Violations
</p>
<span class="ui-li-count"><%= Model.UpdateTotalRecordCount%></span>
</a>
</li>
<li id="lnkNearby">
<a onclick="gotoNearbyDevices();">
<h2 > Active Devices</h2>
<p></p>
<span class="ui-li-count"><%= Model.TotalRecordCount%></span>
</a>
</li>
<li >
<a id="lnkInactiveDevice" onclick="gotoInactiveDevices();">
<h2>Inactive Devices</h2>
<p>New or Decommissioned </p>
<span class="ui-li-count"><%= Model.InactiveTotalRecordCount%></span>
</a>
</li>
</ul>
<br />
<script type="text/javascript">
var userLatitude = "";
var userLongitude = "";
$(document).on("pageinit", function () {
$('#txtSearch').attr('autocorrect', 'off');
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
}
else {
alert("Geolocation is not supported by this browser.");
}
});
function showPosition(position) {
broswerSupportGeo = true;
userLatitude = position.coords.latitude;
userLongitude = position.coords.longitude;
$('#lbluserLatitude').val(userLatitude);
$('#lbluserLongitude').val(userLongitude);
//$('#lnkNearby').show();
}
function mobileLogout() {
$.mobile.loading('show');
$.ajax({
url: "/Account/Mobile_LogOff",
type: "POST",
async: true,
success: function (result) {
window.location = '<%= Url.Action("LogOn", "Account", new{Area=""}) %>';
}
});
}
function GoFullPage() {
window.location = "/Device/Index?mode=full";
}
function gotoNearbyDevices() {
$.mobile.loading('show');
var actionLink = '<%= Url.Action("Index", "Device", new {tabIndex = "2", latitude = "LatitudeValue", longitude = "LongitudeValue"} ) %>';
actionLink = actionLink.replace("LatitudeValue", userLatitude);
actionLink = actionLink.replace("LongitudeValue", userLongitude);
window.location = actionLink;
}
function gotoViolationDevices() {
$.mobile.loading('show');
var actionLink = '<%= Url.Action("Index", "Device", new {tabIndex = "0", latitude = "LatitudeValue", longitude = "LongitudeValue"} ) %>';
actionLink = actionLink.replace("LatitudeValue", userLatitude);
actionLink = actionLink.replace("LongitudeValue", userLongitude);
window.location = actionLink;
}
function gotoInactiveDevices() {
$.mobile.loading('show');
var actionLink = '<%= Url.Action("Index", "Device", new {tabIndex = "1", latitude = "LatitudeValue", longitude = "LongitudeValue"} ) %>';
actionLink = actionLink.replace("LatitudeValue", userLatitude);
actionLink = actionLink.replace("LongitudeValue", userLongitude);
window.location = actionLink;
}
</script>
Is there a more correct way to show the loading animation from one page to another, that is not being loaded into the DOM?
Short answer is not, it is not possible. AJAX loaded is called AJAX loader with reason, it will only work when jQuery Mobile handles page loading into the DOM. In this case page is never refreshed, thus it is possible to show loader during page transitions.
In your case, each time you open new page browser will trigger complete page refresh, nothing visible can't persist during full page refresh/reload/open.
If not, is there a work around?
Short answer is still now. As I already told you in your previous question nothing visible can't persist during full page refresh/reload/open. Thou there's one thing you can do. Because next page is still jQuery Mobile page you can show loader during pagecreate event and hide it during pageshow event, window load if your page is content/image heavy or during AJAX success callback in case you are using AJAX to load additional content.
But again you can't have loader showing before you change page hoping it will still show after new page starts loading. It is simply not possible.
Is there a reason you are using? :
window.location = actionLink;
jQuery Mobile has its own method of handling full page transitions without AJAX, be it data-rel="external" attribute or changePage() function with page reload parameter.
Update
Full non-AJAX change page through attribute:
<a rel="external" href="index.html">Index</a>
Read more about it here. Unfortunately I can't find it explained in current documentation.
Full non-AJAX change page through changePage() function
First a warning, this function is deprecated but stick to it until jQuery Mobile 1.5 is out. There's a replacement function but it will not work for you unless you are using new pagecontainer widget. Plus pagecontainer widget is work in progress so it will be a bad decision to move.
$.mobile.changePage( "confirm.html", {
reloadPage : true
});
More information can be found here.
Related
I have a Javascript function called from a OnClientClick which is changing a forms action. The reason for this is there are other buttons on the form but only one of them is required to do the postback. I would like the target of the postback to open in a new window whilst altering the content of the sender form using div.innerhtml="Some HTML Code HERE!"
I have managed to write a function that works in Chrome, IE and Opera but I cannot get it to work in Firefox. As soon as I add the code to change the content of the Div for some reason the Form.Submit does not appear to happen. The content of the div updates but the new window does not open. If I remove the innerHTML edit from the code below the submit works and new window or tab opens as required. This problem on appears to occur in Firefox.
This is my code.
<script type="text/javascript">
/* Used to change form submission to another address , by dynamically setting a buttons OnClientClick property on server side */
function SetFormAction() {
var frm = document.getElementById("form1");
var paybut = document.getElementById("altCtButton1");
var canbut = document.getElementById("altCtButton2");
var altdiv = document.getElementById("divAltContent");
frm.action = "http://www.awebite.com";
paybut.disabled = "disabled";
canbut.disabled = "disabled";
frm.target = "_blank";
altdiv.innerHTML = "<br /><p>Process has been started, please complete in the new browser window and return to the jobs list when done!</p>" +
"<p><a href='/mysite/apage.aspx' class='btnType2' >Jobs List</a></p><br />";
frm.submit();
return false;
}
</script>
So the function above is called on a OnClick event in from a submit button within the browser. It changes the action of form1, disables the button that called it then for paranoia changes the content of the div that contained the button.
Any help with why this function does not work in Firefox would be appreciated.
So, the markup which calls this function is from a div which rendered from vb code behind but looks like this:
<!-- ShowAltContentMessage() Template ASPX Code Block - BEGIN -->
<div id="divAltContent" class="box">
<div class="content">
<input type="hidden" name="altCtStateData" id="altCtStateData" />
<span id="altCtHdrLabel"><P><B>Proceed to Payment Details Entry?</B></P></span>
<span id="altCtBdyLabel"><P>It appears a process was previously initiated however it may have been cancelled, please ensure you are not making a duplicate process.</P></span>
<span id="altCtFtrLabel"></span>
<input type="submit" name="altCtButton1" value="Yes - Process Job" onclick="SetPaymentServiceAction();" id="altCtButton1" class="btnType2" />
<input type="submit" name="altCtButton2" value="No - Abort" id="altCtButton2" class="btnType2" />
</div>
</div>
<!-- ShowAltContentMessage() Template ASPX Code Block - END -->
Whats interesting is if I remove the line of code:
altdiv.innerHTML = "<br /><p>Process has been started, please complete in the new browser window and return to the jobs list when done!</p>" +
"<p><a href='/mysite/apage.aspx' class='btnType2' >Jobs List</a></p><br />";
From the Javascript function everything works in Firefox with the exception of the content updating. I.E the new window or tab opens with the new web address and the buttons get disabled.
As I mentioned this code works perfectly in Chrome, IE and Opera so appears to be a browser specific issue?
Thanks
I'm trying to use PayPal's in-context checkout in a single page app, but having issues whenever visiting a page with a PayPal button for the second time.
I've just lifted PayPal's sample code from here http://plnkr.co/edit/2GGEyNEFUPCZ7jIIGk9X?p=preview and put it onto a page in my app:
<div>
<div class="container">
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<a href="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm" id="t1">
</a>
</p>
</div>
</div>
<div class="row product">
<div class="col-md-4">
<h3>Toy Story Jessie T-Shirt</h3>
<p>
<form id="t2" class="ajaxasync" method="POST" action="http://166.78.8.98/cgi-bin/aries.cgi?live=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm">
</form>
</p>
</div>
</div>
</div>
<script>
window.paypalCheckoutReady = function() {
paypal.checkout.setup("6XF3MPZBZV6HU", {
environment: 'sandbox',
click: function(event) {
event.preventDefault();
paypal.checkout.initXO();
$.support.cors = true;
$.ajax({
url: "http://166.78.8.98/cgi-bin/aries.cgi?sandbox=1&direct=1&returnurl=http://166.78.8.98/cgi-bin/return.htm&cancelurl=http://166.78.8.98/cgi-bin/cancel.htm",
type: "GET",
data: '&ajax=1&onlytoken=1',
async: true,
crossDomain: true,
//Load the minibrowser with the redirection url in the success handler
success: function (token) {
var url = paypal.checkout.urlPrefix +token;
//Loading Mini browser with redirect url, true for async AJAX calls
paypal.checkout.startFlow(url);
},
error: function (responseData, textStatus, errorThrown) {
alert("Error in ajax post"+responseData.statusText);
//Gracefully Close the minibrowser in case of AJAX errors
paypal.checkout.closeFlow();
}
});
},
buttons: [
{ container: 't1' }, { container: 't2' }]
});
}
</script>
<script async src="//www.paypalobjects.com/api/checkout.js"></script>
</div>
This works great the first time I visit the page. However, on subsequent visits (without a hard reload in between), I get
Uncaught Error: Attempting to load postRobot twice on the same window
This is because it's trying to load the checkout.js script twice. So if I put a conditional to not run the checkout.js script on subsequent pageviews and instead jump straight to paypal.checkout.setup, I get
Error: You are calling paypal.checkout.setup() more than once. This function can only be called once per page load. Any further calls will be ignored.
And the button is never generated.
I need to maintain the in-context experience (the window that pops up) when the button is clicked. I've searched all through PayPal's docs and have inspected the object thoroughly in the console, but hoping I'm missing something.
How can I "reload" the button on a new page if I've already loaded checkout.js and called paypal.checkout.setup() on a prior page?
I ended up writing a directive to solve my own problem, as it does not appear that PayPal has any kind of single-page functionality.
paypal-checkout directive
The directive runs the PayPal instantiation code once, and then subsequent directive placements will simply show the already-primed button on future page/state loads.
I have some pages with dynamic generated partial views, for example in some search pages.
If a user returned to such pages with the browser back button or with a back button implemented like:
#if (Request.UrlReferrer != null)
{
<button onclick="history.go(-1); return false;" class="flatButtonSecondary">back</button>
}
He doesn´t get the dynamic generated inputs loaded from the session or cookies because the page becomes loaded out of the cache of the browser.
I found this similar thread: How do I detect if a user has got to a page using the back button?
and implemented the answer like:
<form name="ignore_me">
<input type="text" value="0" id='page_is_dirty' name='page_is_dirty' style="display: none" />
</form>
<script>
var dirty_bit = $('#page_is_dirty')[0];
if (dirty_bit.value === '1') window.location.reload();
function mark_page_dirty() {
dirty_bit.value = '1';
}
$(function () { mark_page_dirty(); })
</script>
under the tag in my layout view so it is called every time I get the page.
So this works fine in Chrome but in Firefox it runs in an endless loop and in IE 10 it just does nothing.
Does anybody have an idea how to run this in all three browsers, or can give me an alternative implementation?
Edit:
After some experiments with the different browsers I found a solution that seems to work in all three (FF, IE10, Chrome). Here it is:
<input type="hidden" id="page_is_dirty" value="no">
<script type="text/javascript">
onload = function () {
var e = document.getElementById("page_is_dirty");
if (e.value == "no") e.value = "yes";
else { e.value = "no"; location.reload(); }
}
</script>
But I´m not sure, why this is running, and my first version is not. Is someone able to fill this gap in my mind?
I've been smashing my head against a brick wall for the past 3 hours trying to figure out how to handle this.
Here's what I am trying to:
When I press a viewProduct button, it loads a page product/view/{id} via a simple jQuery ajax call and insert it in a div.
Here is my main page (index.php)
<script type="text/javascript">
$(function() {
$(".viewProduct").on('click', function() {
var productID = $(this).data('id');
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/product/view/" + productID,
success: function(view) {
$("#productInfo").html(view);
}
});
});
</script>
<button class="viewProduct" data-id="11">View Product</button>
<div id="productInfo"></div>
Product/view contains some HTML (including viewParentProduct) and some javascript.
Here product/view.php
<script type="text/javascript">
$(function() {
// More javascript here....
$("#viewParentProduct").on('click', function() {
var parentProductID = 15; // This number changes depending on the product and comes from PHP
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/order/view/" + parentProductID,
success: function(view) {
$("#parentProductInfo").html(view);
}
});
});
</script>
<button id="viewParentProduct">View parent product</button>
<div id="parentProductInfo"></div>
So far, it works fine. The dynamically loaded javascript executes perfectly. The problem comes when the the parent product also has a parent product. So if I press the viewParentProduct , it loads the same page (product/view) and inject it in the dom, duplicating the HTML elements and javascript.
Visually:
STAGE 1: Click on viewProduct --> product/view/11 is injected into productInfo div
STAGE 2: Click on viewParentProduct --> product/view/15 is injected into parentProductInfo div
STAGE 3: Click on viewParentProduct --> product/view/{someOtherParentProductID} is injected into parentProductInfo div
At this point I am screwed. Since the same HTML/Javascript has been injected in the DOM twice, the next time I press on viewParentProduct, it'll trigger the wrong button and/or load the content of product/view in the wrong parentProductInfo div.
Of course I could do something like this but it's pretty ugly:
$(".viewProduct_11").on('click', .....
<button class="viewProduct_11" data-id="11">View Product</button>
<div id="productInfo_11"></div>
// Where 11 comes from PHP ex: <?php echo $productID; ?>
So my question is: Is there a way to sort of "namespace" a set of javascript-HTML or do you know a way to fix this problem ? Even if I namespaced the javascript, the HTML element's IDs would still be duplicated.
I'm really out of ideas!
-----------------------EDIT-----------------------
I need to have the javascript inside the view (product/view) because it's rather complex. In fact it has nothing to do with the simple snipped I used as an example in this question. I'd rather have the javascript related to the product/view page inside the view itself to improve cohesion. In reality, when clicking on the viewProduct button, the product/view page is loaded in a modal (a div with an overlay) and there can be multiple modal overlapping each other with the same HTML/javascript code coming from product/view. I could work around the javascript collision by wrapping the product/view's javascript in a namespace, however the HTML and the DOM elements and their ID will still be problematic. Hence why I'm looking for a way for namespacing a block of javascript AND HTML...somehow. I'm clueless.
Try this:
index.php
<script type="text/javascript">
$(function() {
$("body").on('click', '.viewProduct', function() {
var elem = $(this),
productID = elem.data('id');
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/product/view/" + productID,
success: function(view) {
elem.next().html(view);
}
});
});
</script>
<div class='viewWrapper'>
<button class="viewProduct" data-id="11">View Product</button>
<div class="productInfo"></div>
</div>
product/view.php
<div class='viewWrapper'>
<button class="viewProduct" data-id="15">View Parent Product</button>
<div class="productInfo"></div>
</div>
// Where 15 comes from PHP ex: <?php echo $productID; ?>
JavaScript from main page will be working for new loaded content.
ex.: http://jsfiddle.net/BV66Z/1/
Well, I understand there is a way to change contents within the same page using Ajax call & load functions (my example page a)
What i am looking for is, is there a way to call an external page & load dynamic content unto the selected div on that external page. i guess it possible using HTTP Request Methods
but i am really a noob at that.
OK, I have page a (picture attached)
the ajax loads the content into the "RESULT" div on clicking the specific id's
here is the ajax script & the html i have come so far. this loads perfectly on the Result div on the "page a" itself.
<a href="#" id="one" /><br>
<a href="#" id="two" /><br>
<a href="#" id="three" /><br>
<div id="result" class="functions"></div>
$.ajaxSetup({
cache: false
});
var ajax_load = "<img class='loading' src='img/load.gif' alt='loading...' />";
$("#one").click(function () {
var loadUrl = "content.php";
$("#result").html(ajax_load).load(loadUrl);
});
$("#two").click(function () {
var loadUrl = "content1.php";
$("#result").html(ajax_load).load(loadUrl);
});
$("#three").click(function () {
var loadUrl = "content2.php";
$("#result").html(ajax_load).load(loadUrl);
});
so the Query is, i have "page b" & certain buttons, on clickin the button, i want to load "page a" & load the selected content unto the result DIV.
the concept is, on page b, the id is clicked, it LOADS page a in a new tab & loads the selected content on "RESULT" div. both pages are on the same server
Would really appreciate any assistance or tips. thank you.