Listes et checkbox avec Jquery Mobile

Si vous avez eu l’occasion de développer une webapp mobile, vous avez peut-être fait le choix d’utiliser le framework Jquery Mobile.
Framework basé sur HTML5, ce dernier offre une bibliothèque de composants assez bien fournie et ne cesse de s’enrichir au fil des versions.

Jquery Mobile liste checkbox

Exemple de liste Jquery Mobile avec checkbox dans Alinto Motion

Je ne vais pas vous faire une présentation de cette librairie, leur showcase est largement assez complet. Nous allons nous concentrer sur l’utilisation des listes. À ce jour, Jquery Mobile ne propose pas de listes avec checkbox permettant de gérer le changement de page de chaque élément (action par défaut d’une liste) tout en ayant la possibilité de sélectionner une ou plusieurs lignes.

 

Lorsque nous avons développé la version mobile de notre webmail, il a donc fallu utiliser les composants existants et y ajouter cette fonctionnalité. Je vous invite d’ailleurs à essayer Alinto Motion qui vous donnera une idée de ce qu’on peut faire avec Jquery Mobile.

Le code javascript kivabien

Tout d’abord, nous allons inclure le code javascript qui suit dans nos pages :

(function($){

	$.extend($.fn, {

		options: {
			multiple: false,
			checkall: false,
			corners:false,
			icon:'check'
		},

		//add checkbox to each row
		checklist:function(conf)
		{
			this.options = $.extend( {}, $.fn.options, conf );
			var self = this;			

			return this.find("li").each(function(i, el)
			{
				var $row = $(el);

				//if element contains data-checked attributes, this process has already been apply on this item
				if( $row.jqmData('checked') )
				{
					return;
				}
				// create button
				var $checkBtn = $('').attr({
									'data-role': 'button',
									'data-corners':self.options.corners,
									'data-inline': 'true',
									'class': 'checkBtn'
								});

				if( $row.jqmData('role')==='list-divider')
				{
					if( self.options.checkall && self.options.multiple )
					{
						$row.jqmData('checked', "false");
						$row.attr('data-'+ $.mobile.ns + 'checked', "false");

						$row.jqmData('selection', "checkall");
						$row.attr('data-'+ $.mobile.ns + 'selection', "checkall");

						$checkBtn.bind("click", function(e)
						{
							var $selector = $(this).closest('li');
							var pageId = $selector.attr('id');
							var state = $selector.jqmData('checked');

							self.toggleRow( $(this).closest('li') );
							//check all li whose class match witch list-divider id
							self.checkAll($("li."+pageId), state);
						});
						// insert button into list item
						$checkBtn.prependTo($row).button();
					}
				}
				else
				{
					$row.jqmData('checked', "false");
					$row.attr('data-'+ $.mobile.ns + 'checked', "false");

					$checkBtn.bind("click", function(e)
					{
						e.preventDefault();
						self.toggleRow( $(this).closest('li') );
					});
					// insert button into list item
					$checkBtn.prependTo($row).button();
				}
			});
		},

		checkAll: function($elem, state)
		{
			var self = this;
			$elem.each(function(index) 
			{
				if( state === "true" )
				{
					self.unselectRow( $(this) );
				}
				else
				{
					self.selectRow( $(this) );
				}
			});
		},

		getSelection: function()
		{
			//return all checked rows without checkall row
			return $(this).find("li:jqmData(checked='true'):jqmData(selection!='checkall')");
		},

		toggleRow: function( $row )
		{
			var self = this;
			if( $row.jqmData('checked') === "true" )
			{
				self.unselectRow($row);
			}
			else
			{
				self.selectRow($row);
			}
		},

		selectRow: function($row)
		{
			var self = this;

			//if list does not support multiple selection
			if( self.options.multiple === false)
			{
				//unselect selected rows
				self.getSelection().each(function(index) {
					self.unselectRow($(this));
				});
			}
			$row.jqmData('checked', "true");
			$row.attr('data-'+ $.mobile.ns + 'checked', "true");
			if ($row.jqmData('role') != 'list-divider')
			{
				$row.addClass("ui-btn-active");
			}
			$row.find(".checkBtn").addClass("checked");
			$row.find(".ui-btn").addClass("ui-btn-active");
		},

		unselectRow: function( $row )
		{
			var self = this;
			$row.jqmData('checked', "false");
			$row.attr('data-'+ $.mobile.ns + 'checked', "false");
			$row.removeClass("ui-btn-active");
			$row.find(".ui-btn-active").removeClass("ui-btn-active");
			$row.find(".checkBtn").removeClass("checked");

			//unselect previous checkall.
			if( $row.jqmData("selection") !== 'checkall' )
			{
				var $checkall =  $row.prevAll("li:jqmData(selection='checkall'):first");
				if( $checkall.length > 0 )
				{
					self.unselectRow( $checkall );
				}
			}
		}
	});	
})(jQuery);

Styles css de base

Voici les styles de base permettant d’afficher les checkboxes à l’extrémité droite des lignes de vos listes. Je vous laisse adapter à vos besoins.

.checkBtn {
    padding: 0;
    z-index: 2;
    right:0px;
    margin-top: -14px;
    position: absolute;
    top: 50%;
    background:white;
}

li .checkBtn .ui-btn-inner {
	padding-right: 0;
	border-top:none;
	visibility: hidden;
}
li.ui-li-divider .checkBtn .ui-btn-inner {
	margin-left: 0px;
	margin-top: 2px;
}

li .checkBtn.checked .ui-btn-inner {
	visibility: visible;
}

.checkBtn .ui-icon {
	right:2px;	
}

Options

Propriété Défaut Description
icon « check » l’icone utilisée dans la case à cocher
corners false le contour de la checkbox doit-il être arrondi ? Utile pour éventuellement afficher des radios plutôt que checkbox.
multiple false autorise la sélection multiple de ligne
checkall false si l’option sélection multiple est active, permet d’afficher une checkbox dans la ligne « list-divider » de la liste.

Exemple d’utilisation

Le code HTML de votre liste :

  • Check all
  • Item 1
  • Item 2
  • Item 3
  • Page2
  • Item 4
  • Item 5

Appel du plugin avec différentes options :

$(document).on("pageinit", function()
{
   	//Pour afficher une liste avec une sélection simple par checkbox
   	$("ul#maListe").checklist();
   	//Pour afficher une liste avec une sélection multiple et l'icone "delete" sera utilisée quand la checkbox sera cochée
   	$("ul#maListe").checklist({multiple:true,icon:"delete"});    	
   	//Pour afficher la case "Sélectionner tout" (uniquement si vous définissez une ligne avec le data-role "list-divider")
   	$("ul#maListe").checklist({multiple:true,checkall:true});
});

Et là, vous me dites « OK mais c’est bien joli d’afficher les checkboxes mais comment on récupère la sélection ? ». Et bien la transition est toute faite …

Récupérer la sélection

Donc, vous allez voir, après de longues réunions et brainstormings sur la question voici le code js à utiliser quand vous aurez besoin de récupérer les lignes sélectionnées

 $("ul#maListe").getSelection();

… et oui tout simplement 🙂

Vous pouvez télécharger le code complet et des fichiers de démo dans notre repository Github.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *