From 18f29820f3f6cb4936143161f3eac51e8557eb4d Mon Sep 17 00:00:00 2001
From: vitalets <noginsk@rambler.ru>
Date: Tue, 27 Nov 2012 13:25:42 +0400
Subject: [PATCH] many fixes for ie7+ compatibility

---
 src/editable-form/editable-form-bootstrap.js |   4 +-
 src/editable-form/editable-form-jqueryui.js  |   6 +-
 src/editable-form/editable-form.css          |  20 +-
 src/editable-form/editable-form.js           | 247 ++++++++++---------
 src/element/editable-element.js              |   8 +-
 src/inputs/date/date.js                      |   2 +-
 src/inputs/dateui/dateui.js                  |   2 +-
 7 files changed, 154 insertions(+), 135 deletions(-)

diff --git a/src/editable-form/editable-form-bootstrap.js b/src/editable-form/editable-form-bootstrap.js
index f6a5273..d55e3fd 100644
--- a/src/editable-form/editable-form-bootstrap.js
+++ b/src/editable-form/editable-form-bootstrap.js
@@ -14,8 +14,8 @@ Editableform based on Twitter Bootstrap
     });    
     
     //buttons
-    $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary"><i class="icon-ok icon-white"></i></button>'+
-                                '<button type="button" class="btn clearfix"><i class="icon-ban-circle"></i></button>';         
+    $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+
+                                '<button type="button" class="btn editable-cancel"><i class="icon-ban-circle"></i></button>';         
     
     //error classes
     $.fn.editableform.errorGroupClass = 'error';
diff --git a/src/editable-form/editable-form-jqueryui.js b/src/editable-form/editable-form-jqueryui.js
index c0b6683..b5983c8 100644
--- a/src/editable-form/editable-form-jqueryui.js
+++ b/src/editable-form/editable-form-jqueryui.js
@@ -8,12 +8,12 @@ Editableform based on jQuery UI
             this.$form = $($.fn.editableform.template);
 
             //buttons
