/**
 * -----------------------------------------------------------------------------
 * file: ui.inputText.js
 * file version: 1.1.3
 * date: 2012-09-03
 *
 * A jQuery plugin provided by the piwigo's plugin "GrumPluginClasses"
 *
 * -----------------------------------------------------------------------------
 * Author     : Grum
 *   email    : grum@piwigo.com
 *   website  : http://photos.grum.fr
 *
 *   << May the Little SpaceFrog be with you ! >>
 * -----------------------------------------------------------------------------
 *
 *
 *
 *
 * :: HISTORY ::
 *
 * | release | date       |
 * | 1.0.0   | 2010/11/04 | * first release
 * |         |            |
 * | 1.1.0   | 2011/01/09 | * if div content is not empty and text value not
 * |         |            |   defined, use of div content to define text value
 * |         |            |
 * |         |            | * add multilanguage managment
 * |         |            |
 * | 1.1.1   | 2011/01/31 | * add function ':clear' for 'languagesValues' method
 * |         |            |
 * | 1.1.2   | 2012/06/18 | * improve memory managment
 * |         |            |
 * |         |            | * fix bug on regExp option
 * |         |            |
 * | 1.1.3   | 2012/09/03 | * fix bug on initial value settings & check value validity
 * |         |            |
 * |         |            |
 * |         |            |
 * |         |            |
 *
 */



