📂 FileMgr
📍
/var/www/vhosts/dzfarer.com/httpdocs/assets/plugins/rwdtable/js
✏️ Edit File: /var/www/vhosts/dzfarer.com/httpdocs/assets/plugins/rwdtable/js/rwd-table.js
⬅ Kembali
/*! * Responsive Tables v5.2.6 (http://gergeo.se/RWD-Table-Patterns) * This is an awesome solution for responsive tables with complex data. * Authors: Nadan Gergeo <nadan@blimp.se> (www.blimp.se), Lucas Wiener <lucas@blimp.se> & "Maggie Wachs (www.filamentgroup.com)" * Licensed under MIT (https://github.com/nadangergeo/RWD-Table-Patterns/blob/master/LICENSE-MIT) */ (function ($) { 'use strict'; // RESPONSIVE TABLE CLASS DEFINITION // ========================== var ResponsiveTable = function(element, options) { // console.time('init'); var that = this; this.options = options; this.$tableWrapper = null; //defined later in wrapTable this.$tableScrollWrapper = $(element); //defined later in wrapTable this.$table = $(element).find('table'); if(this.$table.length !== 1) { throw new Error('Exactly one table is expected in a .table-responsive div.'); } //apply pattern option as data-attribute, in case it was set via js this.$tableScrollWrapper.attr('data-pattern', this.options.pattern); //if the table doesn't have a unique id, give it one. //The id will be a random hexadecimal value, prefixed with id. //Used for triggers with displayAll button. this.id = this.$table.prop('id') || this.$tableScrollWrapper.prop('id') || 'id' + Math.random().toString(16).slice(2); this.$tableClone = null; //defined farther down this.$stickyTableHeader = null; //defined farther down //good to have - for easy access this.$thead = this.$table.find('thead'); this.$hdrCells = this.$thead.find("tr").first().find('th'); this.$bodyRows = this.$table.find('tbody, tfoot').find('tr'); //toolbar and buttons this.$btnToolbar = null; //defined farther down this.$dropdownGroup = null; //defined farther down this.$dropdownBtn = null; //defined farther down this.$dropdownContainer = null; //defined farther down this.$displayAllBtn = null; //defined farther down this.$focusGroup = null; //defined farther down this.$focusBtn = null; //defined farther down //misc this.displayAllTrigger = 'display-all-' + this.id + '.responsive-table'; this.idPrefix = this.id + '-col-'; this.headerColIndices = {}; this.headerRowIndices = {}; // Setup table // ------------------------- //wrap table this.wrapTable(); //create toolbar with buttons this.createButtonToolbar(); //Build header indices mapping (for colspans in header) this.buildHeaderCellIndices(); // Setup cells // ------------------------- //setup header this.setupTableHeader(); //setup standard cells this.setupBodyRows(); //create sticky table head if(this.options.stickyTableHeader){ this.createStickyTableHeader(); } // hide toggle button if the list is empty if(this.$dropdownContainer.is(':empty')){ this.$dropdownGroup.hide(); } // Event binding // ------------------------- // on orientchange, resize and displayAllBtn-click $(window).bind('orientationchange resize ' + this.displayAllTrigger, function(){ //update the inputs' checked status that.$dropdownContainer.find('input').trigger('updateCheck'); //update colspan and visibility of spanning cells $.proxy(that.updateSpanningCells(), that); }).trigger('resize'); // console.timeEnd('init'); }; ResponsiveTable.DEFAULTS = { pattern: 'priority-columns', stickyTableHeader: true, fixedNavbar: '.navbar-fixed-top', // Is there a fixed navbar? The stickyTableHeader needs to know about it! addDisplayAllBtn: true, // should it have a display-all button? addFocusBtn: true, // should it have a focus button? focusBtnIcon: 'glyphicon glyphicon-screenshot', mainContainer: window, i18n: { focus : 'Focus', display : 'Display', displayAll: 'Display all' } }; // Wrap table ResponsiveTable.prototype.wrapTable = function() { this.$tableScrollWrapper.wrap('<div class="table-wrapper"/>'); this.$tableWrapper = this.$tableScrollWrapper.parent(); }; // Create toolbar with buttons ResponsiveTable.prototype.createButtonToolbar = function() { var that = this; this.$btnToolbar = $('<div class="btn-toolbar" />'); this.$dropdownGroup = $('<div class="btn-group dropdown-btn-group pull-right" />'); this.$dropdownBtn = $('<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">' + this.options.i18n.display + ' <span class="caret"></span></button>'); this.$dropdownContainer = $('<ul class="dropdown-menu"/>'); // Focus btn if(this.options.addFocusBtn) { // Create focus btn group this.$focusGroup = $('<div class="btn-group focus-btn-group" />'); // Create focus btn this.$focusBtn = $('<button class="btn btn-default">' + this.options.i18n.focus + '</button>'); if(this.options.focusBtnIcon) { this.$focusBtn.prepend('<span class="' + this.options.focusBtnIcon + '"></span> '); } // Add btn to group this.$focusGroup.append(this.$focusBtn); // Add focus btn to toolbar this.$btnToolbar.append(this.$focusGroup); // bind click on focus btn this.$focusBtn.click(function(){ $.proxy(that.activateFocus(), that); }); // bind click on rows this.$bodyRows.click(function(){ $.proxy(that.focusOnRow($(this)), that); }); } // Display-all btn if(this.options.addDisplayAllBtn) { // Create display-all btn this.$displayAllBtn = $('<button class="btn btn-default">' + this.options.i18n.displayAll + '</button>'); // Add display-all btn to dropdown-btn-group this.$dropdownGroup.append(this.$displayAllBtn); if (this.$table.hasClass('display-all')) { // add 'btn-primary' class to btn to indicate that display all is activated this.$displayAllBtn.addClass('btn-primary'); } // bind click on display-all btn this.$displayAllBtn.click(function(){ $.proxy(that.displayAll(null, true), that); }); } //add dropdown btn and menu to dropdown-btn-group this.$dropdownGroup.append(this.$dropdownBtn).append(this.$dropdownContainer); //add dropdown group to toolbar this.$btnToolbar.append(this.$dropdownGroup); // add toolbar above table this.$tableScrollWrapper.before(this.$btnToolbar); }; ResponsiveTable.prototype.clearAllFocus = function() { this.$bodyRows.removeClass('unfocused'); this.$bodyRows.removeClass('focused'); }; ResponsiveTable.prototype.activateFocus = function() { // clear all this.clearAllFocus(); if(this.$focusBtn){ this.$focusBtn.toggleClass('btn-primary'); } this.$table.toggleClass('focus-on'); }; ResponsiveTable.prototype.focusOnRow = function(row) { // only if activated (.i.e the table has the class focus-on) if(this.$table.hasClass('focus-on')) { var alreadyFocused = $(row).hasClass('focused'); // clear all this.clearAllFocus(); if(!alreadyFocused) { this.$bodyRows.addClass('unfocused'); $(row).addClass('focused'); } } }; /** * @param activate Forces the displayAll to be active or not. If anything else than bool, it will not force the state so it will toggle as normal. * @param trigger Bool to indicate if the displayAllTrigger should be triggered. */ ResponsiveTable.prototype.displayAll = function(activate, trigger) { if(this.$displayAllBtn){ // add 'btn-primary' class to btn to indicate that display all is activated this.$displayAllBtn.toggleClass('btn-primary', activate); } this.$table.toggleClass('display-all', activate); if(this.$tableClone){ this.$tableClone.toggleClass('display-all', activate); } if(trigger) { $(window).trigger(this.displayAllTrigger); } }; ResponsiveTable.prototype.preserveDisplayAll = function() { var displayProp = 'table-cell'; if($('html').hasClass('lt-ie9')){ displayProp = 'inline'; } $(this.$table).find('th, td').css('display', displayProp); if(this.$tableClone){ $(this.$tableClone).find('th, td').css('display', displayProp); } }; ResponsiveTable.prototype.createStickyTableHeader = function() { var that = this; //clone table head that.$tableClone = that.$table.clone(); //replace ids that.$tableClone.prop('id', this.id + '-clone'); that.$tableClone.find('[id]').each(function() { $(this).prop('id', $(this).prop('id') + '-clone'); }); // wrap table clone (this is our "sticky table header" now) that.$tableClone.wrap('<div class="sticky-table-header"/>'); that.$stickyTableHeader = that.$tableClone.parent(); // give the sticky table header same height as original that.$stickyTableHeader.css('height', that.$thead.height() + 2); //insert sticky table header that.$table.before(that.$stickyTableHeader); // bind scroll on mainContainer with updateStickyTableHeader $(this.options.mainContainer).bind('scroll', function(){ $.proxy(that.updateStickyTableHeader(), that); }); // bind resize on window with updateStickyTableHeader $(window).bind('resize', function(e){ $.proxy(that.updateStickyTableHeader(), that); }); $(that.$tableScrollWrapper).bind('scroll', function(){ $.proxy(that.updateStickyTableHeader(), that); }); // determine what solution to use for rendereing sticky table head (aboslute/fixed). that.useFixedSolution = !isIOS() || (getIOSVersion() >= 8); //add class for rendering solution if(that.useFixedSolution) { that.$tableScrollWrapper.addClass('fixed-solution'); } else { that.$tableScrollWrapper.addClass('absolute-solution'); } }; // Help function for sticky table header ResponsiveTable.prototype.updateStickyTableHeader = function() { var that = this, top = 0, offsetTop = that.$table.offset().top, scrollTop = $(this.options.mainContainer).scrollTop() -1, //-1 to accomodate for top border maxTop = that.$table.height() - that.$stickyTableHeader.height(), rubberBandOffset = (scrollTop + $(this.options.mainContainer).height()) - $(document).height(), navbarHeight = 0; //Is there a fixed navbar? if($(that.options.fixedNavbar).length) { var $navbar = $(that.options.fixedNavbar).first(); navbarHeight = $navbar.height(); scrollTop = scrollTop + navbarHeight; } var shouldBeVisible; if(this.options.mainContainer === window) { shouldBeVisible = (scrollTop > offsetTop) && (scrollTop < offsetTop + that.$table.height()); } else { shouldBeVisible = (offsetTop <= 0) && (-offsetTop < that.$table.height()); } // console.log('offsetTop:' + offsetTop); // console.log('scrollTop:' + scrollTop); // console.log('tableHeight:' + that.$table.height()); // console.log('shouldBeVisible:' + shouldBeVisible); if(that.useFixedSolution) { //fixed solution that.$stickyTableHeader.scrollLeft(that.$tableScrollWrapper.scrollLeft()); // Calculate top property value (-1 to accomodate for top border) top = navbarHeight - 1; // When the user is about to scroll past the table, move sticky table head up if(this.options.mainContainer === window && ((scrollTop - offsetTop) > maxTop)){ top -= ((scrollTop - offsetTop) - maxTop); that.$stickyTableHeader.addClass('border-radius-fix'); } else if(this.options.mainContainer !== window && ((- offsetTop) > maxTop)){ top -= ((- offsetTop) - maxTop); that.$stickyTableHeader.addClass('border-radius-fix'); } else { that.$stickyTableHeader.removeClass('border-radius-fix'); } if (shouldBeVisible) { //show sticky table header and update top and width. that.$stickyTableHeader.css({ 'visibility': 'visible', 'top': top + 'px', 'width': that.$tableScrollWrapper.innerWidth() + 'px'}); //no more stuff to do - return! return; } else { //hide sticky table header and reset width that.$stickyTableHeader.css({'visibility': 'hidden', 'width': 'auto' }); } } else { // alternate method //animation duration var animationDuration = 400; // Calculate top property value (-1 to accomodate for top border) if(this.options.mainContainer === window) { top = scrollTop - offsetTop - 1; } else { top = -offsetTop - 1; // console.log('top:' + top); } // Make sure the sticky table header doesn't slide up/down too far. if(top < 0) { top = 0; } else if (top > maxTop) { top = maxTop; } // Accomandate for rubber band effect if(this.options.mainContainer === window) { if(rubberBandOffset > 0) { top = top - rubberBandOffset; } } if (shouldBeVisible) { //show sticky table header (animate repositioning) that.$stickyTableHeader.css({ 'visibility': 'visible' }); that.$stickyTableHeader.animate({ 'top': top + 'px' }, animationDuration); // hide original table head that.$thead.css({ 'visibility': 'hidden' }); } else { that.$stickyTableHeader.animate({ 'top': '0' }, animationDuration, function(){ // show original table head that.$thead.css({ 'visibility': 'visible' }); // hide sticky table head that.$stickyTableHeader.css({ 'visibility': 'hidden' }); }); } } }; // Setup header cells ResponsiveTable.prototype.setupTableHeader = function() { var that = this; // for each header column that.$hdrCells.each(function(i){ var $th = $(this), id = $th.prop('id'), thText = $th.text(); // assign an id to each header, if none is in the markup if (!id) { id = that.idPrefix + i; $th.prop('id', id); } if(thText === ''){ thText = $th.attr('data-col-name'); } // create the hide/show toggle for the current column if ( $th.is('[data-priority]') && $th.data('priority') !== -1 ) { var $toggle = $('<li class="checkbox-row"><input type="checkbox" name="toggle-'+id+'" id="toggle-'+id+'" value="'+id+'" /> <label for="toggle-'+id+'">'+ thText +'</label></li>'); var $checkbox = $toggle.find('input'); that.$dropdownContainer.append($toggle); $toggle.click(function(){ // console.log("cliiiick!"); $checkbox.prop('checked', !$checkbox.prop('checked')); $checkbox.trigger('change'); }); //Freakin' IE fix if ($('html').hasClass('lt-ie9')) { $checkbox.click(function() { $(this).trigger('change'); }); } $toggle.find('label').click(function(event){ event.stopPropagation(); }); $toggle.find('input') .click(function(event){ event.stopPropagation(); }) .change(function(){ // bind change event on checkbox var $checkbox = $(this), val = $checkbox.val(), //all cells under the column, including the header and its clone $cells = that.$tableWrapper.find('#' + val + ', #' + val + '-clone, [data-columns~='+ val +']'); //if display-all is on - save state and carry on if(that.$table.hasClass('display-all')){ //save state $.proxy(that.preserveDisplayAll(), that); //remove display all class that.$table.removeClass('display-all'); if(that.$tableClone){ that.$tableClone.removeClass('display-all'); } //switch off button that.$displayAllBtn.removeClass('btn-primary'); } // loop through the cells $cells.each(function(){ var $cell = $(this); // is the checkbox checked now? if ($checkbox.is(':checked')) { // if the cell was already visible, it means its original colspan was >1 // so let's increment the colspan // This should not be done for th's in thead. if(!$cell.closest("thead").length && $cell.css('display') !== 'none'){ // make sure new colspan value does not exceed original colspan value var newColSpan = Math.min(parseInt($cell.prop('colSpan')) + 1, $cell.attr('data-org-colspan')); // update colspan $cell.prop('colSpan', newColSpan); } // show cell $cell.show(); } // checkbox has been unchecked else { // decrement colSpan if it's not 1 (because colSpan should not be 0) // This should not be done for th's in thead. if(!$cell.closest("thead").length && parseInt($cell.prop('colSpan'))>1){ $cell.prop('colSpan', parseInt($cell.prop('colSpan')) - 1); } // otherwise, hide the cell else { $cell.hide(); } } }); }) .bind('updateCheck', function(){ if ( $th.css('display') !== 'none') { $(this).prop('checked', true); } else { $(this).prop('checked', false); } }); } // end if }); // end hdrCells loop if(!$.isEmptyObject(this.headerRowIndices)) { that.setupRow(this.$thead.find("tr:eq(1)"), this.headerRowIndices); } }; // Setup body rows // assign matching "data-columns" attributes to the associated cells "(cells with colspan>1 has multiple columns). ResponsiveTable.prototype.setupBodyRows = function() { var that = this; // for each body rows that.$bodyRows.each(function(){ that.setupRow($(this), that.headerColIndices); }); }; ResponsiveTable.prototype.setupRow = function($row, indices) { var that = this; //check if it's already set up if($row.data('setup')){ // don't do anything return; } else { $row.data('setup', true); } var idStart = 0; // for each cell $row.find('th, td').each(function(){ var $cell = $(this); var columnsAttr = ''; var colSpan = $cell.prop('colSpan'); $cell.attr('data-org-colspan', colSpan); // if colSpan is more than 1 if(colSpan > 1) { //give it the class 'spn-cell'; $cell.addClass('spn-cell'); } // loop through columns that the cell spans over for (var k = idStart; k < (idStart + colSpan); k++) { // add column id columnsAttr = columnsAttr + ' ' + that.idPrefix + indices[k]; // get column header var $colHdr = that.$table.find('#' + that.idPrefix + indices[k]); // copy data-priority attribute from column header var dataPriority = $colHdr.attr('data-priority'); if (dataPriority) { $cell.attr('data-priority', dataPriority); } } //remove whitespace in begining of string. columnsAttr = columnsAttr.substring(1); //set attribute to cell $cell.attr('data-columns', columnsAttr); //increment idStart with the current cells colSpan. idStart = idStart + colSpan; }); }; ResponsiveTable.prototype.buildHeaderCellIndices = function() { var that = this; var rowspansBeforeIndex = {}; this.headerColIndices = {}; this.headerRowIndices = {}; var colPadding = 0; var rowPadding = 0; this.$thead.find("tr").first().find('th').each(function(i){ var $th = $(this); var colSpan = $th.prop('colSpan'); var rowSpan = $th.prop("rowSpan"); for(var index = 0; index < colSpan; index++) { that.headerColIndices[colPadding + i + index] = i; if(colPadding + i + index >= 0) { rowspansBeforeIndex[colPadding + i + index - rowPadding] = rowPadding; } } if(rowSpan > 1) { rowPadding++; } colPadding += colSpan - 1; }); if(this.$thead.find("tr").length > 2) { throw new Error("This plugin doesnt support more than two rows in thead."); } if(this.$thead.find("tr").length === 2) { var $row = $(this.$thead.find("tr")[1]); $row.find("th").each(function(cellIndex) { that.headerRowIndices[cellIndex] = that.headerColIndices[rowspansBeforeIndex[cellIndex] + cellIndex]; }); } } // Run this after the content in tbody has changed ResponsiveTable.prototype.update = function() { this.$bodyRows = this.$table.find('tbody, tfoot').find('tr'); this.setupBodyRows(); // Remove old tbody clone from Tableclone this.$tableClone.find('tbody, tfoot').remove(); // Make new clone of tbody var $tbodyClone = this.$table.find('tbody, tfoot').clone(); //replace ids $tbodyClone.find('[id]').each(function() { $(this).prop('id', $(this).prop('id') + '-clone'); }); // Append new clone to tableClone $tbodyClone.appendTo(this.$tableClone); // Make sure columns visibility is in sync, // by triggering a (non-changing) change event on all checkboxes this.$dropdownContainer.find('input').trigger('change'); // ¯\(°_o)/¯ I dunno if this is needed // this.updateSpanningCells(); }; // Update colspan and visibility of spanning cells ResponsiveTable.prototype.updateSpanningCells = function() { var that = this; // iterate through cells with class 'spn-cell' that.$table.find('.spn-cell').each( function(){ var $cell = $(this); var columnsAttr = $cell.attr('data-columns').split(' '); var colSpan = columnsAttr.length; var numOfHidden = 0; for (var i = 0; i < colSpan; i++) { if($('#' + columnsAttr[i]).css('display')==='none'){ numOfHidden++; } } // if one of the columns that the cell belongs to is visible then show the cell if(numOfHidden !== colSpan){ $cell.show(); } else { $cell.hide(); //just in case } // console.log('numOfHidden: ' + numOfHidden); // console.log("new colSpan:" +Math.max((colSpan - numOfHidden),1)); //update colSpan to match number of visible columns that i belongs to $cell.prop('colSpan',Math.max((colSpan - numOfHidden),1)); }); }; // RESPONSIVE TABLE PLUGIN DEFINITION // =========================== var old = $.fn.responsiveTable; $.fn.responsiveTable = function (option) { return this.each(function () { var $this = $(this); var data = $this.data('responsiveTable'); var options = $.extend({}, ResponsiveTable.DEFAULTS, $this.data(), typeof option === 'object' && option); if(options.pattern === '') { return; } if (!data) { $this.data('responsiveTable', (data = new ResponsiveTable(this, options))); } if (typeof option === 'string') { data[option](); } }); }; $.fn.responsiveTable.Constructor = ResponsiveTable; // RESPONSIVE TABLE NO CONFLICT // ===================== $.fn.responsiveTable.noConflict = function () { $.fn.responsiveTable = old; return this; }; // RESPONSIVE TABLE DATA-API // ================== $(document).on('ready.responsive-table.data-api', function () { $('[data-pattern]').each(function () { var $tableScrollWrapper = $(this); $tableScrollWrapper.responsiveTable($tableScrollWrapper.data()); }); }); // DROPDOWN // ========================== // Prevent dropdown from closing when toggling checkbox $(document).on('click.dropdown.data-api', '.dropdown-menu .checkbox-row', function (e) { e.stopPropagation(); }); // FEATURE DETECTION (instead of Modernizr) // ========================== // media queries function mediaQueriesSupported() { return (typeof window.matchMedia !== 'undefined' || typeof window.msMatchMedia !== 'undefined' || typeof window.styleMedia !== 'undefined'); } // touch function hasTouch() { return 'ontouchstart' in window; } // Checks if current browser is on IOS. function isIOS() { return !!(navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i)); } // Gets iOS version number. If the user is not on iOS, the function returns 0. function getIOSVersion() { if(isIOS()){ var iphone_version = parseFloat(('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')); return iphone_version; } else { return 0; } } $(document).ready(function() { // Change `no-js` to `js` $('html').removeClass('no-js').addClass('js'); // Add mq/no-mq class to html if(mediaQueriesSupported()) { $('html').addClass('mq'); } else { $('html').addClass('no-mq'); } // Add touch/no-touch class to html if(hasTouch()) { $('html').addClass('touch'); } else { $('html').addClass('no-touch'); } }); })(jQuery);
💾 Simpan File
Batal
⬅ Naik ke rwdtable
2 item
Nama
Tipe
Ukuran
Diubah
Aksi
📜
rwd-table.js
js
28.3 KB
2025-06-16 21:48
✏️ Edit
👁️ View
🗑 Hapus
📜
rwd-table.min.js
js
11.2 KB
2025-06-16 21:48
✏️ Edit
👁️ View
🗑 Hapus