Advertisement
Guest User

jquery grid

a guest
Aug 20th, 2016
490
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * JsGrid 0.0.1
  3.  */
  4.  
  5. (function ($) {
  6.     var settings,
  7.         state,
  8.         ajax,
  9.         dom,
  10.         defaults = {
  11.             dataset: {
  12.                 connection: null,
  13.                 ajaxUrl: null,
  14.                 id: null,
  15.                 form: null
  16.             },
  17.             controls: {
  18.                 isStateful: false,
  19.                 isControlsShow: true,
  20.                 pagination: 'bottom',
  21.                 headerCreate: null,
  22.                 headerEdit: null,
  23.                 headerButtonCreate: null,
  24.                 headerButtonEdit: null,
  25.                 formCreateClass: 'jsgrid-form-create',
  26.                 formCreateClearHidden: false,
  27.                 isSearch: false,
  28.                 searchPlaceholder: '',
  29.                 isAdd: false,
  30.                 isFastSave: false,
  31.                 isEdit: false,
  32.                 isDelete: true,
  33.                 isDeleteConfirm: true,
  34.                 deleteConfirmMessage: 'Удалить запись?',
  35.                 additional: null,
  36.                 controlsClass: '',
  37.                 perPageOptions: [10, 100, 500, 1000],
  38.                 isTotalShow: true,
  39.                 total: null,
  40.                 totalName: 'Всего: ',
  41.                 tableCssClass: '',
  42.             },
  43.             table: {
  44.                 page: 1,
  45.                 pages: null,
  46.                 limit: 50,
  47.                 orderBy: 'id',
  48.                 order: 'asc',
  49.                 searchColumn: '',
  50.                 searchValue: '',
  51.                 filters: {},
  52.             },
  53.             columns: {
  54.                 id: {
  55.                     name: null,
  56.                     isSearch: false,
  57.                     searchType: 'default',
  58.                     isSortable: false,
  59.                     render: function (content) {
  60.                         return '<td>' + content.id + '</td>';
  61.                     }
  62.                 },
  63.             },
  64.             container: {
  65.                 id: null,
  66.                 class: '.jsgrid-container',
  67.                 contentClass: '.jsgrid-content'
  68.             }
  69.         };
  70.  
  71.     ajax = {
  72.         request: function (url, method, method_hidden, settings) {
  73.             // Ajax запрос в контроллер
  74.             var data;
  75.             if (typeof settings.container !== 'undefined') {
  76.                 this.spinOn(settings);
  77.                 data = {
  78.                     dataset: settings.dataset,
  79.                     table: settings.table
  80.                 }
  81.             }
  82.             else data = settings;
  83.             if (typeof data !== "string") data = $.param(data);
  84.             if (method == 'post') return $.post(url, data + '&_method=' + method_hidden);
  85.             else return $.get(url, data);
  86.         },
  87.         index: function (settings) {
  88.             // Метод контроллера index
  89.             return this.request(settings.dataset.ajaxUrl, 'get', 'get', settings);
  90.         },
  91.         create: function (settings) {
  92.             // Метод контроллера create
  93.             return this.request(settings.dataset.ajaxUrl + '/create', 'get', 'get', settings);
  94.         },
  95.         store: function (settings) {
  96.             // Метод контроллера store
  97.             return $.post(settings.dataset.ajaxUrl, settings.dataset.form);
  98.         },
  99.         edit: function (settings) {
  100.             // Метод контроллера edit
  101.             return $.get(settings.dataset.ajaxUrl + '/' + settings.dataset.id + '/edit', settings.dataset.form);
  102.         },
  103.         update: function (settings) {
  104.             // Метод контроллера update
  105.             return this.request(settings.dataset.ajaxUrl + '/' + settings.dataset.id, 'post', 'put', settings.dataset.form);
  106.         },
  107.         destroy: function (settings) {
  108.             // Метод контроллера destroy
  109.             return this.request(settings.dataset.ajaxUrl + '/' + settings.dataset.id, 'post', 'delete', settings);
  110.         },
  111.         setConnection: function (settings) {
  112.             return 'dataset[connection]=' + settings.dataset.connection + '&';
  113.         },
  114.         spinMainOn: function (settings) {
  115.             $('#' + settings.container.id + ' .jsgrid-content').html('<div class="spin-main text-xs-center"><i class="ficon-spin3 animate-spin"></i></div>');
  116.         },
  117.         spinOn: function (settings) {
  118.             $('#' + settings.container.id + ' .jsgrid-ajax-spin').show();
  119.         },
  120.         spinOff: function (settings) {
  121.             $('#' + settings.container.id + ' .jsgrid-ajax-spin').fadeOut();
  122.         },
  123.         cspinOn: function (container) {
  124.             container.find('.jsgrid-ajax-spin').show();
  125.         },
  126.         cspinOff: function (container) {
  127.             container.find('.jsgrid-ajax-spin').fadeOut();
  128.         },
  129.         typingTimer: 0,
  130.         delay: function (ms) {
  131.             var timer = 0;
  132.             return function (callback) {
  133.                 clearTimeout(timer);
  134.                 timer = setTimeout(callback, ms);
  135.             };
  136.         }
  137.     }
  138.  
  139.     state = {
  140.         save: function (settings) {
  141.             // Сохранение настроек в url
  142.             window.history.pushState(null, null, '?' + settings.container.id + '=' + JSON.stringify(settings.table));
  143.         },
  144.         get: function (settings) {
  145.             // Восстановление state
  146.             if (typeof $('#' + settings.container.id).attr('data-settings') != 'undefined') {
  147.                 // Настройки из контейнера
  148.                 settings.table = JSON.parse($('#' + settings.container.id).attr('data-settings'));
  149.             }
  150.             else if (location.href.indexOf('?' + settings.container.id) >= 0) settings.table = JSON.parse(this.getParam(settings.container.id));
  151.         },
  152.         getParam: function (name) {
  153.             var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
  154.             return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
  155.         }
  156.     };
  157.  
  158.     dom = {
  159.         render: function (settings) {
  160.             // Отображение данных
  161.             if (settings.controls.isStateful) state.save(settings);
  162.             var html = '';
  163.             var request = ajax.index(settings);
  164.             request.done(function (result) {
  165.                 settings.controls.total = result.total;
  166.  
  167.                 // Элементы управления
  168.                 if (settings.controls.isControlsShow) {
  169.                     html = '<div class="jsgrid-controls clearfix">';
  170.                     if (settings.controls.isTotalShow) html += '<div class="jsgrid-total small pull-xs-left">' + settings.controls.totalName + result.total + '</div>';
  171.                     html +=
  172.                         '<div class="pull-xs-right">' +
  173.                         '<i class="jsgrid-ajax-spin ficon-spin5 animate-spin pull-xs-left"></i>';
  174.                     // Поиск по всем полям
  175.                     if (settings.controls.isSearch) html += '<div class="jsgrid-search form-group pull-xs-left">' +
  176.                         '<div class="input-group input-group-sm">' +
  177.                         '<span class="ficon-search input-group-addon"></span>' +
  178.                         '<input class="form-control" value="' + settings.table.searchValue + '" placeholder="' + settings.controls.searchPlaceholder + '" />' +
  179.                         '</div>' +
  180.                         '</div>';
  181.  
  182.                     html += '<div class="btn-group btn-group-sm" role="group">';
  183.                     if (settings.controls.isAdd) html += '<button class="jsgrid-action-create btn btn-secondary"><i class="ficon-plus"></i></button>';
  184.                     html +=
  185.                         '<button class="jsgrid-action-reload btn btn-secondary"><i class="ficon-arrows-cw"></i></button>' +
  186.                         '<div class="btn-group btn-group-sm" role="group">' +
  187.                         '<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">' + settings.table.limit + '</button>' +
  188.                         '<div class="dropdown-menu dropdown-menu-right">';
  189.                     for (var i = 0; i < settings.controls.perPageOptions.length; i++) html += '<a class="jsgrid-action-pplset dropdown-item" href="#">' + settings.controls.perPageOptions[i] + '</a>';
  190.                     html += '</div>' +
  191.                         '</div>' +
  192.                         '</div>' +
  193.                         '</div>' +
  194.                         '</div>';
  195.                 }
  196.  
  197.                 // Таблица
  198.                 html += '<div class="table-responsive"><table class="table ' + settings.controls.tableCssClass + '">';
  199.  
  200.                 // Заголовки
  201.                 html += '<tr>';
  202.                 for (var column in settings.columns) {
  203.                     html += '<th data-name="' + column + '"';
  204.                     // Сортировка
  205.                     if (settings.table.orderBy == column) html += ' data-order="' + settings.table.order + '"';
  206.                     html += '>';
  207.                     if (settings.columns[column].isSortable) html += '<a href="#" class="jsgrid-action-sort">' + settings.columns[column].name + '</a>';
  208.                     else html += settings.columns[column].name;
  209.                     if (settings.table.orderBy == column) html += ' <i class="font-14 opacity-30 ficon-sort-' + settings.table.order + '"></i>';
  210.                     // Фильтры
  211.                     if (settings.columns[column].isSearch) {
  212.  
  213.                         // Иконки поиска
  214.                         var filter_value = '', filter_css = '';
  215.                         if (typeof settings.table.filters[column] !== 'undefined' && settings.table.filters[column].value != '') filter_value = settings.table.filters[column].value;
  216.                         else filter_css = ' opacity-30';
  217.  
  218.                         // Поиск >, <, Like
  219.                         if (settings.columns[column].searchType == 'default') {
  220.                             html += '<div class="jsgrid-filter-default dropdown pull-xs-right">' +
  221.                                 '<i class="ficon-search dropdown-toggle' + filter_css + '" role="button" data-toggle="dropdown" aria-expanded="false"></i>' +
  222.                                 '<div class="dropdown-menu dropdown-menu-right">' +
  223.                                 '<div class="input-group">' +
  224.                                 '<input class="filter-' + column + ' form-control" ' + 'value="' + filter_value + '"/>' +
  225.                                 '<span class="input-group-btn">' +
  226.                                 '<button class="jsgrid-action-filter btn btn-secondary btn-sm" data-type="default" data-column="' + column + '" data-container="filter-' + column + '" type="button"><i class="ficon-filter opacity-70"></i></button>' +
  227.                                 '</span>' +
  228.                                 '</div>' +
  229.                                 '</div>';
  230.                         }
  231.                         // Select
  232.                         if (settings.columns[column].searchType == 'select') {
  233.                             html += '<div class="jsgrid-filter-select dropdown pull-xs-right"><i class="ficon-sort-alt-down dropdown-toggle' + filter_css + '" role="button" data-toggle="dropdown" aria-expanded="false"></i>' +
  234.                                 '<div class="dropdown-menu dropdown-menu-right">';
  235.                             for (var i = 0; i < result.filters[column].length; i++) html += '<a href="#" class="jsgrid-action-filter dropdown-item" data-type="select" data-column="' + column + '" data-value="' + result.filters[column][i].value + '">' + result.filters[column][i].name + '</a>';
  236.                             html +=
  237.                                 '</div>' +
  238.                                 '</div>';
  239.                         }
  240.                     }
  241.                     html += '</th>';
  242.                 }
  243.                 html += '<th></th></tr>';
  244.  
  245.                 // Контент
  246.                 for (var row in result.rows) {
  247.                     html += '<tr data-id="' + result.rows[row].id + '">';
  248.  
  249.                     for (var column in settings.columns) if (typeof settings.columns[column] !== 'undefined') html += settings.columns[column].render(result.rows[row]);
  250.  
  251.                     // Элементы управления
  252.                     html += '<td class="' + settings.controls.controlsClass + '">';
  253.                     if (typeof settings.controls.additional !== 'undefined') for (var el in settings.controls.additional) html += settings.controls.additional[el];
  254.                     if (settings.controls.isFastSave) html += '<a href="#" class="jsgrid-action-fastsave ficon-ok"></a>';
  255.                     if (settings.controls.isEdit) html += '<a href="#" class="jsgrid-action-edit ficon-cog"></a>';
  256.                     if (settings.controls.isDelete) html += '<a href="#" class="jsgrid-action-delete ficon-cancel"></a>';
  257.                     html += '</td></tr>';
  258.                 }
  259.                 html += '</table>';
  260.                 html += '</div>';
  261.                 html += dom.pagination(settings);
  262.                 $('#' + settings.container.id + ' > .jsgrid-content').html(html);
  263.                 ajax.spinOff(settings);
  264.             });
  265.         },
  266.         pagination: function (settings) {
  267.             // Постраничная навигация
  268.             var active, pages, offset, previous, next;
  269.             // Количество страниц
  270.             if (settings.controls.total % settings.table.limit > 0) settings.table.pages = (settings.controls.total / settings.table.limit >> 0) + 1; else settings.table.pages = (settings.controls.total / settings.table.limit);
  271.             // Центрирование текущей страницы
  272.             if (settings.table.page > 2) offset = (settings.table.page - 2); else offset = 1;
  273.             if (settings.table.page > 1) previous = settings.table.page - 1; else previous = 1;
  274.  
  275.             // Ограничение на видимую часть
  276.             if (settings.table.pages - settings.table.page >= 2) pages = 5;
  277.             else {
  278.                 if (settings.table.pages > 5) {
  279.                     if (settings.table.pages - settings.table.page == 0) pages = 3;
  280.                     if (settings.table.pages - settings.table.page == 1) pages = 4;
  281.                 }
  282.                 else pages = settings.table.pages;
  283.             }
  284.             if (settings.table.pages < 2) return '';
  285.  
  286.             if (settings.table.page == settings.table.pages) next = parseInt(settings.table.page);
  287.             else next = parseInt(settings.table.page) + 1;
  288.  
  289.             var html = '<nav>' +
  290.                 '<ul class="pagination pagination-sm">' +
  291.                 '<li class="page-item"><a class="jsgrid-action-page page-link" data-page="1" href="#"><span aria-hidden="true">&laquo;</span></a></li>' +
  292.                 '<li class="page-item"><a class="jsgrid-action-page page-link" data-page="' + previous + '" href="#"><span aria-hidden="true">&larr;</span></a></li>' +
  293.                 '<li class="page-item"><a class="jsgrid-action-page page-link" data-page="' + next + '" href="#"><span aria-hidden="true">&rarr;</span></a></li>';
  294.             for (var i = offset; i <= (pages + offset - 1); i++) {
  295.                 if (i == settings.table.page) active = ' active'; else active = '';
  296.                 html += '<li class="page-item' + active + '"><a class="jsgrid-action-page page-link" data-page="' + i + '" href="#">' + i + '</a></li>';
  297.             }
  298.             html +=
  299.                 '<li class="page-item"><a class="jsgrid-action-page page-link" data-page="' + settings.table.pages + '" href="#"><span aria-hidden="true">&raquo;</span></a></li>' +
  300.                 '</ul>' +
  301.                 '</nav>';
  302.             return html;
  303.         },
  304.         showErrors: function (form, messages) {
  305.             // Показать ошибки
  306.             $.each(messages, function (name, text) {
  307.                 form.find('input[name=' + name + ']').addClass('jsgrid-input-error');
  308.                 form.find('.jsgrid-validation-result').append(text + '<br />');
  309.             });
  310.         },
  311.         removeErrors: function (form) {
  312.             // Удалить ошибки
  313.             form.find('.jsgrid-input-error').removeClass('jsgrid-input-error');
  314.             form.find('.jsgrid-validation-result').html('');
  315.         },
  316.         handlers: function (container, settings) {
  317.             // Поиск по всем полям
  318.             container.on('keyup', '.jsgrid-search input', function (e) {
  319.                 var input = $('#' + settings.container.id + ' .jsgrid-search input');
  320.                 clearTimeout(ajax.typingTimer);
  321.                 ajax.typingTimer = setTimeout(function () {
  322.                     settings.table.searchColumn = 'all';
  323.                     settings.table.searchValue = input.val();
  324.                     dom.render(settings);
  325.                     setTimeout(function () {
  326.                         $('#' + settings.container.id + ' .jsgrid-search input').focus().val('').val(input.val());
  327.                     }, 500);
  328.                 }, 500);
  329.             });
  330.             container.on('keydown', '.jsgrid-search input', function (e) {
  331.                 clearTimeout(ajax.typingTimer);
  332.             });
  333.             // Удаление
  334.             container.on('click', '.jsgrid-action-delete', function (e) {
  335.                 e.preventDefault();
  336.                 settings.dataset.id = $(this).closest('tr').attr('data-id');
  337.                 if (settings.controls.isDeleteConfirm) {
  338.                     if (confirm(settings.controls.deleteConfirmMessage)) ajax.destroy(settings);
  339.                     else return false;
  340.                 }
  341.                 else ajax.destroy(settings);
  342.                 $(this).closest('tr').fadeOut();
  343.                 dom.render(settings);
  344.             });
  345.             // Строк на страницу
  346.             container.on('click', '.jsgrid-action-pplset', function (e) {
  347.                 e.preventDefault();
  348.                 settings.table.limit = $(this).text();
  349.                 dom.render(settings);
  350.             });
  351.             // Обновление таблицы
  352.             container.on('click', '.jsgrid-action-reload', function (e) {
  353.                 e.preventDefault();
  354.                 settings.table.page = 1;
  355.                 settings.table.searchColumn = '';
  356.                 settings.table.searchValue = '';
  357.                 settings.table.filters = {};
  358.                 dom.render(settings);
  359.             });
  360.             // Сортировка
  361.             container.on('click', '.jsgrid-action-sort', function (e) {
  362.                 e.preventDefault();
  363.                 var th = $(this).closest('th');
  364.                 if (!th.attr('data-order')) th.attr('data-order', 'desc');
  365.                 if (th.attr('data-order') == 'asc') settings.table.order = 'desc';
  366.                 else settings.table.order = 'asc';
  367.                 settings.table.orderBy = th.attr('data-name');
  368.                 dom.render(settings);
  369.             });
  370.             // Постраничная навигация
  371.             container.on('click', '.jsgrid-action-page', function (e) {
  372.                 e.preventDefault();
  373.                 settings.table.page = $(this).attr('data-page');
  374.                 dom.render(settings);
  375.             });
  376.             // Фильтрация
  377.             $(document).on('click', '.ficon-search.dropdown-toggle', function () {
  378.                 $(this).parent().find('input.form-control').focus();
  379.             });
  380.             container.on('click', '.jsgrid-action-filter', function (e) {
  381.                 e.preventDefault();
  382.                 var column, value, type;
  383.                 type = $(this).attr('data-type');
  384.                 column = $(this).attr('data-column');
  385.                 if (type == 'default') value = $('.' + $(this).attr('data-container')).val();
  386.                 if (type == 'select') value = $(this).attr('data-value');
  387.                 settings.table.filters[column] = {
  388.                     column: column,
  389.                     value: value,
  390.                     type: type,
  391.                 };
  392.                 dom.render(settings);
  393.             });
  394.             container.on('keyup', '.jsgrid-filter-default input.form-control', function (e) {
  395.                 if (e.which === 13) {
  396.                     var this_ = $(this).parent().find('.jsgrid-action-filter');
  397.                     var column = this_.attr('data-column');
  398.                     settings.table.filters[column] = {
  399.                         column: column,
  400.                         value: $('.' + this_.attr('data-container')).val(),
  401.                         type: this_.attr('data-type'),
  402.                     };
  403.                     dom.render(settings);
  404.                 }
  405.             });
  406.             // Модальное окно
  407.             container.on('hidden.bs.modal', function (e) {
  408.                 var form = container.find('.jsgrid-form-create'), input;
  409.                 if (settings.controls.formCreateClearHidden) input = form.find('input');
  410.                 else input = form.find('input:not([type=hidden])');
  411.                 input.val('').removeClass('jsgrid-input-error');
  412.                 form.find('.jsgrid-validation-result').html('');
  413.             });
  414.             // Добавить
  415.             container.on('click', '.jsgrid-action-create', function (e) {
  416.                 e.preventDefault();
  417.                 var modal = $('#' + settings.container.id + ' .' + settings.controls.formCreateClass);
  418.                 modal.find('form.jsgrid-form-main').attr('data-action', 'create');
  419.                 modal.find('.modal-title').text(settings.controls.headerCreate);
  420.                 modal.find('form.jsgrid-form-main button[type=submit]').text(settings.controls.headerButtonCreate);
  421.                 modal.modal('show');
  422.             });
  423.             container.on('submit', 'form[data-action=create]', function (e) {
  424.                 e.preventDefault();
  425.                 var form = $(this);
  426.                 ajax.cspinOn(form);
  427.                 dom.removeErrors(form);
  428.                 settings.dataset.form = ajax.setConnection(settings);
  429.                 settings.dataset.form += form.serialize();
  430.                 var request = ajax.store(settings);
  431.                 request.done(function (result) {
  432.                     if (result.length == 0) {
  433.                         form.closest('.modal').modal('hide');
  434.                         dom.render(settings);
  435.                     }
  436.                     else dom.showErrors(form, result);
  437.                     ajax.cspinOff(form);
  438.                 });
  439.             });
  440.             // Редактирование
  441.             container.on('click', '.jsgrid-action-edit', function (e) {
  442.                 e.preventDefault();
  443.                 var modal = $('#' + settings.container.id + ' .' + settings.controls.formCreateClass);
  444.                 modal.find('form.jsgrid-form-main').attr('data-action', 'edit');
  445.                 modal.find('.modal-title').text(settings.controls.headerEdit);
  446.                 modal.find('form.jsgrid-form-main button[type=submit]').text(settings.controls.headerButtonEdit);
  447.                 settings.dataset.id = $(this).closest('tr').attr('data-id');
  448.                 settings.dataset.form = ajax.setConnection(settings);
  449.                 var form = $('#' + settings.container.id + ' .' + settings.controls.formCreateClass + ' form');
  450.                 ajax.cspinOn(form);
  451.                 var request = ajax.edit(settings);
  452.                 request.done(function (result) {
  453.                     $.each(result, function (name, value) {
  454.                         form.find('[name=' + name + ']').val(value);
  455.                         ajax.cspinOff(form);
  456.                     });
  457.                 });
  458.                 modal.modal('show');
  459.             });
  460.             container.on('submit', 'form[data-action=edit]', function (e) {
  461.                 e.preventDefault();
  462.                 var form = $(this);
  463.                 ajax.cspinOn(form);
  464.                 dom.removeErrors(form);
  465.                 settings.dataset.form = ajax.setConnection(settings);
  466.                 settings.dataset.form += form.serialize();
  467.                 var request = ajax.update(settings);
  468.                 request.done(function (result) {
  469.                     if (result.length == 0) {
  470.                         form.closest('.modal').modal('hide');
  471.                         dom.render(settings);
  472.                     }
  473.                     else dom.showErrors(form, result);
  474.                     ajax.cspinOff(form);
  475.                 });
  476.             });
  477.             // Быстрое сохранение
  478.             container.on('click', '.jsgrid-action-fastsave', function (e) {
  479.                 e.preventDefault();
  480.                 var row = $(this).closest('tr');
  481.                 settings.dataset.form = ajax.setConnection(settings);
  482.                 settings.dataset.form += 'fastsave=1&';
  483.                 settings.dataset.id = row.attr('data-id');
  484.                 row.find('input').each(function () {
  485.                     settings.dataset.form += $(this).attr('name') + '=' + $(this).val() + '&';
  486.                 });
  487.                 var request = ajax.update(settings);
  488.                 request.done(function (result) {
  489.                     if (result.length == 0) dom.render(settings);
  490.                     else $.each(result, function (name, text) {
  491.                         alert(text);
  492.                     })
  493.                 });
  494.             });
  495.         }
  496.     }
  497.     $.fn.jsGrid = function (options) {
  498.         if ($('#' + $(this).attr('id')).length > 0) {
  499.             // Если плагин ещё не проинициализирован
  500.             if (!this.data('jsgrid')) {
  501.                 settings = $.extend(true, {}, defaults, options);
  502.                 settings.container.id = $(this).attr('id');
  503.                 this.data('jsgrid', settings);
  504.                 ajax.spinMainOn(settings);
  505.                 // Обработчики событий
  506.                 dom.handlers(this, settings);
  507.                 // Проверка state
  508.                 state.get(settings);
  509.             }
  510.             else settings = this.data('jsgrid');
  511.             dom.render(settings);
  512.         }
  513.     }
  514. })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement