/* [0] Constructeur -> définit le conteneur et le bouton d'ajout =========================================================*/ function inputPhoneContact(container, navContainer){ this.container = container; this.nav_container = navContainer; } /* [1] Attributs =========================================================*/ inputPhoneContact.prototype = { container: this.container, // Conteneur des formulaires de contact nav_container: this.nav_container, // Conteneur de la navigation entre les formulaires selected: 0, // UID du permier des contacts sélectionnés (10 par 10) handler: null // Fonction pour l'enregistrement et la synchronisation des données }; /* [2.1] Fiche CALL range =========================================================*/ inputPhoneContact.prototype.callRange = function(uid){ return uid >= 0 && uid < 20; }; /* [2.2] Fiche SMS range =========================================================*/ inputPhoneContact.prototype.smsRange = function(uid){ return uid >= 20 && uid < 40; }; /* [2.3] Si contact identique =========================================================*/ inputPhoneContact.prototype.sameContact = function(uid, username, existing, range){ var contact = null, limits = null; /* (1) Gestion de la tranche ---------------------------------------------------------*/ if( range === 'call' ) limits = { min: 0, max: 19 }; else if( range === 'sms' ) limits = { min: 29, max: 39 }; else if( range === 'mini' ) limits = { min: 40, max: Infinity }; else return false; /* (2) Gestion de la vérification ---------------------------------------------------------*/ for( var a = limits.min, b = limits.max ; a < b ; a++ ){ /* (1) On récupère le contact */ contact = lsi.get('p_contacts', a); // si n'existe pas, on quitte if( contact === null ) break; /* (2) si c'est le contact actuel, on passe au suivant */ if( parseInt(contact.uid) === parseInt(uid) ) continue; /* (3) On vérifie si le contact est identique (si défini par `username`) */ if( contact.username.length > 0 && username === contact.username ) return true; /* (4) On vérifie par référence */ else if( username.length === 0 && parseInt(existing) === parseInt(contact.existing) ) return true; } return false; }; /* [2.4] Vérification des données d'un contact =========================================================*/ inputPhoneContact.prototype.check = function(deflated){ /* On vérifie la validité du formulaire */ var isValid = !isNaN(deflated.existing) || deflated.username.length > 0; if( !isValid ) return false; /* On vérifie l'unicité du contact */ var range = this.callRange(deflated.uid) ? 'call' : this.smsRange(deflated.uid) ? 'sms' : 'mini'; /* (1) Si contact "identique" dans la même tranche ---------------------------------------------------------*/ if( this.sameContact(deflated.uid, deflated.username, deflated.existing, range) ){ if( deflated.username.length > 0 ) Notification.error('Contact dupliqué', 'Le contact de nom '+deflated.username+' est déja utilisé dans cette partie'); else Notification.error('Contact dupliqué', 'Le contact '+lsi.get('p_friends', deflated.existing).name+' est déja utilisé dans cette partie'); return false; } return true; }; /* [3] Gestion de l'enregistrement des formulaires de contact =========================================================*/ inputPhoneContact.prototype.fieldsToStorage = function(){ console.group('[phone.contact] fields to storage'); // {1} Pour chaque formulaire de contact présent // var visibleContacts = $$('[data-sublink="phone"] article.contact-panel .new-contact'); for( var i = 0 ; i < visibleContacts.length ; i++ ){ // {2} On initialise notre deflater pour récupérer les valeurs // var deflater = new FormDeflater(visibleContacts[i], ['input', 'select'], ['data-name']); // {3} On enregistre ce contact si le numéro n'est pas vide et soit pseudo/prénom/nom // var deflated = deflater.deflate(); // Si le formulaire n'est pas valide, on ne l'enregistre pas if( !this.check(deflated) ) continue; // {4} On récupère et met en forme les valeurs du deflater // var obj = { uid: parseInt(deflated.uid), // number: deflated.number, username: deflated.username, existing: (!isNaN(deflated.existing)) ? parseInt(deflated.existing) : '.' }; /* (5) On calcule et ajoute le hash des données */ obj.hash = crc32( JSON.stringify(obj) ); // {6} On enregistre les données dans le 'localStorage' // lsi.set('p_contacts', parseInt(deflated.uid), obj); } console.groupEnd('[phone.contact] fields to storage'); }; /* [4] Gestion de l'ajout physique d'un nouveau contact =========================================================*/ /* * * @objectData Objet contenant les informations nécessaires à l'affichage * */ inputPhoneContact.prototype.add = function(objectData){ // Si pas d'uid, on quitte if( objectData == null || objectData.uid == null || isNaN(objectData.uid) ) return false // {0} On formatte l'object // objectData.username = (objectData.username != null) ? objectData.username : ''; objectData.existing = (objectData.existing != null) ? objectData.existing : '.'; // {1} On récupére la liste des contacts déja renseignés // var existing = lsi.export('p_friends'); var buildData = objectData; buildData.contacts = ''; for( var i in existing ) buildData.contacts += "\t\t\n"; // {2} On ajoute le HTML // this.container.innerHTML += pContactBuilder.build(buildData); // {3} On remplit @existing s'il y a une valeur // var existingOption = $('[data-sublink="phone"] article.contact-panel .new-contact input[data-name="uid"][value="'+objectData.uid+'"] ~ span select[data-name="existing"]>option[value="'+objectData.existing+'"]'); if( existingOption != null ) existingOption.setAttribute('selected', 'selected'); // {4} On attache les évènements sur les formulaires // var contactForms = $$('[data-sublink="phone"] article.contact-panel .new-contact'); // On met à jour les listener (remove, puis add) */ var ptr = this; for( var i = 0 ; i < contactForms.length ; i++ ){ contactForms[i].removeEventListener('click', function(e){ ptr.nav(e.target); ptr.handler(e.target); }, false); contactForms[i].addEventListener('click', function(e){ ptr.nav(e.target); ptr.handler(e.target); }, false); } }; /* [5] Gestion de l'affichage depuis le 'localStorage' =========================================================*/ inputPhoneContact.prototype.storageToFields = function(){ console.group('[phone.contact] storage to fields'); // {1} Pour chaque contact du 'localStorage' // var contactKeys = lsi.keys('p_contacts'); // On réinitialise le HTML this.container.innerHTML = ''; // {2} On ajoute chaque contact (parmi les séléctionnés) à la liste // var min = this.selected; // On affiche du contact sélectionné var max = this.selected+10; // On s'arrête à 10 contacs for( var i = min ; i < max && i < contactKeys.length ; i++ ) this.add( lsi.get('p_contacts', contactKeys[i]) ); // On ajoute un champ de plus à remplir si c'est la dernière page if( max >= contactKeys.length ) this.add({uid: contactKeys.length}); /* (3) On met à jour la barre de navigation */ this.updateNavBar(); console.groupEnd('[phone.contact] storage to fields'); }; /* [6] Gestion de la navigation entre les formulaires (10 par 10) =========================================================*/ inputPhoneContact.prototype.nav = function(element){ /* (1) On vérifie que l'élément contient un nombre et existe */ if( element == null ) return false; if( element.getData('n') === false || isNaN(element.getData('n')) || element.parentNode.id != 'p_nav-contact' ) return false; /* (2) On désactive tous les éléments actifs */ var activeElements = $$('[data-sublink="phone"] #p_nav-contact > span.active'); for( var i = 0 ; i < activeElements.length ; i++ ) activeElements[i].remClass('active'); /* (3) On active l'élément courant */ element.addClass('active'); this.selected = parseInt(element.getData('n')); }; /* [7] Mise à jour de la navigation =========================================================*/ inputPhoneContact.prototype.updateNavBar = function(){ var contactKeys = lsi.keys('p_contacts'); var len = contactKeys.length; /* (1) On vérifie si la barre de navigation est à jour */ var navBarUpToDate = this.nav_container.children.length == len; /* (2) On vide et remplit la barre de nav, si elle n'est pas à jour */ if( !navBarUpToDate ){ this.nav_container.innerHTML = ''; for( var i = 0 ; i < len ; i+=10 ) this.nav_container.innerHTML += ''+ (1+i/10) +''; } /* (4) On séléctionne par défaut la dernière MINI fiche sélectionnée */ this.nav( $('[data-sublink="phone"] #p_nav-contact [data-n="'+( this.selected )+'"]') ); }; /* [8] Point d'amorçage de la gestion des contacts =========================================================*/ inputPhoneContact.prototype.attach = function(handler){ console.group('[phone.contact] attaching events'); /* (1) On initialise le jeu de données */ lsi.createDataset('p_contacts'); /* (2) On charge les contacts depuis la mémoire ('localStorage') */ this.storageToFields(); /* (3) On enregistre le handler */ this.handler = handler; /* (4) On attache l'évènement sur le conteneur de navigation */ var ptr = this; this.nav_container.addEventListener('click', function(e){ // 1. On gère la navigation ptr.nav(e.target); // 2. On gere le chargement dynamique ptr.handler(e.target); }, false); console.groupEnd('[phone.contact] attaching events'); };