AngularJs routing in single page structure [JQM-Single Page] - jquery-mobile

Currently i am doing routing in different pages and it will fine
angular.module('myApp',[]).config(function ($routeProvider, $locationProvider)
{
$locationProvider.html5Mode(true);
$routeProvider.
when("/",
{
templateUrl: "index.html"
}).
when("/foodscreen",
{
templateUrl: "addfood.html"
})
});
through this way everything is fine but now i am making application with AngularJs and JQuery-Mobile in single page structure so my question is that how i configure routing in single page structure
Single Page Structure Example
<body>
<div data-role="page" id="page1">
<div data-role="header">
<h1>Welcome To My Homepage</h1>
</div>
<div data-role="content">
<p>I Am Now A Mobile Developer!!</p>
</div>
<div data-role="footer">
<h1>Footer Text</h1>
</div>
</div>
<div data-role="page" id="page2">
<div data-role="header">
<h1>Welcome To My Homepage</h1>
</div>
<div data-role="content">
<p>I Am Now A Mobile Developer!!</p>
</div>
<div data-role="footer">
<h1>Footer Text</h1>
</div>
</div>

Here's how I'm doing it in backbonejs. Samples are in coffee script. First you need to tell jqm to not listen for hash changes:
$(document).on "mobileinit", ->
# Prevents all anchor click handling including the addition of active button state and alternate link bluring.
$.mobile.linkBindingEnabled = false
# Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false
$.mobile.ajaxEnabled = false;
$.mobile.pushStateEnabled = false;
Sample route config in backbone:
routes:
"": "home"
"home": "home"
home: ->
$.mobile.loading "show"
currentView = new HomeView(
el: "#home"
model: new HomeModel()
)
# render the page... view is using underscorejs for applying templates
currentView.render()
# need to apply jqm styles...
$(currentView.el).trigger('create');
# now use jqm to change the page
$.mobile.changePage "#" + currentView.el.id,
reverse: false
changeHash: false
The routing part is specific to backbonejs. Here is a link that does something similar http://coenraets.org/blog/2012/03/using-backbone-js-with-jquery-mobile/. I had problems when I removed the page on the pagehide event. I think the more elegant approach was to simply use the trigger('create') method to get the jqm markup back on the page. Hope this helps!

Related

Use external panel from dynamically injected page