-            this.$form.find('div.editable-buttons').append($.fn.editableform.buttons);                
-            this.$form.find('button[type=submit]').button({
+            this.$form.find('.editable-buttons').append($.fn.editableform.buttons);                
+            this.$form.find('.editable-submit').button({
                 icons: { primary: "ui-icon-check" },
                 text: false
             }).removeAttr('title');
-            this.$form.find('button[type=button]').button({
+            this.$form.find('.editable-cancel').button({
                 icons: { primary: "ui-icon-cancel" },
                 text: false
             }).removeAttr('title');
diff --git a/src/editable-form/editable-form.css b/src/editable-form/editable-form.css
index 446e3fa..f7acde3 100644
--- a/src/editable-form/editable-form.css
+++ b/src/editable-form/editable-form.css
@@ -9,15 +9,24 @@
 
 .editable-buttons {
    display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
+   vertical-align: top;
+   margin-left: 7px;
+   /* display-inline emulation for IE7*/
+   zoom: 1; 
+   *display: inline;
 }
 
 .editable-input {
     vertical-align: top; 
     display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
     width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
+    white-space: normal; /* reset white-space decalred in parent*/
+   /* display-inline emulation for IE7*/
+   zoom: 1; 
+   *display: inline;   
 }
 
-.editable-buttons button {
+.editable-buttons .editable-cancel {
    margin-left: 7px; 
 }
 
@@ -28,7 +37,8 @@
 
 .editableform-loading {
     background: url('img/loading.gif') center center no-repeat;  
-    height: 25px;  
+    height: 25px;
+    width: auto;  
 }
 
 .editable-inline .editableform-loading {
@@ -39,7 +49,7 @@
     max-width: 300px;
     padding-top: 3px;
     margin: 0;
-    clear: both; 
+    width: auto;
 }
 
 .editable-error {
@@ -57,8 +67,8 @@
 }
 
 .editable-clear {
-    clear: both;
-   float: right; 
+   clear: both;
    font-size: 0.9em;
    text-decoration: none;
+   text-align: right;
 }
\ No newline at end of file
diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js
index 8cf8bd2..ed0ac53 100644
--- a/src/editable-form/editable-form.js
+++ b/src/editable-form/editable-form.js
@@ -8,7 +8,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
 @uses textarea
 **/
 (function ($) {
-    
+
     var EditableForm = function (element, options) {
         this.options = $.extend({}, $.fn.editableform.defaults, options);
         this.$element = $(element); //div (usually), containing form. not form tag!
@@ -19,7 +19,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
         constructor: EditableForm,
         initInput: function() {  //called once
             var TypeConstructor, typeOptions;
-            
+
             //create input of specified type
             if(typeof $.fn.editableform.types[this.options.type] === 'function') {
                 TypeConstructor = $.fn.editableform.types[this.options.type];
@@ -34,7 +34,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
         },
         initTemplate: function() {
             this.$form = $($.fn.editableform.template); 
-            
+
             //buttons
             this.$form.find('div.editable-buttons').append($.fn.editableform.buttons);              
         },
@@ -47,54 +47,57 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             this.$loading = $($.fn.editableform.loading);        
             this.$element.empty().append(this.$loading);
             this.showLoading();
-           
+
             this.initTemplate(); 
-            
+
             /**        
             Fired when rendering starts
             @event rendering 
             @param {Object} event event object
             **/            
             this.$element.triggerHandler('rendering');
-            
+
             //render input
             $.when(this.input.render())
             .then($.proxy(function () {
                 //input
                 this.$form.find('div.editable-input').append(this.input.$input);
-                
-                //clear link
+
+                //"clear" link
                 if(this.input.$clear) {
-                    this.$form.find('div.editable-input').append(this.input.$clear);  
+                    this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear));  
                 }                
-                
-                //attach 'cancel' handler
-                this.$form.find('button[type=button]').click($.proxy(this.cancel, this));
+
                 //append form to container
                 this.$element.append(this.$form);
+
+                //attach 'cancel' handler
+                this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
+                //                this.$form.find('.editable-buttons button').eq(1).click($.proxy(this.cancel, this));
+
                 if(this.input.error) {
                     this.error(this.input.error);
-                    this.$form.find('button[type=submit]').attr('disabled', true);
+                    this.$form.find('.editable-submit').attr('disabled', true);
                     this.input.$input.attr('disabled', true);
                 } else {
                     this.error(false);
                     this.input.$input.removeAttr('disabled');
-                    this.$form.find('button[type=submit]').removeAttr('disabled');
+                    this.$form.find('.editable-submit').removeAttr('disabled');
                     this.input.value2input(this.value);
                     this.$form.submit($.proxy(this.submit, this));
                 }
-                
+
                 /**        
                 Fired when form is rendered
                 @event rendered
                 @param {Object} event event object
                 **/            
                 this.$element.triggerHandler('rendered');                
-                
+
                 this.showForm();
             }, this));
         },
-        cancel: function() {
+        cancel: function() {   
             /**        
             Fired when form was cancelled by user
             @event cancel 
@@ -103,12 +106,18 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             this.$element.triggerHandler('cancel');
         },
         showLoading: function() {
-            var fw, fh, iw, bh;
-            //set loading size equal to form
+            var w;
             if(this.$form) {
+                //set loading size equal to form 
                 this.$loading.width(this.$form.outerWidth());
                 this.$loading.height(this.$form.outerHeight());
                 this.$form.hide();
+            } else {
+                //stretch loading to fill container width
+                w = this.$loading.parent().width();
+                if(w) {
+                    this.$loading.width(w);
+                }
             }
             this.$loading.show(); 
         },
@@ -124,11 +133,11 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             **/                    
             this.$element.triggerHandler('show');
         },
-        
+
         error: function(msg) {
             var $group = this.$form.find('.control-group'),
-                $block = this.$form.find('.editable-error-block');
-                
+            $block = this.$form.find('.editable-error-block');
+
             if(msg === false) {
                 $group.removeClass($.fn.editableform.errorGroupClass);
                 $block.removeClass($.fn.editableform.errorBlockClass).empty().hide(); 
@@ -137,15 +146,15 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                 $block.addClass($.fn.editableform.errorBlockClass).text(msg).show();
             }
         },
-               
+
         submit: function(e) {
             e.stopPropagation();
             e.preventDefault();
 
             var error,
-                //get value from input
-                newValue = this.input.input2value(),
-                newValueStr;
+            //get value from input
+            newValue = this.input.input2value(),
+            newValueStr;
 
             //validation
             if (error = this.validate(newValue)) {
@@ -153,14 +162,14 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                 this.showForm();
                 return;
             } 
-            
+
             //value as string
             newValueStr = this.input.value2str(newValue);
-            
+
             //if value not changed --> cancel
             /*jslint eqeq: true*/
             if (newValueStr == this.input.value2str(this.value)) {
-            /*jslint eqeq: false*/                
+                /*jslint eqeq: false*/                
                 this.cancel();
                 return;
             } 
@@ -175,36 +184,36 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                     this.showForm();
                     return;
                 }                
-                
-               //clear error message
-               this.error(false);   
-               this.value = newValue;
-               /**        
-               Fired when form is submitted
-               @event save 
-               @param {Object} event event object
-               @param {Object} params additional params
-                    @param {mixed} params.newValue submitted value
-                    @param {Object} params.response ajax response
-                    
-               @example
-                   $('#form-div').on('save'), function(e, params){
-                       if(params.newValue === 'username') {...}
-                   });                    
-               **/                
-               this.$element.triggerHandler('save', {newValue: newValue, response: response});
+
+                //clear error message
+                this.error(false);   
+                this.value = newValue;
+                /**        
+                Fired when form is submitted
+                @event save 
+                @param {Object} event event object
+                @param {Object} params additional params
+                @param {mixed} params.newValue submitted value
+                @param {Object} params.response ajax response
+
+                @example
+                $('#form-div').on('save'), function(e, params){
+                if(params.newValue === 'username') {...}
+                });                    
+                **/                
+                this.$element.triggerHandler('save', {newValue: newValue, response: response});
             }, this))
             .fail($.proxy(function(xhr) {
-               this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); 
-               this.showForm();  
+                this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); 
+                this.showForm();  
             }, this));
         },
 
         save: function(value) {
             var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this) : this.options.pk,
-                send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
-                params;
-                
+            send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
+            params;
+
             if (send) { //send to server
                 this.showLoading();
 
@@ -214,7 +223,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                     value: value,
                     pk: pk 
                 };
-                
+
                 //additional params
                 if(typeof this.options.params === 'function') {
                     $.extend(params, this.options.params.call(this, params));  
@@ -236,7 +245,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                 }
             }
         }, 
