I have a two page application. Both pages have all content created dynamically on the client.
Problem is, if I go page A > page B > page A > page B, on the second+ visit, page B does not get enhanced by Jquery Mobile anymore, although pagecreate triggers correctly. I'm stuck with a page of un-enhanced markup.
I can't call create on the separate widgets of the page, because widgets will be of random type and because I cannot call create prior to initialization. After receiving this error I called pagecreate manually on the un-enhanced page, which fixed all widgets.
Problem is, how can I detect if the page has been enhanced by JQM? Because I don't want to call this on an already enhanced page.
So, seemingly easy question:
How can I test if a page has been enhanced by Jquery Mobile?
Thanks for inputs!
It is pretty simple.
In case you were using trigger('pagecreate') to enhance page markup then use this to check if page container has been enhanced:
$(document).on('pagebeforeshow', '#index', function(){
alert($.mobile.activePage.hasClass('ui-page'));
});
Live example: http://jsfiddle.net/Gajotres/HthYd/
In case you are using trigger('create') to enhance only page content div use this to check if content container has been enhanced:
$(document).on('pagebeforeshow', '#index', function(){
alert($.mobile.activePage.find('[data-role="content"]').hasClass('ui-content'));
});
Live example: http://jsfiddle.net/Gajotres/8jcGb/
Of course, this cases will work only in case you are enhancing whole page or whole content.
EDIT :
And here's a real live example with a dynamically added page: http://jsfiddle.net/Gajotres/8jcGb/
Related
Many aspects of my site are dynamic. I am using jquery.
I have a div which once the DOM is ready is populated using load().
Then if a button is clicked, using load() once again, this value is replaced by another value.
This kind of setup is common across my site. My homepage is essentially lots of dynamically loaded, refreshed, and changeable content.
What are the repercussions of this for SEO?
Ive seen sites where each page is loaded using load() and then displayed using the animation functions... It looks awesome !
People have posed this question before, but noone has answered it properly.
So any ideas? JQUERY AND SEO??
Thanks
EDIT
Very interesting points. I dont want to overdo my site with jaascript.. just where neccesary to make it look good - my homepage however is one place of concern.
So when the DOM is readY, it loads content into a div. On clicking a tab, this content is changed. I.E No JS, No content.
The beauty here for me is that, there is no duplicated code. Is the suggestion here that i should simply 'print' some default content, then have the tabs link to pages (with the same content) if JS is disabled. I.E sacrifice a little duplicate code for SEO?
As far as degrading goes, my only other place of concern is tabs on the same page.. I have 3 divs, all containing content. On this page two divs are hidden until a tab is clicked. I used this method first before i started playing with JS. Would it perhaps be best to load() these tabs, then have the tab buttons link to where the content is pulled from?
Thanks
None of the content loaded via JavaScript will be crawled.
The common and correct approach is to use Progressive Enhancement: all links should be normal <a href="..."> to actual pages so that your site "makes sense" to a search spider; and the click() event overrides the normal functionality with load() so normal users with JavaScript enabled will see the "enhanced" version of your site.
If your content is navigable when JavaScript is turned off, you'll be a good ways toward being visible to search engines.
Note that search engine crawlers won't be submitting any forms on your site, so if you have any or elements that are meant to be navigating between your site's content pages, that content is not navigable by search engines.
Here is a guidelines how to make Google to crawl content loaded with ajax: http://code.google.com/web/ajaxcrawling/docs/getting-started.html
I use jquery load() asynchronous page load. It greatly improves user experience, but not seo-friendly. Here's the only solution I have found so far:
On first load I do not use jquery load() and try to write cookie with javascript.document.cookie = 'checkjs=on';
On next page load if php script finds this cookie it means that javascript is enabled and jquery load() can be used. If there's no such cookie then javascript is off (probably spider came), so jquery load() is not used.
if (!$_COOKIE['checkjs'] || $_COOKIE['checkjs']!='on'){echo 'js is off, hello Google!'; } else {echo 'js is on, can use jquery load';}
This way I can be sure that most of users can benefit from asynchronous page blocks load, exept for the very first load. And spiders get all content too.
In your case you could just load the same page with new parameter that makes another tab active. Spider is gonna be happy.
Does anyone know the best place to add the HTML code for jQuery Mobile pages that have been dynamically generated?
I have been adding them to the end of the <body>, however, this is causing problems with other jQuery mobile pages.
I have tried adding the jQuery Mobile pages into a div at the end of the page, however, their ids are no longer accessible via hrefs.
Link to Code: http://jakeserver.com/Apps/BostonLandmarks/B11/index.html
Any ideas?
I recommend you move all script within the individual page divs to a global script tag and then run that code within a pagecreate event of the page e.g.:
$(document).on('pagecreate','#landmarks', function(){
function setNewActiveTab(newTab){
$(".LandmarksTab").removeClass("ui-btn-active");
$(".LandmarksTab").removeClass("ui-btn-active");
$(".MoreTab").removeClass("ui-btn-active");
$(newTab).addClass("ui-btn-active");
}
assembleRows(landmarksArray);
assembleLandmarkPages(landmarksArray);
determineMapScreen();
});
Here is a working jsFiddle based on your code.
This will ensure that the code runs at the correct time with respect to jQM's page creation/enhancement.
I have a jQueryMobile application with multiple single-pages, linked together.
Some of these pages use common javascript files. So I currently import those javascripts only within pages that need them. For example:
Page A -> include fileutils.js and has a link to Page B
Page B -> include fileutils.js
The user clicks on Page B from Page A. Is there the risk of importing fileutils.js multiple time and execute its code multiple times too?
Thanks in advance
You don't need to be worry. Let me explain you how jQuery Mobile works.
What you have is called multi HTML page template. In this case only initial HTML can have more then one data-role="page" page inside, every other subsequent page can have only one data-role="page" page inside.
One first page is initialized it is fully loaded into the DOM. That HTML page becomes a skeleton for a future page loading. Because it is fully loaded it can hold more then one data-role="page" page inside.
When next page is initialized jQuery Mobile will strip everything and load only data-role="page" content. Everything else is going to be discarded, including the HEAD content. Even more only first data-role="page" page is going to be loaded, which means you can't have more then one data-role="page" page inside.
This means that if you have a custom javascript inside subsequent pages it must be inside data-role="page" div, otherwise jQuery Mobile will discard it.
This works in case standard AJAX loading is on, which is a default state. If AJAX loading is turned off jQuery Mobile will load pages like they are normal pages and every subsequent page will replace previous page in the DOM.
Regarding your other question, because of this architecture same js files will never initialize more then once. But there's another problem you will need to be careful with event binding. Because of this specific architecture events can be bind more then once. So you will need to use pageinit page event to initialize your javascript per page. There are several more solutions to this problem but I will describe them only if you want.
I'm having a jQuery mobile page with JavaScript inside. The problem is the JavaScript doesn't work unless the page is refreshed. Here is my code:
jQuery(function($) {
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
To understand this problem you need to understand how jQuery Mobile works.
Your first problem is point where you are trying to initialize JavaScript. From your previous answers I can see you are using several HTML/ASP pages and all of your javascript is initialized form the page <head>. This is the main problem. Only the first HTML file should have JavaScript placed into the <head> content. When jQuery Mobile loads other pages into the DOM it loads only the <div> with a data-role="page" attribute. Everything else, including <head>, will be discarded.
This is because currently loaded page has a <head> already. No point in loading another pages <head> content. This goes even further. If you have several pages in a second HTML file, only the first one is going to be loaded.
I will not try to invent warm water here so here are links to my other 2 answers discussing this problem. Several solutions can be found there:
Why I have to put all the script to index.html in jquery mobile (or in this blog article)
Link fails to work unless refreshing
There's more then enough information there to give you an idea what to do.
The basic solutions to this problem are:
Put all of your JavaScript into a first HTML/ASP file
Move your JavaScript into <body>; to be more precise, move it into a <div> with data-role="page". As I already pointed out, this is the only part of a page that is going to be loaded.
Use rel="external" when switching between pages because it will trigger a full page refresh. Basically, you jQuery mobile that the page will act as a normal web application.
As Archer pointed out, you should use page events to initialize your code. But let me tell you more about this problem. Unlike classic normal web pages, when working with jQuery Mobile, document ready will usually trigger before page is fully loaded/enhanced inside the DOM.
That is why page events were created. There are several of them, but if you want your code to execute only once (like in case of document ready) you should use the pageinit event. In any other case use pagebeforeshow or pageshow.
If you want to find out more about page events and why they should be used instead of document ready take a look at this article on my personal blog. Or find it here.
Your question isn't exactly overflowing with pointers and tips, so I'm going with the thing that immediately sprung to mind when I saw it.
Document ready does not fire on page change with jQuery Mobile, due to "hijax", their method of "ajaxifying" all the links. Try this instead...
$(document).on("pageshow", function() {
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
Try pageinit like this
$(document).delegate("body", "pageinit", function() { // Use body or page wrapper id / class
var url = window.location.search.substring(1);
$('#mydiv').load('real_news.asp?' + url);
});
seems like nothing ever worked for me. Tried many different fixes, but i made the site too messy, that even position of certain javascript files wouldn't make the site work. Enough talk, here is what i came up with.
// write it in head at top of all javascripts
<script type="text/javascript">
$(document).ready(function() {
// stops ajax load thereby refreshing page
$("a,button,form").attr('data-ajax', 'false');
// encourages ajax load, hinders refresh page (in case if you want popup or dialogs to work.)
$("a[data-rel],a[data-dialog],a[data-transition]").attr('data-ajax', 'true');
});
</script>
I'm doing some tests with jQuery Mobile and trying to figure out how to setup an application and its various pages. Ideally, I would like the framework to load the pages with transitions but still keep each pages clearly separated. In particular, it seems that a page loaded via Ajax doesn't "clear" the JavaScript or CSS of the previous page:
Example 1 - JavaScript
For instance, if I have something like this in page1.html:
<script>
setInterval(function() {
console.info('Interval' + (new Date()));
}, 1000);
</script>
Then if I load page2.html, the interval is still running. If I go back to page1, a new interval is started so there are now two intervals running, and 3 and 4, etc. every time I go back to page1.
Example 2 - CSS
Another issue is with styling. Let's say two developers, working independently on two different pages, create an element my-element. In page1, this element is styled:
<style>
#my-element {
color: red;
}
</style>
<span id="my-element">This one is red</span>
in page2, the element is not styled:
<span id="my-element">This one has no style</span>
Again, if I go to page1.html first and then page2.html, my-element ends up being red, even though it wasn't styled in page2.html.
So I guess I have two questions:
Currently it seems that jQuery Mobile approach to loading pages is not scalable at all. CSS, JS created on one page, carry on to the next. So is there any way to make jQuery Mobile load pages "cleanly". i.e. completely deleting everything from the previous page so that bits of JS or CSS don't affect the next page?
If not, what is the correct way to work with multiple pages, in a scalable way, in jQuery Mobile?
the behavior you are describing is what makes JQM work. your DOM persists (including js and css of the first page you load), until you load a page using 'data-ajax=false' or 'rel=external' which will do a regular page load (no ajax).
By loading the page via ajax you will mostly have at least two pages in the DOM - the page you started on (like an anchor page) and any other page you are loading via ajax (which gets removed once the next page is loaded).
this approach allows to have transitions and other functions which you can share across pages.
still you can easily target specific pages with js/css. I'm always runnimg a controller.js file in my applications, which handles page specific things by binding to any of the JQM events (pagebeforeshow, pageshow...). Likewise for page specific css, just use the page id attribute to make css page specific.