jQuery插件 - 使用.each和(this)迭代

时间:2015-11-16 19:44:30

标签: jquery plugins this each

我正在尝试编写一个可附加到表元素的插件,如下所示:

jQuery("#tableid").excelify();

表格将是这样的(本例中的垃圾数据):

<table id="tableid">
<thead>
<tr>
<th>Order</th>
<th>User</th>
<th>Product</th>
<th>Total</th>
</tr>
</thead>

<tbody>
<tr>
    <td data-format="bold">3145</td>
    <td data-format="bold underline">James</td>
    <td>Pens</td>
    <td>230.55</td>
</tr>

<tr>
    <td>31435</td>
    <td>Rich</td>
    <td>Bags</td>
    <td>3320.55</td>
</tr>

<tr>
    <td>4145</td>
    <td>Dobby</td>
    <td>baloons</td>
    <td>30.55</td>
</tr>
</tbody>

<tfoot>
<tr>
    <td></td>
    <td></td>
    <td>TOTAL</td>
    <td>9999.99</td>
</tr>
</tfoot>

插件背后的想法是迭代THEAD,TBODY和TFOOT,并将这些作为JSON数据返回,然后可以将其发送到单独的PHP页面并转换为Excel工作表。

我遇到的问题是,在我的插件中,(this)指的是我附加插件的元素 - 在这种情况下,它是表id“#tableid”。

现在,插件会查找THEAD,TBODY和TFOOT,并在其中迭代th和td等。但是,在插件内部运行时它不起作用。我认为这是因为.each语句中的(this)被父(这) - 实际的Table对象混淆了。

当我运行插件时,它会返回exmpty JSON数据,而如果我在插件之外运行它并且只是在主页内嵌,它就能完美运行。

我认为.each和(这是)的混淆是否正确?

这是我的插件代码:

(function ( $ ) {

$.fn.excelify = function() {
    //Build the Header Rows
    var header = Array();
    jQuery("#" + this.id + " tr th").each(function(i, v){
        header[i] = jQuery(this).text();
    });

    //Write the Footer JSON data to a hidden field on the calling page called "header"
    jQuery("#header").val(JSON.stringify(header));

    //build the Data Rows
    var data = Array();
    jQuery("#" + this.id + " tbody tr").each(function(i, v){
        data[i] = Array();
        jQuery(this).children('td').each(function(ii, vv){

            //if the data is delimited with a pipe, then there is also formatting information, such as Bold
            if(jQuery(this).data('format')) {
                data_format = jQuery(this).data('format');
            } else {
                data_format = "";
            }

            value = jQuery(this).text();
            data[i][ii] = data_format + "|" + value;
        });
    });

    //Write the Tbody JSON data to a hidden field on the calling page called "rows"
    jQuery("#rows").val(JSON.stringify(data));

    //Build the Footer Rows
    var footer = Array();
    jQuery("#" + this.id + " tfoot tr td").each(function(i, v){
        footer[i] = jQuery(this).text();
    });

    //Write the Footer JSON data to a hidden field on the calling page called "footer"
    jQuery("#footer").val(JSON.stringify(footer));


    //Submit the form
    jQuery("#convert_form").submit();
};

}(jQuery));

所以,为了突出问题,我认为.each迭代代码的第一部分中的(this)是失败的:

jQuery("#" + this.id + " tr th").each(function(i, v){
        **//is the (this) on the line below referring to the Plugin's (this)?**
        header[i] = jQuery(this).text();
    });

任何帮助,将不胜感激。 非常感谢

詹姆斯

2 个答案:

答案 0 :(得分:1)

谢谢大家,我发现只是改变选择器的上下文就可以了,特别是这个:

$("thead tr th", this).each(function(i, v){
    console.info($(this));
    header[i] = $(this).text();
});

完整代码如下。它的作用是将表数据提交给隐藏的表单字段,然后可以通过AJAX发送到我也写过的Excel类:

表格和表格如下:

/**
 * Created by PhpStorm.
 * User: james.stoddern
 * Date: 16/11/2015
 * Time: 15:37
 */
error_reporting(E_ERROR);
ini_set('display_errors', 1);

