///////////////////////////////////////////////////////////////////////////////
// Sélecteur de couleurs avec jQuery
// ****************************************************************************
// This software is governed by the CeCILL license under French law and
// abiding by the rules of distribution of free software.  You can  use, 
// modify and/ or redistribute the software under the terms of the CeCILL
// license as circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt".
// 
// Ce logiciel est régi par la licence CeCILL soumise au droit français et
// respectant les principes de diffusion des logiciels libres. Vous pouvez
// utiliser, modifier et/ou redistribuer ce programme sous les conditions
// de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
// à l'adresse "http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt".
// 
// Copyright Cyril Ravat, <ravat@free.fr>, 2009-2011
// Website : http://www.cyril-ravat.fr/scripts/jquery.colorselector.php
// ****************************************************************************
//
// Fonctionne automatiquement sur les input de classe 'colorsel'
// Il suffit d'insérer ce fichier et jquery dans l'entête du fichier html.
// Si le champ input est aussi de classe 'colorcss', les formats acceptés sont
// les formats valides en css : '#xxx', '#xxxxxx' ou 'rgb(xxx,xxx,xxx)'
// Si le champ input est aussi de classe 'colorphp', le seul format accepté est
// le format rgb, mais sans 'rgb()' : 'xxx,xxx,xxx' en valeurs décimales
// 
// Variables utilisées :
//  lastid    -> id du dernier input sélectionné
//  colorfmt  -> format de la couleur dans le dernier input sélectionné
//               hex si '#xxx' ou '#xxxxxx', rgb1 si 'rgb(xxx,xxx,xxx)',
//               rgb2 si 'xxx,xxx,xxx', 'none' sinon
//  sel       -> le sélecteur
//  bgcolor   -> background-color de <body>, simplement pour raccourci
//  s,r,g,b,c -> chaines et compteurs pour la création du sélecteur, peuvent
//               être détruits sans risque
// 
// Classes et identifiants :
//  #colorval    -> <p> dans le sélecteur contenant la couleur en sélection
//  .colorsample -> les échantillons de visualisation derrière chaque input
// 
// Fonctions définies :
//  validcolor -> détecte le format de couleur, corrige (supprime les espaces)
//                la chaine contenu dans le champ input, indique visuellement
//                si le format est incorrect, met à jour #colorval et colorfmt,
//                retourne une chaine valide en css pour changer l'échantillon
//  displaysel -> affiche ou cache le sélecteur
// 
// Compatible avec Jquery 1.3.2 à 1.6.1
///////////////////////////////////////////////////////////////////////////////

$(function(){

  // Variables contenant
  // * l'id du dernier champ ayant appelé le sélecteur
  // * le format d'origine du derniere input modifié
  var lastid = false, colorfmt = false, sel,
      bgcolor = $('body').css('background-color'), s, r, g, b, c;

  // Fonction de détection de format 'hex' ('#xxx' ou '#xxxxxx'),
  // 'rgb1' ('rgb(xxx,xxx,xxx)') ou rgb2 ('xxx,xxx,xxx')
  function validcolor(id) {
    var s = $('#'+id).val(), parts, correct = true;
    if ( s.length == 0 )  {
      if ( $('#'+id).is('.colorphp') )  colorfmt = 'rgb2';
      else  colorfmt = 'hex';
      $('#colorval').text('Pas de valeur');
      s = '#AAA';
    }
    else if ( parts = s.match(/^\s*[#]?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})\s*$/) )  {
      colorfmt = 'hex';
      $('#colorval').text( s = '#'+parts[1] );
      if ( $('#'+id).is('.colorphp') )  correct = false;
      $('#'+id).val(s);
    }
    else if ( parts = s.match(/^\s*rgb\(\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)\s*$/) )  {
      colorfmt = 'rgb1';
      $('#colorval').text( s = 'rgb('+parts[1]+','+parts[2]+','+parts[3]+')' );
      if ( $('#'+id).is('.colorphp') )  correct = false;
      $('#'+id).val(s);
    }
    else if ( parts = s.match(/^\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\s*$/) )  {
      colorfmt = 'rgb2';
      $('#colorval').text( s = parts[1]+','+parts[2]+','+parts[3] );
      if ( $('#'+id).is('.colorcss') )  correct = false;
      $('#'+id).val(s);
      s = 'rgb('+s+')';
    }
    else  {
      colorfmt = 'none';
      $('#colorval').text( '???' );
      s = '#AAA';
      correct = false;
    }
    if ( correct )  $('#'+id).css({'background-color':'#FFF'});
    else  $('#'+id).css({'background-color':'#F33'});
    $('#colorval').css('background-color',s);
    return s;
  };

  // Fonction d'affichage/disparition du sélecteur
  function displaysel(id) {
    lastid = id;
    validcolor(id);
    sel.css({'top':5+$('#'+id).offset().top+$('#'+id).outerHeight(),
             'left':$('#'+id).offset().left}) .show();
  };

  // Sélecteur
  sel = $('<div></div>')
        .css({'background-color':bgcolor,'width':'198px','height':'160px',
              'padding':'1px','margin':'0px','position':'absolute',
              'border':'1px solid #000','display':'none'});
  s = '0369cf';
  for ( r=0; r<6; r++ )
    for ( g=0; g<6; g++ )
      for ( b=0; b<6; b++ )  { 
        c = s[r]+s[r]+s[g]+s[g]+s[b]+s[b];
        // Génération des <div> contenant les couleurs
        sel.append($('<div id="'+c+'"></div>')
                   .css({'background-color':'#'+c,'width':'9px','height':'9px',
                      'float':'left','margin':'0px','padding':'0px',
                      'cursor':'pointer','border':'1px solid '+bgcolor})
                   .click(function() {
                     $('#'+lastid).val($('#colorval').text()).change();
                     sel.hide();
                   })
                   // Au survol, la valeur de #colorval est modifiée
                   .mouseenter(function() {
                     var c = $(this).attr('id');
                     $('#colorval').css({'background-color':'#'+c});
                     // Conversion de hexa à rgb si besoin
                     if ( colorfmt.substr(0,3) == 'rgb' )  {
                       c = [c.substr(0,2),c.substr(2,2),c.substr(4,2)];
                       for ( var i in c )  c[i] = parseInt('0x'+c[i]);
                       c = c.join(',');
                       if ( colorfmt == 'rgb1' )  c = 'rgb('+c+')';
                     }
                     else  c = '#'+c;
                     $('#colorval').text(c);
                     $(this).css({'border':'1px solid #AAA'});
                   })
                   .mouseleave(function() {
                     $(this).css({'border':'1px solid '+bgcolor});
                   })
                  );
      }
  // <p> contenant la dernière valeur survolée
  sel.append($('<p id="colorval"></p>')
             .css({'margin':'1px','padding':'5px','width':'186px','height':'17px',
                   'text-align':'center','clear':'left','cursor':'pointer'})
             .click(function() {
               var c = $(this).text();
               if ( c[0] !== '?' && c[0] !== 'P' )
                 $('#'+lastid).val(c).change();
               sel.hide();
             })
            );
  $('body').append(sel);

  // Un clic dehors cache le sélecteur
  $(document).click(function(event) {
    if ( !$(event.target).is('.colorsel') && !$(event.target).is('.colorsample') )
      sel.hide();
  });

  // S'applique à chaque input de classe colorsel
  $('.colorsel').each(function() {
    var id = this.id, sample;
    if ( id.length == 0 )
      $(this).attr('id',id = 'colorsel'+Math.round(Math.random()*1000000));
    // Échantillon de visualisation de la couleur
    sample=$('<span class="colorsample"></span>')
           .css({'background-color':validcolor(id),'cursor':'pointer',
                 'display':'-moz-inline-block','display':'inline-block',
                 'width':'100px','height':$(this).outerHeight(),
                 'margin':'0px 10px','vertical-align':'middle'});
    $(this).after(sample);
    // Modification manuelle au changement de valeur
    $(this).change(function() {
      sample.css({'background-color':validcolor(id)});
    });
    // Gestion des apparitions et disparitions du sélecteur 
    $(this).focus(function() { displaysel(id); });
    sample.click(function() {
      if ( sel.is(':visible') && ( lastid == id ) )
        sel.hide();
      else  displaysel(id);
    });
  });

});

