Widget does not work - JQuery-mobile - jquery-mobile

I have the following collapsible widget in JQuery Mobile:
When I update the page(press F5), this widget does not work anymore as you can see in the picture:
Here is the code:
<div data-role="main" class="ui-content">
<div data-role="collapsible">
<h1>
What belongs to you but others use it more than you do? <br>(Click
for the answer)
</h1>
<p>Your name!</p>
</div>
</div>

You can try 'refreshing' the collapsible element:
$(document).on("pageinit", function () {
$("div[data-role='collapsible']").collapsible();
});
Hope helps!

Related

Multiple jQuery Mobile Collapsible: Having only one collapsible open at any time

Is there any way to make jQuery Mobile Collapsible elements close all other expanded collapsibles whenever you expand another collapsible element?
This is because in my collapsible list, I want only one item expanded at any time.
I checked the documentation, and theres an event that fires whenever you expand a collapsible. I included this in the <script> tag below. I'm not sure if this is the best way to do this or if its some other simple way to do it. And also I have no idea how to traverse the document to close all opened collapsibles.
<div data-role="collapsible">
<h3>Item 1</h3>
<p>Content 1</p>
</div>
<div data-role="collapsible">
<h3>Item 2</h3>
<p>Content 2</p>
</div>
<script>
$( ".selector" ).collapsible({
expand: function(event, ui) {
// code here to close all opened collapsibles, but i need input how to do this
}
});
</script>
The answer was simple.
jQuery Mobile will visually style a set of collapsibles as a group and will make the set behave like an accordion in that only one collapsible can be open at a time if you wrap the collapsibles in a div that has the attribute data-role="collapsibleset".
http://api.jquerymobile.com/collapsibleset/
Making the final code:
<div data-role="collapsible-set">
<div data-role="collapsible">
<h3>Item 1</h3>
<p>Content 1</p>
</div>
<div data-role="collapsible">
<h3>Item 2</h3>
<p>Content 2</p>
</div>
</div>

JQM 1.4 beta persistent navbar not keeping active state class for links