////////////////////////////////////////
//Standard Reporting, Database and Excel Class stuff
require_once( $_SERVER['DOCUMENT_ROOT'] . "/common/lib/AJAX_PDO_database_connections.php" );
require_once( $_SERVER['DOCUMENT_ROOT'] . "/common/classes/classes.misc/excel_class.php" );
$excel_helper           = new Excel($dbpdo);
if (isset($_REQUEST['export'])) {
    $report_name    = $_REQUEST["report_name"];
    $headers        = $_REQUEST["header"];
    $rows           = $_REQUEST["rows"];
    $footer         = $_REQUEST["footer"];
    $excel_helper->exportExcel($report_name, $headers, $rows, $footer);
    exit();
}

?>
<script src="/res/js/jquery191.js"></script>
<script src="/tests/excelify.js"></script>

<table id="tableid">
    <thead>
    <tr>
    <th>Order</th>
    <th>User</th>
    <th>Product</th>
    <th>Total</th>
    </tr>
    </thead>

    <tbody>
    <tr>
        <td data-format="bold">3145</td>
        <td data-format="bold underline">James</td>
        <td>Pens</td>
        <td>230.55</td>
    </tr>

    <tr>
        <td>31435</td>
        <td>Rich</td>
        <td>Bags</td>
        <td>3320.55</td>
    </tr>

    <tr>
        <td>4145</td>
        <td>Dobby</td>
        <td>baloons</td>
        <td>30.55</td>
    </tr>
    </tbody>

    <tfoot>
    <tr>
        <td></td>
        <td></td>
        <td>TOTAL</td>
        <td>9999.99</td>
    </tr>
    </tfoot>

</table>

<form id="convert_form" name="F1" method="post" action="/tests/convert_table_to_array.php">
    <input type="hidden" id="report_name" name="report_name" value="Test Report">
    <input type="hidden" id="header" name="header" value="" />
    <input type="hidden" id="rows" name="rows" value="" />
    <input type="hidden" id="footer" name="footer" value="" />
    <input type="hidden" name="export" id="export" value="Export to Excel">
</form>

<button id="convert" onclick="convertTableToExcel()">Convert</button>
<script>

    function convertTableToExcel() {
        jQuery("#tableid").excelify("convert_form");
    }
</script>

插件文件如下:

(function ( $ ) {

$.fn.excelify = function(output_form) {
    //Build the Header Rows
    var header = Array();

    $("thead tr th", this).each(function(i, v){
        console.info($(this));
        header[i] = $(this).text();
    });

    //Write the Footer JSON data to a hidden field on the calling page called "header"
    $("#header").val(JSON.stringify(header));
    //console.info(JSON.stringify(header));

    //build the Data Rows
    var data = Array();
    $("tbody tr", this).each(function(i, v){
        data[i] = Array();
        $(this).children('td').each(function(ii, vv){

            //if the data is delimited with a pipe, then there is also formatting information, such as Bold
            if($(this).data('format')) {
                data_format = $(this).data('format');
            } else {
                data_format = "";
            }

            value = $(this).text();
            data[i][ii] = data_format + "|" + value;
        });
    });

    //Write the Tbody JSON data to a hidden field on the calling page called "rows"
    $("#rows").val(JSON.stringify(data));

    //Build the Footer Rows
    var footer = Array();
    $("tfoot tr td", this).each(function(i, v){
        footer[i] = $(this).text();
    });

    //Write the Footer JSON data to a hidden field on the calling page called "footer"
    $("#footer").val(JSON.stringify(footer));


    //Submit the form
    $("#" + output_form).submit();
};

}(jQuery));

我在PHP中编写了一个excel clas,它可以将整个表格数据导出为Excel格式:

////////////////////////////////////////
require_once( $_SERVER['DOCUMENT_ROOT'] . "/common/lib/PHPExcel.php" );
class Excel
{
    private $pdo;
    private $excel;
    private $title;
    private $lastDataRow;

    /////////////////////////////////////////////////////////////
    function __construct($dbpdo)
    {
        //Grab the DB
        $this->pdo = $dbpdo;
        $this->_initialise();
    }


    ////////////////////////////////////////////////////////////////
    /**
     * Instantiate the PHPExcel class
     */
    private function _initialise() {
        $this->excel = new PHPExcel();
    }


    ///////////////////////////////////////////////////////
    /**
     * Export the Excel sheet
     * @param $header
     * @param $rows
     * @param $footer
     */
    public function exportExcel($title, $header, $rows, $footer) {
        $this->title = $title;

        // Set spreadsheet properties
        $this->excel->getProperties()->setCreator("James Inc Reporting");
        $this->excel->getProperties()->setLastModifiedBy("James Inc Reporting");
        $this->excel->getProperties()->setTitle($title);
        $this->excel->getProperties()->setSubject($title);
        $this->excel->getProperties()->setDescription($title);

        // Use first worksheet
        $this->excel->setActiveSheetIndex(0);

        // Set up title
        $this->excel->getActiveSheet()->SetCellValue('A1', $title);
        $this->excel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);
        $this->excel->getActiveSheet()->getStyle('A1')->getFont()->setSize(16);
        $this->excel->getActiveSheet()->getStyle('A1')->getFont()->setUnderline(true);

