-1

好吧,我已经在这里阅读了几个主题,以及如何在 init 函数之外访问 var,但由于我是 javascript 新手,所以我不知道如何去做。我已经感谢你的时间了。

我正在编写我的第一个 jquery 插件 - 一个可以排序、搜索文本、突出显示行......等的表格 - 我面临一个问题。

在“设置”块中,有一个选项 i18N:{'x','y'} - 在 init 方法中,我可以像“options.i18N.search”一样访问它。但是在 *get_table_body* 方法中,在 jqxhr.complete(/* Insert options to manage table data */) 开头,我无法通过 'options.i18N.iSelected' 访问。好的,我知道的都是关于范围的,但我可以解决访问它的唯一方法是制作 'options = $.extend(settings, option)' - 使其成为全球性的。

所以,我问你:我可以在这段代码中访问它的另一种方式是什么——而不使“选项”全局化?我尝试了 $.yTable.options... 和其他几种组合,但没有成功 - 这是意料之中的,因为我不知道自己在做什么。

(function($){
var methods = {
    init : function( option ) { 
        /* Main settings */
        var settings = {
            tableClass:'yTable', /* the class of the table */
            dataFile: 'yTable.php', /* the file that fetch data in JSON format */
            dbTable:'yTableDB', /* the database name that holds the data */
            tColumns: [''], /* an array with the header titles of the table */
            dbTColumns: [''], /* an array with the table name in database */
            dbHColor: '#ded', /* Hover color of rows */
            dbCColor: '#ded', /* Color of column when sorting */
            tStrLen: 1, /* The minimum string length to search */
            insertBottonTh: false, /* Can insert header on bottom? */
            hasFunctions: false, /* Without extra functions */
            canDeleteRow : false, /* Cannot delete single row */
            canDeleteRows: false, /* Cannot delete rows */
            canSort: false, /* Cannot sort table columns */
            /* Options to translate returned text messages */
            i18N: {
                search : 'Buscar',
                confirm : 'Confirmar',
                confirmAll : 'Deseja realmente apagar os registros selecionados'
                        +'? Esta ação não poderá ser desfeita.',
                confirmDel : 'Por favor, confirme a remoção deste registro',
                iSelected : 'Com selecionados',
                noneSelected : 'Para utilizar esta função é necessário que selecione pelo menos um registro.',
                remove : 'Excluir'
            }
        };
        /* Simplify options name */
        var options = $.extend(settings, option);
        var tClass = options.tableClass;
        var tFile = options.dataFile;
        var tName = options.dbTable;
        var tColumns = options.tColumns;
        var dbColumns = options.dbTColumns;
        var tHoverColor = options.dbHColor;
        var tCColor = options.dbCColor;
        var tSLength = options.tStrLen;
        var tThBottom = options.insertBottonTh;
        var tFunctions = options.hasFunctions;
        var tcDeleteRow = options.canDeleteRow;
        var tcDelete = options.canDeleteRows; 
        var tcSort = options.canSort;
        var yTable='table.'+tClass;

        return this.each(function(){
            var obj = $(this);
            var n=tColumns.length;
            if($.isArray(tColumns)&&n>0){
                var th=false;
                var sort_img=false;
                if(tcSort)
                    sort_img='<div class="sort-img"></div>';
                else sort_img='';
                if(tFunctions&&tcDelete)
                    th+='<th width="18"><input type="checkbox" class="check_all" /></th>';
                /* Create the header */
                $.each(tColumns, function(k,v){
                    th+='<th title="'+dbColumns[k]+'" class="th'+k+'">'+v+sort_img+'</th>';
                });
            }
            /* Append table to object */
            var table='<div id="yTableSearch">'+options.i18N.search+': <input type="text" class="yTSearch" /></div>'
            +'<div style="clear:both;"></div><div class="yTableFunctions"></div>'
            +'<table class="'+tClass+'"></table>';
            obj.append(table);
            /* Append delete single row if requested */
            if(tcDeleteRow)
                th+='<th></th>';
            /* Append the headers to table */
            $(yTable).append('<thead>'+th+'</thead>');
            /* If bottom is requested, insert it - its content is the same of thead */
            if(tThBottom)
                $(yTable).append('<tfoot>'+th+'</tfoot>');
            /* Load the body of the table(tbody) */
            methods.get_table_body(tClass, tFile, tName,dbColumns,
                tFunctions, tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable);
        });
    },
    get_table_body: function(tClass, tFile, tName, dbColumns,
        tFunctions, tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom,
        tcDelete, yTable, tCol, qStr){
        $(yTable+' input.check_all').prop('checked',false);
        /* Parameters to receive(order) */
        /* tClass, tFile, tName, dbColumns, tFunctions, tcDeleteRow,tHoverColor,
         * tThBottom, tCColor, tSLength, tcDelete, yTable[, tCol][, qStr] */
        /*****************************************/
        if(!tCol) tCol=':';
        var Cols = tCol.split(':');
        var rCol = $.trim(Cols[0]);
        var sCol = $.trim(Cols[1]);
        var colName = $.inArray(sCol, dbColumns);
        var qCol='';
        var sType='';
        var qByName='';
        var asort=Array(2);
        if(typeof(sCol)=='string' && colName>=0){
            var hObj = $(yTable+' thead th[title='+sCol+']')
            .prop('class');
            var tc=hObj
            .match(/th{1}[^a-z]/);
            var cObj = $(yTable+' th.'+tc);
            var sortImg = $(yTable+' th.'+tc+' div.sort-img');
            var order = hObj.match(/ASC|DESC/);
            if(cObj.hasClass('DESC')&&rCol=='sstring'){
                cObj.removeClass('DESC').addClass('ASC');
                sortImg.css('background-position', '-32px 0');
                asort=[sCol, 'ASC'];
            } else if(cObj.hasClass('ASC')&&rCol=='sstring'){
                cObj.removeClass('ASC').addClass('DESC');
                sortImg.css('background-position', '-48px 0');
                asort=[sCol, 'DESC'];
            } else if(rCol=='qstring'&&order!=null){
                asort=[sCol, $.trim(order)];
            } else {
                $(yTable+' th').removeClass('ASC').removeClass('DESC');
                $(yTable+' th div.sort-img').css('background-position', '0 0');
                cObj.addClass('ASC');
                sortImg.css('background-position', '-32px 0');
                asort=[sCol, 'ASC'];
            }
        }
        if($.isArray(asort)){
            var qCol = asort[0];
            var sType = asort[1];
        }
        if(qStr){
            if(qStr.length>=tSLength && typeof(sCol)=='string'){
                qByName = qStr;
            }
        }

        /*****************************************/
        /* Get data in JSON format */
        var jqxhr = $.get(tFile, {
            'table':tName,
            'cname': dbColumns.join(','),
            'column' : qCol,
            'sort' : sType,
            'sname' : qByName,
            'slength' : tSLength
        },
        function(){
            /* Remove tbody to append a new one */
            $('table.'+tClass+' tbody').remove();
        }).success(function(data){
            /* Mount tbody content */
            if(data!='norow'){
                var rows = $.parseJSON(data);
                var i=0;
                var tbody=false;
                tbody+='<tbody>';
                var tr = false;                
                $.each(rows,function(){
                    var objf = rows['tr'+i];
                    tr+='<tr id="tr'+i+'">'
                    if(tFunctions&&tcDelete)
                        tr+='<td><input type="checkbox" name="tr'+i+'" class="check" /></td>';
                    $.each(objf, function(v){
                        if(v!=='id'){
                            tr+='<td>'+objf[v]+'</td>';
                        }
                    });
                    if(tcDeleteRow)
                        tr+='<td><div class="delete_row" id="r'+objf['id']+'"></div></td>';
                    tr+='</tr>';
                    i++;
                });
            } else {
                var ncolumns = dbColumns.length;
                if(tFunctions&&tcDelete) {
                    ncolumns++;
                }
                if(tcDeleteRow)
                    ncolumns++;
                tr = '<tr><td colspan="'+ncolumns+'">...</td></tr>';
            }
            tbody+=tr+'</tbody>';
            $(yTable).append(tbody);
        }).error(function(){
            alert('Fail');
        });
        jqxhr.complete(function(){
            /* Permit select/deselect all inputs */
            $(yTable+' input.check_all').click(function(){
                var val = this.checked;
                $('.check_all').prop('checked',this.checked);
                var input = $(yTable+' tbody input[type=checkbox]');
                input.prop('checked', val);
                if(input.prop('checked')==true)
                    input.closest('tr').addClass('ySelected');
                else input.closest('tr').removeClass('ySelected');
            });
            /* Insert options to manage table data */
            if(tFunctions&&tcDelete){
                if($('div.yTableFunctions').children().length==0){
                    $('div.yTableFunctions').append(options.i18N.iSelected+': <select class="yTableOperations">'
                        +'<option class="none"> -- </option></select>'
                        +' <input type="button" value="'+options.i18N.confirm+'" name="bConfirm" />');
                    $('div.yTableFunctions').clone().insertAfter(yTable);
                }
                /* If can delete by selection */
                if(tFunctions&&tcDelete){
                    if($('div.yTableFunctions select.yTableOperations option.delete').length==0){
                        methods.delete_selected(yTable);
                    }
                }                    
            }
            /* If requested to delete single row */
            if(tcDeleteRow){
                methods.delete_single_row(tClass);
            }
            /* Stripe table rows */
            methods.stripe_table(tClass);
            /* Select row on click */
            methods.select_on_click(tClass);
            /* First verify what column will be hightlighted ... */
            var i=parseInt($(yTable+' thead th[title='+sCol+']').index(),10)+1;
            /* ... now highlight coresponding column */
            $(yTable+' tr td:nth-child('+i+')').css({
                'background-color': tCColor
            });
            /* ... now sort table */
            methods.sort_table($(yTable+' div.sort-img'),yTable,tClass,
                tFile, tName,dbColumns, tFunctions, tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete);
            /* Highlight on mouse over */
            methods.highlight_on_hover(tClass, tHoverColor,tCColor);
            methods.search_string(tClass, tFile, tName, dbColumns, tFunctions, tcDeleteRow,
                tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable);
        });
    },
    stripe_table: function(c){
        $('table.'+c+' tbody tr').removeClass('stripes');
        $('table.'+c+' tr:nth-child(even)').addClass('stripes');
    },
    highlight_over_highlighted_cell: function(trId,c,h){
        $('table.'+c+' thead th').each(function(){
            if($(this).hasClass('ASC')||$(this).hasClass('DESC'))
                var thId = true;
            if(thId){
                var tHClass=$(this).prop('class').match(/th{1}[^a-z]/);
                /* First verify what column will be hightlighted ... */
                var i=parseInt($('table.'+c+' thead th.'+tHClass).index(),10)+1;
                /* ... now highlight coresponding cell */
                $('table.'+c+' tr#'+trId+' td:nth-child('+i+')').css({
                    'background-color': h
                });
            }
        });
    },
    highlight_on_hover: function(c,h,rh){
        var thisTr = $('table.'+c+' tbody tr');
        thisTr.mouseover(function(){
            /* Tr id */
            var thisTrId=$(this).prop('id');
            $(this).css({
                'background-color':h
            });
            methods.highlight_over_highlighted_cell(thisTrId,c,h);
        }).mouseout(function(){
            $(this).css('background-color','');
            /* Tr id */
            var thisTrId=$(this).prop('id');
            methods.highlight_over_highlighted_cell(thisTrId,c,rh);
        });
    },
    select_on_click:function(c){
        $('table.'+c+' tbody tr').click(function(){
            var $this = $(this);
            var input = $this.children('td').children('input');
            /* Select/desselect row input */
            input.prop('checked', input.prop('checked')?false:true);
            /* Toggle highlight*/
            if(input.prop('checked')==true)
                $this.addClass('ySelected');
            else $this.removeClass('ySelected');
        });
    },
    delete_single_row : function(c){
        $('div.delete_row').click(function(){
            $(this).closest('tr').addClass('highlight_row');
            //                var rId = this.id.replace(/r/,'');
            if(confirm(options.i18N.confirmDel)){
                //                    $.get('delete_row.php',{
                //                        id:rId
                //                    },
                //                    function(data){
                //                        alert(c);
                //                    });
                $(this).closest('tr').hide();
            }else{
                $(this).closest('tr').removeClass('highlight_row');
            }
        });
    },
    delete_selected: function(c){
        var oper = $('select.yTableOperations');
        oper.append('<option class="delete" value="delete">'+options.i18N.remove+'</option>');
        oper.change(function(){
            var opt = $(this).val();
            oper.each(function(){
                $(this).prop('value',opt); 
            });
        });
        $('.yTableFunctions input[type=button]').click(function(){
            if(this.value === options.i18N.confirm && oper.val()==='delete'){
                var regs=[];
                var i=0;
                $(c+' input[type=checkbox].check')
                .each(function(){
                    if(this.checked){
                        regs[i] = this.name;
                        $('tr#'+regs[i]).addClass('highlight_row');/* Highlight marked rows */
                        i++;
                    }
                });
                if(regs.length>0){
                    var rows=[];
                    if(confirm(
                        options.i18N.confirmAll
                        )){
                        $.each(regs, function(k,v){/* Loop through each row */
                            rows[k]='"'+k+'":"'+v+'"';
                            $('tr#'+v).addClass('highlight_del')/* Highlight to delete */
                            .hide('slow') /* Give some time to hide */
                            .remove();/* Remove row */
                        });
                        rows = '{'+rows.join()+'}'; 
                        $(c+' input[type=checkbox].check_all')
                        .prop('checked',false);
                    } else {
                        $('tr').removeClass('highlight_row');
                    }
                }else{
                    alert(options.i18N.noneSelected);
                }
            }
        });            
    },
    sort_table : function(ce,yTable, tClass, tFile, tName,dbColumns,
        tFunctions, tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete){
        $(ce).unbind('click').click(function(e){
            e.stopPropagation();
            var tCol='sstring:'+$(this).closest('th').prop('title');
            var qStr=$('#yTableSearch input.yTSearch').val();
            /* Get data sorted */
            methods.get_table_body(tClass, tFile, tName,dbColumns, tFunctions,
                tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable, tCol, qStr);
        });
    },
    search_string : function(tClass, tFile, tName,dbColumns, tFunctions, tcDeleteRow,
        tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable){
        $('#statistics').unbind('keyup').on('keyup', '#yTableSearch input.yTSearch',
            function(e){
                e.stopImmediatePropagation();
                var qStr=null;
                if(this.value.length>=tSLength
                    &&((e.keyCode>46&&e.keyCode<91)
                        ||(e.keyCode>95&&e.keyCode<106))
                    ||e.keyCode==8||e.keyCode==46
                    ){
                    qStr = this.value;
                    var noSort = 'qstring:';
                    $(yTable+' thead tr th').each(function(e){
                        if($(this).hasClass('ASC')|| $(this).hasClass('DESC')){
                            noSort += $(this).prop('title');
                        }
                    })
                    methods.get_table_body(tClass, tFile, tName,dbColumns, tFunctions,
                        tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable, noSort, qStr);
                }                        
            });
    }
};
$.fn.yTable=function(method){
    /* Method calling logic */
    if ( methods[method] ) {
        return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Desculpe-me, mas o método "' +  method + '" não existe no plugin yTable!' );
    }    
};
})(jQuery);

