Monday, January 6, 2014

jsTransform - Event Fixed (Version 1.0)

After some time for the development and look through the Stackoverflow to study for the need of difficulties, the jqTransform has many aspects needed to be fixed and modified.
However, i still give my first version now.

(I do not give a packed for the example because not one need it, no one wants it.)

jqtransform-dev-2.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<script type="text/javascript" src="/js/jquery-1.7.1.js"></script>
<script type="text/javascript" src="/js/jqtransform/jquery.jqtransform.js"></script>

<link rel="stylesheet" href="/js/jqtransform/jqtransform.css" />
<link rel="stylesheet" href="/js/jqtransform/jqtransform-theme.css" />

<script type="text/javascript">
$(function(){
 $('form.jqtransform').jqTransform({imgPath:'/js/jqtransform/img/'});
});

function onFocusHandler(elem, e){
 elem = $(elem);
 console.log('onFocusHandler - id: ' + elem.attr('id'));
}
function onClickHandler(elem, e){
 elem = $(elem);
 console.log('onClickHandler - id: ' + elem.attr('id'));
}
function onChangeHandler(elem, e){
 elem = $(elem);
 console.log('onChangeHandler - id: ' + elem.attr('id'));
}
function onBlurHandler(elem, e){
 elem = $(elem);
 console.log('onBlurHandler - id: ' + elem.attr('id'));
}
</script>
</head>
<body style="padding:20px;">
<h1>jqTransform - enhancement</h1>

<br/>
<form class="jqtransform" id="form1">
 <div class="rowElem">
  <label for="fullname">Full Name:</label>
  <input type="text" id="fullname" name="fullname" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>
 <div class="rowElem">
  <label for="nickname">Nickname:</label>
  <input type="text" id="nickname" name="nickname" value="Raymond" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>
 <div class="rowElem">
  <label>Gender:</label>
  <input type="radio" id="gender_m" name="gender" value="m" checked="checked" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="radiovalue" for="gender_m">M</label>
  <input type="radio" id="gender_f" name="gender" value="f" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="radiovalue" for="gender_f">F</label>
 </div>
 <div class="rowElem">
  <label>Interest In:</label>
  <input type="checkbox" id="programming" name="programming" value="programming" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="checkboxvalue" for="programming">programming</label>
  <input type="checkbox" id="hiking" name="hiking" value="hiking" checked="checked" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="checkboxvalue" for="hiking">hiking</label>
 </div>
 <div class="rowElem">
  <input type="button" id="button" value="Button" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>

 <div class="rowElem"></div>
</form>
<br/><br/><br/><br/>

<form id="form2">
 <div class="rowElem">
  <label for="fullname2">Full Name:</label>
  <input type="text" id="fullname2" name="fullname2" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>
 <div class="rowElem">
  <label for="nickname2">Nickname:</label>
  <input type="text" id="nickname2" name="nickname2" value="Raymond" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>
 <div class="rowElem">
  <label>Gender:</label>
  <input type="radio" id="gender_m2" name="gender2" value="m" checked="checked" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="radiovalue" for="gender_m2">M</label>
  <input type="radio" id="gender_f2" name="gender2" value="f" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="radiovalue" for="gender_f2">F</label>
 </div>
 <div class="rowElem">
  <label>Interest In:</label>
  <input type="checkbox" id="programming2" name="programming2" value="programming" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="checkboxvalue" for="programming2">programming</label>
  <input type="checkbox" id="hiking2" name="hiking2" value="hiking" checked="checked" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
  <label class="checkboxvalue" for="hiking2">hiking</label>
 </div>
 <div class="rowElem">
  <input type="button" id="button2" value="Button" onfocus="onFocusHandler(this,event);" onblur="onBlurHandler(this,event);" onclick="onClickHandler(this,event);" onchange="onChangeHandler(this,event);"/>
 </div>

 <div class="rowElem"></div>
</form>
<br/>
<br/>
</body>
</html>


jqTransformed form

Before jqTransform
The html contains two forms, and the input elements have HTML attributes for event. Onfocus, onclick , onchange and onblur gives a message log in the console of the browser.


And here is the jqTransform js file.
I wont give explanation this time, since it is not perfect. Some code may need big change in the future versions.

