diff --git a/css/footable.core.min.css b/css/footable.core.min.css new file mode 100644 index 0000000..f898f3e --- /dev/null +++ b/css/footable.core.min.css @@ -0,0 +1 @@ +@font-face{font-family:footable;src:url(../fonts/footable.eot);src:url(../fonts/footable.eot?#iefix) format('embedded-opentype'),url(../fonts/footable.woff) format('woff'),url(../fonts/footable.ttf) format('truetype'),url(../fonts/footable.svg#footable) format('svg');font-weight:400;font-style:normal}@media screen and (-webkit-min-device-pixel-ratio:0){@font-face{font-family:footable;src:url(../fonts/footable.svg#footable) format('svg');font-weight:400;font-style:normal}}.footable{width:100%}.footable.breakpoint>tbody>tr.footable-detail-show>td{border-bottom:none}.footable.breakpoint>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e001"}.footable.breakpoint>tbody>tr:hover:not(.footable-row-detail){cursor:pointer}.footable.breakpoint>tbody>tr>td.footable-cell-detail{background:#eee;border-top:none}.footable.breakpoint>tbody>tr>td>span.footable-toggle{display:inline-block;font-family:footable;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-right:5px;font-size:14px;color:#888}.footable.breakpoint>tbody>tr>td>span.footable-toggle:before{content:"\e000"}.footable.breakpoint.toggle-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e005"}.footable.breakpoint.toggle-circle>tbody>tr>td>span.footable-toggle:before{content:"\e004"}.footable.breakpoint.toggle-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e003"}.footable.breakpoint.toggle-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e002"}.footable.breakpoint.toggle-square>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e007"}.footable.breakpoint.toggle-square>tbody>tr>td>span.footable-toggle:before{content:"\e006"}.footable.breakpoint.toggle-square-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e009"}.footable.breakpoint.toggle-square-filled>tbody>tr>td>span.footable-toggle:before{content:"\e008"}.footable.breakpoint.toggle-arrow>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00f"}.footable.breakpoint.toggle-arrow>tbody>tr>td>span.footable-toggle:before{content:"\e011"}.footable.breakpoint.toggle-arrow-small>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e013"}.footable.breakpoint.toggle-arrow-small>tbody>tr>td>span.footable-toggle:before{content:"\e015"}.footable.breakpoint.toggle-arrow-circle>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01b"}.footable.breakpoint.toggle-arrow-circle>tbody>tr>td>span.footable-toggle:before{content:"\e01d"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e00b"}.footable.breakpoint.toggle-arrow-circle-filled>tbody>tr>td>span.footable-toggle:before{content:"\e00d"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e01f"}.footable.breakpoint.toggle-arrow-tiny>tbody>tr>td>span.footable-toggle:before{content:"\e021"}.footable.breakpoint.toggle-arrow-alt>tbody>tr.footable-detail-show>td>span.footable-toggle:before{content:"\e017"}.footable.breakpoint.toggle-arrow-alt>tbody>tr>td>span.footable-toggle:before{content:"\e019"}.footable.breakpoint.toggle-medium>tbody>tr>td>span.footable-toggle{font-size:18px}.footable.breakpoint.toggle-large>tbody>tr>td>span.footable-toggle{font-size:24px}.footable>thead>tr>th{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:-moz-none;-ms-user-select:none;user-select:none}.footable>thead>tr>th.footable-sortable:hover{cursor:pointer}.footable>thead>tr>th.footable-sorted>span.footable-sort-indicator:before{content:"\e013"}.footable>thead>tr>th.footable-sorted-desc>span.footable-sort-indicator:before{content:"\e012"}.footable>thead>tr>th>span.footable-sort-indicator{display:inline-block;font-family:footable;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;-webkit-font-smoothing:antialiased;padding-left:5px}.footable>thead>tr>th>span.footable-sort-indicator:before{content:"\e022"}.footable>tfoot .pagination{margin:0}.footable.no-paging .hide-if-no-paging{display:none}.footable-row-detail-inner{display:table}.footable-row-detail-row{display:table-row;line-height:1.5em}.footable-row-detail-group{display:block;line-height:2em;font-size:1.2em;font-weight:700}.footable-row-detail-name{display:table-cell;font-weight:700;padding-right:.5em}.footable-row-detail-value{display:table-cell}.footable-odd{background-color:#f7f7f7} \ No newline at end of file diff --git a/fonts/footable.eot b/fonts/footable.eot new file mode 100644 index 0000000..3722979 Binary files /dev/null and b/fonts/footable.eot differ diff --git a/fonts/footable.svg b/fonts/footable.svg new file mode 100644 index 0000000..5a6e1fd --- /dev/null +++ b/fonts/footable.svg @@ -0,0 +1,78 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/fonts/footable.ttf b/fonts/footable.ttf new file mode 100644 index 0000000..2d5c84a Binary files /dev/null and b/fonts/footable.ttf differ diff --git a/fonts/footable.woff b/fonts/footable.woff new file mode 100644 index 0000000..4864dbb Binary files /dev/null and b/fonts/footable.woff differ diff --git a/images/icons/icon-afavor.png b/images/icons/icon-afavor.png new file mode 100644 index 0000000..16f47e7 Binary files /dev/null and b/images/icons/icon-afavor.png differ diff --git a/images/icons/icon-contra.png b/images/icons/icon-contra.png new file mode 100644 index 0000000..9779c60 Binary files /dev/null and b/images/icons/icon-contra.png differ diff --git a/index.html b/index.html index 52c9cd4..373c4c6 100644 --- a/index.html +++ b/index.html @@ -48,6 +48,7 @@ 'css/bootstrap.min.css', 'css/bootstrap-alert.min.css', 'css/hover.custom.css', + 'css/footable.core.min.css', 'http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css', 'http://fonts.googleapis.com/css?family=Open+Sans:400,300,700', 'http://fonts.googleapis.com/css?family=Asap:400,700', @@ -323,15 +324,18 @@ Última atualização -
- - - - - - - - +
+
Posição PropostasExibições
+ + + + + + + + + + {{#each proposals}} @@ -341,6 +345,7 @@ {{/each}} +
Posição PropostasExibiçõesA favorContra
{{calcPosition @index ../pagination.per_page ../pagination.page}}°{{votes_against}}
diff --git a/js/footable.js b/js/footable.js new file mode 100644 index 0000000..234e4f4 --- /dev/null +++ b/js/footable.js @@ -0,0 +1,824 @@ +/*! + * FooTable - Awesome Responsive Tables + * Version : 2.0.3 + * http://fooplugins.com/plugins/footable-jquery/ + * + * Requires jQuery - http://jquery.com/ + * + * Copyright 2014 Steven Usher & Brad Vincent + * Released under the MIT license + * You are free to use FooTable in commercial projects as long as this copyright header is left intact. + * + * Date: 11 Nov 2014 + */ +(function ($, w, undefined) { + w.footable = { + options: { + delay: 100, // The number of millseconds to wait before triggering the react event + breakpoints: { // The different screen resolution breakpoints + phone: 480, + tablet: 1024 + }, + parsers: { // The default parser to parse the value out of a cell (values are used in building up row detail) + alpha: function (cell) { + return $(cell).data('value') || $.trim($(cell).text()); + }, + numeric: function (cell) { + var val = $(cell).data('value') || $(cell).text().replace(/[^0-9.\-]/g, ''); + val = parseFloat(val); + if (isNaN(val)) val = 0; + return val; + } + }, + addRowToggle: true, + calculateWidthOverride: null, + toggleSelector: ' > tbody > tr:not(.footable-row-detail)', //the selector to show/hide the detail row + columnDataSelector: '> thead > tr:last-child > th, > thead > tr:last-child > td', //the selector used to find the column data in the thead + detailSeparator: ':', //the separator character used when building up the detail row + toggleHTMLElement: '', // override this if you want to insert a click target rather than use a background image. + createGroupedDetail: function (data) { + var groups = { '_none': { 'name': null, 'data': [] } }; + for (var i = 0; i < data.length; i++) { + var groupid = data[i].group; + if (groupid !== null) { + if (!(groupid in groups)) + groups[groupid] = { 'name': data[i].groupName || data[i].group, 'data': [] }; + + groups[groupid].data.push(data[i]); + } else { + groups._none.data.push(data[i]); + } + } + return groups; + }, + createDetail: function (element, data, createGroupedDetail, separatorChar, classes) { + /// This function is used by FooTable to generate the detail view seen when expanding a collapsed row. + /// This is the div that contains all the detail row information, anything could be added to it. + /// + /// This is an array of objects containing the cell information for the current row. + /// These objects look like the below: + /// obj = { + /// 'name': String, // The name of the column + /// 'value': Object, // The value parsed from the cell using the parsers. This could be a string, a number or whatever the parser outputs. + /// 'display': String, // This is the actual HTML from the cell, so if you have images etc you want moved this is the one to use and is the default value used. + /// 'group': String, // This is the identifier used in the data-group attribute of the column. + /// 'groupName': String // This is the actual name of the group the column belongs to. + /// } + /// + /// The grouping function to group the data + /// The separator charactor used + /// The array of class names used to build up the detail row + + var groups = createGroupedDetail(data); + for (var group in groups) { + if (groups[group].data.length === 0) continue; + if (group !== '_none') element.append('
' + groups[group].name + '
'); + + for (var j = 0; j < groups[group].data.length; j++) { + var separator = (groups[group].data[j].name) ? separatorChar : ''; + element.append($('
').addClass(classes.detailInnerRow).append($('
').addClass(classes.detailInnerName) + .append(groups[group].data[j].name + separator)).append($('
').addClass(classes.detailInnerValue) + .attr('data-bind-value', groups[group].data[j].bindName).append(groups[group].data[j].display))); + } + } + }, + classes: { + main: 'footable', + loading: 'footable-loading', + loaded: 'footable-loaded', + toggle: 'footable-toggle', + disabled: 'footable-disabled', + detail: 'footable-row-detail', + detailCell: 'footable-row-detail-cell', + detailInner: 'footable-row-detail-inner', + detailInnerRow: 'footable-row-detail-row', + detailInnerGroup: 'footable-row-detail-group', + detailInnerName: 'footable-row-detail-name', + detailInnerValue: 'footable-row-detail-value', + detailShow: 'footable-detail-show' + }, + triggers: { + initialize: 'footable_initialize', //trigger this event to force FooTable to reinitialize + resize: 'footable_resize', //trigger this event to force FooTable to resize + redraw: 'footable_redraw', //trigger this event to force FooTable to redraw + toggleRow: 'footable_toggle_row', //trigger this event to force FooTable to toggle a row + expandFirstRow: 'footable_expand_first_row', //trigger this event to force FooTable to expand the first row + expandAll: 'footable_expand_all', //trigger this event to force FooTable to expand all rows + collapseAll: 'footable_collapse_all' //trigger this event to force FooTable to collapse all rows + }, + events: { + alreadyInitialized: 'footable_already_initialized', //fires when the FooTable has already been initialized + initializing: 'footable_initializing', //fires before FooTable starts initializing + initialized: 'footable_initialized', //fires after FooTable has finished initializing + resizing: 'footable_resizing', //fires before FooTable resizes + resized: 'footable_resized', //fires after FooTable has resized + redrawn: 'footable_redrawn', //fires after FooTable has redrawn + breakpoint: 'footable_breakpoint', //fires inside the resize function, when a breakpoint is hit + columnData: 'footable_column_data', //fires when setting up column data. Plugins should use this event to capture their own info about a column + rowDetailUpdating: 'footable_row_detail_updating', //fires before a detail row is updated + rowDetailUpdated: 'footable_row_detail_updated', //fires when a detail row is being updated + rowCollapsed: 'footable_row_collapsed', //fires when a row is collapsed + rowExpanded: 'footable_row_expanded', //fires when a row is expanded + rowRemoved: 'footable_row_removed', //fires when a row is removed + reset: 'footable_reset' //fires when FooTable is reset + }, + debug: false, // Whether or not to log information to the console. + log: null + }, + + version: { + major: 0, minor: 5, + toString: function () { + return w.footable.version.major + '.' + w.footable.version.minor; + }, + parse: function (str) { + var version = /(\d+)\.?(\d+)?\.?(\d+)?/.exec(str); + return { + major: parseInt(version[1], 10) || 0, + minor: parseInt(version[2], 10) || 0, + patch: parseInt(version[3], 10) || 0 + }; + } + }, + + plugins: { + _validate: function (plugin) { + ///Simple validation of the to make sure any members called by FooTable actually exist. + ///The object defining the plugin, this should implement a string property called "name" and a function called "init". + + if (!$.isFunction(plugin)) { + if (w.footable.options.debug === true) console.error('Validation failed, expected type "function", received type "{0}".', typeof plugin); + return false; + } + var p = new plugin(); + if (typeof p['name'] !== 'string') { + if (w.footable.options.debug === true) console.error('Validation failed, plugin does not implement a string property called "name".', p); + return false; + } + if (!$.isFunction(p['init'])) { + if (w.footable.options.debug === true) console.error('Validation failed, plugin "' + p['name'] + '" does not implement a function called "init".', p); + return false; + } + if (w.footable.options.debug === true) console.log('Validation succeeded for plugin "' + p['name'] + '".', p); + return true; + }, + registered: [], // An array containing all registered plugins. + register: function (plugin, options) { + ///Registers a and its default with FooTable. + ///The plugin that should implement a string property called "name" and a function called "init". + ///The default options to merge with the FooTable's base options. + + if (w.footable.plugins._validate(plugin)) { + w.footable.plugins.registered.push(plugin); + if (typeof options === 'object') $.extend(true, w.footable.options, options); + } + }, + load: function(instance){ + var loaded = [], registered, i; + for(i = 0; i < w.footable.plugins.registered.length; i++){ + try { + registered = w.footable.plugins.registered[i]; + loaded.push(new registered(instance)); + } catch (err) { + if (w.footable.options.debug === true) console.error(err); + } + } + return loaded; + }, + init: function (instance) { + ///Loops through all registered plugins and calls the "init" method supplying the current of the FooTable as the first parameter. + ///The current instance of the FooTable that the plugin is being initialized for. + + for (var i = 0; i < instance.plugins.length; i++) { + try { + instance.plugins[i]['init'](instance); + } catch (err) { + if (w.footable.options.debug === true) console.error(err); + } + } + } + } + }; + + var instanceCount = 0; + + $.fn.footable = function (options) { + ///The main constructor call to initialize the plugin using the supplied . + /// + ///A JSON object containing user defined options for the plugin to use. Any options not supplied will have a default value assigned. + ///Check the documentation or the default options object above for more information on available options. + /// + + options = options || {}; + var o = $.extend(true, {}, w.footable.options, options); //merge user and default options + return this.each(function () { + instanceCount++; + var footable = new Footable(this, o, instanceCount); + $(this).data('footable', footable); + }); + }; + + //helper for using timeouts + function Timer() { + ///Simple timer object created around a timeout. + var t = this; + t.id = null; + t.busy = false; + t.start = function (code, milliseconds) { + ///Starts the timer and waits the specified amount of before executing the supplied . + ///The code to execute once the timer runs out. + ///The time in milliseconds to wait before executing the supplied . + + if (t.busy) { + return; + } + t.stop(); + t.id = setTimeout(function () { + code(); + t.id = null; + t.busy = false; + }, milliseconds); + t.busy = true; + }; + t.stop = function () { + ///Stops the timer if its runnning and resets it back to its starting state. + + if (t.id !== null) { + clearTimeout(t.id); + t.id = null; + t.busy = false; + } + }; + } + + function Footable(t, o, id) { + ///Inits a new instance of the plugin. + ///The main table element to apply this plugin to. + ///The options supplied to the plugin. Check the defaults object to see all available options. + ///The id to assign to this instance of the plugin. + + var ft = this; + ft.id = id; + ft.table = t; + ft.options = o; + ft.breakpoints = []; + ft.breakpointNames = ''; + ft.columns = {}; + ft.plugins = w.footable.plugins.load(ft); + + var opt = ft.options, + cls = opt.classes, + evt = opt.events, + trg = opt.triggers, + indexOffset = 0; + + // This object simply houses all the timers used in the FooTable. + ft.timers = { + resize: new Timer(), + register: function (name) { + ft.timers[name] = new Timer(); + return ft.timers[name]; + } + }; + + ft.init = function () { + var $window = $(w), $table = $(ft.table); + + w.footable.plugins.init(ft); + + if ($table.hasClass(cls.loaded)) { + //already loaded FooTable for the table, so don't init again + ft.raise(evt.alreadyInitialized); + return; + } + + //raise the initializing event + ft.raise(evt.initializing); + + $table.addClass(cls.loading); + + // Get the column data once for the life time of the plugin + $table.find(opt.columnDataSelector).each(function () { + var data = ft.getColumnData(this); + ft.columns[data.index] = data; + }); + + // Create a nice friendly array to work with out of the breakpoints object. + for (var name in opt.breakpoints) { + ft.breakpoints.push({ 'name': name, 'width': opt.breakpoints[name] }); + ft.breakpointNames += (name + ' '); + } + + // Sort the breakpoints so the smallest is checked first + ft.breakpoints.sort(function (a, b) { + return a['width'] - b['width']; + }); + + $table + .unbind(trg.initialize) + //bind to FooTable initialize trigger + .bind(trg.initialize, function () { + //remove previous "state" (to "force" a resize) + $table.removeData('footable_info'); + $table.data('breakpoint', ''); + + //trigger the FooTable resize + $table.trigger(trg.resize); + + //remove the loading class + $table.removeClass(cls.loading); + + //add the FooTable and loaded class + $table.addClass(cls.loaded).addClass(cls.main); + + //raise the initialized event + ft.raise(evt.initialized); + }) + .unbind(trg.redraw) + //bind to FooTable redraw trigger + .bind(trg.redraw, function () { + ft.redraw(); + }) + .unbind(trg.resize) + //bind to FooTable resize trigger + .bind(trg.resize, function () { + ft.resize(); + }) + .unbind(trg.expandFirstRow) + //bind to FooTable expandFirstRow trigger + .bind(trg.expandFirstRow, function () { + $table.find(opt.toggleSelector).first().not('.' + cls.detailShow).trigger(trg.toggleRow); + }) + .unbind(trg.expandAll) + //bind to FooTable expandFirstRow trigger + .bind(trg.expandAll, function () { + $table.find(opt.toggleSelector).not('.' + cls.detailShow).trigger(trg.toggleRow); + }) + .unbind(trg.collapseAll) + //bind to FooTable expandFirstRow trigger + .bind(trg.collapseAll, function () { + $table.find('.' + cls.detailShow).trigger(trg.toggleRow); + }); + + //trigger a FooTable initialize + $table.trigger(trg.initialize); + + //bind to window resize + $window + .bind('resize.footable', function () { + ft.timers.resize.stop(); + ft.timers.resize.start(function () { + ft.raise(trg.resize); + }, opt.delay); + }); + }; + + ft.addRowToggle = function () { + if (!opt.addRowToggle) return; + + var $table = $(ft.table), + hasToggleColumn = false; + + //first remove all toggle spans + $table.find('span.' + cls.toggle).remove(); + + for (var c in ft.columns) { + var col = ft.columns[c]; + if (col.toggle) { + hasToggleColumn = true; + var selector = '> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > td:nth-child(' + (parseInt(col.index, 10) + 1) + '),' + + '> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > th:nth-child(' + (parseInt(col.index, 10) + 1) + ')'; + $table.find(selector).not('.' + cls.detailCell).prepend($(opt.toggleHTMLElement).addClass(cls.toggle)); + return; + } + } + //check if we have an toggle column. If not then add it to the first column just to be safe + if (!hasToggleColumn) { + $table + .find('> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > td:first-child') + .add('> tbody > tr:not(.' + cls.detail + ',.' + cls.disabled + ') > th:first-child') + .not('.' + cls.detailCell) + .prepend($(opt.toggleHTMLElement).addClass(cls.toggle)); + } + }; + + ft.setColumnClasses = function () { + var $table = $(ft.table); + for (var c in ft.columns) { + var col = ft.columns[c]; + if (col.className !== null) { + var selector = '', first = true; + $.each(col.matches, function (m, match) { //support for colspans + if (!first) selector += ', '; + selector += '> tbody > tr:not(.' + cls.detail + ') > td:nth-child(' + (parseInt(match, 10) + 1) + ')'; + first = false; + }); + //add the className to the cells specified by data-class="blah" + $table.find(selector).not('.' + cls.detailCell).addClass(col.className); + } + } + }; + + //moved this out into it's own function so that it can be called from other add-ons + ft.bindToggleSelectors = function () { + var $table = $(ft.table); + + if (!ft.hasAnyBreakpointColumn()) return; + + $table.find(opt.toggleSelector).unbind(trg.toggleRow).bind(trg.toggleRow, function (e) { + var $row = $(this).is('tr') ? $(this) : $(this).parents('tr:first'); + ft.toggleDetail($row); + }); + + $table.find(opt.toggleSelector).unbind('click.footable').bind('click.footable', function (e) { + if ($table.is('.breakpoint') && $(e.target).is('td,th,.'+ cls.toggle)) { + $(this).trigger(trg.toggleRow); + } + }); + }; + + ft.parse = function (cell, column) { + var parser = opt.parsers[column.type] || opt.parsers.alpha; + return parser(cell); + }; + + ft.getColumnData = function (th) { + var $th = $(th), hide = $th.data('hide'), index = $th.index(); + hide = hide || ''; + hide = jQuery.map(hide.split(','), function (a) { + return jQuery.trim(a); + }); + var data = { + 'index': index, + 'hide': { }, + 'type': $th.data('type') || 'alpha', + 'name': $th.data('name') || $.trim($th.text()), + 'ignore': $th.data('ignore') || false, + 'toggle': $th.data('toggle') || false, + 'className': $th.data('class') || null, + 'matches': [], + 'names': { }, + 'group': $th.data('group') || null, + 'groupName': null, + 'isEditable': $th.data('editable') + }; + + if (data.group !== null) { + var $group = $(ft.table).find('> thead > tr.footable-group-row > th[data-group="' + data.group + '"], > thead > tr.footable-group-row > td[data-group="' + data.group + '"]').first(); + data.groupName = ft.parse($group, { 'type': 'alpha' }); + } + + var pcolspan = parseInt($th.prev().attr('colspan') || 0, 10); + indexOffset += pcolspan > 1 ? pcolspan - 1 : 0; + var colspan = parseInt($th.attr('colspan') || 0, 10), curindex = data.index + indexOffset; + if (colspan > 1) { + var names = $th.data('names'); + names = names || ''; + names = names.split(','); + for (var i = 0; i < colspan; i++) { + data.matches.push(i + curindex); + if (i < names.length) data.names[i + curindex] = names[i]; + } + } else { + data.matches.push(curindex); + } + + data.hide['default'] = ($th.data('hide') === "all") || ($.inArray('default', hide) >= 0); + + var hasBreakpoint = false; + for (var name in opt.breakpoints) { + data.hide[name] = ($th.data('hide') === "all") || ($.inArray(name, hide) >= 0); + hasBreakpoint = hasBreakpoint || data.hide[name]; + } + data.hasBreakpoint = hasBreakpoint; + var e = ft.raise(evt.columnData, { 'column': { 'data': data, 'th': th } }); + return e.column.data; + }; + + ft.getViewportWidth = function () { + return window.innerWidth || (document.body ? document.body.offsetWidth : 0); + }; + + ft.calculateWidth = function ($table, info) { + if (jQuery.isFunction(opt.calculateWidthOverride)) { + return opt.calculateWidthOverride($table, info); + } + if (info.viewportWidth < info.width) info.width = info.viewportWidth; + if (info.parentWidth < info.width) info.width = info.parentWidth; + return info; + }; + + ft.hasBreakpointColumn = function (breakpoint) { + for (var c in ft.columns) { + if (ft.columns[c].hide[breakpoint]) { + if (ft.columns[c].ignore) { + continue; + } + return true; + } + } + return false; + }; + + ft.hasAnyBreakpointColumn = function () { + for (var c in ft.columns) { + if (ft.columns[c].hasBreakpoint) { + return true; + } + } + return false; + }; + + ft.resize = function () { + var $table = $(ft.table); + + if (!$table.is(':visible')) { + return; + } //we only care about FooTables that are visible + + if (!ft.hasAnyBreakpointColumn()) { + $table.trigger(trg.redraw); + return; + } //we only care about FooTables that have breakpoints + + var info = { + 'width': $table.width(), //the table width + 'viewportWidth': ft.getViewportWidth(), //the width of the viewport + 'parentWidth': $table.parent().width() //the width of the parent + }; + + info = ft.calculateWidth($table, info); + + var pinfo = $table.data('footable_info'); + $table.data('footable_info', info); + ft.raise(evt.resizing, { 'old': pinfo, 'info': info }); + + // This (if) statement is here purely to make sure events aren't raised twice as mobile safari seems to do + if (!pinfo || (pinfo && pinfo.width && pinfo.width !== info.width)) { + + var current = null, breakpoint; + for (var i = 0; i < ft.breakpoints.length; i++) { + breakpoint = ft.breakpoints[i]; + if (breakpoint && breakpoint.width && info.width <= breakpoint.width) { + current = breakpoint; + break; + } + } + + var breakpointName = (current === null ? 'default' : current['name']), + hasBreakpointFired = ft.hasBreakpointColumn(breakpointName), + previousBreakpoint = $table.data('breakpoint'); + + $table + .data('breakpoint', breakpointName) + .removeClass('default breakpoint').removeClass(ft.breakpointNames) + .addClass(breakpointName + (hasBreakpointFired ? ' breakpoint' : '')); + + //only do something if the breakpoint has changed + if (breakpointName !== previousBreakpoint) { + //trigger a redraw + $table.trigger(trg.redraw); + //raise a breakpoint event + ft.raise(evt.breakpoint, { 'breakpoint': breakpointName, 'info': info }); + } + } + + ft.raise(evt.resized, { 'old': pinfo, 'info': info }); + }; + + ft.redraw = function () { + //add the toggler to each row + ft.addRowToggle(); + + //bind the toggle selector click events + ft.bindToggleSelectors(); + + //set any cell classes defined for the columns + ft.setColumnClasses(); + + var $table = $(ft.table), + breakpointName = $table.data('breakpoint'), + hasBreakpointFired = ft.hasBreakpointColumn(breakpointName); + + $table + .find('> tbody > tr:not(.' + cls.detail + ')').data('detail_created', false).end() + .find('> thead > tr:last-child > th') + .each(function () { + var data = ft.columns[$(this).index()], selector = '', first = true; + $.each(data.matches, function (m, match) { + if (!first) { + selector += ', '; + } + var count = match + 1; + selector += '> tbody > tr:not(.' + cls.detail + ') > td:nth-child(' + count + ')'; + selector += ', > tfoot > tr:not(.' + cls.detail + ') > td:nth-child(' + count + ')'; + selector += ', > colgroup > col:nth-child(' + count + ')'; + first = false; + }); + + selector += ', > thead > tr[data-group-row="true"] > th[data-group="' + data.group + '"]'; + var $column = $table.find(selector).add(this); + if (breakpointName !== '') { + if (data.hide[breakpointName] === false) $column.addClass('footable-visible').show(); + else $column.removeClass('footable-visible').hide(); + } + + if ($table.find('> thead > tr.footable-group-row').length === 1) { + var $groupcols = $table.find('> thead > tr:last-child > th[data-group="' + data.group + '"]:visible, > thead > tr:last-child > th[data-group="' + data.group + '"]:visible'), + $group = $table.find('> thead > tr.footable-group-row > th[data-group="' + data.group + '"], > thead > tr.footable-group-row > td[data-group="' + data.group + '"]'), + groupspan = 0; + + $.each($groupcols, function () { + groupspan += parseInt($(this).attr('colspan') || 1, 10); + }); + + if (groupspan > 0) $group.attr('colspan', groupspan).show(); + else $group.hide(); + } + }) + .end() + .find('> tbody > tr.' + cls.detailShow).each(function () { + ft.createOrUpdateDetailRow(this); + }); + + $table.find("[data-bind-name]").each(function () { + ft.toggleInput(this); + }); + + $table.find('> tbody > tr.' + cls.detailShow + ':visible').each(function () { + var $next = $(this).next(); + if ($next.hasClass(cls.detail)) { + if (!hasBreakpointFired) $next.hide(); + else $next.show(); + } + }); + + // adding .footable-first-column and .footable-last-column to the first and last th and td of each row in order to allow + // for styling if the first or last column is hidden (which won't work using :first-child or :last-child) + $table.find('> thead > tr > th.footable-last-column, > tbody > tr > td.footable-last-column').removeClass('footable-last-column'); + $table.find('> thead > tr > th.footable-first-column, > tbody > tr > td.footable-first-column').removeClass('footable-first-column'); + $table.find('> thead > tr, > tbody > tr') + .find('> th.footable-visible:last, > td.footable-visible:last') + .addClass('footable-last-column') + .end() + .find('> th.footable-visible:first, > td.footable-visible:first') + .addClass('footable-first-column'); + + ft.raise(evt.redrawn); + }; + + ft.toggleDetail = function (row) { + var $row = (row.jquery) ? row : $(row), + $next = $row.next(); + + //check if the row is already expanded + if ($row.hasClass(cls.detailShow)) { + $row.removeClass(cls.detailShow); + + //only hide the next row if it's a detail row + if ($next.hasClass(cls.detail)) $next.hide(); + + ft.raise(evt.rowCollapsed, { 'row': $row[0] }); + + } else { + ft.createOrUpdateDetailRow($row[0]); + $row.addClass(cls.detailShow) + .next().show(); + + ft.raise(evt.rowExpanded, { 'row': $row[0] }); + } + }; + + ft.removeRow = function (row) { + var $row = (row.jquery) ? row : $(row); + if ($row.hasClass(cls.detail)) { + $row = $row.prev(); + } + var $next = $row.next(); + if ($row.data('detail_created') === true) { + //remove the detail row + $next.remove(); + } + $row.remove(); + + //raise event + ft.raise(evt.rowRemoved); + }; + + ft.appendRow = function (row) { + var $row = (row.jquery) ? row : $(row); + $(ft.table).find('tbody').append($row); + + //redraw the table + ft.redraw(); + }; + + ft.getColumnFromTdIndex = function (index) { + /// Returns the correct column data for the supplied index taking into account colspans. + /// The index to retrieve the column data for. + /// A JSON object containing the column data for the supplied index. + var result = null; + for (var column in ft.columns) { + if ($.inArray(index, ft.columns[column].matches) >= 0) { + result = ft.columns[column]; + break; + } + } + return result; + }; + + ft.createOrUpdateDetailRow = function (actualRow) { + var $row = $(actualRow), $next = $row.next(), $detail, values = []; + if ($row.data('detail_created') === true) return true; + + if ($row.is(':hidden')) return false; //if the row is hidden for some reason (perhaps filtered) then get out of here + ft.raise(evt.rowDetailUpdating, { 'row': $row, 'detail': $next }); + $row.find('> td:hidden').each(function () { + var index = $(this).index(), column = ft.getColumnFromTdIndex(index), name = column.name; + if (column.ignore === true) return true; + + if (index in column.names) name = column.names[index]; + + var bindName = $(this).attr("data-bind-name"); + if (bindName != null && $(this).is(':empty')) { + var bindValue = $('.' + cls.detailInnerValue + '[' + 'data-bind-value="' + bindName + '"]'); + $(this).html($(bindValue).contents().detach()); + } + var display; + if (column.isEditable !== false && (column.isEditable || $(this).find(":input").length > 0)) { + if(bindName == null) { + bindName = "bind-" + $.now() + "-" + index; + $(this).attr("data-bind-name", bindName); + } + display = $(this).contents().detach(); + } + if (!display) display = $(this).contents().clone(true, true); + values.push({ 'name': name, 'value': ft.parse(this, column), 'display': display, 'group': column.group, 'groupName': column.groupName, 'bindName': bindName }); + return true; + }); + if (values.length === 0) return false; //return if we don't have any data to show + var colspan = $row.find('> td:visible').length; + var exists = $next.hasClass(cls.detail); + if (!exists) { // Create + $next = $('
'); + $row.after($next); + } + $next.find('> td:first').attr('colspan', colspan); + $detail = $next.find('.' + cls.detailInner).empty(); + opt.createDetail($detail, values, opt.createGroupedDetail, opt.detailSeparator, cls); + $row.data('detail_created', true); + ft.raise(evt.rowDetailUpdated, { 'row': $row, 'detail': $next }); + return !exists; + }; + + ft.raise = function (eventName, args) { + + if (ft.options.debug === true && $.isFunction(ft.options.log)) ft.options.log(eventName, 'event'); + + args = args || { }; + var def = { 'ft': ft }; + $.extend(true, def, args); + var e = $.Event(eventName, def); + if (!e.ft) { + $.extend(true, e, def); + } //pre jQuery 1.6 which did not allow data to be passed to event object constructor + $(ft.table).trigger(e); + return e; + }; + + //reset the state of FooTable + ft.reset = function() { + var $table = $(ft.table); + $table.removeData('footable_info') + .data('breakpoint', '') + .removeClass(cls.loading) + .removeClass(cls.loaded); + + $table.find(opt.toggleSelector).unbind(trg.toggleRow).unbind('click.footable'); + + $table.find('> tbody > tr').removeClass(cls.detailShow); + + $table.find('> tbody > tr.' + cls.detail).remove(); + + ft.raise(evt.reset); + }; + + //Switch between row-detail and detail-show. + ft.toggleInput = function (column) { + var bindName = $(column).attr("data-bind-name"); + if(bindName != null) { + var bindValue = $('.' + cls.detailInnerValue + '[' + 'data-bind-value="' + bindName + '"]'); + if(bindValue != null) { + if($(column).is(":visible")) { + if(!$(bindValue).is(':empty')) $(column).html($(bindValue).contents().detach()); + } else if(!$(column).is(':empty')) { + $(bindValue).html($(column).contents().detach()); + } + } + } + }; + + ft.init(); + return ft; + } +})(jQuery, window); diff --git a/js/main.js b/js/main.js index 0781c73..c8ee7de 100644 --- a/js/main.js +++ b/js/main.js @@ -164,6 +164,8 @@ define(['handlebars', 'fastclick', 'handlebars_helpers'], function(Handlebars, F $(".timeago").timeago(); $resultsContainer.show(); + $('.footable').footable(); + if(data.pagination.total > data.pagination.per_page) { $resultsContainer.find('.paging').pagination({ items: data.pagination.total, diff --git a/js/requirejs-config.js b/js/requirejs-config.js index 4f06788..97c6223 100644 --- a/js/requirejs-config.js +++ b/js/requirejs-config.js @@ -15,6 +15,7 @@ requirejs.config({ jquery_timeago: 'jquery.timeago', jquery_timeago_pt: 'jquery.timeago.pt-br', jquery_simplePagination: 'jquery.simplePagination', + jquery_simplePagination: 'footable', handlebars: 'handlebars-v3.0.1', handlebars_helpers: 'handlebars-helpers', jquery_maxlength: 'jquery.maxlength.min', @@ -41,6 +42,9 @@ requirejs.config({ 'jquery_simplePagination': { deps: ['jquery'] }, + 'footable': { + deps: ['jquery'] + }, 'jquery_ui': { deps: ['jquery'] }, @@ -66,5 +70,5 @@ requirejs.config({ } }); -requirejs(['jquery', 'proposal_app', 'jquery_ui', 'jquery_xdomainrequest', 'jquery_timeago_pt', 'jquery_simplePagination', 'handlebars_helpers']); +requirejs(['jquery', 'proposal_app', 'jquery_ui', 'jquery_xdomainrequest', 'jquery_timeago_pt', 'jquery_simplePagination', 'footable', 'handlebars_helpers']); requirejs(['slick', 'fastclick', 'jquery_maxlength', 'layout','main']); diff --git a/sass/_proposal_detail.scss b/sass/_proposal_detail.scss index b208f43..d69ae4a 100644 --- a/sass/_proposal_detail.scss +++ b/sass/_proposal_detail.scss @@ -283,7 +283,7 @@ } td { background-color: #eeeff1; - padding: 10px 20px; + padding: 10px; border: 1px solid #fff; text-align: center; &.abstract-text { @@ -388,7 +388,7 @@ .truncate { display: table; table-layout: fixed; - width: 100%; + width: 90%; } .truncated { overflow-x: hidden; diff --git a/sass/style.scss b/sass/style.scss index 5ffcf87..16a6535 100755 --- a/sass/style.scss +++ b/sass/style.scss @@ -224,3 +224,72 @@ form { } } } + +.footable { + &-loaded { + td { + font-weight: 500 !important; + } + } + &-detail { + &-show { + td { + background-color: #ddd !important; + } + } + } + &-row { + &-detail { + &-cell { + border-top: 1px solid #ccc !important; + padding: 0 !important; + } + &-inner { + background-color: #ccc; + display: block; + padding: 10px; + width: 100%; + } + &-row { + display: inline-block; + } + &-row:nth-child(2) { + div:nth-child(1) { + background: url(images/icons/icon-afavor.png) no-repeat center top; + text-indent: -99999px; + } + } + &-row:nth-child(3) { + div:nth-child(1) { + background: url(images/icons/icon-contra.png) no-repeat center top; + text-indent: -99999px; + } + } + &-name { + display: block; + padding: 2px 15px; + text-transform: uppercase; + font-size: 16px; + } + &-value { + display: block; + } + } + } + &.breakpoint { + > tbody { + > tr { + > td { + > span { + &.footable-toggle { + background-color: #ccc; + float: right; + margin: -10px; + padding: 12px; + } + } + } + } + } + } +} -- libgit2 0.21.2