-        
+
         validate: function (value) {
             if (value === undefined) {
                 value = this.value;
@@ -245,38 +254,38 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
                 return this.options.validate.call(this, value);
             }
         },
-        
-       option: function(key, value) {
-          this.options[key] = value;
-          if(key === 'value') {
-              this.setValue(value);
-          }
-       },
-       
-       setValue: function(value, convertStr) {
-          if(convertStr) {
-              this.value = this.input.str2value(value);
-          } else {
-              this.value = value;
-          }
-       }               
+
+        option: function(key, value) {
+            this.options[key] = value;
+            if(key === 'value') {
+                this.setValue(value);
+            }
+        },
+
+        setValue: function(value, convertStr) {
+            if(convertStr) {
+                this.value = this.input.str2value(value);
+            } else {
+                this.value = value;
+            }
+        }               
     };
 
     /*
     Initialize editableform. Applied to jQuery object.
-    
+
     @method $().editableform(options)
     @params {Object} options
     @example
-        var $form = $('&lt;div&gt;').editableform({
-            type: 'text',
-            name: 'username',
-            url: '/post',
-            value: 'vitaliy'
-        });
-        
-        //to display form you should call 'render' method
-        $form.editableform('render');     
+    var $form = $('&lt;div&gt;').editableform({
+    type: 'text',
+    name: 'username',
+    url: '/post',
+    value: 'vitaliy'
+    });
+
+    //to display form you should call 'render' method
+    $form.editableform('render');     
     */
     $.fn.editableform = function (option) {
         var args = arguments;
@@ -287,20 +296,20 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             if (!data) {
                 $this.data('editableform', (data = new EditableForm(this, options)));
             }
-            
+
             if (typeof option === 'string') { //call method 
                 data[option].apply(data, Array.prototype.slice.call(args, 1));
             } 
         });
     };
-    
+
     //keep link to constructor to allow inheritance
     $.fn.editableform.Constructor = EditableForm;    
 
     //defaults
     $.fn.editableform.defaults = {
         /* see also defaults for input */
-        
+
         /**
         Type of input. Can be <code>text|textarea|select|date|checklist</code>
 
@@ -318,12 +327,12 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
         @default null
         @example
         url: function(params) {
-           if(params.value === 'abc') {
-               var d = new $.Deferred;
-               return d.reject('field cannot be "abc"'); //returning error via deferred object
-           } else {
-               someModel.set(params.name, params.value); //save data in some js model
-           }
+        if(params.value === 'abc') {
+        var d = new $.Deferred;
+        return d.reject('field cannot be "abc"'); //returning error via deferred object
+        } else {
+        someModel.set(params.name, params.value); //save data in some js model
+        }
         }        
         **/        
         url:null,
@@ -331,7 +340,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
         Additional params for submit. Function can be used to calculate params dynamically
         @example
         params: function() {
-           return { a: 1 };
+        return { a: 1 };
         }
 
         @property params 
@@ -382,54 +391,54 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
         @default null
         @example
         validate: function(value) {
-            if($.trim(value) == '') {
-                return 'This field is required';
-            }
+        if($.trim(value) == '') {
+        return 'This field is required';
+        }
         }
         **/         
         validate: null,
         /**
         Success callback. Called when value successfully sent on server and response status = 200.
         Can be used to process json response. If this function returns string - means error occured and string is shown as error message.
-        
+
         @property success 
         @type function
         @default null
         @example
         success: function(response, newValue) {
-            if(!response.success) return response.msg;
+        if(!response.success) return response.msg;
         }
         **/          
         success: function(response, newValue) {}         
     };   
 
     /*
-      Note: following params could redefined in engine: bootstrap or jqueryui:
-      Classes 'control-group' and 'editable-error-block' must always present!
+    Note: following params could redefined in engine: bootstrap or jqueryui:
+    Classes 'control-group' and 'editable-error-block' must always present!
     */      