I'm facing an issue with the latest beta release of jQuery Mobile. I'm trying to implement a fixed persistent footer navbar, the persistent part is working but whenever I click a link and navigate to another page the ui-btn-active class is lost and no link appears selected.
Here's a demo fiddle that reproduces the issue: http://jsfiddle.net/koala_dev/DgdMg/2/
And here's the complete markup:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile.structure-1.4.0-beta.1.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile-1.4.0-beta.1.min.js"></script>
<script>
$(function() {
$("[data-role='header'],[data-role='footer']").toolbar();
$.mobile.window.triggerHandler("throttledresize");
});
</script>
</head>
<body>
<div data-role="header" data-position="fixed" data-id="header">
<h1>My fixed header</h1>
</div>
<div data-role="page" id="page-1">
<div data-role="content">
<p>Page 1 content goes here.</p>
</div>
</div>
<!-- /page -->
<div data-role="page" id="page-2">
<div data-role="content">
<p>Page 2 content goes here.</p>
</div>
</div>
<!-- /page -->
<div data-role="footer" data-position="fixed" data-id="footer">
<div data-role="navbar">
<ul>
<li>Page 1
</li>
<li>Page 2
</li>
</ul>
</div>
</div>
</body>
</html>
I followed the instruction from the demos in the docs (which don't seem to be complete) and placed the footer outside the page container. I tried adding .ui-state-persist to the first link and to both links but it didn't produce any effect and since even the demos are not working correctly I'm not sure how to proceed.
I would appreciate any insight on how to keep the ui-btn-active class for the clicked link.
Well, I found this on jQM updated demo page. Adding .ui-btn-active for external fixed toolbars depends on data-role=page's data-title attribute.
<div data-role="page" id="page-1" data-title="Page 1">
Navbar buttons text, should match data-title in order to determine which button should be updated with .ui-btn-active, as well as updating data-role=header title.
Demo
$(document).on("pageinit", function () {
$("[data-role='navbar']").navbar();
$("[data-role='header'], [data-role='footer']").toolbar();
});
// Update the contents of the toolbars
$(document).on("pageshow", "[data-role='page']", function () {
// Each of the four pages in this demo has a data-title attribute
// which value is equal to the text of the nav button
// For example, on first page: <div data-role="page" data-title="Info">
var current = $(this).jqmData("title");
// Change the heading
$("[data-role='header'] h1").text(current);
// Remove active class from nav buttons
$("[data-role='navbar'] a.ui-btn-active").removeClass("ui-btn-active");
// Add active class to current nav button
$("[data-role='navbar'] a").each(function () {
if ($(this).text() === current) {
$(this).addClass("ui-btn-active");
}
});
});
Source: http://view.jquerymobile.com/1.4.0-rc.1/dist/demos/toolbar-fixed-persistent/
I had this same issue for links in the navbar. It was very frustrating. I fired up firebug and debugged jqm. I ended up patching the jquery mobile code like so:
In jquery.mobile-1.4.0.js
From:
$navbtns.removeClass( $.mobile.activeBtnClass );
activeBtn.addClass( $.mobile.activeBtnClass );
To:
if ( !($navbtns.filter( ".ui-state-persist" ) ) ) {
$navbtns.removeClass( $.mobile.activeBtnClass );
activeBtn.addClass( $.mobile.activeBtnClass );
}
I minified jqm here: http://jscompress.com/

ng-model on select in AngularJS + JQM works partly

For app based on AngularJS, JQuery Mobile and JQuery Mobile Angular Adapter.
When i set ng-controller on tag with data-role="page", ng-model on select tag works perfectly:
<body ng-app>
<div data-role="page" id="product" ng-controller="Controller">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print()">print</button>
http://jsfiddle.net/ilya7u/Ddt7G/
When ng-controller present in body tag, variable associated with select tag through ng-model remains unchanged:
<body ng-app ng-controller="Controller">
<div data-role="page" id="product">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
http://jsfiddle.net/ilya7u/qgbj2/
Why and how i can fix it? I want to use one controller in app with many pages!
including the ng-app in the html of your page will solve the problem
try
<html ng-app="myModule">
<body ng-controller="Controller">
<div id="product" >
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print()">print</button>
</div>
</div>
</body>
</html>
and change the controller to
var myApp = angular.module('myModule',[]);
myApp.controller('Controller', function($scope) {
$scope.colors = ['red', 'black', 'white'];
$scope.color = $scope.colors[0];
$scope.Print = function () {
alert($scope.color);
};
});
updated fiddle here http://jsfiddle.net/qgbj2/2/
So it looks like there are really two scopes here. The page has its own scope, but the Print is in the parent scope. I've updated the fiddle to show that the color does indeed change, but the $scope.color in Print does not: http://jsfiddle.net/qgbj2/6/
To remedy this particular situation, I would pass in the color to Print from the DOM:
<body ng-app ng-controller="Controller">
<div data-role="page" id="product">
<div data-role="content">
<select ng-model="color" ng-options="c for c in colors"></select>
<button ng-click="Print(color)">print</button>
</div>
</div>
</body>
A general solution for this multiple scope situation does not occur to me at the moment.

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>

JQueryUI - A Challenge perhaps?

I'm working on a website which requires a chunk of code, the nature of which is proving to greatly exceed my limited knowledge of JQuery. The structure of the site is as follows (not quite sure if this is optimally structured for what needs to be done with it, JQuery-wise):
<script>
$(function() {
$(".menutype,.contenttype").draggable({revert:true});
$(".content").droppable({accept:".menutype,.contenttype"});
$(".content").droppable({
drop:function(event,ui){
$(this)
$('div.content').attr('id', 'contenthover')
.find( "p" )
.html( "Droppped!" );
}
});
});
</script>
<body>
<div class="header"><p>///HEADER///</p></div>
<div class="container">
<div class="wrapper1">
<div class="wrapper2">
<div class="content">
<p>///CONTENT///</p>
</div><!-- END "content" -->
<div class="menuL">
<div class="menutype-container">
<div class="menutype"></div>
<div class="menutype"></div>
<div class="menutype"></div>
<div class="menutype"></div>
</div><!-- END "menutype-container" -->
</div><!-- END "menuL" -->
<div class="menuR">
<div class="contenttype-container">
<div class="contenttype"></div>
<div class="contenttype"></div>
<div class="contenttype"></div>
<div class="contenttype"></div>
</div><!-- END "contenttype-container" -->
</div><!-- END "menuR" -->
</div><!-- END "wrapper2" -->
</div><!-- END "wrapper1" -->
</div><!-- END "container" -->
<div class="footer"><p>///FOOTER///</p></div>
</body>
The basic premise is that once one of the "menutype" DIVs is dropped within the droppable area, a corresponding menu structure is revealed in the content DIV. Similarly, once dropped, "contenttype" shows the inline content within that menu.
At this point i'm stumped as to how I go about achieving this. My main problem is that I do not know how to differentiate the menu and content types within the .droppable, as I only know how to define which items it accepts, and not what to individually do with draggable items.
I'm not expecting someone to spit out the necessary code, but some pointers or examples would be greatly appreciated.
I see a lot of people try and use draggable/droppable when what they really need is sortable. Menus are usually unordered lists. Try converting your
<div class="menuL">
into
<ul class="menuL">
with all the
<div class="menutype"></div>
changed to
<li class="menutype"></li>
with this js code
$(".menuL").sortable({
items : 'li',
connectWith : '.menuR',
update : function(event, ui){
},
recieve : function(event, ui){
}
});
if you want to drag and drop between menus you could use common class for both ul elements

Resources