A new thing in version 1.4.0 alpha 2 of jQuery-Mobile is that panels no longer have to be inside the page that uses them. Instead, external panels can be siblings to the pages.
This works fine with static pages:
<div id="panel" data-role="panel" data-theme="b" data-position="left"
data-display="push">
<h3>This is a panel</h3>
</div>
<div data-role="page" id="staticPage">
<div data-role="header" data-position="fixed">
Panel
<h1>Static page</h1>
</div>
<div data-role="content">
<div class="content-primary">
Go to dynamic page
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#panel').panel();
});
</script>
However, when I generate and inject a page dynamically, the link to the panel no longer works as it is supposed to:
<script type="text/x-template" id="dynamicPageTemplate">
<div data-role="page" id="staticPage">
<div data-role="header" data-position="fixed">
Panel
<h1>Dynamic page</h1>
</div>
<div data-role="content">
<div class="content-primary">
<a href="#staticPage" data-role="button" data-inline="true">
Go to static page
</a>
</div>
</div>
</div>
</script>
<script type="text/javascript">
$(document).bind("pagebeforechange", function (e, data) {
if (typeof data.toPage === "string") {
var url = $.mobile.path.parseUrl(data.toPage);
if (url.hash.search(/^#dynamicPage$/) !== -1) {
$('#dynamicPage').remove();
var template = $("#dynamicPageTemplate").html();
var $page = $(template);
$page.attr('id', 'dynamicPage');
$('body').append($page);
$page.page();
$.mobile.changePage($page, {changeHash: false});
e.preventDefault();
}
}
});
</script>
When I click the "Panel" button in header of the dynamic page, the URL changes to …#panel and nothing is shown. I suspect that jQuery-Mobile tries to show the panel as a page rather than a panel. Am I doing something wrong, or is this a bug?
Fiddle with complete example
jQuery Mobile 1.4 panel (and a lot of other widgets) implementation still don't work correctly. Several new components are not even implemented yet. Not to mention, demo site was not updated since they announced alpha version 1.
Let me get back to pane implementation. It is still under heavy development. Any panel inner content (except buttons) is not properly styled. Just add a listview and see a final result.
Only thing you can do is wait for RC1 versions, or maybe just maybe first beta version (but I wouldn't hold my breath for the beta release).

Dynamic listview not loading until refresh

I'm using JS render to create dynamic pages in Jquery Mobile for my Phonegap app. The problem however is that the listview isn't loaded until the page is refreshed. Clearly that's not what I want and in another app I used the exact same technique and the listview is loaded immediately. Thing is that there's no difference between the two, so I have no idea why it isn't working in this one.
Here's my script for loading the pages:
<script src="jquery/jsrender.min.js"></script>
<script type="text/javascript">
$(document).on('pageinit', '#kunstwerken_exp1', function (event, ui) {
var $page = $(event.target);
$.ajax({
dataType:"json",
url:"json/exp1_index.js",
success:function(data, textStatus, jqHXR){
for( var x = 0; x < data.length; x++){
//create valid unique IDs for each page.
data[x].id = data[x].link.replace("?","").replace("=","").replace("#","");
}
console.log("success:");
console.log(data);
$("#templateDropPoint").html($("#template").render(data));
$("#templateDropPoint").listview("refresh");
$("body").append($("#pagetemplate").render(data));
},
error:function(jqXHR, textStatus, errorThrown ){
console.log(textStatus+ " "+ errorThrown);
}
});
});
</script>
This is the HTML:
<div data-role="page" id="kunstwerken_exp1" data-url="kunstwerken_exp1">
<div data-role="content">
<ul data-role="listview" id="templateDropPoint"></ul>
</div><!-- /content -->
</div>
<script id="template" type="text/x-jsrender">
<li>
<a href="#{{>id}}">
<img src={{>img}} />
<h5><b>{{>naam}}</b></h5>
<h6>{{>kunstwerk}}</h6>
</a>
</li>
</script>
<script type="text/x-jsrender" id="pagetemplate">
<div data-role="page" id="{{>id}}">
{{if pagina}}
<div data-role="content">
<h1>{{>naam}} ({{:pagina.nationaliteit}})</h1>
<h2>{{:pagina.kunstwerk}}</h2>
<em>{{:pagina.onderschrift}}</em>
<div class="ui-grid-a my-breakpoint">
<div class="ui-block-a">
<div class="koloma">
<div class="callbacks_container">
<ul class="rslides">
<li id="callbacks1_s0">
<img src="{{:pagina.afbeelding1}}" alt=""><p class="caption">{{:pagina.onderschrift1}}</p>
</li>
</ul>
</div>
{{if pagina.videooff}}
<ul class="tabs">
<li><img src="images/video.png"/></li><br>
</ul>
{{/if}}
</div>
</div>
<div class="ui-block-b">
<div class="kolomb">{{:pagina.tekst}}</div>
</div>
</div>
</div>
{{/if}}
</div>
</script>
To understand this situation you need to understand how jQuery Mobile works. It uses AJAX to load other pages.
First page is loaded normally. Its HEAD and BODY is loaded into the DOM, and they are there to await other content. When second page is loaded, only its BODY content is loaded into the DOM. To be more precise, even BODY is not fully loaded. Only first div with an attribute data-role="page" will be loaded, everything else is going to be discarded. Even if you have more pages inside a BODY only first one is going to be loaded. This rule only applies to subsequent pages, if you have more pages in an initial HTML all of them will be loaded.
That's why your listview is show successfully only after a page refresh.
Here's an official documentation: http://jquerymobile.com/demos/1.2.0/docs/pages/page-links.html
Unfortunately you are not going to find this described in their documentation. Ether they think this is a common knowledge or they forgot to describe this like my other topics. (jQuery Mobile documentation is big but lacking many things).
I have another ANSWER that discusses this problem. Solutions and working examples can be found there.

How to inject the same panel into multiple pages using jquery mobile

jQuery Mobile 1.3.1 has a very nice sliding panel feature, but the panel code must be placed within the same page it's used on.
I'm working on an app that needs to have the same panel on many pages. Instead of replicating code is there a way to dynamically inject the panel into these pages so that it will still retain the jqm panel functionality?
jQuery Mobile >= 1.4
Solution one:
Use an External panel that can be accessed from any page, this is in case you want to have the same panel contents in all pages.
Append panel to $.mobile.pageContainer once only on pagebeforecreate and then enhance the panel using $(".selector").panel().
var panel = '<div data-role="panel" id="mypanel" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.prepend(panel);
$("#mypanel").panel();
});
Add button to open the panel in each header (or wherever you want).
Note: When using External Panel data-theme should be added to panel div, as it doesn't inherit any styles/theme.
Demo
Solution two:
If you wish to do changes to panel before appending it, based on number of pages in DOM, add panel to each one with a different ID and a button to open that panel.
Note that you don't need to call any kind of enhancement, because you're adding panels on pagebeforecreate. Hence, panels will be auto-initialized once page is created.
var p = 1,
b = 1;
$(document).one('pagebeforecreate', function () {
$.mobile.pageContainer.find("[data-role=page]").each(function () {
var panel = '<div data-role="panel" id="mypanel' + p + '" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
$(this).prepend(panel);
p++;
});
$.mobile.pageContainer.find("[data-role=header]").each(function () {
var panelBtn = ''
$(this).append(panelBtn);
b++;
});
});
Demo
Note: Make sure you use .one() not .on(), if you use the latter, panels will be added whenever a page is created.
jQuery Mobile <= 1.3
You can do it this way, using pagebeforecreate event and by checking if there is no Panel added already. Keeping in mind that panels markup should always be placed before [data-role=header] that's why I used .before().
There is no need to call any enhancement method since panels are added on pagebeforecreate. They will be initialized during that event.
Demo
Your panel
var panel = '<div data-role="panel" id="mypanel" data-position="right" data-display="push"><h1>Panel</h1><p>stuff</p></div>';
Add panels dynamically
$(document).on('pagebeforecreate', '[data-role=page]', function () {
if ($(this).find('[data-role=panel]').length === 0) {
$('[data-role=header]').before(panel);
}
});
Update
There are two alternative methods to inject "External Panel" dynamically.
For some one coming across this issue, there is something called External Panels in JQuery Mobile 1.4+, which can make our life easier.
http://demos.jquerymobile.com/1.4.0/panel-external/
You can do something like this.
<div data-role="panel" id="mainPanel">
<!-- .... -->
</div>
<div data-role="page" id="page1" >
<!-- .... -->
</div>
<div data-role="page" id="page2" >
<!-- .... -->
</div>
You can also do one thing create a panel at the end or start of all pages and open that by Id and script code mentioned below.....its working fine for me.
$(function(){
$("#navigation").enhanceWithin().panel();
});
<div data-role="page" id="page1">
<div data-role="main" class="ui-content ui-body-a ui-responsive">
<div data-role="header">
<div data-role="navbar">
<ul>
<li class="">
</li>
</li>
</ul>
</div>
</div>
</div>
</div>
<div data-role="page" id="page2">
<div data-role="main" class="ui-content ui-body-a ui-responsive">
<div data-role="header">
<div data-role="navbar">
<ul>
<li class="">
</li>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="ui-panel ui-panel-position-left ui-panel-display-reveal ui-body-b ui-panel-animate ui-panel-open" data-role="panel" id="navigation" data-position="left" data-display="overlay" data-theme="b" data-dismissible="true" data-swipe-close="true">
<div class="ui-panel-inner">
<ul class="">
</ul>
</div>
</div>
In order for hashcoder his response to work you need to initialize the external panel. Also add .enhanceWithin() to make listviews etc render properly within the panel.
Als add a data-rel=... attribute to the link via which you want to open the external panel.
<script>
$(function () {
$("div[data-role='panel']").panel().enhanceWithin();
});
</script>
<div data-role="panel" id="mainMenu">
<!-- .... -->
</div>
<div data-role="page" id="page1" >
Open main menu panel
<!-- .... -->
</div>
<div data-role="page" id="page2" >
Open main menu panel
<!-- .... -->
</div>

