I am facing a very strange problem where my javascript code does not run the first time the page is loaded. If I reload/refresh the page, the script runs fine.
After some hit-and-trial's I realized that if I remove the jquery.mobile-1.4.3.min.js library from the previous page (which redirects to my current page) then the script is running as expected.
Can anyone please help on why this is occurring and how can I resolve it ?
Update:
On opening the hpme page (which contains the link to the page containing the JS), I can see the following error in console:
Uncaught TypeError: Cannot set property 'mobile' of undefined .
Please note that this home page is basically a simple code with library declarations and html links.
Edit :
I had missed the jQuery lib earlier and hence the Uncaught TypeError.
Now, my libraries are in the following order :
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jquerymobile/1.4.3/jquery.mobile.min.css" />
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/themes/smoothness/jquery-ui.css" />
Now there are no errors in my console, but still the JS in the next page does not run in the first load. Oddly, if I remove the jquery.mobile-1.4.3.min.js library, the JS works fine.
Single Page Model
jQuery Mobile loads external pages via Ajax; when you have a link to another page, jQM loads first page div <div data-role="page"> in that page and neglects other tags outside that div.
If you have JS code that you want to run in the loaded page, you have to place it inside page div.
<div data-role="page">
<!-- JS code -->
</div>
Related
I have two very simple pages as below. If I browse to "mysite.com/" the webserver returns the "index.html" content, as is normal. If I then click the "page2" link, jquery mobile loads the 2nd page into the DOM, but doesn't unload the first page from the DOM, although it is hidden (display:none) from view.
I now have 2 <div data-role="page"> elements in the DOM, with only page2 page visible on screen. If I then click the "index" link on page2, jquery mobile unloads page2 from the DOM, and loads the index.html page into a new DOM element. I now have two instances of <div id="index"> in the DOM which is obviously incorrect!
What is going on? I thought I'd ask on here before reporting it as a bug but it seems like a very simple example that is completely broken!
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head>
<body>
<div data-role="page" id="index">
Page2
<p>index page</p>
</div>
</body>
</html>
page2.html
<html>
<body>
<div data-role="page" id="page-2">
Index
<p>Page 2</p>
</div>
</body>
</html>
EDIT:
I found a workaround of page2.html linking to rather than "index.html", which prevents the 2nd duplicate loading, but it still seems wrong that the original page loaded is always kept in the DOM.
EDIT 2: This is a known issue https://github.com/jquery/jquery-mobile/issues/4050 - I just didn't manage to find it despite extensive googling before posting this question. I might raise a bug report against their documentation though, because it is highly unexpected behaviour IMO.
This is the default behavior of jQuery Mobile, first landing page is always kept in DOM. It only removes external pages which aren't cached data-dom-cache="true". You will always have two pages in DOM, landing page and active external page.
Nevertheless, if you wish to remove landing page once you navigate to another page, add data-external-page="true" to page div of the landing page. Once it's created pagecreate, flag it for removal .page("bindRemove"). This is the way jQuery Mobile removes external pages.
Note that is fix will work as long as .page() widget isn't removed and replaced by .pagecontainer() widget.
<div data-role="page" id="pageID" data-external-page="true">
$(document).on("pagecreate", "#pageID", function (e) {
$(e.target).page("bindRemove");
});
Demo
I created a test as described in your question with the two files index.html and page2.html and tested with Chrome (version 38.0). I loaded index.html and then navigated to page2.html and then back to index.html. Using Chrome Developer Tools, I then examined the elements in the page and found the following (screen shot):
As we see, there is one instance of the page called index and one instance of the page called page-2 but no duplicates.
I realize that this does not line up with your own results but am offering this is an answer demonstrating that the story works as expected. If we determine a flaw in the logic of this answer, I'll happily delete it.
Problem: datepicker is not showing up at all. No errors in the console. All files are included and accessible via Firebug.
After spending way too much time trying to get the jQuery UI datepicker to work, and that includes reading through dozens of Google results, I need your help. Not even the simplest, plain, straightforward implementation of the datepicker is working for me.
Current example I'm testing (stripped down to nothing but the datepicker):
<html>
<head>
<meta charset="UTF-8">
<title>DatePicker Test</title>
<!-- JavaScript -->
<script type="text/javascript" src="../js/jquery/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="../js/jquery/jquery-ui-1.8.19.custom.min.js"></script>
<!--script type="text/javascript" src="../js/jquery/jquery.ui.datepicker.js"></script-->
<!-- Stylesheets -->
<link rel="stylesheet" href="../css/ui-lightness/jquery-ui-1.8.19.custom.css" />
<script type="text/javascript">
$(function() {
$( "#datepicker" ).datepicker();
});
</script>
</head>
<body>
<div><input type="text" id="datepicker" class="hasDatepicker" /></div>
</body>
</html>
This does NOT work. I've downloaded the entire jQuery UI code (jquery-ui-1.8.19.custom.min.js) and tried everything. I've even tried to add a simple datepicker field to the demo HTML page that comes with jQuery UI. Nothing.
Then I downloaded the developer bundle of jQuery UI, and tried just the datepicker.js with jQuery, but even that failed.
So although I get no errors, and I can see my selector in the code and through calling it up from the console, I just get plain old nothing.
Then I've tried numerous CSS modifications that have been posted in several forum posts, moved my JavaScript from the top to the bottom, after the datepicker . . . and all kinds of mutations, but nothing has worked.
Is it me?
Certainly, it's possible for others to use the datepicker plug-in, what am I doing wrong?
Hey so I looked into your issue. I suggest removing the class declaration in the input that helped me. Also make sure your script links are correct. You are currently asking them to pull from a folder that comes before your current page. If the page and css/js folders are in the same directory you can remove the "../" at the front.
<input type="text" id="datepicker" />
A helpful add-on in FireFox are the Web Developer tools
Check out this js fiddle here for a working example. It's pretty similar to what you are doing minus the class on the input field, aswell as in this case the example is using CDN's.
You must have something wrong (maybe a script or css isn't getting sourced).
I have this index.html and login.html and I use a href to link from index to login. and in each index.html and login.html I import the javascript. However, it seems that only the ones come from index.html that is being loaded. so if I place the js in index.html for the login.html, it works fine. but then, we I place it separately ( another js for login.html that is not in index.html) , it doesnt work
TIA
When JQM(jQuery mobile) loads a page it uses ajax to accomplish this. When this happens all code in the <head> section is ignored. JQM looks for the data-role="page" part and inserts it into the same dom as index.html. So basically you are doing it the correct way when you add your js in the index.html page.
If you would like to compartmentalize your js code to work for certain pages use this example:
$(document).on('pageinit', '#page1', function(){
// code for #page1
});
$(document).on('pageinit', '#page2', function(){
// code for #page2
});
$(document).on('pageinit', '[data-role=page]', function(){
// this code will execute for every page that is data-role="page"
});
So go ahead and put all your code in one file. Split your code into appropriate pages like above and include that in your index.html file.
Also if you are using JQM version 1.0.1 with jQuery version 1.6.4(recommended with 1.0.1) use .delegate() instead of .on(). i.e.
$(document).delegate('#page1', 'pageinit', function(){ // notice that pageinit and #page1 are switched around for delegate
// code for #page1
}); // interesting to note that if you use delegate in jQuery 1.7.x it actually just calls the .on() method.
Note If you were making a web application instead of a phonegap app you would be smart to put your javascript in that one file and include that in every page. This way if someone is following a link or bookmarked your page they will still get the correct javascript file they need.
Anyways I hope that helps you out. Good luck!
If you are doing a window.location.href then it will load the new HTML(In you case it is login.html) If you are using this approach then you have to reload all you scripts again and hence add these scripts in all your .html pages.
<script src="cordova-1.6.0.js" type="text/javascript"></script>
<script type="text/javascript" src="jquery/jquery-1.7.1.min.js"></script>
<link rel="stylesheet" href="jquerymobile/jquery.mobile-1.1.0.min.css" />
<script type="text/javascript" src="jquerymobile/jquery.mobile-1.1.0.min.js"></script>
However if you use the approach recommended by #deadlock then you will just need to load the script once. The later approach is the best one.
Please post your code, specifically how the pages link to each other, and the global config settings you set for app, if any. Like much with jQM, there are multiple practices and strategies supported for page arch.
You can also learn by using desktop browser tools and view the "Resources" to see what and when your resources are being loaded.
I want to open the the .html file from my .js file. So I Used the $.mobile.changePage("file.html"). In the file.html have file.js. But The file.js does not call when the file.html in invoked.
THanks in advance.
first.js
$.mobile.changePage ("file.html");
file.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jQuery Mobile Framework - Dialog Example</title>
<link rel="stylesheet" href="jquery.mobile-1.0a2.min.css" />
<script src="jquery-1.4.4.min.js"></script>
<script src="jquery.mobile-1.0a2.min.js"></script>
<script src="../Scripts/file.js"/> // Could not imported
<script src="../Scripts/helperArrays.js"/> // Could not imported
<script src="../Scripts/globalVariables.js"/> // Could not imported
</head>
<body>
<div data-role="page">
<div data-role="header" data-nobackbtn="true">
<h1>Vaults</h1>
</div>
<!-- <div data-role="content" data-theme="c" id="contentVault">
Sample Vault
My Vault
</div> -->
<div data-role="content" id="content">
<ul id="listview" data-role="listview" data-inset="true" data-theme="e" data-dividertheme="b">
<li id="listdiv" data-role="list-divider">List of Items</li>
</ul>
</div><!-- /content -->
</div>
</body>
</html>
Please help me..
When jQM loads another page through AJAX it only pulls in anything within your div[data-role="page"] and nothing else, like the head
So you can if you wanted to, include any JS/CSS within this div, the problem is that if this page is accessed multiple times any CSS will accumulate, but the problem is much worse for JS.
You are basically getting every page appended to the DOM, so the JS runs on the entire DOM (every page you loaded) if you use a global selector like $('div.someClass'), even using an ID isn't a perfect solution because if you can link to the same page twice.
For Smaller Sites
I've solved this by moving all the CSS into one file and for JS code that I want to run each time the page is loaded, I bind to the pageinit and pageshow jQM events:
<script type="text/javascript">
$("div:jqmData(role='page'):last").bind('pageinit', function(){
//your code here - $.mobile.activePage not declared
});
$("div:jqmData(role='page'):last").bind('pageshow', function(){
//your code here - $.mobile.activePage works now
});
</script>
The pageinit event runs when the page is loaded, only ever once (after it's loaded it stays in memory if you navigate back to it, even via a back button this isn't fired again), pageshow on the other hand fires everytime the page is shown, even when you navigate back to it via the back button on the browser for example.
The pageinit runs when the DOM is there, the pageshow event is only if you have some code that depends on the DOM being rendered and you need a quick reference to the active page through $.mobile.activePage or some data changed and you need to refresh this back everytime it's shown. For most purposes I only use the pageinit as a document.ready for jQM and bind my events there. Use bind for static elements, and on instead of live for dynamic elements, because live events listen at the document root, you want to listen at the page div.
For Larger Sites
For larger sites there are advantages to binding a live event to any pages and handling types of pages, this way js code isn't loaded more than once.
If you have external js files with say helper functions that you only need once put that in the head of all your pages (if there aren't too many), if you had a very big site you could probably do better by tracking which JS files have been loaded server side.
All this can be avoided by just not using AJAX to load new pages, so think about whether that transition/loading effect is worthwhile
*Here's how I handle large jQM sites: *
bind a live event to all pages/dialogs pageinit and pageshow events:
$(document).on('pageinit pageshow', 'div:jqmData(role="page"), div:jqmData(role="dialog")', function(event){
I reference each page with a name: <div data-role="page" data-mypage="employeelist">
In this live event you can basically have a switch statement for each page "name", and then check event.type for pageinit/pageshow or both and put your code there, then every time a page is created/shown this event will be fired, it knows what page triggered it and then calls the corresponding code
I eventually had too much code, so I built a handler object where each page's js is included in a separate js file and can register handlers with the live event
The drawback is that all your js for your entire site is loaded on the first page the user reaches, but minified even a large site is smaller than jQuery or jQM so this shouldn't be a concern. The advantage is you are no longer loading all your JS for each page through AJAX each time the user navigates to a new page.
*note: now RequireJS can make this even more manageable
Jquery mobile gets pages via AJAX and adds their content to the current page.
I saw some notices about changing the page title to the incoming one, so they are (planning?) accessing the head, but at the moment jquery mobile doesn't seem to load external js when loadin a page.
More importantly - if you use $(document).ready() it will not be triggered, because it was AJAX
I'm just trying to set up an input with datepicker and I'm getting the following error: "Object doesn't support this property or method".
I downloaded the JQueryUI without a theme and there is my head section of the master page:
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.4.1.min.js" type="text/javascript" />
<script src="/Scripts/jquery-ui-1.8.5.custom.min.js" type="text/javascript" />
<asp:ContentPlaceHolder ID="ScriptContent" runat="server" />
After that, I created an input text inside a partial view (that remains inside a view):
<input type="text" id="txtDataIda" />
And at the beggining of this partial view:
$(function() {
$("#txtDataIda").datepicker();
});
When I open the page, the error is shown and the datepicker won't work.
I suppose I must be doing something wrong since I've never got the chance to work with JQueryUI before.
Thanks in advance!
You should go to http://jqueryui.com/download and build a custom download with the features that you want. Then, just reference the 2 files (jquery-1.4.2.js, jquery-ui-1.8.5.custom.min.js) in the "js" folder and not all of the files in the "development-bundle" folder. Then, you don't have to worry about multiple files conflicting. I have a feeling that the .widget, .datepicker, and 1.8.custom files may be conflicting. But, if it's all in one custom file, then you don't have to worry about that.
Or if you're not using any other ui features, you could try referencing only the jquery-1.4.2.js, ui.core.js, ui.datepicker.js files to see if that works without conflict.
And, of course, double check that you've put the references in the correct master page that is being used.
Fixed!
The JQuery wasn't being loaded, because the script tag was self closing. When I changed it to , it worked, as bizarre as it seems.
Thanks!