(
  function($)
  {
    /*
     * plugin 'public' functions
     */
    var publicMethods =
    {
      init : function (opt)
        {
          return this.each(function()
            {
              // default values for the plugin
              var $this=$(this),
                  data = $this.data('options'),
                  objects = $this.data('objects'),
                  properties = $this.data('properties'),
                  options =
                    {
                      languages:[],
                      currentLanguage:'',
                      languagesValues:{},
                      languageSelector:'',
                      multilines:false,
                      disabled:false,
                      textAlign:'left',
                      displayChar:0,
                      maxChar:0,
                      numRows:1,
                      regExp:'',
                      value:'',
                      change:null
                    };

              // if options given, merge it
              // if(opt) $.extend(options, opt); ==> options are set by setters
              if(options.value=='' && $.trim($this.html())!='') options.value=$.trim($this.html());

              $this.data('options', options);

              if(!properties)
              {
                $this.data('properties',
                  {
                    initialized:false,
                    re:/.*/,
                    value:'',
                    isValid:true,
                    languagesValues:{}
                  }
                );
                properties=$this.data('properties');
              }

              if(!objects)
              {
                objects =
                  {
                    container:$('<div/>',
                        {
                          'class':'ui-inputText',
                          css:{
                            width:'100%'
                          }
                        }
                    ).bind('click.inputText',
                        function ()
                        {
                          objects.input.focus();
                        }
                      ),
                    input:null
                  };

                $this
                  .html('')
                  .append(objects.container);

                $this.data('objects', objects);
              }

              privateMethods.setOptions($this, opt);
            }
          );
        }, // init
      destroy : function ()
        {
          return this.each(
            function()
            {
              // default values for the plugin
              var $this=$(this),
                  objects = $this.data('objects');
              objects.input.unbind().remove();
              objects.container.unbind().remove();
              $this
                .unbind('.inputText')
                .removeData()
                .css(
                  {
                    width:'',
                    height:''
                  }
                );
              delete $this;
            }
          );
        }, // destroy

      options: function (value)
        {
          return(
            this.each(
              function()
              {
                privateMethods.setOptions($(this), value);
              }
            )
          );
        }, // options

      disabled: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setDisabled($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.disabled);
            }
            else
            {
              return('');
            }
          }
        }, // disabled

      textAlign: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setTextAlign($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.textAlign);
            }
            else
            {
              return('');
            }
          }
        }, // textAlign

      displayChar: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setDisplayChar($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.displayChar);
            }
            else
            {
              return('');
            }
          }
        }, // displayChar

      maxChar: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setMaxChar($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.maxChar);
            }
            else
            {
              return('');
            }
          }
        }, // maxChar

      numRows: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setNumRows($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.numRows);
            }
            else
            {
              return('');
            }
          }
        }, // numRows

      regExp: function (value)
        {
          if(value!=null)
          {
            return(
              this.each(
                function()
                {
                  privateMethods.setRegExp($(this), value);
                }
              )
            );
          }
          else
          {
            var options = this.data('options');

            if(options)
            {
              return(options.regExp);
            }
            else
            {
              return('');
            }
          }
        }, // regExp

      multilines: function ()
        {
          // return the selected tags
          var properties=this.data('properties');
          return(properties.multilines);
        }, // multilines

      languages: function (value)
        {
          if(value!=null)
          {
            // set the known languages
            return(
              this.each(
                function()
                {
                  privateMethods.setLanguages($(this), value);
                }
              )
            );
          }
          else
          {
            // return the known languages
            var options = this.data('options');
            return(options.languages);
          }
        },

      currentLanguage: function (value)
        {
          if(value!=null)
          {
            // set the current language
            return(
              this.each(
                function()
                {
                  privateMethods.setCurrentLanguage($(this), value);
                }
              )
            );
          }
          else
          {
            // return the current language
            var options = this.data('options');
            return(options.currentLanguage);
          }
        },

      languageSelector: function (value)
        {
          if(value!=null)
          {
            // set the language selector id (inputList object)
            return(
              this.each(
                function()
                {
                  privateMethods.setLanguageSelector($(this), value);
                }
              )
            );
          }
          else
          {
            // return the language selector id
            var options = this.data('options');
            return(options.languageSelector);
          }
        }, //languageSelector

      languagesValues: function (value)
        {
          if(value!=null)
          {
            // set the languages values
            return(
              this.each(
                function()
                {
                  privateMethods.setLanguagesValues($(this), value);
                }
              )
            );
          }
          else
          {
            // return the languages values
            var properties=this.data('properties');
            return(properties.languagesValues);
          }
        },

      value: function (value, language)
        {
          if(value!=null)
          {
            var options=this.data('options');

            // set selected value
            return(
              this.each(
                function()
                {
                  if(language!=null)
                  {
                    privateMethods.setLanguageValue($(this), language, value, options.currentLanguage==language);
                  }
                  else
                  {
                    privateMethods.setValue($(this), value, true);
                  }
                }
              )
            );
          }
          else
          {
            // return the selected tags
            var properties=this.data('properties');
            return(properties.value);
          }
        }, // value

      isValid: function (value)
        {
          if(value!=null)
          {
            // set selected value
            return(
              this.each(
                function()
                {
                  privateMethods.setIsValid($(this), value);
                }
              )
            );
          }
          else
          {
            // return the selected tags
            var properties=this.data('properties');
            return(properties.isValid);
          }
        }, // isValid

      change: function (value)
        {
          if(value!=null && $.isFunction(value))
          {
            // set selected value
            return(
              this.each(
                function()
                {
                  privateMethods.setEventChange($(this), value);
                }
              )
            );
          }
          else
          {
            // return the selected value
            var options=this.data('options');

            if(options)
            {
              return(options.change);
            }
            else
            {
              return(null);
            }
          }
        }, // change

      doTranslation: function ()
        {
          // set selected value
          return(
            this.each(
              function()
              {
                privateMethods.doTranslation($(this));
              }
            )
          );
        } // doTranslation

    }; // methods


    /*
     * plugin 'private' methods
     */
    var privateMethods =
    {
      /**
       * return true is given value is a valid numeric value, according to the
       * rules defined by the object
       * @param Object object
       * @param value
       * @return Bool
       */
      isValid : function (object, value)
        {
          var properties=object.data('properties');

          return(properties.re.test(value));
        },

      setOptions : function (object, value)
        {
          var properties=object.data('properties'),
              options=object.data('options');

          if(!$.isPlainObject(value)) return(false);

          properties.initialized=false;

          privateMethods.setMultilines(object, (value.multilines!=null)?value.multilines:options.multilines);
          privateMethods.setDisplayChar(object, (value.displayChar!=null)?value.displayChar:options.displayChar);
          privateMethods.setMaxChar(object, (value.maxChar!=null)?value.maxChar:options.maxChar);
          privateMethods.setNumRows(object, (value.numRows!=null)?value.numRows:options.numRows);
          privateMethods.setRegExp(object, (value.regExp!=null)?value.regExp:options.regExp);

          privateMethods.setLanguages(object, (value.languages!=null)?value.languages:options.languages);
          privateMethods.setLanguagesValues(object, (value.languagesValues!=null)?value.languagesValues:options.languagesValues);
          privateMethods.setCurrentLanguage(object, (value.currentLanguage!=null)?value.currentLanguage:options.currentLanguage);
          privateMethods.setLanguageSelector(object, (value.languageSelector!=null)?value.languageSelector:options.languageSelector);

          if((properties.languagesValues[options.currentLanguage]!=null &&
              properties.languagesValues[options.currentLanguage]!='' ||
              properties.languagesValues[options.currentLanguage]==null) &&
             (value.value!=null && value.value!='' || options.value!='')
            ) privateMethods.setValue(object, (value.value!=null)?value.value:options.value, true);

          privateMethods.setTextAlign(object, (value.textAlign!=null)?value.textAlign:options.textAlign);

          privateMethods.setDisabled(object, (value.disabled!=null)?value.disabled:options.disabled);

          privateMethods.setEventChange(object, (value.change!=null)?value.change:options.change);

          properties.initialized=true;
        },

      /**
       * define the regular expression used to check validity of a numeric value
       * @param Object object
       */
      setRegExp : function (object, value)
        {
          var properties=object.data('properties'),
              flagRE=/^\/(.*)\/(.*)$/,
              flags=flagRE.exec(value);

          if(flags==null)
          {
            flags=['.*', ''];
          }

          delete properties.re;
          properties.re = new RegExp(flags[1],flags[2]);
        },

      setIsValid : function (object, value)
        {
          var objects=object.data('objects'),
              properties=object.data('properties'),
              check=false;

          if(value=='check')
          {
            value=privateMethods.isValid(object, properties.value);
            check=true;
          }

          if(properties.isValid!=value && properties.initialized || check)
          {
            properties.isValid=value;
            if(properties.isValid)
            {
              objects.container.removeClass('ui-error');
              objects.input.removeClass('ui-error');
            }
            else
            {
              objects.container.addClass('ui-error');
              objects.input.addClass('ui-error');
            }
          }
          return(properties.isValid);
        },

      setDisplayChar : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects');
              properties=object.data('properties');

          if((!properties.initialized || options.displayChar!=value) && value>=0)
          {
            options.displayChar=value;
            if(options.displayChar>0)
            {
              if(options.multilines)
              {
                objects.input.attr('cols', options.displayChar);
              }
              else
              {
                objects.input.attr('size', options.displayChar);
              }
            }
            else
            {
              if(options.multilines)
              {
                objects.input.removeAttr('size');
              }
              else
              {
                objects.input.removeAttr('cols');
              }
            }
          }
          if(object.width()>0)
          {
            objects.input.css(
              {
                'width': object.width()+'px',
                'max-width': object.width()+'px'
              }
            );
          }
          return(options.displayChar);
        },

      setMaxChar : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects'),
              properties=object.data('properties');

          if((!properties.initialized || options.maxChar!=value) && value>=0)
          {
            options.maxChar=value;
            if(!options.multilines)
            {
              if(options.maxChar>0)
              {
                objects.input.attr('maxlength', options.maxChar);
              }
              else
              {
                objects.input.removeAttr('maxlength');
              }
            }
          }
          return(options.maxChar);
        },

      setNumRows : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects'),
              properties=object.data('properties');

          if((!properties.initialized || options.numRows!=value) && value>0)
          {
            options.numRows=value;
            if(options.multilines)
            {
              objects.input.attr('rows', options.numRows);
            }
          }
          return(options.numRows);
        },

      setDisabled : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects'),
              properties=object.data('properties');

          if((!properties.initialized || options.disabled!=value) && (value==true || value==false))
          {
            options.disabled=value;
            objects.input.attr('disabled', options.disabled);
          }
          return(options.disabled);
        },

      setTextAlign : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects'),
              properties=object.data('properties');

          if((!properties.initialized || options.textAlign!=value) && (value=='left' || value=='right'))
          {
            options.textAlign=value;
            objects.input.css('text-align', options.textAlign);
          }
          return(options.textAlign);
        },


      setMultilines : function (object, value)
        {
          var options=object.data('options'),
              objects=object.data('objects'),
              properties=object.data('properties');

          if((!properties.initialized || options.multilines!=value) && (value==true || value==false))
          {
            options.multilines=value;

            if(options.multilines)
            {
              objects.input=$('<textarea/>');
            }
            else
            {
              objects.input=$('<input>',
                      {
                        type:"text",
                        value:''
                      }
                    );
            }

            objects.container.append(
                objects.input.bind('keyup.inputText',
                                      function (event)
                                      {
                                        return(privateMethods.keyUp(object, event));
                                      }
                                    )
                                  .bind('change.inputText',
                                      function (event)
                                      {
                                        return(privateMethods.change(object, event));
                                      }
                                    )
                                  .bind('keydown.inputText',
                                      function (event)
                                      {
                                        return(privateMethods.keyDown(object, event));
                                      }
                                    )
            );

          }
          return(options.textAlign);
        }, //setMultilines

      setLanguages : function (object, value)
        {
          var properties=object.data('properties'),
              options=object.data('options');

          options.languages=value;
          options.languagesValues={};

          if(options.languages.length>0)
          {
            if($.inArray(options.currentLanguage, options.languages)<0 ||
               options.currentLanguage=='') options.currentLanguage=options.languages[0];

            for(var i=0;i<options.languages.length;i++)
            {
              properties.languagesValues[options.languages[i]]='';
            }
          }
          else
          {
            options.currentLanguage='';
          }

          return(options.languages);
        }, //setLanguages

      setLanguagesValues : function (object, value)
        {
          var options=object.data('options'),
              properties=object.data('properties');

          if(value==':clear')
          {
            for(var langValue in properties.languagesValues)
            {
              privateMethods.setLanguageValue(object, langValue, '', langValue==options.currentLanguage);
            }
          }
          else if(!$.isEmptyObject(value))
          {
            for(var langValue in value)
            {
              if(properties.languagesValues[langValue]!=null)
                  privateMethods.setLanguageValue(object, langValue, value[langValue], langValue==options.currentLanguage);
            }
          }

          return(properties.languagesValues);
        }, //setLanguagesValues

      setLanguageValue : function (object, language, value, updateInput)
        {
          var options=object.data('options'),
              properties=object.data('properties');

          if(properties.languagesValues[language]!=null)
          {
            properties.languagesValues[language]=value;

            if(updateInput) privateMethods.setValue(object, properties.languagesValues[options.currentLanguage], true);
          }

          return(options.languagesValues);
        }, //setLanguageValue

      setCurrentLanguage : function (object, value)
        {
          var options=object.data('options'),
              properties=object.data('properties');

          if((!properties.initialized || options.currentLanguage!=value) && $.inArray(value, options.languages)>=0)
          {
            options.currentLanguage=value;

            privateMethods.setValue(object, properties.languagesValues[options.currentLanguage], true);
          }

          return(options.currentLanguage);
        }, //setCurrentLanguage

      setLanguageSelector : function (object, value)
        {
          var options=object.data('options'),
              properties=object.data('properties');

          if((!properties.initialized || options.languageSelector!=value) && value!='' && $('#'+value).length>0)
          {
            if(options.languageSelector!='') $('#'+options.languageSelector).unbind('inputListChange');
            options.languageSelector=value;

            if(options.languageSelector!='')
              $('#'+options.languageSelector).bind('inputListChange',
                function (event, lang)
                {
                  privateMethods.setCurrentLanguage(object, lang);
                }
              );
          }

          return(options.currentLanguage);
        }, //setCurrentLanguage

      setValue : function (object, value, apply)
        {
          var options=object.data('options'),
              properties=object.data('properties'),
              objects=object.data('objects');

          if(properties.initialized && properties.value==value)
          {
            return(properties.value);
          }

          privateMethods.setIsValid(object, privateMethods.isValid(object, value));

          properties.value=value;

          if(apply)
          {
            objects.input.val(properties.value);
          }

          if(options.currentLanguage!='') privateMethods.setLanguageValue(object, options.currentLanguage, value, false);

          if(options.change) object.trigger('inputTextChange', properties.value);

          return(properties.value);
        }, //setValue

      setEventChange : function (object, value)
        {
          var options=object.data('options');

          options.change=value;
          object.unbind('inputTextChange');
          if(value) object.bind('inputTextChange', options.change);
          return(options.change);
        },

      keyUp : function (object, event)
        {
          var objects=object.data('objects');

          if(event.keyCode==9 || //DOM_VK_TAB
             event.keyCode==12 || //DOM_VK_CLEAR
             event.keyCode==16 || //DOM_VK_SHIFT
             event.keyCode==17 || //DOM_VK_CONTROL
             event.keyCode==18 || //DOM_VK_ALT
             event.keyCode==33 || //DOM_VK_PAGE_UP
             event.keyCode==34 || //DOM_VK_PAGE_DOWN
             event.keyCode==35 || //DOM_VK_END
             event.keyCode==36 || //DOM_VK_HOME
             event.keyCode==37 || //DOM_VK_LEFT
             event.keyCode==38 || //DOM_VK_UP
             event.keyCode==39 || //DOM_VK_RIGHT
             event.keyCode==40 || //DOM_VK_DOWN
             event.keyCode==45 || //DOM_VK_INSERT
             event.keyCode==93  //DOM_VK_CONTEXT_MENU
            ) return(false);

          return(privateMethods.setValue(object, objects.input.val(), false));
        },

      change : function (object, event)
        {
          var objects=object.data('objects');

          return(privateMethods.setValue(object, objects.input.val(), false))
        },

      keyDown : function (object, event)
        {
          var objects=object.data('objects'),
              options=object.data('options');

          if(options.maxChar>0 &&
             objects.input.val().length>=options.maxChar &&
             !(event.keyCode==8 || //DOM_VK_BACK_SPACE
               event.keyCode==9 || //DOM_VK_TAB
               event.keyCode==12 || //DOM_VK_CLEAR
               event.keyCode==16 || //DOM_VK_SHIFT
               event.keyCode==17 || //DOM_VK_CONTROL
               event.keyCode==18 || //DOM_VK_ALT
               event.keyCode==33 || //DOM_VK_PAGE_UP
               event.keyCode==34 || //DOM_VK_PAGE_DOWN
               event.keyCode==35 || //DOM_VK_END
               event.keyCode==36 || //DOM_VK_HOME
               event.keyCode==37 || //DOM_VK_LEFT
               event.keyCode==38 || //DOM_VK_UP
               event.keyCode==39 || //DOM_VK_RIGHT
               event.keyCode==40 || //DOM_VK_DOWN
               event.keyCode==45 || //DOM_VK_INSERT
               event.keyCode==46 || //DOM_VK_DELETE
               event.keyCode==93 || //DOM_VK_CONTEXT_MENU
               objects.input.get(0).selectionStart!=objects.input.get(0).selectionEnd
              )
          ) return(false);
        },

        /**
         * do translation through a google translate API call (need the GPC google_translate.js file is loaded)
         *
         * @param String input : id of input field ; if empty, translate all localized fields
         */
      doTranslation : function(object)
        {
          var objects=object.data('objects'),
              properties=object.data('properties'),
              options=object.data('options');

          if(googleTranslate!=null)
          {
            googleTranslate(properties.value, '', options.currentLanguage.substr(0,2),
              function (result)
              {
                privateMethods.setValue(object, result, true);
              }
            );
          }
        }

    };


    $.fn.inputText = function(method)
    {
      if(publicMethods[method])
      {
        return publicMethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
      }
      else if(typeof method === 'object' || ! method)
      {
        return publicMethods.init.apply(this, arguments);
      }
      else
      {
        $.error( 'Method ' +  method + ' does not exist on jQuery.inputText' );
      }
    } // $.fn.inputText

  }
)(jQuery);