how to prevent jquery UI ajax tabs send request back to server endlessly in rails 3?

I got a issue like this:
I am using Rails 3.2.9 and jqueryUI 1.9.0
I had a tabs UI and use ajax for each tab.
the html and Javascript code is like this:
<!-- index.html.erb -->
<div id="tabs">
<ul>
<li>page1</li>
<li>page2</li>
</ul>
</div>
<!-- page1.html.erb-->
<p>this is page 1</p>
<!-- page2.html.erb-->
<p>this is page 2</p>
and in home.js:
$(document).ready(function () {
$( "#tabs" ).tabs();
});
so, when I start the server, and try to activate any tab, the front end will keeping send the requests back to server. does any one know what happened on this?
Thank you
Update
I change the home.js like this but still doesn't work:
$(document).ready(function () {
$( "#tabs" ).tabs({
beforeLoad: function( event, ui ) {
if ( ui.tab.data( "loaded" ) ) {
event.preventDefault();
return;
}
ui.jqXHR.success(function() {
ui.tab.data( "loaded", true );
});
}
});
});
I still can not find the reason why this happened. A big thank you if some one can figure it out.
Thank you!
Because you specify home/page1 and home/page2 in your href links, it will load them up each time you click on the relevant tab.
Instead you can load the pages up once in index.html.erb by rendering partials into your page. If you rename page1.html.erb to _page1.html.erb and page2.html.erb to _page2.html.erb you can change your code to:
<div id="tabs">
<ul>
<li>Page 1</li>
<li>Page 2</li>
</ul>
<div id="page1">
<%= render 'home/page1' %>
</div>
<div id="page2">
<%= render 'home/page2' %>
</div>
</div>
Edit
If you still want to load the pages dynamically when you click each tab but only once, then don't use partials - you can just use the cache option:
$( "#tabs" ).tabs({
cache: true
//some other options
});
Try this in your controler
respond_to do |format|
format.html { render :layout => false }
end
That prevented me to keep looping the requests.

