text: (function($, w, undefined) {
    if (w.footable === undefined || w.foobox === null) throw new Error('Please check and make sure footable.js is included in the page and is loaded prior to this script.');
    var defaults = {
      grid: {
        enabled: true,
        data: null,
        template: null, //row html template, use for make a row.
        cols: null, //column define
        items: null, //data items
        url: null, //get data from url
        ajax: null, //paramater for $.ajax
        activeClass: 'active', //add to row selected
        multiSelect: false, //allow select multiple row
        showIndex: false, //show row index
        showCheckbox: false, //show checkbox for select
        showEmptyInfo: false, //when that is not data in table, show a info to notify user
        emptyInfo: '<p class="text-center text-warning">No Data</p>',
        pagination: {
          "page-size": 20,
          "pagination-class": "pagination pagination-centered"
        },
        indexFormatter: function(val, $td, index) {
          return index + 1;
        },
        checkboxFormatter: function(isTop) {
          return '<input type="checkbox" class="' + (isTop ? 'checkAll' : 'check') + '">';
        },
        events: {
          loaded: 'footable_grid_loaded',
          created: 'footable_grid_created',
          removed: 'footable_grid_removed',
          updated: 'footable_grid_updated'
        }
      }
    };
  
    function makeTh(col) {
      var $th = $('<th>' + col.title + '</th>');
      if ($.isPlainObject(col.data)) {
        $th.data(col.data);
      }
      if ($.isPlainObject(col.style)) {
        $th.css(col.style);
      }
      if (col.className) {
        $th.addClass(col.className);
      }
      return $th;
    }
  
    function initThead($table, options) {
      var $thead = $table.find('thead');
      if ($thead.size() === 0) {
        $thead = $('<thead>').appendTo($table);
      }
      var $row = $('<tr>').appendTo($thead);
      for (var i = 0, len = options.cols.length; i < len; i++) {
        $row.append(makeTh(options.cols[i]));
      }
    }
  
    function initTBody($table) {
      var $tbody = $table.find('tbody');
      if ($tbody.size() === 0) {
        $tbody = $('<tbody>').appendTo($table);
      }
    }
  
    function initPagination($table, cols, options) {
      if (options) {
        $table.attr("data-page-size", options['page-size']);
        var $tfoot = $table.find('tfoot');
        if ($tfoot.size() === 0) {
          $tfoot = $('<tfoot class="hide-if-no-paging"></tfoot>').appendTo($table);
        }
        $tfoot.append('<tr><td colspan=' + cols.length + '></td></tr>');
        var $pagination = $("<div>").appendTo($tfoot.find("tr:last-child td"));
        $pagination.addClass(options['pagination-class']);
      }
    }
  
    function setToggleColumn(cols) {
      var toggleColumn = cols[0];
      for (var i = 0, len = cols.length; i < len; i++) {
        var col = cols[i];
        if (col.data && (col.data.toggle === true || col.data.toggle === "true")) {
          return;
        }
      }
      toggleColumn.data = $.extend(toggleColumn.data, {
        toggle: true
      });
    }
  
    function makeEmptyInfo($table, cols, emptyInfo) {
      if ($table.find("tr.emptyInfo").size() === 0) {
         $table.find('tbody').append('<tr class="emptyInfo"><td colspan="' + cols.length + '">' + emptyInfo + '</td></tr>');
      }
    }
  
    function updateRowIndex($tbody, $newRow, detailClass, offset) {
      //update rows index
      $tbody.find('tr:not(.' + detailClass + ')').each(function() {
        var $row = $(this),
          index = $newRow.data('index'),
          oldIndex = parseInt($row.data('index'), 0),
          newIndex = oldIndex + offset;
        if (oldIndex >= index && this !== $newRow.get(0)) {
          $row.attr('data-index', newIndex).data('index', newIndex);
        }
      });
    }
  
    function Grid() {
      var grid = this;
      grid.name = 'Footable Grid';
      grid.init = function(ft) {
        var toggleClass = ft.options.classes.toggle;
        var detailClass = ft.options.classes.detail;
        var options = ft.options.grid;
        if (!options.cols) return;
        grid.footable = ft;
        var $table = $(ft.table);
        $table.data('grid', grid);
        if ($.isPlainObject(options.data)) {
          $table.data(options.data);
        }
        grid._items = [];
        setToggleColumn(options.cols);
        if (options.showCheckbox) {
          options.multiSelect = true;
          options.cols.unshift({
            title: options.checkboxFormatter(true),
            name: '',
            data: {
              "sort-ignore": true
            },
            formatter: options.checkboxFormatter
          });
        }
        if (options.showIndex) {
          options.cols.unshift({
            title: '#',
            name: 'index',
            data: {
              "sort-ignore": true
            },
            formatter: options.indexFormatter
          });
        }
        initThead($table, options);
        initTBody($table);
        initPagination($table, options.cols, options.pagination);
        $table.off('.grid').on({
          'footable_initialized.grid': function(e) {
            if (options.url || options.ajax) {
              $.ajax(options.ajax || {
                url: options.url
              }).then(function(resp) {
                grid.newItem(resp);
                ft.raise(options.events.loaded);
              }, function(jqXHR) {
                throw 'load data from ' + (options.url || options.ajax.url) + ' fail';
              });
            } else {
              grid.newItem(options.items || []);
              ft.raise(options.events.loaded);
            }
          },
          'footable_sorted.grid footable_grid_created.grid footable_grid_removed.grid': function(event) {
            if (options.showIndex && grid.getItem().length > 0) {
              $table.find('tbody tr:not(.' + detailClass + ')').each(function(index) {
                var $td = $(this).find('td:first');
                $td.html(options.indexFormatter(null, $td, index));
              });
            }
          },
          'footable_redrawn.grid footable_row_removed.grid': function(event) {
            if (grid.getItem().length === 0 && options.showEmptyInfo) {
              makeEmptyInfo($table, options.cols, options.emptyInfo);
            }
          }
        }).on({
          'click.grid': function(event) {
            if ($(event.target).closest('td').find('>.' + toggleClass).size() > 0) {
              return true;
            }
            var $tr = $(event.currentTarget);
            if ($tr.hasClass(detailClass)) {
              return true;
            }
            if (!options.multiSelect && !$tr.hasClass(options.activeClass)) {
              $table.find('tbody tr.' + options.activeClass).removeClass(options.activeClass);
            }
            $tr.toggleClass(options.activeClass);
            if (options.showCheckbox) {
              $tr.find('input:checkbox.check').prop('checked', function(index, val) {
                if (event.target === this) {
                  return val;
                }
                return !val;
              });
            }
            ft.toggleDetail($tr);
          }
        }, 'tbody tr').on('click.grid', 'thead input:checkbox.checkAll', function(event) {
          var checked = !! event.currentTarget.checked;
          if (checked) {
            $table.find('tbody tr').addClass(options.activeClass);
          } else {
            $table.find('tbody tr').removeClass(options.activeClass);
          }
          $table.find('tbody input:checkbox.check').prop('checked', checked);
        });
      };
      /**
       * get selected rows index;
       */
      grid.getSelected = function() {
        var options = grid.footable.options.grid,
          $selected = $(grid.footable.table).find('tbody>tr.' + options.activeClass);
        return $selected.map(function() {
          return $(this).data('index');
        });
      };
      /**
       * get row's data by index
       */
      grid.getItem = function(index) {
        if (index !== undefined) {
          if ($.isArray(index)) {
            return $.map(index, function(item) {
              return grid._items[item];
            });
          }
          return grid._items[index];
        }
        return grid._items;
      };
  
      function makeCell(col, value, index) {
        var $td = $('<td>');
        if (col.formatter) {
          $td.html(col.formatter(value, $td, index));
        } else {
          $td.html(value || '');
        }
        return $td;
      }
      grid._makeRow = function(item, index) {
        var options = grid.footable.options.grid;
        var $row;
        if ($.isFunction(options.template)) {
          $row = $(options.template($.extend({}, {
            __index: index
          }, item)));
        } else {
          $row = $('<tr>');
          for (var i = 0, len = options.cols.length; i < len; i++) {
            var col = options.cols[i];
            $row.append(makeCell(col, item[col.name] || '', index));
          }
        }
        $row.attr('data-index', index);
        return $row;
      };
      /**
       * create rows by js object
       */
      grid.newItem = function(item, index, wait) {
        var $tbody = $(grid.footable.table).find('tbody');
        var detailClass = grid.footable.options.classes.detail;
        $tbody.find('tr.emptyInfo').remove();
        if ($.isArray(item)) {
          for (var atom;
            (atom = item.pop());) {
            grid.newItem(atom, index, true);
          }
          grid.footable.redraw();
          grid.footable.raise(grid.footable.options.grid.events.created, {
            item: item,
            index: index
          });
          return;
        }
        if (!$.isPlainObject(item)) {
          return;
        }
        var $tr, len = grid._items.length;
        if (index === undefined || index < 0 || index > len) {
          $tr = grid._makeRow(item, len++);
          grid._items.push(item);
          $tbody.append($tr);
        } else {
          $tr = grid._makeRow(item, index);
          if (index === 0) {
            grid._items.unshift(item);
            $tbody.prepend($tr);
          } else {
            var $before = $tbody.find('tr[data-index=' + (index - 1) + ']');
            grid._items.splice(index, 0, item);
            if ($before.data('detail_created') === true) {
              $before = $before.next();
            }
            $before.after($tr);
          }
          updateRowIndex($tbody, $tr, detailClass, 1);
        }
        if (!wait) {
          grid.footable.redraw();
          grid.footable.raise(grid.footable.options.grid.events.created, {
            item: item,
            index: index
          });
        }
      };
      /**
       * update row by js object
       */
      grid.setItem = function(item, index) {
        if (!$.isPlainObject(item)) {
          return;
        }
        var $tbody = $(grid.footable.table).find('tbody'),
          $newTr = grid._makeRow(item, index);
        $.extend(grid._items[index], item);
        var $tr = $tbody.find('tr').eq(index);
        $tr.html($newTr.html());
        grid.footable.redraw();
        grid.footable.raise(grid.footable.options.grid.events.updated, {
          item: item,
          index: index
        });
      };
      /**
       * remove rows by index
       */
      grid.removeItem = function(index) {
        var $tbody = $(grid.footable.table).find('tbody');
        var detailClass = grid.footable.options.classes.detail;
        var result = [];
        if ($.isArray(index)) {
          for (var i;
            (i = index.pop());) {
            result.push(grid.removeItem(i));
          }
          grid.footable.raise(grid.footable.options.grid.events.removed, {
            item: result,
            index: index
          });
          return result;
        }
        if (index === undefined) {
          $tbody.find('tr').each(function() {
            result.push(grid._items.shift());
            grid.footable.removeRow(this);
          });
        } else {
          var $tr = $tbody.find('tr[data-index=' + index + ']');
          result = grid._items.splice(index, 1)[0];
          grid.footable.removeRow($tr);
          //update rows index
          updateRowIndex($tbody, $tr, detailClass, -1);
        }
        grid.footable.raise(grid.footable.options.grid.events.removed, {
          item: result,
          index: index
        });
        return result;
      };
    }
    w.footable.plugins.register(Grid, defaults);
  })(jQuery, window);
  