-1

さて、私はすでにいくつかのトピックを読みましたが、 init 関数の外で var にアクセスする方法として、私は javascript に慣れていないので、その方法を理解していませんでした。お時間をいただきありがとうございます。

私は最初の jquery プラグイン (テキストの並べ替え、テキストの検索、行の強調表示などを行うことができるテーブル) を作成していますが、1 つの問題に直面しています。

「設定」ブロックには、オプション i18N:{'x','y'} があります - init メソッド内では、「options.i18N.search」のようにアクセスできます。しかし、*get_table_body*メソッドで、jqxhr.complete(/*テーブルデータを管理するためのオプションを挿入*/)の先頭で、'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にアクセスできるようになりました。メソッドget_table_bodyに i18N を渡す必要があるため、*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 = ...) で宣言された変数は、特定の呼び出しではなく、プラグイン自体に固有 (および非公開) になります。
  • 任意のメソッドで宣言された変数は、そのメソッドの特定の呼び出しごとに固有 (および非公開) であり、他のメソッドから直接使用することはできません。この点では、init メソッドは他のメソッドと何ら変わりはありません。

したがって、メソッド間で変数を共有する明確な方法はありません。

DOM による救助

幸いなことに、jQuery を使用すると DOM にデータを簡単に格納できます。これはまさにここで必要なことです。

チュートリアルhereに基づいた 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 に答える