ASP.NET MVC JQuery UI TAB - How to make post-back on each tab click. How to make it SEO friendy?

I am using jquery tab as given bellow. Clicking on each tab it make a AJAX call according to its href url. Problem is AJAX call is not SEO friendly. How i can make it SEO friendly? How to do a postback on each tab click and keep current tab as selected after postback. Also how to update url on each tab click i mean if user click on [SPECIFICATION] tab, after post back url should look like www.domnainname/cardetails/specification
I AM USING ASP.NET MVC 4.0.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.0/jquery-ui.min.js"></script>
<script type="text/javascript">
$(function ($) {
$('#example').tabs();
});
</script>
<div id="example" class="tabs" style="width: 698px;">
<ul style="list-style: none;">
<li>Overview</li>
<li>Specifications</li>
<li>Exterior</li>
<li><a href="/Version/Details?ID=#ViewBag.versionId&grpId=2" title="tabs-4" >Interior</a></li>
<li>Dimensions</li>
<li>Feature</li>
<li>Instrument Panel</li>
</ul>
<div id="tabs-1" style="width: 698px;">
This is Tab one
</div>
<div id="tabs-2">
</div>
<div id="tabs-3">
</div>
<div id="tabs-4">
</div>
<div id="tabs-5">
</div>
<div id="tabs-6">
</div>
<div id="tabs-7">
</div>
</div>
Thanks,
#Paul
Based on what you are trying to do I would suggest the following:
Replace href="/Your/links/address" with href="#corresponding-panel"
Add a 'data-link' attribute to house your url
Subscribe to tab's select event
$(".tabs").tabs({select:function(ui, event){
if(!$(event.panel).hasClass('loaded')){
var linkURL = $(ui.currentTarget).attr('data-link');
//Ajax load has happend
if(linkURL != undefined){
//USE the 'linkURL' variable in place of '/echo/json'
$.ajax({
url: "/echo/json" ,
success:function(data){
$(event.panel).addClass('loaded').html("<h1>Some ajax content loaded from " + $(ui.currentTarget).attr('data-link') );
}
});
}
} }});​
Here is the JSFiddle example

Resources