Coder Social home page Coder Social logo

jquery-mobile-angular-adapter's Introduction

PROJECT IS IN MAINTENANCE MODE.

NEW PROJECT angular-jqm#

Newer versions of jqm will be integrated using angular-jqm and not this project.

Background: See the post in the angular mailing list: https://groups.google.com/d/msg/angular/qG8YRwVaL_g/zgKAvaArmB0J

Build Status #JQuery Mobile Angular Adapter

##Description

Integration between jquery mobile and angular.js. Needed as jquery mobile enhances the pages with new elements and styles and so does angular. With this adapter, all widgets in jquery mobile can be used directly in angular, without further modifications. Furthermore, this adapter also provides special utilities useful for mobile applications.

If you are interested in how to build mobile web apps with this adapter, have a look at the german book Mobile Web-Apps mit JavaScript.

##Dependencies

  • angular 1.0.6
  • jquery 1.8+
  • jquery mobile 1.3.1 Final

##Examples

##Reporting Issues

  • Issues can be reported at the Github project.
  • Please provide a JS-Fiddle or a Plunk. A plunk is great if you have external jqm pages in your example.

##Usage Note: The directive ng-app for the html element is required, as in all angular applications.

Plain

Include this adapter after angular and jquery mobile (see below).

<html ng-app>
<head>
    <title>MobileToys</title>
    <link rel="stylesheet" href="lib/jquery.mobile.css"/>
    <script src="lib/jquery.js"></script>
    <script src="lib/jquery.mobile.js"></script>
    <script src="lib/angular.js"></script>
    <script src="lib/jquery-mobile-angular-adapter.js"></script>
</head>

With requirejs 2.x

Create a index.xhtml file like the one below:

<html ng-app>
<head>
    <title>MobileToys</title>
    <link rel="stylesheet" href="lib/jquery.mobile.css"/>
    <script src="lib/requirejs.js" data-main="main.js"/>
</head>
<body>
   ... your jqm pages ...
</body>
</html>

And a main.js file with the following content:

require.config({
  shim:{
    'angular':{ deps:['jquery'], exports:'angular'}
  }
});
function tryHoldReady() {
  if (!tryHoldReady.executed && window.jQuery) {
    window.jQuery.holdReady(true);
    tryHoldReady.executed = true;
  }
}
tryHoldReady();
require.onResourceLoad = tryHoldReady;
require([
  "jquery",
  "jquery-mobile-angular-adapter",
  ... // your controllers, angular modules, ...
], function (jquery) {
  jquery.holdReady(false);
});

Notes:

  • This assumes that all libs are in the root folder of your webapp. To put them into a subfolder like lib use the paths argument in the call to require.config (e.g. paths: {angular: lib/angular}, ...)
  • The libraries jQuery, jQuery Mobile and the adapter are already AMD modules. Only angular is not, which is why we need a shim config for it.
  • We simulate a later load event of the document by using jQuery.holdReady, by which we wait until all modules have been loaded. This is needed as the normal load event may occur before all modules have been loaded by requirejs. Note that this functionality was already included in requirejs 1.x, but no more in requirejs 2.x.
  • Usage of manual bootstrap of angular does not work well with jquery-mobile, as jquery-mobile relies on the jQuery ready event to be fired at the right time.

Versioning

The adapter always takes the major and minor version of jquery mobile, e.g. if you want to use jquery mobile 1.3.x, use the adapter version 1.3.x. The patch version is assigend incrementally.

Build

Directory structure

  • compiled: The created versions of the adapter.

    • jquery-mobile-angular-adapter.js: The adapter.
    • jquery-mobile-angular-adapter-standalone.js: Version of the adapter that includes jquery, angular and jquery mobile. If you want to do something during the initialization of jquery- mobile, use the following callback: window.mobileinit = function() { ... }
  • src: The main files of uitest.js

  • test/ui: The ui self tests for uitest.js

  • test/unit: The unit tests of uitest.js

Install the dependencies: npm install.

Build it: ./node_modules/.bin/grunt

Auto-Run tests when file change: ./node_modules/.bin/grunt dev

##Navigation and routes