有效!感谢您花时间帮助我解决这个问题。我将把解决方案放在下面,因为其他人可能会遇到同样的问题。遵循@Beetroot-Beetroot 指令,我更好地理解了这个问题。

修改很少......见下文

方法初始化:

首先,我从设置中取出 i18N 块并将其放入 return this.each()

    init : function( options ) { 
  // codes ...
return this.each(function(){
            var obj = $(this);
            var data = obj.data('yTable');
            data ={
                /* Options to translate returned text messages */
                i18N: {
                    target : obj,
                    search : 'Buscar',
                    confirm : 'Confirmar',
                    confirmAll : 'Deseja realmente apagar os registros selecionados'
                    +'? Esta ação não poderá ser desfeita.',
                    confirmDel : 'Por favor, confirme a remoção deste registro',
                    iSelected : 'Com selecionados',
                    noneSelected : 'Para utilizar esta função é necessário que selecione pelo menos um registro.',
                    remove : 'Excluir',
                    showReg : 'Mostar ',
                    showRegEnd : ' por página',
                    failDbQuery : 'Erro! Não foi possível buscar dados na base de dados. Por favor, verifique sua configuração.'
                }

            }
            obj.data('yTable', data);

// var options = $.extend(data,options); var yOptionLang = obj.data('yTable');

现在我可以通过 yOptionLang.i18N.showReg 在init中访问i18N。因为我需要将 i18N 传递给方法 get_table_body 所以我通过执行 *methods.get_table_body(tClass...yTable).apply(this)* 来实现。

当我从get_table_body调用其他方法时,我将其重写为...

get_table_body:function(tClass,...nReg){
        return $.each(function(){
            var yOption = $(this).data('yTable');
            // code here ...

我可以通过执行 yOption.i18N.iSelected 来访问 i18N ...现在,在此方法中,我必须将 i18N 传递给其他方法,所以我通过...

/* If requested to delete single row */
                if(tcDeleteRow){
                    methods.delete_single_row(tClass).apply(yOption);
                }

...在这种情况下,方法delete_single_row将以...开头

delete_selected:function(c){
        return $.each(function(){
            var yOption = this;
            // code here...

...我可以通过 yOption.i18N.remove 访问i18N

其他棘手的事情是,我需要从其他方法调用get_table_body,所以我必须将.apply(this)放入这些方法中,如下所示对表格进行排序。

sort_table:function(ce,yTable, tClass, tFile, tName,dbColumns,
        tFunctions, tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete){
        $(ce).unbind('click').click(function(e){
            e.stopPropagation();
            var tCol='sstring:'+$(this).closest('th').prop('title');
            var qStr=$('#yTableSearch input.yTSearch').val();
            var nReg = $('div#yTableRegs select#yTableRegSelect').prop('value');
            /* Get data sorted */
            methods.get_table_body(tClass, tFile, tName,dbColumns, tFunctions,
                tcDeleteRow, tHoverColor, tCColor, tSLength, tThBottom, tcDelete, yTable, tCol, qStr, nReg).apply(this);
        });
    }

好吧,现在有了这个修改,我可以将变量从方法传递到方法 - 谢谢你的帮助!

4

1 回答 1

1

问题

这种模式非常聪明,但很难渗透。

要了解的主要内容是:

  • 在最外层范围(之前)中声明的任何变量var methods = ...都将是插件本身特定的(和私有的),而不是对它的任何特定调用
  • 在任何方法中声明的任何 var 都将特定于(和私有)该方法的每个特定调用,并且不能直接用于任何其他方法。在这方面,init 方法与任何其他方法没有什么不同。

因此,没有明显的方法可以在方法之间共享变量。

DOM 来拯救

幸运的是,jQuery 使得在 DOM 中存储数据变得很简单,而这正是这里所需要的。

这是 init 的模板,基于此处的教程:

init : function(options) {
    return this.each(function(index){
        var $this = $(this);
        var data = $this.data(pluginName);
        // If the plugin hasn't been initialized yet
        if (!data) {
            var settings = {
                //default settings here
            };
            if(options) { $.extend(settings, options); }
            data = {
                target : $this,
                //other data properties here
            }
            $this.data(pluginName, data);
            //do other init stuff here
            //create further data properties as required
        }
    });
},

因此,在 init 中建立的数据可用于其他方法:

myMethod : function() {
    return this.each(function(index){
        var $this = $(this);
        var data = $this.data(pluginName);
        //do other method stuff here
        //access data properties as required
    });
},
于 2012-07-29T20:46:24.113 回答