/** * DataGrid widget * * @param appendTo {String} element id which will be appended. * @param target {HTMLELement} data element. * @param aData {Array} [[],[],...,[]]. * @param aNames {Array} ["name1", "name2",...]. * @param isEdit {Boolean} decide whether datagrid can be edited * @param hasHeader {Boolean} * @param headerCont {Array} * @param hasTotal {Boolean} * @param trEvent {JSON} ex. {event:function}. * @param tdEvent {JSON} ex. {event:function}. * @param tdUnbind {Array} the cell index which event do not bind. * @param zebras {JSON} tr css. * @param norTrCss {JSON} tr css. * @param curTrCss {JSON} tr css. * @param align {String} td align. * @param editPos {String} row edit area position. * @param editBtns {Array} array of edit buttons. * @param editBtnHandler {Array} event function of edit buttons. ex.[{event1:function}, {event1:function},...]. * @param deleteBtnCss {String} default delete button style. * @param deleteRowCallback {Function} delete callback function. * @param batchBarPos {String} batch bar position * @param batchBtns {Array} array of batch buttons * @param batchBtnHandler {Array} the same with editBtnHandler * @param selectAllCss {String} the style of select all checkbox * @param batchDeleteCss {String} default batch delete button style. * @param batchDeleteCallback{Function} batch delete callback function. * */ var datagrid = function(params, undefined){ this.options = { appendTo:"", target:"", //data and post names aData:[], aNames:[], isEdit:true, //header and total handler hasHeader:false, headerCont:[], hasTotal:false, //totalCells:[], //totalHandler:{}, //td event trEvent:{}, tdEvent:{}, tdUnbind:[], //tr css zebras:{background:"#d4e4ff"}, norTrCss:{background:""}, curTrCss:{background:"#dddddd"}, align:"center", //edit area editPos:"right", editBtns:[], editBtnHandler:[], deleteBtnCss:"", deleteRowCallback:function(){}, //batch area batchBarPos:"top", batchBtns:[], batchBtnHandler:[], selectAllCss:"", batchDeleteCss:"", batchDeleteCallback:function(){} }; wapi.extend(this.options, params); if(this.options.appendTo != "" && document.getElementById(this.options.appendTo)) wapi("#" + this.options.appendTo).append(this.options.target); else if(this.options.target == ""){ this.options.target = wapi("<table>").attr({cellspacing:0, cellpadding:0})[0]; wapi("body").append(this.options.target); } //default edit button and handler this.editBtns = [wapi("<a>").html("DELETE").attr("style", this.options.deleteBtnCss)]; this.editBtnHandler = [{click:function(){ if(this.datagrid.block) return; //block edit mode wapi(this.tr).remove(); this.datagrid.block = false; this.datagrid.options.deleteRowCallback.apply(this, arguments); } }]; //default batch button and handlers this.batchBtns = [wapi("<input>").attr({type:"checkbox", name:"selectAll"}).attr("style", this.options.selectAllCss), wapi("<a>").html("DELETE").attr("style", this.options.batchDeleteCss)]; this.batchBtnHandler = [ { click:function(){ var chkBox = this.datagrid.getChkbox(); function set(chk){ wapi.each(chkBox.chkBox, function(i, elem){ elem.checked = chk; }); } if(chkBox.chkBox.length > 0) set(!(chkBox.selectAllBox.checked == false)); } }, { click:function(){ if(this.datagrid.block) return; //block edit mode if(this.tr.length > 0){ var chkBox = this.datagrid.getChkbox(true); chkBox.selectAllBox.checked = false; } wapi.each(this.tr, function(i, elem){ wapi(this).remove(); }); this.datagrid.block = false; this.datagrid.options.batchDeleteCallback.apply(this, arguments); } } ]; //handler array this.curTr = []; this.curTd = []; //edit block this.block = false; this.cellsNum = 0; this.init(); }; datagrid.prototype = { init:function(){ this.createHeader(); if(this.options.isEdit) { this.bindBtnHandler(this.batchBtns.concat(this.options.batchBtns), this.batchBtnHandler.concat(this.options.batchBtnHandler), this.batchBar = wapi(this.options.target.insertRow((this.options.batchBarPos === "bottom" ? this.options.target.rows.length : 0)).insertCell(0)).attr({colspan:this.cellsNum})); } var add = wapi.bindScope(this, this.add); wapi.each(this.options.aData, function(index, dataItem){ if(dataItem.length > 0) add(dataItem); }); }, createHeader:function(){ if(this.options.hasHeader){ if(this.options.headerCont.length > 0) { var tr = this.options.target.insertRow(0); this.setCellsNum(this.options.headerCont); for(var i=0; i<this.cellsNum; i++){ if(i == this.cellsNum -1 && this.options.isEdit){ if(this.options.editPos == "left") tr.insertCell(1); else tr.insertCell(i); }else wapi(tr.insertCell(i)).html(this.options.headerCont[i]); } }else{ this.setCellsNum(this.options.aData[0]); var tr = this.options.target.rows[0]; if(this.options.isEdit){ if(this.options.editPos == "left") tr.insertCell(1); else tr.insertCell(tr.cells.length); } } } }, setCellsNum:function(aData){ //if(this.cellsNum != 0) return; if(!!aData) this.cellsNum = aData.length > 0 ? this.options.isEdit ? aData.length + 1 : aData.length : 0; if(typeof this.headerCellsNum === "undefined" && this.options.hasHeader) this.headerCellsNum = this.options.isEdit ? this.options.target.rows[0].cells.length + 1 : this.options.target.rows[0].cells.length; this.cellsNum = Math.max(this.headerCellsNum, this.cellsNum); }, bindBtnHandler:function(aElem, aFn, target, source){ var getSelected = wapi.bindScope(this, this.getSelected); var bindTrEvent = wapi.bindScope(this, this.bindTrEvent); wapi.each(aElem, function(i, btn){ btn = wapi(btn[0].cloneNode(true)); if(!!aFn[i] && !wapi.isEmptyObject(aFn[i])){ wapi.each(aFn[i], function(pro, fn){ target.append( btn[pro](function(){ fn.apply(getSelected(source), arguments); bindTrEvent(); }) ); }); }else target.append(btn); }); }, bindTdEvent:function(td, fn, event){ var datagrid = { td:td, datagrid:this }; this.curTd = td; this.cancelBubble(event); if(!this.options.isEdit) return; if(!this.block) fn.call(datagrid, event); }, bindTrEvent:function(tr){ var target = this.options.target; var isEdit = this.options.isEdit; var hasTotal = this.options.hasTotal; var hasHeader = this.options.hasHeader; var mouseOver = wapi.bindScope(this, function(tr){ if(!this.block) wapi(tr).css(this.options.curTrCss); }); var norMouseout = wapi.bindScope(this, function(tr){ wapi(tr).css(this.options.norTrCss); }); var zebrasMouseout = wapi.bindScope(this, function(tr){ wapi(tr).css(this.options.zebras); }) var bindMouseEvent = wapi.bindScope(this, function(a, tr){ if(a) tr.css(this.options.zebras).mouseout(function(){zebrasMouseout(this)}); else tr.mouseout(function(){norMouseout(this)}); tr.mouseover(function(){ mouseOver(this); }); }); var setEvent = wapi.bindScope(this, function(tr){ var index = tr.rowIndex; tr = wapi(tr); tr.css(this.options.norTrCss); switch(this.options.batchBarPos) { case "bottom": if(isEdit && index == target.rows.length - 1) return; if(isEdit && index == 0 && hasHeader) return; if(hasTotal && ((isEdit && index == target.rows.length - 2) || (!isEdit && index == target.rows.length - 1))) return; bindMouseEvent(index%2 != 0, tr); break; case "top": if(isEdit && index == 0) return; if(isEdit && index == 1 && hasHeader) return; if(hasTotal && index == target.rows.length - 1) return; bindMouseEvent(index%2 == 0, tr); break; } }); if(tr) { setEvent(tr); this.curTr = tr; } else { var _target = wapi(this.options.target); if(_target.child("tbody").length > 0) _target = _target.child("tbody"); _target.child("tr").each(function(i, tr){ setEvent(tr); }); } }, update:function(aData){ var index = 0; var endIndex = 0; if(this.block) return; if(this.options.hasHeader){ if(this.options.isEdit && this.options.batchBarPos == "top") index = 2; else index = 1; }else if(this.options.isEdit && this.options.batchBarPos == "top") index = 1; if(this.options.hasTotal ){ if(this.options.isEdit && this.options.batchBarPos == "bottom") endIndex = 2; else endIndex = 1; }else if(this.options.isEdit && this.options.batchBarPos == "bottom") endIndex = 1; while(this.options.target.rows.length > index + endIndex){ this.options.target.deleteRow(index); } this.options.aData = aData; var add = wapi.bindScope(this, this.add); wapi.each(this.options.aData, function(index, dataItem){ if(dataItem.length > 0) add(dataItem); }); this.resetSelectAll(); }, add:function(aData){ var target = this.options.target; var tick = this.options.isEdit && this.options.batchBarPos === "bottom" ? 1 : 0; var index = this.options.hasTotal ? target.rows.length - 1 - tick : target.rows.length - tick; var tr = target.insertRow(index); this.bindTrEvent(tr); this.items(tr, aData, this.options.aNames); wapi(tr).css("opacity", 0).animate({opacity:"=1"}, 300); this.resetSelectAll(); }, items:function(tr, aData, aNames){ var bindTdEvent = wapi.bindScope(this, this.bindTdEvent); if(this.cellsNum === 0) { this.setCellsNum(aData); if(this.options.isEdit && this.batchBar.attr("colspan") == 0) this.batchBar.attr("colspan", this.cellsNum); } for(var i = 0; i < this.cellsNum; i++){ (function(i, datagrid){ var td = tr.insertCell(i); var name = typeof aNames[i] !== "undefined" ? aNames[i] : ""; var data = aData[i]; td.align = datagrid.options.align; td.data = wapi("<input>").attr({name:name, type:"hidden", value:data}); if(datagrid.options.isEdit){ if(i == 0) { var chkBox = datagrid.getChkbox(); wapi(td).append(wapi("<input>").attr({type:"checkbox", name:name, value:data})).append(td.data).click(function(){ chkBox.selectAllBox.checked = false; }); //for batch edit return; } else if(i == datagrid.cellsNum - 1){ if(datagrid.options.editPos === "left") td = tr.insertCell(1); datagrid.bindBtnHandler(datagrid.editBtns.concat(datagrid.options.editBtns), datagrid.editBtnHandler.concat(datagrid.options.editBtnHandler), wapi(td), td); return; } } if(typeof data === "undefined" || data == "" || data == 0 || data == "disabled" || data == "none") td.innerHTML = "-";//no data else { wapi(td).html(data).append(td.data); var isBind = true; if(datagrid.options.tdUnbind.length > 0) wapi.each(datagrid.options.tdUnbind, function(i, index){ if(td.cellIndex == index) isBind = false; }); if(isBind && !wapi.isEmptyObject(datagrid.options.tdEvent)) wapi.each(datagrid.options.tdEvent, function(pro, fn){ wapi(td)[pro](function(event){ bindTdEvent(this, fn, event); }); }); } })(i, this) } return tr; }, getSelected:function(elem){ var curTr = []; var curTd = []; var datagridObject = this; var getIt = wapi.bindScope(this, this.getIt); if(elem !== undefined && elem){ var aSelect = this.getIt(elem); curTr = aSelect.tr; curTd = aSelect.td; }else{ wapi.each(this.getChkbox(true).chkBox, function(i, elem){ curTr.push(getIt(elem).tr); }); } this.curTr = curTr; this.curTd = curTd return { tr:curTr, td:curTd, datagrid:datagridObject } }, resetSelectAll:function(){ var chkbox = this.getChkbox(); if(this.options.isEdit) chkbox.selectAllBox.checked = false; }, getIt:function(elem){ var _tr, _td; while(elem){ if(elem.tagName === "TR"){ _tr = elem; break; } if(elem.tagName === "TD") _td = elem; elem = elem.parentNode; } return{ tr:_tr, td:_td } }, /* * get checkbox * * @param filter {Boolean} filter checkbox * * return {JSON} */ getChkbox:function(filter){ var inputs = this.options.target.getElementsByTagName("input"); var selectAllBox = []; var chkBox = []; if(typeof filter !== "undefined") wapi.each(inputs, function(i, elem){ if(wapi(elem).attr("type") === "checkbox"){ if(wapi(elem).attr("name") === "selectAll") selectAllBox = elem; else if(elem.checked == filter) chkBox.push(elem); } }); else wapi.each(inputs, function(i, elem){ if(wapi(elem).attr("type") === "checkbox" ) { if(wapi(elem).attr("name") === "selectAll") selectAllBox = elem; else chkBox.push(elem); } }); return { chkBox:chkBox, selectAllBox:selectAllBox } }, cancelBubble:function(e){ e = e || window.event; window.event ? e.cancelBubble = true : e.stopPropagation(); } };
test page:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>data grid</title> <script src="wishfi.js" type="text/javascript"></script> <script src="dataGrid.js" type="text/javascript"></script> </head> <body> <input id="minimum_impression" name="" type="text"> <div style="660px;"> <table id="categoryData" width="100%" border="0" cellspacing="0" cellpadding="3"> <tbody> <tr> <th width="30"></th> <th width="180">Category Name</th> <th width="170">Impressions Budget</th> <th width="170">Percentage(%)</th> </tr> <tr> <th width="30"> </th> <th width="180">total</th> <th width="170" id="impressionTotal">0</th> <th width="170" id="percentTotal">0%</th> </tr> </tbody> </table> <div id="addCategory" style="position:relative; height:27px; overflow:hidden;"> <table cellspacing="0" cellpadding="3" border="0" width="100%" style="position:absolute; top:-35px;"> <tbody> <tr> <td width="30"> </td> <td align="center" width="180" valign="middle"> <select style="height: 18px; 130px; display: block;" name="category" class="category" id="category"> <option selected="" value="">Choose an category</option> <option value="1"> TELECO NETWK,FIXED&MOBILEPHONE</option><option value="2">INTERNET SP/ PORTAL ALL</option><option value="3">BANKING/FINANCE</option><option value="4">AIRLINES</option><option value="5">GOVT SVCS (STAT BOARD,GOVT CAMPAIGN)</option><option value="6">CREDIT/CHARGE/DEBIT CARD/TRAVEL</option><option value="7">MOVIE</option><option value="8">INSURANCE</option><option value="9">LOTTERIES/COMPETITIONS</option><option value="10">HOTELS/RESORTS</option><option value="11">PHOTOGRAPHIC</option><option value="12">HAIR CARE PRODUCTS</option><option value="13">FASTFOOD OUTLETS</option><option value="14">EDUCATION (OTHERS)</option><option value="15">BEAUTY & FITNESS SVCS</option><option value="16">TRAVEL AGENCIES/TOURIST COMMIS</option><option value="17">ALL CARS + MOTORING</option><option value="18">SPORTS/GYM EQUIPMENT/SPORTS CTR/CLUB</option><option value="19">PC/NOTEBOOK/TABLET PC/SERVER/N</option><option value="20">SKIN CARE PRODUCTS</option><option value="21">OPTICALS</option><option value="22">FREIGHT/LOGISTICS/COURIER/SHIP</option><option value="23">EVENTS/ CONCERTS/ EXHIBTIONS ALL</option><option value="24">TELEVISION</option><option value="25">INVESTMENT/FUNDS</option><option value="26">CONFECTIONARY ALL</option><option value="27">BEER & STOUT ALL</option><option value="28">SUPER/HYPER/MINI MARKET/FOOD STORES</option><option value="29">PERFUME/COLOGNE</option><option value="30">AUDIO VISUAL EQUIPMENT</option> </select> </td> <td align="center" width="170" valign="middle"><input type="text" style=" 130px; text-align: center;" id="impressions" name="impressions_temp[]" class="impressions[]" value=""></td> <td align="center" width="170" valign="middle"><input type="text" style=" 130px; text-align: center;" id="percentage" name="percentage_temp[]" class="percentage[]" value=""></td> <td align="center" width=""> <a id="upload">upload</a> <a id="exitAdd">exit</a> </td> </tr> </tbody> </table> </div> </div> <script> (function(){ /** * init category datagrid * */ var categoryData = new datagrid({ target:wapi("#categoryData")[0], aData:[ [3, "a", "10"], [4, "b", "10"] ], aNames:["category_id[]", "category_name[]", "impressions[]", "percentage[]"], isEdit:true, hasHeader:true, hasTotal:true, //row edit deleteRowCallback:function(){ deleteTotal(this.tr); }, //batch handler area selectAllCss:"margin:0 9px; padding:0;", batchBarPos:"bottom", batchDeleteCallback:function(){ wapi.each(this.tr, function(i, tr){ deleteTotal(tr); }) }, batchBtns:[ wapi("<input>").attr({type:"button", value:"add"}) ], batchBtnHandler:[ { click:function(){ if(!this.datagrid.block) wapi("#addCategory").child("table").animate({top:"=0"}, 300); this.datagrid.block = true; //enter edit mode var i = 0; if(categoryData.options.isEdit) i++; if(categoryData.options.hasTotal) i++; if(categoryData.options.hasHeader) i++; if(categoryData.options.target.rows.length == i) { impressions.attr("value", "").css("color", "")[0].removeAttribute("disabled"); percentage.attr("value", "").css("color", "")[0].removeAttribute("disabled"); } var exitAdd = wapi.bindScope(this, function(){ wapi("#addCategory").child("table").animate({top:"=-35"}, 300); hidErro(category[0]); hidErro(impressions[0]); hidErro(percentage[0]); this.datagrid.block = false; //exit edit mode }); wapi("#exitAdd").click(exitAdd); } } ], tdUnbind:[1], tdEvent:{ click:editCell } }); var categoryReg = { reg:/^[1-9]\d*$|^[0]\d+$/i, msg:"Integer required." } var emptyFN = function(){}; var upload = wapi("#upload"); var category = wapi("#category").change(function(){ chkData({ reg:/^[1-9]\d*$|^[0]\d+$/i, msg:"Select a category." }, this); }); var impressions = wapi("#impressions").keyup(function(){ keyuphandler(impressions, percentage); }); var percentage = wapi("#percentage").keyup(function(){ keyuphandler(percentage, impressions); }); initTotal(); /*total handler*/ function initTotal(){ var percentageTotal = 0 var impressionsTotal = 0; function disabled(elem){ elem.attr({value:"disabled", disabled:"disabled"}).css("color", "#cccccc"); } wapi.each(categoryData.options.target.rows, function(i, tr){ wapi.each(tr.cells, function(i, td){ if(typeof td.data !== "undefined"){ var input = td.data var name = input.attr("name"); var value = parseFloat(input.attr("value")) + "" === "NaN" ? 0 :parseFloat(input.attr("value")) if(name == "percentage[]") percentageTotal += value; else if(name == "impressions[]") impressionsTotal += value; } }); }); wapi("#percentTotal").html(percentageTotal + "%"); wapi("#impressionTotal").html(impressionsTotal); if(percentageTotal == 0) disabled(percentage); else if(impressionsTotal == 0) disabled(impressions); } function deleteTotal(tr){ var td = tr.cells; for(var i = 0 , l = td.length; i < l; i++){ if(typeof td[i].data !== "undefined") { if(i == 1){ category.child("option").each(function(n, elem){ if(elem.innerHTML == td[i].data.attr("value")) elem.removeAttribute("disabled"); }); } var total = 0; var input = td[i].data var name = input.attr("name"); var percentTotal = parseFloat(wapi("#percentTotal").html()); var impressionTotal = parseFloat(wapi("#impressionTotal").html()); if(name == "percentage[]" && percentTotal > 0) { percentTotal -= parseFloat(input.attr("value")); wapi("#percentTotal").html(percentTotal + "%"); } else if(name == "impressions[]" && impressionTotal > 0) { impressionTotal -= parseFloat(input.attr("value")); wapi("#impressionTotal").html(impressionTotal); } } } } function totalHandler(name){ var total = 0; var isPass = true; wapi.each(categoryData.options.target.getElementsByTagName("input"), function(i, elem){ elem = wapi(elem); if(elem.attr("type") === "hidden" && elem.attr("name") === name){ total += parseFloat(elem.attr("value")); } }); if(name == "percentage[]"){ if(total / 100 > 1) isPass = false; else wapi("#percentTotal").html(total + "%"); }else if(name == "impressions[]"){ var totalLimit = parseFloat(wapi("#minimum_impression").attr("value")) + "" !== "NaN" ? parseFloat(wapi("#minimum_impression").attr("value")) : 0; if(totalLimit != 0){ if(total > totalLimit) isPass = false; else wapi("#impressionTotal").html(total); } else if(totalLimit == 0) wapi("#impressionTotal").html(total); else wapi("#impressionTotal").html(total); } return { isPass:isPass, total:total } } /*-- total handler end --*/ function keyuphandler(a, b){ var name = a.attr("name"); name = name.slice(0, name.indexOf("_")) + "[]"; var total = totalHandler(name).total; total = total + parseFloat(a.attr("value")); var totalLimit = parseFloat(wapi("#minimum_impression").attr("value")) + "" !== "NaN" ? parseFloat(wapi("#minimum_impression").attr("value")) : 0; totalLimit = name == "percentage[]" ? 100 : totalLimit; if(a.attr("value") == "") { hidErro(a[0]); return; } if(chkData(categoryReg, a[0])){ if(total > totalLimit && totalLimit != 0){ showErro(a[0], "Out of limit."); upload.click(emptyFN); }else{ hidErro(b[0]); b.attr({value:"disabled", disabled:"disabled"}).css("color", "#cccccc"); upload.click(addCategory); } }else if(a.attr("value") == ""){ hidErro(a[0]); var i = 0; if(categoryData.options.isEdit) i++; if(categoryData.options.hasTotal) i++; if(categoryData.options.hasHeader) i++; if(categoryData.options.target.rows.length == i) b.attr("value", "").css("color", "")[0].removeAttribute("disabled"); upload.click(emptyFN); }else upload.click(emptyFN); } function addCategory(){ var v0 = category[0].value; var v1 = category[0].options[category[0].selectedIndex].innerHTML; var v2 = impressions.attr("value") === "disabled" ? "" : impressions.attr("value"); var v3 = percentage.attr("value") === "disabled" ? "" : percentage.attr("value"); if(v0 == ""){ chkData({ reg:/^[1-9]\d*$|^[0]\d+$/i, msg:"Select a category." }, category[0]); return; } categoryData.add([v0, v1, v2, v3]); //reset select&input element category[0].options[category[0].selectedIndex].disabled = "disabled"; category[0].options[0].selected = "selected"; if(v2 !== "") impressions.attr("value",""); if(v3 !== "") percentage.attr("value",""); initTotal(); } /** * category cell edit method * */ function editCell(){ var td = wapi(this.td); var datagrid = this.datagrid; var name = td[0].data.attr("name"); var oldValue = td.child("input").attr("value"); var oldTotal = totalHandler(name).total - parseFloat(td[0].data.attr("value")); var input = wapi("<input>").attr({type:"text", value:oldValue}).css({"80px", height:"16px", textAlign:"center"}).click(function(event){ datagrid.cancelBubble(event); }).blur(function(){ if(chkData(categoryReg, this)){ td[0].data.attr("value", this.value); if(!totalHandler(name).isPass){ td[0].data.attr("value", oldValue); showErro(input[0], "Out of limit."); }else{ td.html(this.value); td.append(td[0].data).css("background", ""); datagrid.block = false; hidErro(input[0]); input = null; } } }).keyup(function(event){ if(this.value == ""){ hidErro(this); if(name == "percentage[]") wapi("#percentTotal").html(oldTotal + "%"); else if(name == "impressions[]") wapi("#impressionTotal").html(oldTotal); }else { if(chkData(categoryReg, this)){ td[0].data.attr("value", this.value);//set current data if(!totalHandler(name).isPass){//check total limite and calculate td[0].data.attr("value", oldValue); totalHandler(name) //restore last total showErro(input[0], "Out of limit."); }else hidErro(input[0]); td[0].data.attr("value", oldValue);//restore original data } } if(event.keyCode == 27){ this.onblur = function(){}; // unbind onblur event hidErro(this); td[0].data.attr("value", oldValue); td.html(oldValue); td.append(td[0].data).css("background", ""); datagrid.block = false; input = null; } }); td.html("").append(input).append(td[0].data).css("background", "#F60"); input[0].focus(); this.datagrid.block = true; } /*-- cell edit method end --*/ /** * check data format * */ function chkData(reg, elem){ var value = elem.value; if(!reg.reg.test(elem.value)) { showErro(elem, (typeof reg.msg === "undefined" ? "" : reg.msg)); return false; } else{ hidErro(elem); return true; } } function showErro(elem, msg){ var erroCss = { height:"16px", lineHeight:"16px", padding:"0 3px", border:"1px solid #666666", background:"#FFFFFF" }; msg = wapi("<div>").css(erroCss).html(msg); if(typeof elem.hover !== "undefined"){ if(elem.hover.element.css("display") == "none") { elem.hover.element.html("").append(msg); elem.hover.show("fast"); }else elem.hover.element.html("").append(msg); }else { wapi(elem).hover("right", msg, {left:1}); elem.hover.show("fast"); } } function hidErro(elem){ if(typeof elem.hover !== "undefined" && elem.hover.element.css("display") != "none") elem.hover.hidden("fast"); } /*-- check format end --*/ })() </script> </body> </html>