        // decode the JSON arrays
        $header     = json_decode($header);
        $footer     = json_decode($footer);
        $rows       = json_decode($rows);

        //render the ouutput
        $this->_renderHeader($header);
        $this->_renderRows($header, $rows);
        $this->_renderFooter($footer, $lastrow);

        //send to the browser
        $this->_output();
    }


    /////////////////////////////////////////////////////
    /**
     * Render the Header Rows
     */
    private function _renderHeader($header) {
        $colNumber = 0;
        foreach($header as $cell) {
            $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber,3)->getFont()->setUnderline(true);
            $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber,3)->getFont()->setBold(true);
            //$this->excel->getActiveSheet()->getColumnDimension($colNumber)->setAutoSize(true);
            $this->excel->getActiveSheet()->setCellValueByColumnAndRow($colNumber, 3, $cell);
            $colNumber++;
        }
    }


    ////////////////////////////////////////////////////////////
    /**
     * Render the Data Rows
     */
    private function _renderRows($header, $rows) {
        $startRow = 4;
        $rowNumber = 0;

        foreach($rows as $row) {
            $colNumber = 0;
            foreach($row as $key => $value) {

                //If the value is a pipe delimited string, then the first element contains formatting information
                if(preg_match("/^|/", $value)) {
                    $arr_data = explode("|", $value);
                    $data = $arr_data[1];
                    $format = $arr_data[0];

                    //bold
                    if(preg_match("/bold/", $format)) {
                        $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber, $startRow + $rowNumber)->getFont()->setBold(true);
                    }

                    //underline
                    if(preg_match("/underline/", $format)) {
                        $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber, $startRow + $rowNumber)->getFont()->setUnderline(true);
                    }
                } else {
                    //else, the values are just plain text values
                    $data = $value;
                }

                if($data > 0) {
                    $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber,$startRow + $rowNumber)->getNumberFormat()->setFormatCode('#,##0.000');
                }



                $this->excel->getActiveSheet()->setCellValueByColumnAndRow($colNumber, $startRow + $rowNumber, $data);

                $colNumber++;
            }
            $rowNumber++;
        }
        $this->lastDataRow = $rowNumber + $startRow;
    }



    ////////////////////////////////////////////////////////
    /**
     * Render the Footer Rows
     */
    private function _renderFooter($footer, $lastrow) {
        $colNumber = 0;
        foreach($footer as $cell) {
            if($cell > 0) {
                $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber, $this->lastDataRow+1)->getNumberFormat()->setFormatCode('#,##0.000');
            }
            $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber, $this->lastDataRow+1)->getFont()->setUnderline(true);
            $this->excel->getActiveSheet()->getStyleByColumnAndRow($colNumber, $this->lastDataRow+1)->getFont()->setBold(true);
            $this->excel->getActiveSheet()->setCellValueByColumnAndRow($colNumber, $this->lastDataRow+1, $cell);
            $colNumber++;
        }
    }

    //////////////////////////////////////////////////////////
    /**
     * Output the file and redirect in the browser to open immediately
     */
    private function _output() {
        $objWriter2007 = PHPExcel_IOFactory::createWriter($this->excel, 'Excel2007');

        // set headers to redirect output to client browser as a file download
        header('Content-Type: application/vnd.openXMLformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $this->title . '.xlsx"');
        header('Cache-Control: max-age=0');
        header('Content-Encoding: UTF-8');

        //-----Output the file to the browser-----
        $objWriter2007->save('php://output');  //push out to the client browser
    }
}

现在工作正常。如果您觉得有用,请随时使用。我的想法是,我可以生成大量报告并添加一行Excel转换功能。

感谢你的帮助,它让我走上正轨。

非常感谢。

詹姆斯

答案 1 :(得分:0)

我认为这就是你想要的:

        $.fn.excelify = function () {
            //Build the Header Rows
            var header = Array();
            var table = this[0];
            var tableid = this.attr("id");
            jQuery("#" + tableid + " tr th").each(function (i, v) {
                header[i] = jQuery(this).text();
            });
            ... etc.