The adapter integrates angular routes with jquery mobile:

  • We set $locationProvider.html5Mode(true), $locationProvider.hashPrefix('!') and add the tag <base href="{address of your html file}"> to your header.

    • See the angular docs on details about this!
    • By this, we are compatible to the default jquery mobile url layout, e.g. links like <a href="somePage.html"> are possible and do not reload the whole page but use AJAX and result in modern browsers in a url of /somePage.html (via history API).
    • The <base> tag is created by jquery mobile. For routes, this makes all routes relative to the current page. E.g. if your page is under /test/index.html, and you want a route to /test/somePage.html then your route would be $routeProvider.when(/somePage.html`).
  • Default routing: If no route is defined, the default jquery mobile url handling applies:

    • Navigation to a hash shows the page whose id is the same as the hash, e.g. <a href="#somePage">.
    • Navigation to a normal page loads that page using ajax and then navigates to that page, e.g. <a href="somePage.html">
  • You can set the special property jqmOptions on routes, e.g.

      $routeProvider.when('/somePage', {
          templateUrl:'someTemplate.html',
          jqmOptions: { transition: 'flip' }
      });
    

    Those properties are directly passed to $.mobile.changePage. For a documentation of the available options have a look at the jquery mobile documentation.

  • You can set the special property onActivate in routes. If this is set, it will be evaluated in the scope of the page to which the route navigates to, before the pagebeforeshow event.

    This expression can also use the properties from $routeParams and $route.current.locals, which are calculates by the resolve entry of the route. E.g.

      $routeProvider.when('/somePage/:name', {
          templateUrl:'someTemplate.html',
          onActivate: 'someFn(someParam, name)',
          resolve: {someParam: function() { return 'hello'; }}
      });
    
      function SomePageController($scope) {
         $scope.someFn = function(someParam, name) {
            expect(someParam).toBe('hello');
         }
      }
    
  • relative links in pages are treated relative to the templateUrl of the route, not the route path. E.g. given the mapping

      $routeProvider.when('/someFolder/page1.html', { templateUrl:'#page1' });
      $routeProvider.when('/someFolder/page2.html', { templateUrl:'/someTemplateFolder/page2.html' });
    

    Page1 is embedded page, and therefore, all links within that page are relative to the initial url of the app. Page2 is an external page and all relative links in that page are relative to the folder /someTemplateFolder.

  • Please also look at the extensions to the $location service for controlling history and changing route params for just one route call.

Default routing: basePath+$location.url()

  • E.g. for a page /somePath/somePage.html and location.url()=='/page1' this results in /somePath/page1.
  • To be compatible to plain jquery mobile the adapter creates a default routing for all urls that are not mapped by other routes.
  • If a document contains the link <a href="somePage"> and the user clicks on that link, angular updates $location.url to /somePage. However, in plain jquery mobile, this should load the page /somePath/somePage. This is why we append the basePath to the $location.url().

Notes:

  • Using $.mobile.changePage directly is not recommended. It still works, but it will no more update the browser location.href.

  • If you don't want $locationProvider.html5Mode you can disable it. By this, you get hash urls like /index.html#!/somePath... back. E.g.

         module.config(function($locationProvider) { $locationProvider.html5Mode(false) }));
    
  • Internally, we use jquery mobile to load the pages and do the transition between the pages. By this, we automatically support the prefetching and caching functionality for pages from jquery mobile (see their docs for details). E.g. use <a href="prefetchThisPage.html" data-prefetch> ... </a> in a parent page to prefetch a child page.

  • If you want to start an app directly on a subpage, use the following url:

    • For an external page that should be loaded using ajax: index.html#!/somePage.html
    • For an internal page that is also contained in the index.html: index.html#/!index.html#someOtherPage (yes, this url contains 2 hashes). If you are sure that all browsers that you use support the new history API, you can also use the url index.html#someOtherPage to start at an internal page.

Restrictions:

  • controllers on routes are not supported. Please use ng-controller within the page to be loaded for this or the onActivate function on routes. The reasoning behind this is that some pages of jquery mobile are local pages in the same document as the main page and others are loaded using ajax. However, the pages in the same document are compiled at the same time the main page is compiled. Furthermore, by supporting the page cache of jquery mobile assigning a controller would also not be possible. To pass data via routes just let your controllers examine the current route using the $route and $routeParams service.
  • Routes with a templateUrl must point to a full jquery mobile page. Loading parts of jquery mobile pages is not supported.
  • The ngView directive cannot be used as jqm pages need to be inserted at a special place in the DOM. However, the adapter takes care of the normal ngView handling and inserts the pages at the right place.
  • There needs to be an initial page in the main document of the application. I.e. a <div data-role="page"> within that html file that also includes angular and jqm. All other pages can then be included using routes with a templateUrl property.

##Scopes Every page of jquery mobile gets a separate scope. The $digest of the global scope only evaluates the currently active page, so there is no performance interaction between pages.

For communicating between the pages use the ngm-shared-controller directive (see below).

##Directives, Filters and Services

Directive ngm-shared-controller

Syntax: <div ngm-shared-controller="name1:Controller1,name2:Controller2, ...">

Mobile pages are small, so often a usecase is split up into multiple pages. To share common behaviour and state between those pages, this directive allows shared controllers.

The directive will create an own scope for every given controllers and store it in the variables as name1, name2, .... If the controller is used on more than one page, the instance of the controller is shared.

Note that the shared controller have the full scope functionality, e.g. for dependecy injection or using $watch.

Event-Directives of jQuery Mobile

The following event directives are supported (see http://jquerymobile.com/demos/1.2.0/docs/api/events.html):

  • ngm-tap,taphold,
  • ngm-swipe,ngm-swiperight,ngm-swipeleft,
  • ngm-vmouseover,ngm-vmouseout,ngm-vmousedown,ngm-vmousemove,ngm-vmouseup,ngm-vclick,ngm-vmousecancel,
  • ngm-orientationchange,
  • ngm-scrollstart,ngm-scrollend,
  • ngm-pagebeforeshow,ngm-pagebeforehide,ngm-pageshow,ngm-pagehide

Usage: E.g. <a href="#" ngm-swipeleft="myFn()">

Directive ngm-if

The directive @ngm-if allows to add/remove an element to/from the dom, depending on an expression. This is especially useful at places where we cannot insert an ng-switch into the dom. E.g. jquery mobile does not allow elements between an ul and an li element.

Usage: E.g. <div ngm-if="myFlag">asdfasdf</div>

Service $history

Methods and Properties:

  • $history.go(relativeIndex): This will directly call window.history.go(relativeIndex).
  • $history.goBack(): Calls $history.go(-1).
  • $history.urlStack: This contains the list of visited urls
  • $history.activeIndex: This defines the currently active index in the urlStack
  • $history.removePastEntries(number): This will remove the given number of history entries before the current entry. The current entry stays current. Used when leaving dialogs, or for $location.back(). Note: This does not fire any $locationChange* events.

Service $location (extensions)

  • $location.routeOverride(someOverride): By this, you can override route properties only for the next routing. This is useful e.g. for passing special parameters to the onActivate expression. The following properties of routes can be overridden:

    • jqmOptions: Options to give to $.mobile.changePage of jquery mobile (e.g. transition, ...)
    • locals: the resolved functions from the resolve hash in a route.
    • onActivate: the expression to evaluate on the target page with the locals.

    E.g.

       $location.routeOverride({
         locals: {someKey: 'someValue'},
         jqmOptions: {transition: 'pop'}
       });
       $location.path('/someRoutePath');
    
       function SomePageController($scope) {
          $scope.someActivateFn = function(someKey) {
             expect(someKey).toBe(someValue);
          }
       }
    
  • $location.backMode(): This will try to go back in history to the url specified by $location. E.g. if the navigation path to the current page is page1->page2->page3 and we then call $location.path('page1'); $location.backMode() this will go two steps back in history. Note that this is in analogy to the already existing angular method $location.replace.

Service $waitDialog

The service $waitDialog allows the access to the jquery mobile wait dialog. It provides the following functions:

  • show(msg, callback): Opens the wait dialog and shows the given message (if existing). If the user clicks on the wait dialog the given callback is called. This can be called even if the dialog is currently showing. It will the change the message and revert back to the last message when the hide function is called.
  • hide(): Restores the dialog state before the show function was called.
  • waitFor(promise, msg): Shows the dialog as long as the given promise runs. Shows the given message if defined.
  • waitForWithCancel(promise, cancelData, msg): Same as above, but rejects the promise with the given cancelData when the user clicks on the wait dialog.

Default messages are:

  • $.mobile.loader.prototype.options.textWithCancel: for waitForWithCancel. This is a new property.
  • $.mobile.loader.prototype.options.text: for all other cases, see the jquery mobile docs.

Filter paged: Paging for lists

Lists can be paged in the sense that more entries can be additionally loaded. By "loading" we mean the display of a sublist of a list that is already fully loaded in JavaScript. This is useful, as the main performance problems result from DOM operations, which can be reduced with this paging mechanism.

To implement this paging mechanism, the angular filter paged was created. For displaying a page within a list, simply use:

list | paged:'pagerId':12

This returns the subarray of the given array with the currently loaded pages.

Parameters:

  1. The first parameter is required and must be unique for every usage of the paged filter. It is the property name in the scope which stores the state of pagination for this filter usage, and also contains the function loadMore and hasMore (see below).

  2. If the second parameter is a number, it is interpreted as the pageSize. If this parameter is omitted, the default page size is used. This is by default 10, and can be configured using

    module(["ng"]).value('defaultListPageSize', 123);

For filtering and sorting the paged array, you can use filter chaining with the angular filters filter and orderBy, e.g.

list | filter:{name:'someName'} | orderBy:'name' | paged:'pagerId'

To show a button that loads the next page of the list, use the following syntax:

<a href="#" ngm-if="pagerId.hasMore" ngm-vclick="pagerId.loadMore()">Load More</a>
  • pagerId is the id used in the paged filter.
  • pagerId.hasMore returns a boolean indicating if all pages of the list have been loaded.
  • pagerId.loadMore() loads the next page into the list.

The following example shows an example for a paged list for the data in the variable myList:

<ul data-role="listview">
    <li ng-repeat="item in list | paged:'pager1'">{{item}}</li>
    <li ngm-if="pager1.hasMore">
        <a href="#" ngm-vclick="pager1.loadMore()">Load more</a>
     </li>
</ul>

Note: pagerId.cache stores the last result that was returns for a list | paged:'pagerId' expression. This can be used to check whether the paged list is empty, .. without refiltering the list.

Notes on the integration of some jqm widgets

widget collapsible

  • The attribute data-collapsed has bidirectional data binding, e.g.

      <div data-role="collapsible" data-collapsed="someProperty">...</div>
    

widget checkboxradio

  • using ng-repeat with a checkbox or radio button without a wrapper element can be done like the following:

      <label ng-repeat="l in [1,2]">
          {{l}}
          <input type="checkbox">
      </label>
    

widget popup

  • the jqm adapter does not change the url when a popup is opened/closed. This is due to the fact that the jqm adatper assumes that urls represent routings for pages, and not parts of pages.

  • The new attribute data-opened has bidirectional data binding for opening/closing the popup, e.g.

      <div data-role="popup" data-opened="someProperty">...</div>
    

widget panel

  • the jqm adapter does not change the url when a panel is opened/closed. This is due to the fact that the jqm adatper assumes that urls represent routings for pages, and not parts of pages.

  • The new attribute data-opened has bidirectional data binding for opening/closing the panel, e.g.

      <div data-role="panel" data-opened="someProperty">...</div>
    

widget slider in a <select>

  • jQuery Mobile does not yet support refreshing a slider widget when child <option> elements have changed. As a consequence, using <select data-role="slider"> with ng-options only uses the initial state of the ng-options collection. Chaning the ng-options collection will not update the widget.
  • ng-repeat is not supported on a <select data-role="slider"> yet, as jqm creates a sibling element to the select, instead of a wrapper (like in all other cases).

##Integrating custom jquery mobile plugins with angular

All integration work is done using the jqmNgWidget provider.

This will automatically create angular directives for all jqm widgets that are contained in $.mobile and use the jqm widget factory (e.g. $.mobile.dialog). If you want to specify a custom handler for a jqm directive, use the following pattern:

ng.config(["jqmNgWidgetProvider", function(jqmNgWidgetProvider) {
    jqmNgWidgetProvider.widget("somePlugin", ["jqmNgWidget", function(jqmNgWidget) {
        return {
            link: function(widgetName, scope, iElement, iAttrs, ngModelCtrl) {
                jqmNgWidet.createWidget(widgetName, iElement, iAttrs);
                // Do additional binding work...
            }
        }
    }]);
}]);

See src/main/webapp/widgetAdapters.js for more examples.

##Integration strategy

Jquery mobile has two kinds of markup:

  • Stateless markup/widgets: Markup, that does not hold state or event listeners, and just adds css classes to the dom. E.g. $.fn.buttonMarkup, which is created using <a href="..." data-role="button">
  • Stateful markup/widgets: Markup that holds state (e.g. event listeners, ...). This markup uses the jquery ui widget factory. E.g. $.mobile.button, which is created using <button>.

Integration strategy:

  1. We have a precompile phase: This is called before the angular compiles does it's work, i.e. before $compile is called, and before directive.template and directive.templateUrl is evaluated. Here, we trigger the jqm create and pagecreate event. Before this, we instrument all stateful jqm widgets (see above), so they do not really create the jqm widget, but only add the attribute jqm-create=<widgetName> and jqm-link=<widgetname> to the corresponding element. By this, all stateless markup can be used by angular for stamping (e.g. in ng-repeat), without calling a jqm method again, so we are fast. Furthermore, we have special handlers in the precompile phase for those jqm widgets that wrap themselves into new elements (checkboxradio, slider, button, selectmenu, search input), as the angular compiler does not like this. Finally, we also mark all jqm pages with the jqm-page attribute. This is needed as jqm pages are represented as data-role=page in the dom and angular does not allow to create directives that only match pages but not other jqm widgets.

  2. We have the directive ngmPage: This creates an own scope for every page. By this, we are able to disconnect the scope of the pages that are not visible right now. This is important for optimizing performance. This creates the jqm pages by calling element.page() in the pre link phase, however without the pagecreate event. By this, we only create the page instance, but do not modify the dom (as this is not allowed in the pre link phase). Furthermore, the page jqm widget instance is already available for the other widgets, which are created in the post link phase.

  3. We have the directive ngmCreate: This will create the jqm widgets in the post link phase. For widgets that wrap themselves into new elements this needs to be called for the wrapper, that was already created in the precompile phase. This is important as the jqm widgets do more DOM transformations during creations that the angular compiler does not like (e.g. the jqm widget <input type="checkbox>" enhances the sibling <label> element and wraps that element). By calling the widget during the post link phase of the wrapper element those DOM modifications are ok with angular.

  4. We have the directive ngmLink: Here we listen for changes in the model and refresh the jqm widgets when needed and vice versa. For elements that wrap themselves into new elements this will be called on the original element (e.g. the <input> for <input type="checkbox"> elements), in contrast to the ngmCreate directive.

  5. All together: This minimizes the number DOM traversals and DOM changes

    • We use angular's stamping for stateless widget markup, i.e. we call the jqm functions only once, and let angular do the rest.
    • We do not use the jqm create event for refreshing widgets, but angular's directives. By this, we prevent unneeded executions of jquery selectors.
    • We reuse the selectors in jqm for detecting which elements should be enhanced with which jqm widgets.

Ohter possibilities not chosen:

  • Calling the jqm "create"-Event whenever the DOM changes (see the jqm docs). However, this is very slow, as this would lead to many DOM traversals by the different jqm listeners for the "create"-Event.

Integration of jqm routing and angular routing:

  • We chose to use the angular routing, as it is very flexible and programmable, and it is easier to integrate jqm routing with angular routing and the other way around.

jquery-mobile-angular-adapter's People

Contributors

ajoslin avatar chrtho avatar jperl avatar kanakiyajay avatar markmyoung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jquery-mobile-angular-adapter's Issues

Styling problems for links in lists in 1.0.4

Hi,
links in lists appear sometimes blue and sometimes not:

  1. Clear the browser cache and visit the page below for the first time: The link appears in black text color.
  2. Click on the link and reload the page: The link appears in blue color.
  3. Click on the link and do not reload the page: A new link is added to the list (as intended), but the link is again in black text color.
  4. In contrast: If the list is built without ng:repeat, the link always appears in black text color.

Note for 3: Internally, the first a-tag gets an ui-link css class, but the second does not.

<div data-role="page" id="start" ng:init="data = {mylist:[1]}">
<div data-role="content">
    <ul data-role="listview" id="list">
        <li ng:repeat="l in data.mylist">
            <a href="#test2" ng:click="data.mylist=[1,2]">Test
            </a>
        </li>
    </ul>
</div>
</div>

slider does not update the model in 1.0.0rc1

Hello,

Thank you for a great adapter, I have started using it for a couple of things.

One issue I was having with is using the slider in jquery mobile

http://jsfiddle.net/nKGWD/3/

It updates the model when I adjust the text field, but does not update with the slider.

Does anyone have a way to fix this?

Thanks and regards
Brendan

Problem with require.js

The 1.0.6 version works when loaded from of index.html, but when loading with require.js, I get this:

Uncaught TypeError: Cannot set property 'globalScope' of undefined       (line 27706)
GET http://localhost:1234/adaptertest/jquery.js 404 (Not Found)
Uncaught Error: Load timeout for modules: jquery 
http://requirejs.org/docs/errors.html#timeout

$paged and list entry styling

Hi,
Given page-size 10, and a list with 11 entries, followed by a "load next page" button that also uses a "li" tag.
E.g.:

When I click on the button, the last entry updates it's data, however the jquery mobile list entry style is not updated.

Tobias

Changing element text with .text() breaks radio and text button rendering

This is the most hard to explain problem I had with rc2. I have a directive which I use to replace text with translations. In the jsFiddle http://jsfiddle.net/jupiter/hUtqV/5/ I have called this directive replace. The directive replaces attribute values with

<input type="button" replace="value" value="replace me" />

or the HTML element's text as in

<div replace>replace me</div>.

The el.text() which replaces the text breaks the rendering of the radio buttons if I have the replace directive in the enclosing div to replace the page title and at the same time in the radio button to replace the radio buttons text.

If I either remove replace="data-title" of the page element, the replace of the radio button or change jquery-mobile-angular-adapter-1.0.7-rc2.js to jquery-mobile-angular-adapter-1.0.7-rc1.js it works.

The button in the footer is always broken with the replace directive.

I have used jquery mobile 1.1.0 and AngularJS 1.0.0rc9.

ngm-if attribute does not refresh jQuery Mobile content

Attribute widget @ngm-if can be used for adding and removing elements from the DOM. An use case has been found in which element just added is not refreshed as jQM elements dynamically added need to, causing not enhanced elements to appear on screen.

The following example shows this effect:

http://jsfiddle.net/LucasG2000/Ev4AN/

This is the structure of the example and how to reproduce it:

  • A controller is created (TestController) which has an ItemCollection which will be used for feeding a jQM ListView.
  • Another field of this controller is called IDItemEditable. This field will be used as the condition in the ngm-if for putting a row in edit mode when it is clicked.
  • Initially IDItemEditable is null, causing that only content for read-only items is added to the DOM. These entries are enhanced by jQM as expected.
  • When one row is clicked, condition changes removing read-only items and adding content for editing the row
    • Expected result: New shown content is jQM enhanced.
    • Obtained result: New shown content is not jQM enhanced, rendering as normal HTML.
  • When save button is clicked, condition changes again inverting condition
    • Expected result: Rendering of new content enhanced again by jQM.
    • Obtained result: New shown content is not jQM enhanced again.

I suppose that a refresh method is missing somewhere.

Software versions used:

  • jQuery Mobile 1.1.0-rc2
  • jQuery 1.7.1
  • Angular JS 1.0.0-rc4
  • jQuery Mobile Angular Adapter 1.0.7-rc1

Best regards.

Nested Collapsibles

There's a bug on nested collapsibles.
Please, run this code:

<head>

    <title>jQuery Mobile Angular Adapter</title>

    <meta name="viewport" content="width=device-width, initial-scale=1"> 

    <link  rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css">

    <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>

    <script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>

    <script src="http://code.angularjs.org/1.0.1/angular-1.0.1.min.js"></script>

    <script src="https://raw.github.com/tigbro/jquery-mobile-angular-adapter/master/compiled/min/jquery-mobile-angular-adapter-1.1.0.js"></script>

</head>

<body>

    <div data-role="page">

        <div data-role="header">

            <h1>jQuery Mobile Angular Adapter</h1>

        </div>

        <div data-role="content">

            <div data-role="collapsible">

                <h3>Hello</h3>

                <p>World</p>

                <div data-role="collapsible">

                    <h3>Foo</h3>

                    <p>Bar</p>

                </div>

            </div>

        </div>

    </div>

</body> 

ng-model not respected inside of directive

I'm using a directive with an ng-model on it, but it is not updating the dom or the value when I update it. From below, I can change the ng-model to text or leave it with the huge parent expression, but neither seems to work.

Insight.module.directive('text', [function() {
return {
restrict: 'E',
scope: {
parameter: 'accessor'
},
template: '',
replace: true,
compile: function () {

        return function (scope, element, attrs) {
            var control = scope.parameter();

            if (control.DefaultValues && control.DefaultValues.length) {
                control.Value = control.DefaultValues[0];
                scope.text = control.Value;
            }
        }

    }
}

}]);

Images rendered by ng-repeat needs to be pre-cached.

For example, say you have 2 sets of images on a page. One that is
rendered normally, eg

<img src="alpha.jpg"> 

And another set that is rendered by ng-repeat: eg.

<ul ng-repeat="member in family_members"> 
        <li> 
                <img src="{{ member.image }}"> 
                <h3>{{ member.name }}</h3> 
                <p>{{ member.relationship }}</p> 
        </li> 
</ul> 

I have observed that

<img src="alpha.jpg">

and the text {{ member.name }} and {{ member.relationship }} are already present on the page as the page gets loaded. However, the images,

<img src="{{ member.image }}">

take a short while (probably in the range of less than a second but still discernible) to load. This does not happen in the desktop browser but happens for me in my phonegap app.

Here is the way to reproduce the issue on an iPad. Should work on iPhone as well.

1st load http://hackerspacesg.valcatohosted.com/jqm-angular and click on the big button 'Go to home' to cache the images at http://hackerspacesg.valcatohosted.com/jqm-angular/home.html

For a quick and dirty simulation of an embedded web view, similar to PhoneGap (same rendering deal, minus phone gap.js), go to http://hackerspacesg.valcatohosted.com/jqm-angular , save it to your home screen in iOS, then open it and browse the site. The issue that I reported should be reproduced.

Manual initialization of AngularJS not working

I've seen in your readme that the ng-app directive is required and that the usage of manual bootstrap of angular does not work well with jquery-mobile, as jquery-mobile relies on the jQuery ready event to be fired at the right time.

However, it has worked so far with the former rc3-SNAPSHOT and rc2. No it seems that the current rc3-SNAPSHOT with manual initialization of AngularJS (http://docs.angularjs.org/guide/bootstrap) is no longer working. I have provided a jsFiddle which shows the problem: http://jsfiddle.net/jupiter/rJvPG/.

In Firefox the following error message is shown:

[Exception... "Node cannot be inserted at the specified point in the hierarchy" code: "3" nsresult: "0x80530003 (HierarchyRequestError)" location: "https://github.com/tigbro/jquery-mobile-angular-adapter/raw/master/compiled/jquery-mobile-angular-adapter-1.0.7-rc3-SNAPSHOT.js Line: 275"]

In Chrome a similar error message is displayed:

Error: HIERARCHY_REQUEST_ERR: DOM Exception 3
Error: A Node was inserted somewhere it doesn't belong.
at connectToDocument (https://raw.github.com/tigbro/jquery-mobile-angular-adapter/master/compiled/jquery-mobile-angular-adapter-1.0.7-rc3-SNAPSHOT.js:275:38)

I use manual initialization because I use a script loader to conditionally load AngularJS modules and other code before I bootstrap the application.

If you do not plan to support manual initialization what could be an alternative to defer the AngularJS bootstrapping so that conditional loading can take place? I specifically use this in order to load the correct language files.

My current code looks something like this:

angular.element(document).ready(function() {
    var locale = localStorage.getItem('locale');    
    var url = 'i18n/angular-locale_'+locale+'.js';

    yepnope({
        load: url,
        callback: function(url, result, key) {
            angular.bootstrap(document,['myapp']);
        }
    });
});

Feature request: Performance check on startup

Some phones running android have a very poor performance, especially regarding the DOM (javascript is not the real problem...). For those phones it would be great to show a warning dialog when the application starts that the performance might be bad...

Angular expression not evaulated within jQuery Mobile component

This jQuery Mobile checkbox is bound is to ng-model value, but expressions using that model value are not evaluated unless they are outside the jQuery Mobile widget (in this case, the fieldset). Other references within the page are updating correctly. See this fiddle:

http://jsfiddle.net/gscottolson/hEegk/

The following message appears in the browser JavaScript console: 'undefined' is not an object (evaluating 'node[0].nodeValue = value')

jQuery Mobile markup fails to render in templateUrl file

I just added 1.0.7-rc2-SNAPSHOT to my project. It resolves a couple issues I was having, but it introduces another issue:

I have a few directives that include template files via the templateUrl property. Any jQuery Mobile markup within these templates (like a <div data-role="navbar" > element with a nested ;<ul>) is not converted into a jQuery Mobile widget. Instead, this content appears as a regular unstyled unordered list.

There is workaround for this issue. If I use the template property for the directives (instead of using templateUrl), the jQuery Mobile markup is correctly converted to the appropriate jQuery Mobile widget (in the above case, the data-role="navbar" element correctly renders as a jQuery Mobile navbar.

This isn't a huge issue, but it means I have to use embedded templates with my directives. Also, the 1.0.7-rc1 version of this adapter worked with the templateUrl property in my directives. This issues seems to be related to the rc2 changes.

Feature request: Allow argument passing between $activePage and onActivate

Hi,
it would be nice if the following were possible:
Call $activePage service, with an argument. When the page is changed, that argument should be given to the onActivate callback of the selected page.

Would also be nice to save that object in the url / hash, so the new page gets bookmarkable / refreshable...

Benefits:
The pages are decoupled: The new page does not need to know who called that page / introspect the calling scope.

A button with the ngDisabled directive is not disabled

I am using AngularJS 1.0.0rc8, jQuery mobile 1.2.0 Pre and jQuery mobile Angular adapter 1.0.7-rc1.

I have used the following line of HTML-code:

<input type="button" ng-disabled="someexpression" value="Some title"></input>

However, the button is not disabled when someexpression is true.

I have tracked this down in the code. Here is an extract of the code which seems to not work correctly:

jqmng.define('jqmng/widgets/disabledHandling', ['jquery', 'angular'], function ($, angular) {
        var mod = angular.module('ng');

        function instrumentAttrSetter(element, attr) {
       // ...
            attr.$set = function (key, value) {
                var res = _$set.apply(this, arguments);
                if (key === 'disabled') {
                    var jqmOperation = 'enable';
                    if (value === 'disabled' || value == 'true') {
                        jqmOperation = 'disable';
                    }
      // ..

The jqmOperation is set to disabled if value is 'disabled' or 'true'. Unfortunately, the function is invoked with a boolean value true not a string value 'true'.

To test this assumption I have just added a value == true as in

 if (value === 'disabled' || value == 'true' || value == true) {

and now it works as intended. As I don't know how the frameworks actually work internally this is probably not the right way to fix it but it gives an idea of what is going wrong.

Feature request: Handle multiple options in $navigate

Hi,

Firstly, thank you very much for this useful project!

I wanted to point out that, for now, $navigate accepts a single argument in the form ´[transition]:pageId´. It would be great to split this argument into two, the first one still being the pageId and the second one being of the same type of object that $.mobile.changePage accepts as a second 'options' argument, so that we can specify the 'reverse' attribute, the 'role', the 'reloadPage', etc. (as all listed here: http://jquerymobile.com/demos/1.0/docs/api/methods.html).
It would be more coherent to the original jQueryMobile capabilities, though still easily adaptable to a different library (like Sensa Touch). The 'back' transition can still be handled if set in the 'transition' attribute of this second argument.

Thanks in advance,
MisterK

Custom namespaces for jQuery mobile attributes do not work

I have defined a custom namespace for data-attributes (http://jquerymobile.com/test/docs/api/globalconfig.html) by binding to the mobileinit event in order to use e. g. data-jqm-role instead of data-role. With rc2 all namespaced data-attributes don't seem to be recognized.

See the jsFiddle at http://jsfiddle.net/jupiter/bmBHN/4/.

Change jquery-mobile-angular-adapter-1.0.7-rc2.js to jquery-mobile-angular-adapter-1.0.7-rc1.js to see it work with rc1.

I have used jquery mobile 1.1.0 and AngularJS 1.0.0rc9.

$xhr no more working

Hi,
when using the current version of the adapter, the $xhr service is no more working.

Tobias

HTML elements outside of the jQuery mobile page break radio button rendering

I have inserted two pairs of divs. One pair before the page and another pair after the page. Both divs cause the rendering to break. The first pair of divs causes the rendering of the button's disabled state to break and the second div causes the rendering of the radio buttons to break.

I use divs this way e. g. for application wide overlays.

See the jsFiddle at http://jsfiddle.net/jupiter/kk7K9/2/.

Change jquery-mobile-angular-adapter-1.0.7-rc2.js to jquery-mobile-angular-adapter-1.0.7-rc1.js to see it work with rc1 or comment or delete the two divs to see it work in rc2.

I have used jquery mobile 1.1.0 and AngularJS 1.0.0rc9.

Duplicated items from an angular list

As you can see from this demo I put together, the two items in the controller list are displayed 4 times in the table created from an ng-repeat directive.

This is using the latest precompiled version (jquery-mobile-angular-adapter-standalone-1.0.7-rc3-SNAPSHOT.js), since I don't have everything set up to build myself.

Refactor into modules with require.js

There should be two builds:

  1. A build that creates one js file that does not need any other library, uses the javascript module pattern and global variables. This should be usable in the same place as the current implementation
  2. A build that create one js file that represents a require-js module. All services of the adapter should not more be exposed as global variables but as a requirejs module.

Problems with IE7 / Windows Phone 7

Hi,
there is a problem when using the adapter in version 1.0.2 with windows phone 7:
German: "Die type Eigenschaft wurde nicht gefunden, dieser Befehl wird nicht unterstützt"
(English: "The type property was not found, the command is not supported").

In line 1130 of jquery-mobile-angular-adapter-1.0.2.js
...
proxyUtil.createAngularWidgetProxy('input', function(element) {
...
1129: if (isTextinput) {
1130: element[0].type = 'text';

injection of $location results in failing page-refreshes

I am not sure if this is a designed trade-off, but the (patched) $location service doesn't like to be injected into a controller.
For example, change the controller def of the 'todo-mobile' example, as such:

line 2:
-- module.factory('todoStore', function ($http, $waitDialog) {
++module.factory('todoStore', function ($http, $waitDialog, $location) {

Navigate to /todo.html#settings, reload the page and see window.location go haywire.

ngm-if creates multiple rows when the value changes

If I use ngm-if e.g. for displaying a message like so:

    <div class="error" ngm-if="rental.errorMessage">{{rental.errorMessage}}</div>

And I first set rental.errorMessage to abc and then to def both messages are visible.

Tobias

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.