I have a jQuery Mobile page with a dynamically generated collapsible. It works great, except if I leave the page then return to it. When that happens, the collapsible appears twice. A refresh fixes the issue but that's obviously not a good solution. Others on here have described similar symptoms, but their solutions didn't work for me. I'm hoping someone can help me out. I think I may be misusing pageinit...
I'm using jQuery 1.9.1 with jQuery Mobile 1.3.1. I'm using Codiqa to generate my pages, hence why I'm on jQuery 1.3.1. I generated the code such that every page is a separate html file.
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Characters | PCT</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link href="css/codiqa.ext.css" rel="stylesheet">
<link href="css/jquery.mobile-1.3.1.css" rel="stylesheet">
<script src="js/jquery-1.9.1.js"></script>
<script src="js/jquery.mobile-1.3.1.js"></script>
<script src="js/codiqa.ext.js"></script>
<script src="http://www.parsecdn.com/js/parse-1.2.15.min.js"></script>
<script src="js/pct.js"></script>
</head>
<body>
<div data-role="page" data-control-title="Characters" id="characters"
class="character_page">
<script>
$(document).on("pageinit", "#characters", function() {
var charQuery = new Parse.Query("Character");
charQuery.equalTo("user", Parse.User.current());
charQuery.find({
success: function(results) {
for (var j = 0; j < results.length; j++) {
var object = results[j];
var charName = object.get('charName');
var charNumActions = object.get('charNumActions');
var charSpd = object.get('charSpd');
$("#char_list").append("<div data-role='collapsible'><h4> " +
charName + "</h4><p><strong>Number of Actions:</strong> " +
charNumActions + "</p><p><strong>Spd:</strong> " + charSpd + "</p>
<a data-role='button' class='edit_button'
href='edit_character.html?charname=" + charName + "' data-icon='edit'
data-iconpos='left'>Edit</a><a data-role='button'
id='delete_char_button' class='delete_button' data-inline='true'
data-icon='delete' data-iconpos='left'>Delete</a></div>");
$("#char_list").collapsibleset("refresh");
$(".edit_button").buttonMarkup();
$(".delete_button").buttonMarkup();
}
}
});
});
</script>
<div data-theme="a" data-role="header">
Thank you in advance for taking the time to look at this.
Update:
Based on your edited OP and comment below, when using single page model, functions/JS code that is related to a specific page should be placed inside that page's div.
jQuery Mobile uses Ajax to load pages, it loads all libraries and code of first loaded page's head tag, and neglects the rest as it loads only data-role="page" div.
<div data-role="page" id="characters">
<script>
<!-- place code here -->
</script>
</div>
Because you bind to pageinit without specifying a page. The code will be executed whenever a page is initiated.
You should bind it to page id to fire once only.
$(document).on("pageinit", "#page_id", function () {
// code
});
Related
I see some others (e.g. this post) have had trouble using external javascript scripts in JQuery Mobile - as of today I have joined their ranks.
I have a single external js script (controllers.js) which contains code that affects several pages on the site. It is loaded on every page of the site. I put the js file just before the tag it works fine on the initial page load. However when I navigate thereafter (using the JQM Ajax methods) all functions in the script stop working. I would have thought the script would remain in cache - but heyho. Anyhow there's an FAQ which answers this question and I've implemented their suggestion which is: "...to reference the same set of stylesheets and scripts in the head of every page." I have done this but when I do even on the first page load the js doesn't fire. There aren't page specific scripts - so the remainder of that FAQ does not apply.
My cut down html looks like this:
<!doctype html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="/static/jquery-ui-1.10.3.custom.min.css">
<link rel="stylesheet" href="/static/jquery-mobile/css/themes/default/jquery.mobile-1.3.2.min.css">
<script src="/static/jquery-1.9.1.min.js"></script>
<script src="/static/jquery-ui/jquery-ui-1.10.3.custom/js/jquery-ui-1.10.3.custom.min.js"></script>
<script src="/static/jquery-mobile/js/jquery.mobile-1.3.2.min.js"></script>
<!-- CSS: implied media="all" -->
</head>
<body>
<div data-role="page" id = "main-page">
<div data-role="header" style="overflow:hidden;">
</div>
<div id = "home" data-role="content">
<input type ='button' id = "some_btn" value="press me">
</div>
</div>
<script type="text/javascript" src="/static/js/controllers.js"></script>
</body>
</html>
and within the javascript file
controllers.js
$('#some_btn').click(function()
{
alert('button pressed');
});
Any ideas on what I may be doing wrong here?
Since the content in the #page is loaded dynamically via ajax, click will not work, since it only works on elements that are on the page when the script is called.
You need to use the .on() method:
$('body').on('click','#some_btn',function()
{
alert('button pressed');
});
I have an issue with vclick (or click) events when fired.
This is my html code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Document</title>
<link rel="stylesheet" href="css/jquery.mobile-1.3.1.css">
<link rel="stylesheet" href="css/estilo.css">
<script src="js/cordova-2.6.0.js"></script>
<script src="js/jquery-2.0.0.js"></script>
<script src="js/functions.js"></script>
<script src="js/jquery.mobile-1.3.1.js"></script>
</head>
<body>
<div data-role="page" id="page">
<div data-role="header" position="fixed">
<h1>Data</h1>
</div>
<div data-role="content">
<div id="btn_comentar">
</div>
</div>
</div>
</body>
</html>
And this is my functions.js
$(document ).bind("mobileinit", function(){
$(document).bind("pageinit",function(){
$("#btn_comentar").bind("vclick",function(e){
console.log(e.isDefaultPrevented());
console.log(e.result);
console.log(e.relatedTarget);
alert("buttooon");
list_comments();
});
});
}
When I click my #btn_comentar, the data that I want to retrieve from function list_comments (sending via ajax) is duplicated; I realized that it was sending twice, and finally that it was something about when I clicked on my button.
This is the output from the console (twice):
false
undefined
null
and also the alert message box (twice) "buttoon";
I have tried some solutions like:
jQuery Mobile : replace click event by vclick event
but without success, please need some help
This is my new code and how it is now working, but it seems that without jQuery Mobile's default configuration
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Document</title>
<link rel="stylesheet" href="css/jquery.mobile-1.3.1.css">
<link rel="stylesheet" href="css/estilo.css">
<script src="js/cordova-2.6.0.js"></script>
<script src="js/jquery-2.0.0.js"></script>
<script src="js/custom-mobile.js"></script>
<script src="js/jquery.mobile-1.3.1.js"></script>
<script src="js/functions.js"></script>
</head>
<body>
<div data-role="page" id="page">
<div data-role="header" position="fixed">
<h1>Data</h1>
</div>
<div data-role="content">
<div id="btn_comentar">
</div>
</div>
</div>
</body>
</html>
custom-mobile.js
$(document ).bind("mobileinit", function(){
//$.mobile.allowCrossDomainPages = true;
});
functions.js
$(document).on("ready",function(){
$("#btn_comentar").bind("vclick",function(){
list_comments();
});
});
According to docs,
These enhancements are applied based on jQuery Mobile's default configuration, which is designed to work with common scenarios, but may or may not match your particular needs. Fortunately, these settings are easy to configure using the mobileinit event.
So that's what you need to use mobileinit for. For setting defaults like this :
$(document).bind('mobileinit', function(){
$.mobile.defaultTransition = 'slideup';
});
If my understanding is right, mobileinit is included/fired before jQuery Mobile's js is included. Assuming you done that, your script order must look like this :
<script src="jquery.js"></script>
<script src="custom-scripting.js"></script> <!-- This script must have mobileinit -->
<script src="jquery-mobile.js"></script>
At this point of time (when custom-scripting.js is loaded), pageinit wouldnt be defined.
It would be wise to add your pageinit event AFTER jQM script.
<script src="jquery.js"></script>
<script src="custom-scripting.js"></script> <!-- This script must have mobileinit -->
<script src="jquery-mobile.js"></script>
<script>
$(document).bind("pageinit", function(){
$(document).bind("vclick", "#btn_comentar" ,function(e){
console.log(e.isDefaultPrevented());
console.log(e.result);
console.log(e.relatedTarget);
alert("buttooon");
list_comments();
});
});
</script>
use once on pageinit:
$(document).on('pageinit') {
$("#btn_comentar").on("vclick",function(e){
console.log(e.isDefaultPrevented());
console.log(e.result);
console.log(e.relatedTarget);
alert("buttooon");
list_comments();
});
}
this should work
Another cause of double-vclicks I've encountered is due to Chromium synthesizing both touch events in addition to mouse events. I confirmed this cause by running the app in desktop Chrome's developer "device mode" (where the mouse cursor changes into a circle), confirming the problem exists, then toggling off device mode, and confirming the problem is "fixed".
jblas discusses it, partial excerpt:
Note that vclick does NOT suppress the synthesized mouse/click events that are generated by the browser because it does not know what context it is being used in, AND form input elements require the mouse/click events to function normally.
If you use a joystick or mouse (desktop), the alert will fire on the normal mouse click event.
If you want to suppress the click event while using touch, you have to call event.preventDefault() in your vclick handler. This will queue the request to kill the click event that follows but due to the differences in the way device vendors implement their events, and some bugs within different android OS versions, this turns out to be very hard to do. We try a couple of methods to figure out whether or not to kill a click event ... one is based on the element the touch event was triggered, on, and another is the position of the touch event. This is necessary because The browser does not necessarily dispatch the mouse events to the same element that it used for the touch event.
Ok so im expanding my existing MVC4 app into a mobile app.
Totally new to jquery mobile and im having so many issues with this in MVC.
Layout pages (MVC) and jquery mobile are a nightmare to work with or is it just me?
So im simply trying to show jquery ui datepicker in my page, it does not show!
I have to do a reload of the page for it to show, why???
Ok Layout page
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css"/>
<script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
</head>
<body>
#RenderBody();
</body>
</html>
and now the view
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_AppLayout.Iphone.cshtml";
}
<script>
$(function() {
$( "#datepicker" ).datepicker();
});
</script>
#using (Html.BeginForm())
{
<div data-role="page" id="pageAccount">
<div data-role="content">
<div id="datepicker"></div>
</div>
</div>
}
Any ideas why the page shows, but no datepicker (I have to reload the page for it to show)?
Solution :
This should be changed:
$(function() {
$( "#datepicker" ).datepicker();
});
to this:
$(document).on('pageshow', '#pageAccount', function(){
$( "#datepicker" ).datepicker();
});
To make a story short. jQuery Mobile should not be used with classic DOM ready jQuery functions. Instead jQuery Mobile is providing us with page events. If you want to find out more about jQuery mobile page events and how they work take a look at this ARTICLE, to make it transparent it is my personal blog. Or you can take a look HERE.
Edit :
Here's a working example:
Change positions of
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
into:
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
jQuery Mobile should always load last when used with jQuery UI.
Also you have forgot jQuery UI CSS, you will find datepicker without its CSS formatting.
I am having trouble with using OpenLayers in Gmaps4Rails (Gem version 1.5.2.) When I click on a marker I would like to show the typical callout (Infobox). Unfortunately I get the following JavaScript error:
this.serviceObject is undefined
Firebug calls the line 195 of the file "gmaps4rails.openlayers.js" responsable:
return this.serviceObject.addPopup(popup);
If I use Google Maps as API provider instead, everything works fine. Showing and hiding the infobox works nicely. This is why I assume that the error must be somewhere in "gmaps4rails.openlayers.js"
I tried on the latest FF and Chrome on Mac.
For reproducing the error in a reduced example, I created a simple HTML page in the public folder of my Rails 3.2 app and directly linked the needed JS and CSS files. To create the HTML page I copied the HTML code of my broken Rails app and reduced it.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href="/assets/gmaps4rails.css" media="screen" rel="stylesheet" type="text/css" />
<script src="/assets/gmaps4rails/gmaps4rails.base.js" type="text/javascript"></script>
<script src="/assets/gmaps4rails/gmaps4rails.openlayers.js" type="text/javascript"></script>
</head>
<body>
<div class="map_container">
<div id="map" class="gmaps4rails_map"></div>
</div>
<script src="http://www.openlayers.org/api/OpenLayers.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
Gmaps.map = new Gmaps4RailsOpenlayers();
Gmaps.load_map = function() {
Gmaps.map.map_options.provider = "openlayers";
Gmaps.map.initialize();
Gmaps.map.markers = [
{"description":"<p>This shall be in in the popup</p>",
"id":117979030,
"lat":39.5715,
"lng":2.64694}
];
Gmaps.map.create_markers();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
Gmaps.oldOnload = window.onload;
window.onload = function() {
Gmaps.triggerOldOnload();
Gmaps.loadMaps();
};
</script>
</body>
</html>
Unfortunately I could not find a working example of a successful Gmap4Rails–Openlayers integration on the web. Am I missing a mandatory parameter?
Thanks in advance.
It's a bug.
Replace:
return this.serviceObject.addPopup(popup);
with:
return this.map.addPopup(popup);
I'll push a fix soon, thanks and +1
I must be missing something very basic in the CSS. My jQuery anchor button is functional, but it's rendering as a simple underlined label, not asa rounded-corner UI button. I would be grateful if someone could point out the error in this simple example.
Thanks
!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<HTML LANG="en-US">
<HEAD>
<TITLE>button test</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Expires" content="Sat, 22 May 2010 00:00:11 GMT">
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.1/jquery-ui.min.js"></script>
<SCRIPT type="text/javascript">
$(document).ready(
function() {
$('a','.test').click(function(){showIntro();return false;});
});
function showIntro()
{
document.location.href="intro.htm";
}
</script>
<body>
<div class='test'>Button</div>
</body>
</html>
You need to actually make it a button using .button(), like this:
$(function() {
$(".test a").button();
});
You can see the jQuery UI demos here and a demo of your markup working here.
You need to add the proper class to the link, using jQuery or otherwise.
Try:
Button
You do not need to make it a button you just need
$(".test a").click(function(){showIntro();return false;});
What you are trying to do with your selector passing the second paramater is the Scope.
The second paramater is not mean to be a string (selector) it should be a jQuery Object.
So if you wanted to do it your way your would have to say
var test = $('.test');
$('a',test).click...
But the 1st method is prefered over doing it this way.
Sorry to be providing an answer, if not "the" answer, to my own question, but I have discovered a clue as to what's going on, if not the ultimate cause of the behavior. Below is code cut and pasted from the Button example on the jQuery website; take it to jsFiddle and run it: it works. But if you remove this line relating to the input-button:
$("button, input:submit, a", ".demo").button();
then the anchor-button fails to render properly. Why is the anchor-element's rendering dependent on the existence of the input-button?
<script type="text/javascript">
$(function() {
$("button, input:submit, a", ".demo").button();
$("a", ".demo").click(function() { return false; });
});
</script>
<style>
</style>
<div class="demo">
<button>A button element</button>
<input type="submit" value="A submit button">
An anchor
</div><!-- End demo -->
​