-      $.fn.editableform.template = '<form class="form-inline editableform">'+
-       '<div class="control-group">' + 
-           '<div class="editable-input"></div><div class="editable-buttons"></div>'+
-           '<div class="editable-error-block"></div>' + 
-       '</div>' + 
-       '</form>';
-      
-      //loading div
-      $.fn.editableform.loading = '<div class="editableform-loading"></div>';
-      
-      //buttons
-      $.fn.editableform.buttons = '<button type="submit">ok</button>'+
-                                  '<button type="button">cancel</button>';      
-      
-      //error class attahced to control-group
-      $.fn.editableform.errorGroupClass = null;  
-      
-      //error class attahced to editable-error-block
-      $.fn.editableform.errorBlockClass = 'editable-error';
+    $.fn.editableform.template = '<form class="form-inline editableform">'+
+    '<div class="control-group">' + 
+    '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+
+    '<div class="editable-error-block"></div>' + 
+    '</div>' + 
+    '</form>';
 
-      //input types
-      $.fn.editableform.types = {};
-      //utils
-      $.fn.editableform.utils = {};
+    //loading div
+    $.fn.editableform.loading = '<div class="editableform-loading"></div>';
+
+    //buttons
+    $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+
+    '<button type="button" class="editable-cancel">cancel</button>';      
+
+    //error class attahced to control-group
+    $.fn.editableform.errorGroupClass = null;  
+
+    //error class attahced to editable-error-block
+    $.fn.editableform.errorBlockClass = 'editable-error';
+
+    //input types
+    $.fn.editableform.types = {};
+    //utils
+    $.fn.editableform.utils = {};
 
 }(window.jQuery));
\ No newline at end of file
diff --git a/src/element/editable-element.js b/src/element/editable-element.js
index fe581cd..f51afec 100644
--- a/src/element/editable-element.js
+++ b/src/element/editable-element.js
@@ -35,7 +35,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             //create input of specified type. Input will be used for converting value, not in form
             if(typeof $.fn.editableform.types[this.options.type] === 'function') {
                 TypeConstructor = $.fn.editableform.types[this.options.type];
-                this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, Object.keys(TypeConstructor.defaults));
+                this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
                 this.input = new TypeConstructor(this.typeOptions);
             } else {
                 $.error('Unknown type: '+ this.options.type);
@@ -53,7 +53,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             //attach handler to close any container on escape
             $(document).off('keyup.editable').on('keyup.editable', function (e) {
                 if (e.which === 27) {
-                    $('.editable-container').find('button[type=button]').click();
+                    $('.editable-container').find('.editable-cancel').click();
                 }
             }); 
             
@@ -65,7 +65,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
                     return;
                 }
                 //close all other containers
-                $('.editable-container').find('button[type=button]').click();
+                $('.editable-container').find('.editable-cancel').click();
             });
             
             //add 'editable' class
@@ -229,7 +229,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             }      
                                          
             //hide all other editable containers. Required to work correctly with toggle = manual
-            $('.editable-container').find('button[type=button]').click();
+            $('.editable-container').find('.editable-cancel').click();
             
             //show container
             this.container.show();
diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js
index b16f57e..6490021 100644
--- a/src/inputs/date/date.js
+++ b/src/inputs/date/date.js
@@ -56,7 +56,7 @@ $(function(){
             this.$input.datepicker(this.options.datepicker);
                         
             if(this.options.clear) {
-                this.$clear = $('<a href="#">').addClass('editable-clear').html(this.options.clear).click($.proxy(function(e){
+                this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
                     e.preventDefault();
                     e.stopPropagation();
                     this.clear();
diff --git a/src/inputs/dateui/dateui.js b/src/inputs/dateui/dateui.js
index 986726a..5b39f27 100644
--- a/src/inputs/dateui/dateui.js
+++ b/src/inputs/dateui/dateui.js
@@ -54,7 +54,7 @@ $(function(){
             this.$input.datepicker(this.options.datepicker);
             
             if(this.options.clear) {
-                this.$clear = $('<a href="#">').addClass('editable-clear').html(this.options.clear).click($.proxy(function(e){
+                this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
                     e.preventDefault();
                     e.stopPropagation();
                     this.clear();