/*
 *
 * jqTransform
 * by mathieu vilaplana mvilaplana@dfc-e.com
 * Designer ghyslain armand garmand@dfc-e.com
 *
 *
 * Version 1.0 25.09.08
 * Version 1.1 06.08.09
 * Add event click on Checkbox and Radio
 * Auto calculate the size of a select element
 * Can now, disabled the elements
 * Correct bug in ff if click on select (overflow=hidden)
 * No need any more preloading !!
 * 
 ******************************************** */
 /*
 * jqTransform - improvement
 * By Raymond Mak wrmond@hotmail.com
 * Add event handles of html attributes for different browsers
 * Version 1.0 2014/01/06
 **/
 
(function($){
 var defaultOptions = {preloadImg:true};
 var jqTransformImgPreloaded = false;

 var jqTransformPreloadHoverFocusImg = function(strImgUrl) {
  //guillemets to remove for ie
  strImgUrl = strImgUrl.replace(/^url\((.*)\)/,'$1').replace(/^\"(.*)\"$/,'$1');
  var imgHover = new Image();
  imgHover.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-hover.$1');
  var imgFocus = new Image();
  imgFocus.src = strImgUrl.replace(/\.([a-zA-Z]*)$/,'-focus.$1');    
 };

 
 /***************************
   Labels
 ***************************/
 var jqTransformGetLabel = function(objfield){
  var selfForm = $(objfield.get(0).form);
  var oLabel = objfield.next();
  if(!oLabel.is('label')) {
   oLabel = objfield.prev();
   if(oLabel.is('label')){
    var inputname = objfield.attr('id');
    if(inputname){
     oLabel = selfForm.find('label[for="'+inputname+'"]');
    } 
   }
  }
  if(oLabel.is('label')){return oLabel.css('cursor','pointer');}
  return false;
 };
 
 /* Hide all open selects */
 var jqTransformHideSelect = function(oTarget){
  var ulVisible = $('.jqTransformSelectWrapper ul:visible');
  ulVisible.each(function(){
   var oSelect = $(this).parents(".jqTransformSelectWrapper:first").find("select").get(0);
   //do not hide if click on the label object associated to the select
   if( !(oTarget && oSelect.oLabel && oSelect.oLabel.get(0) == oTarget.get(0)) ){$(this).hide();}
  });
 };
 /* Check for an external click */
 var jqTransformCheckExternalClick = function(event) {
  if ($(event.target).parents('.jqTransformSelectWrapper').length === 0) { jqTransformHideSelect($(event.target)); }
 };

 /* Apply document listener */
 var jqTransformAddDocumentListener = function (){
  $(document).mousedown(jqTransformCheckExternalClick);
 }; 
   
 /* Add a new handler for the reset action */
 var jqTransformReset = function(f){
  var sel;
  $('.jqTransformSelectWrapper select', f).each(function(){sel = (this.selectedIndex<0) ? 0 : this.selectedIndex; $('ul', $(this).parent()).each(function(){$('a:eq('+ sel +')', this).click();});});
  $('a.jqTransformCheckbox, a.jqTransformRadio', f).removeClass('jqTransformChecked');
  $('input:checkbox, input:radio', f).each(function(){if(this.checked){$('a', $(this).parent()).addClass('jqTransformChecked');}});
 };

 /***************************
   Buttons
  ***************************/
 $.fn.jqTransInputButton = function(){
  return this.each(function(){
   var $input = $(this);
   
   var newBtn = $('<button id="'+ this.id +'" name="'+ this.name +'" type="'+ this.type +'" class="'+ this.className +' jqTransformButton"><span><span>'+ $(this).attr('value') +'</span></span>')
    .hover(function(){newBtn.addClass('jqTransformButton_hover');},function(){newBtn.removeClass('jqTransformButton_hover')})
    .mousedown(function(){newBtn.addClass('jqTransformButton_click')})
    .mouseup(function(){newBtn.removeClass('jqTransformButton_click')})
    
    .focus(function(){
     newBtn.addClass("jqTransformButton_hover");
     $input[0].onfocus && $input[0].onfocus();
    })
    .click(function(){
     $input[0].onclick && $input[0].onclick();
    })
    .blur(function(){
     newBtn.removeClass("jqTransformButton_hover");
     $input[0].onblur && $input[0].onblur();
    })
   ;
   
   //$(this).replaceWith(newBtn);
   $input.addClass('jqTransformHidden').wrap(newBtn);
  });
 };
 
 /***************************
   Text Fields 
  ***************************/
 $.fn.jqTransInputText = function(){
  return this.each(function(){
   var $input = $(this);
 
   if($input.hasClass('jqtranformdone') || !$input.is('input')) {return;}
   $input.addClass('jqtranformdone');
 
   var oLabel = jqTransformGetLabel($(this));
   oLabel && oLabel.bind('click',function(){$input.focus();});
 
   var inputSize=$input.width();
   if($input.attr('size')){
    inputSize = $input.attr('size')*10;
    $input.css('width',inputSize);
   }
   
   $input.addClass("jqTransformInput").wrap('<div class="jqTransformInputWrapper"><div class="jqTransformInputInner"><div></div></div></div>');
   var $wrapper = $input.parent().parent().parent();
   $wrapper.css("width", inputSize+10);
   $input
    .focus(function(){$wrapper.addClass("jqTransformInputWrapper_focus");})
    .blur(function(){$wrapper.removeClass("jqTransformInputWrapper_focus");})
    .hover(function(){$wrapper.addClass("jqTransformInputWrapper_hover");},function(){$wrapper.removeClass("jqTransformInputWrapper_hover");})
   ;
 
   /* If this is safari we need to add an extra class */
   $.browser.safari && $wrapper.addClass('jqTransformSafari');
   $.browser.safari && $input.css('width',$wrapper.width()+16);
   this.wrapper = $wrapper;
   
  });
 };
 
 /***************************
   Check Boxes 
  ***************************/ 
 $.fn.jqTransCheckBox = function(){
  return this.each(function(){
   if($(this).hasClass('jqTransformHidden')) {return;}

   var $input = $(this);
   var inputSelf = this;

   //set the click on the label
   var oLabel=jqTransformGetLabel($input);

   
   var aLink = $('<a href="#" class="jqTransformCheckbox"></a>');
   //wrap and add the link
   $input.addClass('jqTransformHidden').wrap('<span class="jqTransformCheckboxWrapper"></span>').parent().prepend(aLink);
   //on change, change the class of the link
   
   if (oLabel){
    oLabel
    .click(function(){
     $input[0].onfocus && $input[0].onfocus();
     aLink.focus();
     //click
     if($input.attr('disabled')){return false;}
     
     //edit:
     
     //edit: if ie8 or lower , trigger change
     if ($.browser.msie && parseFloat($.browser.version) < 9){
      $input.trigger('click');
      $input.trigger('change');
     }

     //click
     !aLink.hasClass('jqTransformChecked') && aLink.addClass('jqTransformChecked') 
     || aLink.removeClass('jqTransformChecked');
    });
   }
   
   //edit: remove
   //$input.change(function(){
   // this.checked && aLink.addClass('jqTransformChecked') || aLink.removeClass('jqTransformChecked');
   // return true;
   //});
   
   // Click Handler, trigger the click and change event on the input
   aLink
   .mousedown(function(){
    $input[0].onfocus && $input[0].onfocus();
    $(this).focus();
   })
   .blur(function(){
    $input[0].onblur && $input[0].onblur();
   })   
   .click(function(){
    //do nothing if the original input is disabled
    if($input.attr('disabled')){return false;}
    //trigger the envents on the input object
    //$input.trigger('click').trigger("change"); 
    
    //edit:
    $input.trigger('click');
    //edit: if ie8 or lower , trigger change
    if ($.browser.msie && parseFloat($.browser.version) < 9){
     $input.trigger('change');
    }
    //edit: control this style
    !$(this).hasClass('jqTransformChecked') && $(this).addClass('jqTransformChecked') 
    || $(this).removeClass('jqTransformChecked');
    
    return false;
   });

   // set the default state
   this.checked && aLink.addClass('jqTransformChecked');  
  });
 };
 /***************************
   Radio Buttons 
  ***************************/ 
 $.fn.jqTransRadio = function(){
  return this.each(function(){
   if($(this).hasClass('jqTransformHidden')) {return;}

   var $input = $(this);
   var inputSelf = this;
    
   oLabel = jqTransformGetLabel($input);
 
   var aLink = $('<a href="#" class="jqTransformRadio" rel="'+ this.name +'"></a>');
   $input.addClass('jqTransformHidden').wrap('<span class="jqTransformRadioWrapper"></span>').parent().prepend(aLink);
   
   if (oLabel){
    oLabel
    .click(function(){
     $input[0].onfocus && $input[0].onfocus();
     aLink.focus();
     //click
     if($input.attr('disabled')){return false;}
     aLink.addClass('jqTransformChecked');
     
     //edit: if ie8 or lower , trigger change
     if ($.browser.msie && parseFloat($.browser.version) < 9){
      $input.trigger('click');
      $input.trigger('change');
     }
     
     // uncheck all others of same name input radio elements
     $('input[name="'+$input.attr('name')+'"][type=radio]',inputSelf.form).not($input).each(function(){
      $(this).closest('.jqTransformRadioWrapper').find('.jqTransformRadio').removeClass('jqTransformChecked');
     });
    });
   }
   
   //edit: remove this
   //$input.change(function(){
   // inputSelf.checked && aLink.addClass('jqTransformChecked') || aLink.removeClass('jqTransformChecked');
   // return true;
   //});
   
   // Click Handler
   aLink
   .mousedown(function(){
    $input[0].onfocus && $input[0].onfocus();
    $(this).focus();
   })
   .blur(function(){
    $input[0].onblur && $input[0].onblur();
   })
   .click(function(){
    if($input.attr('disabled')){return false;}
    
    $input.trigger('click');
    //edit: if ie8 or lower , trigger change
    if ($.browser.msie && parseFloat($.browser.version) < 9){
     $input.trigger('change');
    }
    //edit: control this style
    $(this).addClass('jqTransformChecked');
 
    // uncheck all others of same name input radio elements
    $('input[name="'+$input.attr('name')+'"][type=radio]',inputSelf.form).not($input).each(function(){
     //$(this).attr('type')=='radio' && $(this).trigger('change');
     //edit: not trigger change event 
     $(this).closest('.jqTransformRadioWrapper').find('.jqTransformRadio').removeClass('jqTransformChecked');
    });
    return false;
   })
   ;
   // set the default state
   inputSelf.checked && aLink.addClass('jqTransformChecked');
  });
 };
 
 /***************************
   TextArea 
  ***************************/ 
 $.fn.jqTransTextarea = function(){
  return this.each(function(){
   var textarea = $(this);
 
   if(textarea.hasClass('jqtransformdone')) {return;}
   textarea.addClass('jqtransformdone');
 
   oLabel = jqTransformGetLabel(textarea);
   oLabel && oLabel.click(function(){textarea.focus();});
   
   var strTable = '<table cellspacing="0" cellpadding="0" border="0" class="jqTransformTextarea">';
   strTable +='<tr><td id="jqTransformTextarea-tl"></td><td id="jqTransformTextarea-tm"></td><td id="jqTransformTextarea-tr"></td></tr>';
   strTable +='<tr><td id="jqTransformTextarea-ml"> </td><td id="jqTransformTextarea-mm"><div></div></td><td id="jqTransformTextarea-mr"> </td></tr>'; 
   strTable +='<tr><td id="jqTransformTextarea-bl"></td><td id="jqTransformTextarea-bm"></td><td id="jqTransformTextarea-br"></td></tr>';
   strTable +='</table>';     
   var oTable = $(strTable)
     .insertAfter(textarea)
     .hover(function(){
      !oTable.hasClass('jqTransformTextarea-focus') && oTable.addClass('jqTransformTextarea-hover');
     },function(){
      oTable.removeClass('jqTransformTextarea-hover');     
     })
    ;
    
   textarea
    .focus(function(){oTable.removeClass('jqTransformTextarea-hover').addClass('jqTransformTextarea-focus');})
    .blur(function(){oTable.removeClass('jqTransformTextarea-focus');})
    .appendTo($('#jqTransformTextarea-mm div',oTable))
   ;
   this.oTable = oTable;
   if($.browser.safari){
    $('#jqTransformTextarea-mm',oTable)
     .addClass('jqTransformSafariTextarea')
     .find('div')
      .css('height',textarea.height())
      .css('width',textarea.width())
    ;
   }
  });
 };
 
 /***************************
   Select 
  ***************************/ 
 $.fn.jqTransSelect = function(){
  return this.each(function(index){
   var $select = $(this);

   if($select.hasClass('jqTransformHidden')) {return;}
   if($select.attr('multiple')) {return;}

   var oLabel  =  jqTransformGetLabel($select);
   /* First thing we do is Wrap it */
   var $wrapper = $select
    .addClass('jqTransformHidden')
    .wrap('<div class="jqTransformSelectWrapper"></div>')
    .parent()
    .css({zIndex: 10-index})
   ;
   
   /* Now add the html for the select */
   $wrapper.prepend('<div><span></span><a href="#" class="jqTransformSelectOpen"></a></div><ul></ul>');
   var $ul = $('ul', $wrapper).css('width',$select.width()).hide();
   /* Now we add the options */
   $('option', this).each(function(i){
    var oLi = $('<li><a href="#" index="'+ i +'">'+ $(this).html() +'</a></li>');
    $ul.append(oLi);
   });
   
   /* Add click handler to the a */
   $ul.find('a').click(function(){
     $('a.selected', $wrapper).removeClass('selected');
     $(this).addClass('selected'); 
     /* Fire the onchange event */
     if ($select[0].selectedIndex != $(this).attr('index') && $select[0].onchange) { $select[0].selectedIndex = $(this).attr('index'); $select[0].onchange(); }
     $select[0].selectedIndex = $(this).attr('index');
     $('span:eq(0)', $wrapper).html($(this).html());
     $ul.hide();
     return false;
   });
   /* Set the default */
   $('a:eq('+ this.selectedIndex +')', $ul).click();
   $('span:first', $wrapper).click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
   oLabel && oLabel.click(function(){$("a.jqTransformSelectOpen",$wrapper).trigger('click');});
   this.oLabel = oLabel;
   
   /* Apply the click handler to the Open */
   var oLinkOpen = $('a.jqTransformSelectOpen', $wrapper)
    .click(function(){
     //Check if box is already open to still allow toggle, but close all other selects
     if( $ul.css('display') == 'none' ) {jqTransformHideSelect();} 
     if($select.attr('disabled')){return false;}

     $ul.slideToggle('fast', function(){     
      var offSet = ($('a.selected', $ul).offset().top - $ul.offset().top);
      $ul.animate({scrollTop: offSet});
     });
     return false;
    })
   ;

   // Set the new width
   var iSelectWidth = $select.outerWidth();
   var oSpan = $('span:first',$wrapper);
   var newWidth = (iSelectWidth > oSpan.innerWidth())?iSelectWidth+oLinkOpen.outerWidth():$wrapper.width();
   $wrapper.css('width',newWidth);
   $ul.css('width',newWidth-2);
   oSpan.css({width:iSelectWidth});
  
   // Calculate the height if necessary, less elements that the default height
   //show the ul to calculate the block, if ul is not displayed li height value is 0
   $ul.css({display:'block',visibility:'hidden'});
   var iSelectHeight = ($('li',$ul).length)*($('li:first',$ul).height());//+1 else bug ff
   (iSelectHeight < $ul.height()) && $ul.css({height:iSelectHeight,'overflow':'hidden'});//hidden else bug with ff
   $ul.css({display:'none',visibility:'visible'});
   
  });
 };
 $.fn.jqTransform = function(options){
  var opt = $.extend({},defaultOptions,options);
  
  /* each form */
   return this.each(function(){
   var selfForm = $(this);
   if(selfForm.hasClass('jqtransformdone')) {return;}
   selfForm.addClass('jqtransformdone');
   
   $('input:submit, input:reset, input[type="button"]', this).jqTransInputButton();   
   $('input:text, input:password', this).jqTransInputText();   
   $('input:checkbox', this).jqTransCheckBox();
   $('input:radio', this).jqTransRadio();
   $('textarea', this).jqTransTextarea();
   
   if( $('select', this).jqTransSelect().length > 0 ){jqTransformAddDocumentListener();}
   selfForm.bind('reset',function(){var action = function(){jqTransformReset(this);}; window.setTimeout(action, 10);});
   
   //preloading dont needed anymore since normal, focus and hover image are the same one
   /*if(opt.preloadImg && !jqTransformImgPreloaded){
    jqTransformImgPreloaded = true;
    var oInputText = $('input:text:first', selfForm);
    if(oInputText.length > 0){
     //pour ie on eleve les ""
     var strWrapperImgUrl = oInputText.get(0).wrapper.css('background-image');
     jqTransformPreloadHoverFocusImg(strWrapperImgUrl);     
     var strInnerImgUrl = $('div.jqTransformInputInner',$(oInputText.get(0).wrapper)).css('background-image');
     jqTransformPreloadHoverFocusImg(strInnerImgUrl);
    }
    
    var oTextarea = $('textarea',selfForm);
    if(oTextarea.length > 0){
     var oTable = oTextarea.get(0).oTable;
     $('td',oTable).each(function(){
      var strImgBack = $(this).css('background-image');
      jqTransformPreloadHoverFocusImg(strImgBack);
     });
    }
   }*/
   
   
  }); /* End Form each */
    
 };/* End the Plugin */

})(jQuery);
       



A better version will be scheduled. It needs time.

No comments:

Post a Comment