diff --git a/css/admin-style.css b/css/admin-style.css index eb3189a..5504984 100644 --- a/css/admin-style.css +++ b/css/admin-style.css @@ -7,6 +7,7 @@ * 2. Tab: Tracks * 3. Tab: Settings * 4. Tab: Help + * */ /** @@ -16,15 +17,31 @@ /** * 2.0 Tab: Tracks */ + #table tbody tr:hover { + background: #eee; +} /** * 3.0 Tab: Settings */ - .wpgpxmaps-container-tab-settings { +.wpgpxmaps-container-tab-settings { display: block; padding: 5px 20px 1px 20px; } +.wpgpxmaps-container-tab-settings table.form-table input[type="checkbox"] { + margin-top: -4px; + margin-right: 4px; +} + +.wpgpxmaps-container-tab-settings table.form-table input[type="radio"] { + margin-right: 4px; +} + +.wpgpxmaps-container-tab-settings table.form-table input[type="text"] { + margin-right: 4px; +} + /** * 4.0 Tab: Tracks */ @@ -44,8 +61,12 @@ border-radius: 6px; } -.wpgpxmaps-container-tab-faq table.widefat tbody tr:hover { - background:#eeeeee; +.wpgpxmaps-container-tab-faq table.widefat thead th.title { + font-weight: 650; +} + +.wpgpxmaps-container-tab-faq table.widefat td { + width: 200px; } .wpgpxmaps-container-tab-faq table.widefat th, @@ -53,10 +74,11 @@ padding: 4px 10px; } -.wpgpxmaps-container-tab-faq table.widefat thead tr th { - font-size: 14px; +.wpgpxmaps-container-tab-faq table.widefat tbody tr:hover { + background: #eee; } -.wpgpxmaps-container-tab-faq table.widefat td { - width: 200px; + +.wpgpxmaps-container-tab-faq table.widefat thead th { + font-size: 14px; } diff --git a/css/bootstrap-table.css b/css/bootstrap-table.css new file mode 100644 index 0000000..1db7ae9 --- /dev/null +++ b/css/bootstrap-table.css @@ -0,0 +1,337 @@ +/** + * @author zhixin wen + * version: 1.13.2 + * https://github.com/wenzhixin/bootstrap-table/ + */ + +.bootstrap-table .table { + margin-bottom: 0 !important; + border-bottom: 1px solid #dddddd; + border-collapse: collapse !important; + border-radius: 1px; +} + +.bootstrap-table .table:not(.table-condensed), +.bootstrap-table .table:not(.table-condensed) > tbody > tr > th, +.bootstrap-table .table:not(.table-condensed) > tfoot > tr > th, +.bootstrap-table .table:not(.table-condensed) > thead > tr > td, +.bootstrap-table .table:not(.table-condensed) > tbody > tr > td, +.bootstrap-table .table:not(.table-condensed) > tfoot > tr > td { + padding: 8px; +} + +.bootstrap-table .table.table-no-bordered > thead > tr > th { + border-top: none; +} + +.bootstrap-table .table.table-no-bordered > thead > tr > th, +.bootstrap-table .table.table-no-bordered > tbody > tr > td { + border-right: 2px solid transparent; +} + +.bootstrap-table .table.table-no-bordered > tbody > tr > td:last-child { + border-right: none; +} + +.fixed-table-container { + position: relative; + clear: both; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; +} + +.fixed-table-container.table-no-bordered { + border: 1px solid transparent; +} + +.fixed-table-footer, +.fixed-table-header { + overflow: hidden; +} + +.fixed-table-footer { + border-top: 1px solid #dddddd; +} + +.fixed-table-body { + overflow-x: auto; + overflow-y: auto; + height: 100%; +} + +.fixed-table-container table { + width: 100%; +} + +.fixed-table-container thead th { + height: 0; + padding: 0; + margin: 0; + border-left: 1px solid #dddddd; +} + +.fixed-table-container thead th:focus { + outline: 0 solid transparent; +} + +.fixed-table-container thead th:first-child:not([data-not-first-th]) { + border-left: none; + border-top-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.fixed-table-container thead th .th-inner, +.fixed-table-container tbody td .th-inner { + padding: 8px; + line-height: 24px; + vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.fixed-table-container thead th .sortable { + cursor: pointer; + background-position: right; + background-repeat: no-repeat; + padding-right: 30px; +} + +.fixed-table-container thead th .both { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); +} + +.fixed-table-container thead th .asc { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=='); +} + +.fixed-table-container thead th .desc { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '); +} + +.fixed-table-container th.detail { + width: 30px; +} + +.fixed-table-container tbody td { + border-left: 1px solid #dddddd; +} + +.fixed-table-container tbody tr:first-child td { + border-top: none; +} + +.fixed-table-container tbody td:first-child { + border-left: none; +} + +/* the same color with .active */ +.fixed-table-container tbody .selected td { + background-color: #f5f5f5; +} + +.fixed-table-container .bs-checkbox { + text-align: center; +} + +.fixed-table-container input[type="radio"], +.fixed-table-container input[type="checkbox"] { + margin: 0 auto !important; +} + +.fixed-table-container .no-records-found { + text-align: center; +} + +.fixed-table-pagination div.pagination, +.fixed-table-pagination .pagination-detail { + margin-top: 10px; + margin-bottom: 10px; +} + +.fixed-table-pagination div.pagination .pagination { + margin: 0; +} + +.fixed-table-pagination .pagination a { + padding: 6px 12px; + line-height: 1.428571429; +} + +.fixed-table-pagination ul.pagination li.page-intermediate a { + color:#c8c8c8; +} + +.fixed-table-pagination ul.pagination li.page-intermediate a:before { + content: '\2B05'; +} + +.fixed-table-pagination ul.pagination li.page-intermediate a:after { + content: '\27A1'; +} + +.fixed-table-pagination .pagination-info { + line-height: 34px; + margin-right: 5px; +} + +.fixed-table-pagination .btn-group { + position: relative; + display: inline-block; + vertical-align: middle; +} + +.fixed-table-pagination .dropup .dropdown-menu { + margin-bottom: 0; +} + +.fixed-table-pagination .page-list { + display: inline-block; +} + +.fixed-table-toolbar .columns-left { + margin-right: 5px; +} + +.fixed-table-toolbar .columns-right { + margin-left: 5px; +} + +.fixed-table-toolbar .columns label { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; +} + +.fixed-table-toolbar .bs-bars, +.fixed-table-toolbar .search, +.fixed-table-toolbar .columns { + position: relative; + margin-top: 10px; + margin-bottom: 10px; +} + +.fixed-table-pagination li.disabled a { + pointer-events: none; + cursor: default; +} + +.fixed-table-loading { + display: none; + position: absolute; + top: 42px; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + background-color: #fff; + text-align: center; +} + +.fixed-table-body .card-view .title { + font-weight: bold; + display: inline-block; + min-width: 30%; + text-align: left !important; +} + +/* support bootstrap 2 */ +.fixed-table-body thead th .th-inner { + box-sizing: border-box; +} + +.table th, .table td { + vertical-align: middle; + box-sizing: border-box; +} + +.fixed-table-toolbar .dropdown-menu { + text-align: left; + max-height: 300px; + overflow: auto; +} + +.fixed-table-toolbar .btn-group > .btn-group { + display: inline-block; + margin-left: -1px !important; +} + +.fixed-table-toolbar .btn-group > .btn-group > .btn { + border-radius: 0; +} + +.fixed-table-toolbar .btn-group > .btn-group:first-child > .btn { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +.fixed-table-toolbar .btn-group > .btn-group:last-child > .btn { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.bootstrap-table .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 1px solid #ddd; +} + +.bootstrap-table .table > thead.thead-dark > tr > th { + border-bottom: 1px solid #212529; +} + +/* support bootstrap 3 */ +.bootstrap-table .table thead > tr > th { + padding: 0; + margin: 0; +} + +.bootstrap-table .fixed-table-footer tbody > tr > td { + padding: 0 !important; +} + +.bootstrap-table .fixed-table-footer .table { + border-bottom: none; + border-radius: 0; + padding: 0 !important; +} + +.bootstrap-table .pull-right .dropdown-menu { + right: 0; + left: auto; +} + +/* calculate scrollbar width */ +p.fixed-table-scroll-inner { + width: 100%; + height: 200px; +} + +div.fixed-table-scroll-outer { + top: 0; + left: 0; + visibility: hidden; + width: 200px; + height: 150px; + overflow: hidden; +} + +/* for get correct heights */ +.fixed-table-toolbar:after, .fixed-table-pagination:after { + content: ""; + display: block; + clear: both; +} + +.bootstrap-table.fullscreen { + position: fixed; + top: 0; + left: 0; + z-index: 1050; + width: 100%!important; + background: #FFF; +} diff --git a/css/output-style.css b/css/output-style.css new file mode 100644 index 0000000..2a87409 --- /dev/null +++ b/css/output-style.css @@ -0,0 +1,65 @@ +/** + * This file contains the style definitions for the output + * + */ +.wpgpxmaps img, +.entry-content .wpgpxmaps img, +#content .wpgpxmaps img { + width: none; + max-width: none; + margin: 0; + padding: 0; + border: none; + background: none; +} + +.wpgpxmaps { + clear: both; +} + +.wpgpxmaps .ngimages { + display: none; +} + +.wpgpxmaps .myngimages { + position: absolute; + z-index :1; + margin:0; + border: 1px solid #fff; + cursor: pointer; +} + +.wpgpxmaps_summary .summarylabel { + font-weight: 400; +} + +.wpgpxmaps_summary .summaryvalue { + font-weight: 600; +} + +.wpgpxmaps .report { + line-height :120; +} + +.wpgpxmaps .gmnoprint div:first-child { } + +.wpgpxmaps .wpgpxmaps_osm_footer { + position: absolute; + z-index: 999; + right: 0; + bottom: 0; + left: 0; + width: 100%; + height: 13px; + margin: 0; + background: #fff; + font-size: 12px; +} + +.wpgpxmaps .wpgpxmaps_osm_footer span { + position: absolute; + bottom: 0; + padding: 0 6px 6px 6px; + background: #fff; + vertical-align: baseline; +} diff --git a/js/WP-GPX-Maps.js b/js/WP-GPX-Maps.js index 6cd0cfe..550e996 100644 --- a/js/WP-GPX-Maps.js +++ b/js/WP-GPX-Maps.js @@ -48,7 +48,7 @@ var WPGPXMAPS = { MapEngines: { - /* NOT WORKING AND TESTED! old code copy&pate */ + /* NOT WORKING AND TESTED! old code copy&paste */ GoogleMaps: function() { this.map = null, this.EventSelectChart = null, diff --git a/js/bootstrap-table.js b/js/bootstrap-table.js new file mode 100644 index 0000000..27fa8bf --- /dev/null +++ b/js/bootstrap-table.js @@ -0,0 +1,3223 @@ +/** + * @author zhixin wen + * version: 1.13.2 + * https://github.com/wenzhixin/bootstrap-table/ + */ + +($ => { + // TOOLS DEFINITION + // ====================== + + let bootstrapVersion = 3 + try { + const rawVersion = $.fn.dropdown.Constructor.VERSION + + // Only try to parse VERSION if is is defined. + // It is undefined in older versions of Bootstrap (tested with 3.1.1). + if (rawVersion !== undefined) { + bootstrapVersion = parseInt(rawVersion, 10) + } + } catch (e) { + // ignore + } + + const bootstrap = { + 3: { + iconsPrefix: 'glyphicon', + icons: { + paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', + paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', + refresh: 'glyphicon-refresh icon-refresh', + toggleOff: 'glyphicon-list-alt icon-list-alt', + toggleOn: 'glyphicon-list-alt icon-list-alt', + columns: 'glyphicon-th icon-th', + detailOpen: 'glyphicon-plus icon-plus', + detailClose: 'glyphicon-minus icon-minus', + fullscreen: 'glyphicon-fullscreen' + }, + classes: { + buttons: 'default', + pull: 'pull' + }, + html: { + toobarDropdow: [''], + toobarDropdowItem: '
  • ', + pageDropdown: [''], + pageDropdownItem: '' + } + }, + 4: { + iconsPrefix: 'fa', + icons: { + paginationSwitchDown: 'fa-caret-square-down', + paginationSwitchUp: 'fa-caret-square-up', + refresh: 'fa-sync', + toggleOff: 'fa-toggle-off', + toggleOn: 'fa-toggle-on', + columns: 'fa-th-list', + detailOpen: 'fa-plus', + detailClose: 'fa-minus', + fullscreen: 'fa-arrows-alt' + }, + classes: { + buttons: 'secondary', + pull: 'float' + }, + html: { + toobarDropdow: [''], + toobarDropdowItem: '', + pageDropdown: [''], + pageDropdownItem: '%s' + } + } + }[bootstrapVersion] + + const Utils = { + bootstrapVersion, + + // it only does '%s', and return '' when arguments are undefined + sprintf (_str, ...args) { + let flag = true + let i = 0 + + const str = _str.replace(/%s/g, () => { + const arg = args[i++] + + if (typeof arg === 'undefined') { + flag = false + return '' + } + return arg + }) + return flag ? str : '' + }, + + getFieldTitle (list, value) { + for (const item of list) { + if (item.field === value) { + return item.title + } + } + return '' + }, + + setFieldIndex (columns) { + let totalCol = 0 + const flag = [] + + for (const column of columns[0]) { + totalCol += column.colspan || 1 + } + + for (let i = 0; i < columns.length; i++) { + flag[i] = [] + for (let j = 0; j < totalCol; j++) { + flag[i][j] = false + } + } + + for (let i = 0; i < columns.length; i++) { + for (const r of columns[i]) { + const rowspan = r.rowspan || 1 + const colspan = r.colspan || 1 + const index = flag[i].indexOf(false) + + if (colspan === 1) { + r.fieldIndex = index + // when field is undefined, use index instead + if (typeof r.field === 'undefined') { + r.field = index + } + } + + for (let k = 0; k < rowspan; k++) { + flag[i + k][index] = true + } + for (let k = 0; k < colspan; k++) { + flag[i][index + k] = true + } + } + } + }, + + getScrollBarWidth () { + if (this.cachedWidth === null) { + const $inner = $('
    ').addClass('fixed-table-scroll-inner') + const $outer = $('
    ').addClass('fixed-table-scroll-outer') + + $outer.append($inner) + $('body').append($outer) + + const w1 = $inner[0].offsetWidth + $outer.css('overflow', 'scroll') + let w2 = $inner[0].offsetWidth + + if (w1 === w2) { + w2 = $outer[0].clientWidth + } + + $outer.remove() + this.cachedWidth = w1 - w2 + } + return this.cachedWidth + }, + + calculateObjectValue (self, name, args, defaultValue) { + let func = name + + if (typeof name === 'string') { + // support obj.func1.func2 + const names = name.split('.') + + if (names.length > 1) { + func = window + for (const f of names) { + func = func[f] + } + } else { + func = window[name] + } + } + + if (func !== null && typeof func === 'object') { + return func + } + + if (typeof func === 'function') { + return func.apply(self, args || []) + } + + if ( + !func && + typeof name === 'string' && + this.sprintf(name, ...args) + ) { + return this.sprintf(name, ...args) + } + + return defaultValue + }, + + compareObjects (objectA, objectB, compareLength) { + const aKeys = Object.keys(objectA) + const bKeys = Object.keys(objectB) + + if (compareLength && aKeys.length !== bKeys.length) { + return false + } + + for (const key of aKeys) { + if (bKeys.includes(key) && objectA[key] !== objectB[key]) { + return false + } + } + + return true + }, + + escapeHTML (text) { + if (typeof text === 'string') { + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/`/g, '`') + } + return text + }, + + getRealDataAttr (dataAttr) { + for (const [attr, value] of Object.entries(dataAttr)) { + const auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase() + if (auxAttr !== attr) { + dataAttr[auxAttr] = value + delete dataAttr[attr] + } + } + return dataAttr + }, + + getItemField (item, field, escape) { + let value = item + + if (typeof field !== 'string' || item.hasOwnProperty(field)) { + return escape ? this.escapeHTML(item[field]) : item[field] + } + + const props = field.split('.') + for (const p of props) { + value = value && value[p] + } + return escape ? this.escapeHTML(value) : value + }, + + isIEBrowser () { + return navigator.userAgent.includes('MSIE ') || + /Trident.*rv:11\./.test(navigator.userAgent) + }, + + findIndex (items, item) { + for (const [i, it] of items.entries()) { + if (JSON.stringify(it) === JSON.stringify(item)) { + return i + } + } + return -1 + } + } + + // BOOTSTRAP TABLE CLASS DEFINITION + // ====================== + + const DEFAULTS = { + locale: undefined, + height: undefined, + undefinedText: '-', + classes: 'table table-hover', + theadClasses: '', + sortClass: undefined, + striped: false, + rowStyle (row, index) { + return {} + }, + rowAttributes (row, index) { + return {} + }, + sortable: true, + silentSort: true, + sortName: undefined, + sortOrder: 'asc', + sortStable: false, + rememberOrder: false, + customSort: $.noop, + columns: [ + [] + ], + data: [], + totalField: 'total', + dataField: 'rows', + method: 'get', + url: undefined, + ajax: undefined, + cache: true, + contentType: 'application/json', + dataType: 'json', + ajaxOptions: {}, + queryParams (params) { + return params + }, + queryParamsType: 'limit', // 'limit', undefined + responseHandler (res) { + return res + }, + pagination: false, + onlyInfoPagination: false, + paginationLoop: true, + sidePagination: 'client', // client or server + totalRows: 0, // server side need to set + pageNumber: 1, + pageSize: 10, + pageList: [10, 25, 50, 100], + paginationHAlign: 'right', // right, left + paginationVAlign: 'bottom', // bottom, top, both + paginationDetailHAlign: 'left', // right, left + paginationPreText: '‹', + paginationNextText: '›', + paginationSuccessivelySize: 5, // Maximum successively number of pages in a row + paginationPagesBySide: 1, // Number of pages on each side (right, left) of the current page. + paginationUseIntermediate: false, // Calculate intermediate pages for quick access + search: false, + searchOnEnterKey: false, + strictSearch: false, + trimOnSearch: true, + searchAlign: 'right', + searchTimeOut: 500, + searchText: '', + customSearch: $.noop, + showHeader: true, + showFooter: false, + footerStyle (row, index) { + return {} + }, + showColumns: false, + minimumCountColumns: 1, + showPaginationSwitch: false, + showRefresh: false, + showToggle: false, + showFullscreen: false, + smartDisplay: true, + escape: false, + idField: undefined, + uniqueId: undefined, + cardView: false, + detailView: false, + detailFormatter (index, row) { + return '' + }, + detailFilter (index, row) { + return true + }, + selectItemName: 'btSelectItem', + clickToSelect: false, + ignoreClickToSelectOn ({tagName}) { + return ['A', 'BUTTON'].includes(tagName) + }, + singleSelect: false, + checkboxHeader: true, + maintainSelected: false, + toolbar: undefined, + toolbarAlign: 'left', + buttonsToolbar: undefined, + buttonsAlign: 'right', + buttonsClass: bootstrap.classes.buttons, + icons: bootstrap.icons, + iconSize: undefined, + iconsPrefix: bootstrap.iconsPrefix, // glyphicon or fa(font-awesome) + onAll (name, args) { + return false + }, + onClickCell (field, value, row, $element) { + return false + }, + onDblClickCell (field, value, row, $element) { + return false + }, + onClickRow (item, $element) { + return false + }, + onDblClickRow (item, $element) { + return false + }, + onSort (name, order) { + return false + }, + onCheck (row) { + return false + }, + onUncheck (row) { + return false + }, + onCheckAll (rows) { + return false + }, + onUncheckAll (rows) { + return false + }, + onCheckSome (rows) { + return false + }, + onUncheckSome (rows) { + return false + }, + onLoadSuccess (data) { + return false + }, + onLoadError (status) { + return false + }, + onColumnSwitch (field, checked) { + return false + }, + onPageChange (number, size) { + return false + }, + onSearch (text) { + return false + }, + onToggle (cardView) { + return false + }, + onPreBody (data) { + return false + }, + onPostBody () { + return false + }, + onPostHeader () { + return false + }, + onExpandRow (index, row, $detail) { + return false + }, + onCollapseRow (index, row) { + return false + }, + onRefreshOptions (options) { + return false + }, + onRefresh (params) { + return false + }, + onResetView () { + return false + }, + onScrollBody () { + return false + } + } + + const LOCALES = {} + LOCALES['en-US'] = LOCALES.en = { + formatLoadingMessage () { + return 'Loading, please wait...' + }, + formatRecordsPerPage (pageNumber) { + return Utils.sprintf('%s rows per page', pageNumber) + }, + formatShowingRows (pageFrom, pageTo, totalRows) { + return Utils.sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows) + }, + formatDetailPagination (totalRows) { + return Utils.sprintf('Showing %s rows', totalRows) + }, + formatSearch () { + return 'Search' + }, + formatNoMatches () { + return 'No matching records found' + }, + formatPaginationSwitch () { + return 'Hide/Show pagination' + }, + formatRefresh () { + return 'Refresh' + }, + formatToggle () { + return 'Toggle' + }, + formatFullscreen () { + return 'Fullscreen' + }, + formatColumns () { + return 'Columns' + }, + formatAllRows () { + return 'All' + } + } + + $.extend(DEFAULTS, LOCALES['en-US']) + + const COLUMN_DEFAULTS = { + radio: false, + checkbox: false, + checkboxEnabled: true, + field: undefined, + title: undefined, + titleTooltip: undefined, + 'class': undefined, + align: undefined, // left, right, center + halign: undefined, // left, right, center + falign: undefined, // left, right, center + valign: undefined, // top, middle, bottom + width: undefined, + sortable: false, + order: 'asc', // asc, desc + visible: true, + switchable: true, + clickToSelect: true, + formatter: undefined, + footerFormatter: undefined, + events: undefined, + sorter: undefined, + sortName: undefined, + cellStyle: undefined, + searchable: true, + searchFormatter: true, + cardVisible: true, + escape: false, + showSelectTitle: false + } + + const EVENTS = { + 'all.bs.table': 'onAll', + 'click-cell.bs.table': 'onClickCell', + 'dbl-click-cell.bs.table': 'onDblClickCell', + 'click-row.bs.table': 'onClickRow', + 'dbl-click-row.bs.table': 'onDblClickRow', + 'sort.bs.table': 'onSort', + 'check.bs.table': 'onCheck', + 'uncheck.bs.table': 'onUncheck', + 'check-all.bs.table': 'onCheckAll', + 'uncheck-all.bs.table': 'onUncheckAll', + 'check-some.bs.table': 'onCheckSome', + 'uncheck-some.bs.table': 'onUncheckSome', + 'load-success.bs.table': 'onLoadSuccess', + 'load-error.bs.table': 'onLoadError', + 'column-switch.bs.table': 'onColumnSwitch', + 'page-change.bs.table': 'onPageChange', + 'search.bs.table': 'onSearch', + 'toggle.bs.table': 'onToggle', + 'pre-body.bs.table': 'onPreBody', + 'post-body.bs.table': 'onPostBody', + 'post-header.bs.table': 'onPostHeader', + 'expand-row.bs.table': 'onExpandRow', + 'collapse-row.bs.table': 'onCollapseRow', + 'refresh-options.bs.table': 'onRefreshOptions', + 'reset-view.bs.table': 'onResetView', + 'refresh.bs.table': 'onRefresh', + 'scroll-body.bs.table': 'onScrollBody' + } + + class BootstrapTable { + constructor (el, options) { + this.options = options + this.$el = $(el) + this.$el_ = this.$el.clone() + this.timeoutId_ = 0 + this.timeoutFooter_ = 0 + + this.init() + } + + init () { + this.initLocale() + this.initContainer() + this.initTable() + this.initHeader() + this.initData() + this.initHiddenRows() + this.initFooter() + this.initToolbar() + this.initPagination() + this.initBody() + this.initSearchText() + this.initServer() + } + + initLocale () { + if (this.options.locale) { + const locales = $.fn.bootstrapTable.locales + const parts = this.options.locale.split(/-|_/) + parts[0].toLowerCase() + if (parts[1]) { + parts[1].toUpperCase() + } + if (locales[this.options.locale]) { + // locale as requested + $.extend(this.options, locales[this.options.locale]) + } else if ($.fn.bootstrapTable.locales[parts.join('-')]) { + // locale with sep set to - (in case original was specified with _) + $.extend(this.options, locales[parts.join('-')]) + } else if ($.fn.bootstrapTable.locales[parts[0]]) { + // short locale language code (i.e. 'en') + $.extend(this.options, locales[parts[0]]) + } + } + } + + initContainer () { + const topPagination = ['top', 'both'].includes(this.options.paginationVAlign) + ? '
    ' : '' + const bottomPagination = ['bottom', 'both'].includes(this.options.paginationVAlign) + ? '
    ' : '' + + this.$container = $(` +
    +
    + ${topPagination} +
    +
    +
    +
    + ${this.options.formatLoadingMessage()} +
    +
    + +
    + ${bottomPagination} +
    + `) + + this.$container.insertAfter(this.$el) + this.$tableContainer = this.$container.find('.fixed-table-container') + this.$tableHeader = this.$container.find('.fixed-table-header') + this.$tableBody = this.$container.find('.fixed-table-body') + this.$tableLoading = this.$container.find('.fixed-table-loading') + this.$tableFooter = this.$container.find('.fixed-table-footer') + // checking if custom table-toolbar exists or not + if (this.options.buttonsToolbar) { + this.$toolbar = $('body').find(this.options.buttonsToolbar) + } else { + this.$toolbar = this.$container.find('.fixed-table-toolbar') + } + this.$pagination = this.$container.find('.fixed-table-pagination') + + this.$tableBody.append(this.$el) + this.$container.after('
    ') + + this.$el.addClass(this.options.classes) + if (this.options.striped) { + this.$el.addClass('table-striped') + } + if (this.options.classes.split(' ').includes('table-no-bordered')) { + this.$tableContainer.addClass('table-no-bordered') + } + } + + initTable () { + const columns = [] + const data = [] + + this.$header = this.$el.find('>thead') + if (!this.$header.length) { + this.$header = $(``).appendTo(this.$el) + } + this.$header.find('tr').each((i, el) => { + const column = [] + + $(el).find('th').each((i, el) => { + // #2014: getFieldIndex and elsewhere assume this is string, causes issues if not + if (typeof $(el).data('field') !== 'undefined') { + $(el).data('field', `${$(el).data('field')}`) + } + column.push($.extend({}, { + title: $(el).html(), + 'class': $(el).attr('class'), + titleTooltip: $(el).attr('title'), + rowspan: $(el).attr('rowspan') ? +$(el).attr('rowspan') : undefined, + colspan: $(el).attr('colspan') ? +$(el).attr('colspan') : undefined + }, $(el).data())) + }) + columns.push(column) + }) + + if (!Array.isArray(this.options.columns[0])) { + this.options.columns = [this.options.columns] + } + + this.options.columns = $.extend(true, [], columns, this.options.columns) + this.columns = [] + this.fieldsColumnsIndex = [] + + Utils.setFieldIndex(this.options.columns) + + this.options.columns.forEach((columns, i) => { + columns.forEach((_column, j) => { + const column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, _column) + + if (typeof column.fieldIndex !== 'undefined') { + this.columns[column.fieldIndex] = column + this.fieldsColumnsIndex[column.field] = column.fieldIndex + } + + this.options.columns[i][j] = column + }) + }) + + // if options.data is setting, do not process tbody data + if (this.options.data.length) { + return + } + + const m = [] + this.$el.find('>tbody>tr').each((y, el) => { + const row = {} + + // save tr's id, class and data-* attributes + row._id = $(el).attr('id') + row._class = $(el).attr('class') + row._data = Utils.getRealDataAttr($(el).data()) + + $(el).find('>td').each((_x, el) => { + const cspan = +$(el).attr('colspan') || 1 + const rspan = +$(el).attr('rowspan') || 1 + let x = _x + + // skip already occupied cells in current row + for (; m[y] && m[y][x]; x++) { + // ignore + } + + // mark matrix elements occupied by current cell with true + for (let tx = x; tx < x + cspan; tx++) { + for (let ty = y; ty < y + rspan; ty++) { + if (!m[ty]) { // fill missing rows + m[ty] = [] + } + m[ty][tx] = true + } + } + + const field = this.columns[x].field + + row[field] = $(el).html() + // save td's id, class and data-* attributes + row[`_${field}_id`] = $(el).attr('id') + row[`_${field}_class`] = $(el).attr('class') + row[`_${field}_rowspan`] = $(el).attr('rowspan') + row[`_${field}_colspan`] = $(el).attr('colspan') + row[`_${field}_title`] = $(el).attr('title') + row[`_${field}_data`] = Utils.getRealDataAttr($(el).data()) + }) + data.push(row) + }) + this.options.data = data + if (data.length) { + this.fromHtml = true + } + } + + initHeader () { + const visibleColumns = {} + const html = [] + + this.header = { + fields: [], + styles: [], + classes: [], + formatters: [], + events: [], + sorters: [], + sortNames: [], + cellStyles: [], + searchables: [] + } + + this.options.columns.forEach((columns, i) => { + html.push('') + + if (i === 0 && !this.options.cardView && this.options.detailView) { + html.push(` +
    + + `) + } + + columns.forEach((column, j) => { + let text = '' + + let halign = '' // header align style + + let align = '' // body align style + + let style = '' + const class_ = Utils.sprintf(' class="%s"', column['class']) + let unitWidth = 'px' + let width = column.width + + if (column.width !== undefined && (!this.options.cardView)) { + if (typeof column.width === 'string') { + if (column.width.includes('%')) { + unitWidth = '%' + } + } + } + if (column.width && typeof column.width === 'string') { + width = column.width.replace('%', '').replace('px', '') + } + + halign = Utils.sprintf('text-align: %s; ', column.halign ? column.halign : column.align) + align = Utils.sprintf('text-align: %s; ', column.align) + style = Utils.sprintf('vertical-align: %s; ', column.valign) + style += Utils.sprintf('width: %s; ', (column.checkbox || column.radio) && !width + ? (!column.showSelectTitle ? '36px' : undefined) + : (width ? width + unitWidth : undefined)) + + if (typeof column.fieldIndex !== 'undefined') { + this.header.fields[column.fieldIndex] = column.field + this.header.styles[column.fieldIndex] = align + style + this.header.classes[column.fieldIndex] = class_ + this.header.formatters[column.fieldIndex] = column.formatter + this.header.events[column.fieldIndex] = column.events + this.header.sorters[column.fieldIndex] = column.sorter + this.header.sortNames[column.fieldIndex] = column.sortName + this.header.cellStyles[column.fieldIndex] = column.cellStyle + this.header.searchables[column.fieldIndex] = column.searchable + + if (!column.visible) { + return + } + + if (this.options.cardView && (!column.cardVisible)) { + return + } + + visibleColumns[column.field] = column + } + + html.push(` 0 ? ' data-not-first-th' : '', + '>') + + html.push(Utils.sprintf('
    ', this.options.sortable && column.sortable + ? 'sortable both' : '')) + + text = this.options.escape ? Utils.escapeHTML(column.title) : column.title + + const title = text + if (column.checkbox) { + text = '' + if (!this.options.singleSelect && this.options.checkboxHeader) { + text = '' + } + this.header.stateField = column.field + } + if (column.radio) { + text = '' + this.header.stateField = column.field + this.options.singleSelect = true + } + if (!text && column.showSelectTitle) { + text += title + } + + html.push(text) + html.push('
    ') + html.push('
    ') + html.push('
    ') + html.push('') + }) + html.push('') + }) + + this.$header.html(html.join('')) + this.$header.find('th[data-field]').each((i, el) => { + $(el).data(visibleColumns[$(el).data('field')]) + }) + this.$container.off('click', '.th-inner').on('click', '.th-inner', e => { + const $this = $(e.currentTarget) + + if (this.options.detailView && !$this.parent().hasClass('bs-checkbox')) { + if ($this.closest('.bootstrap-table')[0] !== this.$container[0]) { + return false + } + } + + if (this.options.sortable && $this.parent().data().sortable) { + this.onSort(e) + } + }) + + this.$header.children().children().off('keypress').on('keypress', e => { + if (this.options.sortable && $(e.currentTarget).data().sortable) { + const code = e.keyCode || e.which + if (code === 13) { // Enter keycode + this.onSort(e) + } + } + }) + + $(window).off('resize.bootstrap-table') + if (!this.options.showHeader || this.options.cardView) { + this.$header.hide() + this.$tableHeader.hide() + this.$tableLoading.css('top', 0) + } else { + this.$header.show() + this.$tableHeader.show() + this.$tableLoading.css('top', this.$header.outerHeight() + 1) + // Assign the correct sortable arrow + this.getCaret() + $(window).on('resize.bootstrap-table', $.proxy(this.resetWidth, this)) + } + + this.$selectAll = this.$header.find('[name="btSelectAll"]') + this.$selectAll.off('click').on('click', ({currentTarget}) => { + const checked = $(currentTarget).prop('checked') + this[checked ? 'checkAll' : 'uncheckAll']() + this.updateSelected() + }) + } + + initFooter () { + if (!this.options.showFooter || this.options.cardView) { + this.$tableFooter.hide() + } else { + this.$tableFooter.show() + } + } + + initData (data, type) { + if (type === 'append') { + this.options.data = this.options.data.concat(data) + } else if (type === 'prepend') { + this.options.data = [].concat(data).concat(this.options.data) + } else { + this.options.data = data || this.options.data + } + + this.data = this.options.data + + if (this.options.sidePagination === 'server') { + return + } + this.initSort() + } + + initSort () { + let name = this.options.sortName + const order = this.options.sortOrder === 'desc' ? -1 : 1 + const index = this.header.fields.indexOf(this.options.sortName) + let timeoutId = 0 + + if (this.options.customSort !== $.noop) { + this.options.customSort.apply(this, [this.options.sortName, this.options.sortOrder]) + return + } + + if (index !== -1) { + if (this.options.sortStable) { + this.data.forEach((row, i) => { + row._position = i + }) + } + + this.data.sort((a, b) => { + if (this.header.sortNames[index]) { + name = this.header.sortNames[index] + } + let aa = Utils.getItemField(a, name, this.options.escape) + let bb = Utils.getItemField(b, name, this.options.escape) + const value = Utils.calculateObjectValue(this.header, this.header.sorters[index], [aa, bb, a, b]) + + if (value !== undefined) { + if (this.options.sortStable && value === 0) { + return a._position - b._position + } + return order * value + } + + // Fix #161: undefined or null string sort bug. + if (aa === undefined || aa === null) { + aa = '' + } + if (bb === undefined || bb === null) { + bb = '' + } + + if (this.options.sortStable && aa === bb) { + aa = a._position + bb = b._position + return a._position - b._position + } + + // IF both values are numeric, do a numeric comparison + if ($.isNumeric(aa) && $.isNumeric(bb)) { + // Convert numerical values form string to float. + aa = parseFloat(aa) + bb = parseFloat(bb) + if (aa < bb) { + return order * -1 + } + return order + } + + if (aa === bb) { + return 0 + } + + // If value is not a string, convert to string + if (typeof aa !== 'string') { + aa = aa.toString() + } + + if (aa.localeCompare(bb) === -1) { + return order * -1 + } + + return order + }) + + if (this.options.sortClass !== undefined) { + clearTimeout(timeoutId) + timeoutId = setTimeout(() => { + this.$el.removeClass(this.options.sortClass) + const index = this.$header.find(Utils.sprintf('[data-field="%s"]', + this.options.sortName).index() + 1) + this.$el.find(Utils.sprintf('tr td:nth-child(%s)', index)) + .addClass(this.options.sortClass) + }, 250) + } + } + } + + onSort ({type, currentTarget}) { + const $this = type === 'keypress' ? $(currentTarget) : $(currentTarget).parent() + const $this_ = this.$header.find('th').eq($this.index()) + + this.$header.add(this.$header_).find('span.order').remove() + + if (this.options.sortName === $this.data('field')) { + this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc' + } else { + this.options.sortName = $this.data('field') + if (this.options.rememberOrder) { + this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc' + } else { + this.options.sortOrder = this.columns[this.fieldsColumnsIndex[$this.data('field')]].order + } + } + this.trigger('sort', this.options.sortName, this.options.sortOrder) + + $this.add($this_).data('order', this.options.sortOrder) + + // Assign the correct sortable arrow + this.getCaret() + + if (this.options.sidePagination === 'server') { + this.initServer(this.options.silentSort) + return + } + + this.initSort() + this.initBody() + } + + initToolbar () { + let html = [] + let timeoutId = 0 + let $keepOpen + let $search + let switchableCount = 0 + + if (this.$toolbar.find('.bs-bars').children().length) { + $('body').append($(this.options.toolbar)) + } + this.$toolbar.html('') + + if (typeof this.options.toolbar === 'string' || typeof this.options.toolbar === 'object') { + $(Utils.sprintf('
    ', bootstrap.classes.pull, this.options.toolbarAlign)) + .appendTo(this.$toolbar) + .append($(this.options.toolbar)) + } + + // showColumns, showToggle, showRefresh + html = [Utils.sprintf('
    ', + this.options.buttonsAlign, bootstrap.classes.pull, this.options.buttonsAlign)] + + if (typeof this.options.icons === 'string') { + this.options.icons = Utils.calculateObjectValue(null, this.options.icons) + } + + if (this.options.showPaginationSwitch) { + html.push(Utils.sprintf(`') + } + + if (this.options.showFullscreen) { + this.$toolbar.find('button[name="fullscreen"]') + .off('click').on('click', $.proxy(this.toggleFullscreen, this)) + } + + if (this.options.showRefresh) { + html.push(Utils.sprintf(`') + } + + if (this.options.showToggle) { + html.push(Utils.sprintf(`') + } + + if (this.options.showFullscreen) { + html.push(Utils.sprintf(`') + } + + if (this.options.showColumns) { + html.push(Utils.sprintf('
    ', + this.options.formatColumns()), + `', + bootstrap.html.toobarDropdow[0]) + + this.columns.forEach((column, i) => { + if (column.radio || column.checkbox) { + return + } + + if (this.options.cardView && !column.cardVisible) { + return + } + + const checked = column.visible ? ' checked="checked"' : '' + + if (column.switchable) { + html.push(Utils.sprintf(bootstrap.html.toobarDropdowItem, + Utils.sprintf(' %s', + column.field, i, checked, column.title))) + switchableCount++ + } + }) + html.push(bootstrap.html.toobarDropdow[1], '
    ') + } + + html.push('
    ') + + // Fix #188: this.showToolbar is for extensions + if (this.showToolbar || html.length > 2) { + this.$toolbar.append(html.join('')) + } + + if (this.options.showPaginationSwitch) { + this.$toolbar.find('button[name="paginationSwitch"]') + .off('click').on('click', $.proxy(this.togglePagination, this)) + } + + if (this.options.showRefresh) { + this.$toolbar.find('button[name="refresh"]') + .off('click').on('click', $.proxy(this.refresh, this)) + } + + if (this.options.showToggle) { + this.$toolbar.find('button[name="toggle"]') + .off('click').on('click', () => { + this.toggleView() + }) + } + + if (this.options.showColumns) { + $keepOpen = this.$toolbar.find('.keep-open') + + if (switchableCount <= this.options.minimumCountColumns) { + $keepOpen.find('input').prop('disabled', true) + } + + $keepOpen.find('li').off('click').on('click', e => { + e.stopImmediatePropagation() + }) + $keepOpen.find('input').off('click').on('click', ({currentTarget}) => { + const $this = $(currentTarget) + + this.toggleColumn($this.val(), $this.prop('checked'), false) + this.trigger('column-switch', $this.data('field'), $this.prop('checked')) + }) + } + + if (this.options.search) { + html = [] + html.push( + Utils.sprintf('') + + this.$toolbar.append(html.join('')) + $search = this.$toolbar.find('.search input') + $search.off('keyup drop blur').on('keyup drop blur', event => { + if (this.options.searchOnEnterKey && event.keyCode !== 13) { + return + } + + if ([37, 38, 39, 40].includes(event.keyCode)) { + return + } + + clearTimeout(timeoutId) // doesn't matter if it's 0 + timeoutId = setTimeout(() => { + this.onSearch(event) + }, this.options.searchTimeOut) + }) + + if (Utils.isIEBrowser()) { + $search.off('mouseup').on('mouseup', event => { + clearTimeout(timeoutId) // doesn't matter if it's 0 + timeoutId = setTimeout(() => { + this.onSearch(event) + }, this.options.searchTimeOut) + }) + } + } + } + + onSearch ({currentTarget, firedByInitSearchText}) { + const text = $.trim($(currentTarget).val()) + + // trim search input + if (this.options.trimOnSearch && $(currentTarget).val() !== text) { + $(currentTarget).val(text) + } + + if (text === this.searchText) { + return + } + this.searchText = text + this.options.searchText = text + + if (!firedByInitSearchText) { + this.options.pageNumber = 1 + } + this.initSearch() + if (firedByInitSearchText) { + if (this.options.sidePagination === 'client') { + this.updatePagination() + } + } else { + this.updatePagination() + } + this.trigger('search', text) + } + + initSearch () { + if (this.options.sidePagination !== 'server') { + if (this.options.customSearch !== $.noop) { + Utils.calculateObjectValue(this.options, this.options.customSearch, [this.searchText]) + return + } + + const s = this.searchText && (this.options.escape + ? Utils.escapeHTML(this.searchText) : this.searchText).toLowerCase() + const f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns + + // Check filter + this.data = f ? this.options.data.filter((item, i) => { + for (const key in f) { + if ( + (Array.isArray(f[key]) && + !f[key].includes(item[key])) || + (!Array.isArray(f[key]) && + item[key] !== f[key]) + ) { + return false + } + } + return true + }) : this.options.data + + this.data = s ? this.data.filter((item, i) => { + for (let j = 0; j < this.header.fields.length; j++) { + if (!this.header.searchables[j]) { + continue + } + + const key = $.isNumeric(this.header.fields[j]) ? parseInt(this.header.fields[j], 10) : this.header.fields[j] + const column = this.columns[this.fieldsColumnsIndex[key]] + let value + + if (typeof key === 'string') { + value = item + const props = key.split('.') + for (let i = 0; i < props.length; i++) { + if (value[props[i]] !== null) { + value = value[props[i]] + } + } + } else { + value = item[key] + } + + // Fix #142: respect searchForamtter boolean + if (column && column.searchFormatter) { + value = Utils.calculateObjectValue(column, + this.header.formatters[j], [value, item, i], value) + } + + if (typeof value === 'string' || typeof value === 'number') { + if (this.options.strictSearch) { + if ((`${value}`).toLowerCase() === s) { + return true + } + } else { + if ((`${value}`).toLowerCase().includes(s)) { + return true + } + } + } + } + return false + }) : this.data + } + } + + initPagination () { + if (!this.options.pagination) { + this.$pagination.hide() + return + } + this.$pagination.show() + + + const html = [] + let $allSelected = false + let i + let from + let to + let $pageList + let $pre + let $next + let $number + const data = this.getData() + let pageList = this.options.pageList + + if (this.options.sidePagination !== 'server') { + this.options.totalRows = data.length + } + + this.totalPages = 0 + if (this.options.totalRows) { + if (this.options.pageSize === this.options.formatAllRows()) { + this.options.pageSize = this.options.totalRows + $allSelected = true + } else if (this.options.pageSize === this.options.totalRows) { + // Fix #667 Table with pagination, + // multiple pages and a search this matches to one page throws exception + const pageLst = typeof this.options.pageList === 'string' + ? this.options.pageList.replace('[', '').replace(']', '') + .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList + if (pageLst.includes(this.options.formatAllRows().toLowerCase())) { + $allSelected = true + } + } + + this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1 + + this.options.totalPages = this.totalPages + } + if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) { + this.options.pageNumber = this.totalPages + } + + this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1 + this.pageTo = this.options.pageNumber * this.options.pageSize + if (this.pageTo > this.options.totalRows) { + this.pageTo = this.options.totalRows + } + + html.push( + Utils.sprintf('
    ', bootstrap.classes.pull, this.options.paginationDetailHAlign), + '', + this.options.onlyInfoPagination ? this.options.formatDetailPagination(this.options.totalRows) + : this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows), + '') + + if (!this.options.onlyInfoPagination) { + html.push('') + + const pageNumber = [ + Utils.sprintf('', + this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' + ? 'dropdown' : 'dropup'), + `', + bootstrap.html.pageDropdown[0] + ] + + if (typeof this.options.pageList === 'string') { + const list = this.options.pageList.replace('[', '').replace(']', '') + .replace(/ /g, '').split(',') + + pageList = [] + for (const value of list) { + pageList.push( + (value.toUpperCase() === this.options.formatAllRows().toUpperCase() || + value.toUpperCase() === 'UNLIMITED') + ? this.options.formatAllRows() : +value) + } + } + + pageList.forEach((page, i) => { + if (!this.options.smartDisplay || i === 0 || pageList[i - 1] < this.options.totalRows) { + let active + if ($allSelected) { + active = page === this.options.formatAllRows() ? 'active' : '' + } else { + active = page === this.options.pageSize ? 'active' : '' + } + pageNumber.push(Utils.sprintf(bootstrap.html.pageDropdownItem, active, page)) + } + }) + pageNumber.push(`${bootstrap.html.pageDropdown[1]}`) + + html.push(this.options.formatRecordsPerPage(pageNumber.join(''))) + html.push('') + + html.push('
    ', + Utils.sprintf(' + `) + } + this.$pagination.html(html.join('')) + + if (!this.options.onlyInfoPagination) { + $pageList = this.$pagination.find('.page-list a') + $pre = this.$pagination.find('.page-pre') + $next = this.$pagination.find('.page-next') + $number = this.$pagination.find('.page-item').not('.page-next, .page-pre') + + if (this.options.smartDisplay) { + if (this.totalPages <= 1) { + this.$pagination.find('div.pagination').hide() + } + if (pageList.length < 2 || this.options.totalRows <= pageList[0]) { + this.$pagination.find('span.page-list').hide() + } + + // when data is empty, hide the pagination + this.$pagination[this.getData().length ? 'show' : 'hide']() + } + + if (!this.options.paginationLoop) { + if (this.options.pageNumber === 1) { + $pre.addClass('disabled') + } + if (this.options.pageNumber === this.totalPages) { + $next.addClass('disabled') + } + } + + if ($allSelected) { + this.options.pageSize = this.options.formatAllRows() + } + // removed the events for last and first, onPageNumber executeds the same logic + $pageList.off('click').on('click', $.proxy(this.onPageListChange, this)) + $pre.off('click').on('click', $.proxy(this.onPagePre, this)) + $next.off('click').on('click', $.proxy(this.onPageNext, this)) + $number.off('click').on('click', $.proxy(this.onPageNumber, this)) + } + } + + updatePagination (event) { + // Fix #171: IE disabled button can be clicked bug. + if (event && $(event.currentTarget).hasClass('disabled')) { + return + } + + if (!this.options.maintainSelected) { + this.resetRows() + } + + this.initPagination() + if (this.options.sidePagination === 'server') { + this.initServer() + } else { + this.initBody() + } + + this.trigger('page-change', this.options.pageNumber, this.options.pageSize) + } + + onPageListChange (event) { + event.preventDefault() + const $this = $(event.currentTarget) + + $this.parent().addClass('active').siblings().removeClass('active') + this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() + ? this.options.formatAllRows() : +$this.text() + this.$toolbar.find('.page-size').text(this.options.pageSize) + + this.updatePagination(event) + return false + } + + onPagePre (event) { + event.preventDefault() + if ((this.options.pageNumber - 1) === 0) { + this.options.pageNumber = this.options.totalPages + } else { + this.options.pageNumber-- + } + this.updatePagination(event) + return false + } + + onPageNext (event) { + event.preventDefault() + if ((this.options.pageNumber + 1) > this.options.totalPages) { + this.options.pageNumber = 1 + } else { + this.options.pageNumber++ + } + this.updatePagination(event) + return false + } + + onPageNumber (event) { + event.preventDefault() + if (this.options.pageNumber === +$(event.currentTarget).text()) { + return + } + this.options.pageNumber = +$(event.currentTarget).text() + this.updatePagination(event) + return false + } + + initRow (item, i, data, parentDom) { + const html = [] + let style = {} + const csses = [] + let data_ = '' + let attributes = {} + const htmlAttributes = [] + + if (Utils.findIndex(this.hiddenRows, item) > -1) { + return + } + + style = Utils.calculateObjectValue(this.options, this.options.rowStyle, [item, i], style) + + if (style && style.css) { + for (const [key, value] of Object.entries(style.css)) { + csses.push(`${key}: ${value}`) + } + } + + attributes = Utils.calculateObjectValue(this.options, + this.options.rowAttributes, [item, i], attributes) + + if (attributes) { + for (const [key, value] of Object.entries(attributes)) { + htmlAttributes.push(`${key}="${Utils.escapeHTML(value)}"`) + } + } + + if (item._data && !$.isEmptyObject(item._data)) { + for (const [k, v] of Object.entries(item._data)) { + // ignore data-index + if (k === 'index') { + return + } + data_ += ` data-${k}="${v}"` + } + } + + html.push('' + ) + + if (this.options.cardView) { + html.push(`
    `) + } + + if (!this.options.cardView && this.options.detailView) { + html.push('') + + if (Utils.calculateObjectValue(null, this.options.detailFilter, [i, item])) { + html.push(` + + + + `) + } + + html.push('') + } + + this.header.fields.forEach((field, j) => { + let text = '' + let value_ = Utils.getItemField(item, field, this.options.escape) + let value = '' + let type = '' + let cellStyle = {} + let id_ = '' + let class_ = this.header.classes[j] + let style_ = '' + let data_ = '' + let rowspan_ = '' + let colspan_ = '' + let title_ = '' + const column = this.columns[j] + + if (this.fromHtml && typeof value_ === 'undefined') { + if ((!column.checkbox) && (!column.radio)) { + return + } + } + + if (!column.visible) { + return + } + + if (this.options.cardView && (!column.cardVisible)) { + return + } + + if (column.escape) { + value_ = Utils.escapeHTML(value_) + } + + if (csses.concat([this.header.styles[j]]).length) { + style_ = ` style="${csses.concat([this.header.styles[j]]).join('; ')}"` + } + // handle td's id and class + if (item[`_${field}_id`]) { + id_ = Utils.sprintf(' id="%s"', item[`_${field}_id`]) + } + if (item[`_${field}_class`]) { + class_ = Utils.sprintf(' class="%s"', item[`_${field}_class`]) + } + if (item[`_${field}_rowspan`]) { + rowspan_ = Utils.sprintf(' rowspan="%s"', item[`_${field}_rowspan`]) + } + if (item[`_${field}_colspan`]) { + colspan_ = Utils.sprintf(' colspan="%s"', item[`_${field}_colspan`]) + } + if (item[`_${field}_title`]) { + title_ = Utils.sprintf(' title="%s"', item[`_${field}_title`]) + } + cellStyle = Utils.calculateObjectValue(this.header, + this.header.cellStyles[j], [value_, item, i, field], cellStyle) + if (cellStyle.classes) { + class_ = ` class="${cellStyle.classes}"` + } + if (cellStyle.css) { + const csses_ = [] + for (const [key, value] of Object.entries(cellStyle.css)) { + csses_.push(`${key}: ${value}`) + } + style_ = ` style="${csses_.concat(this.header.styles[j]).join('; ')}"` + } + + value = Utils.calculateObjectValue(column, + this.header.formatters[j], [value_, item, i, field], value_) + + if (item[`_${field}_data`] && !$.isEmptyObject(item[`_${field}_data`])) { + for (const [k, v] of Object.entries(item[`_${field}_data`])) { + // ignore data-index + if (k === 'index') { + return + } + data_ += ` data-${k}="${v}"` + } + } + + if (column.checkbox || column.radio) { + type = column.checkbox ? 'checkbox' : type + type = column.radio ? 'radio' : type + + const c = column['class'] || '' + const isChecked = value === true || (value_ || (value && value.checked)) + const isDisabled = !column.checkboxEnabled || (value && value.disabled) + + text = [ + this.options.cardView + ? `
    ` + : ``, + ``, + this.header.formatters[j] && typeof value === 'string' ? value : '', + this.options.cardView ? '
    ' : '' + ].join('') + + item[this.header.stateField] = value === true || (!!value_ || (value && value.checked)) + } else { + value = typeof value === 'undefined' || value === null + ? this.options.undefinedText : value + + if (this.options.cardView) { + const cardTitle = this.options.showHeader + ? `${Utils.getFieldTitle(this.columns, field)}` : '' + + text = `
    ${cardTitle}${value}
    ` + + if (this.options.smartDisplay && value === '') { + text = '
    ' + } + } else { + text = `${value}` + } + } + + html.push(text) + }) + + if (this.options.cardView) { + html.push('
    ') + } + html.push('') + + return html.join('') + } + + initBody (fixedScroll) { + const data = this.getData() + + this.trigger('pre-body', data) + + this.$body = this.$el.find('>tbody') + if (!this.$body.length) { + this.$body = $('').appendTo(this.$el) + } + + // Fix #389 Bootstrap-table-flatJSON is not working + if (!this.options.pagination || this.options.sidePagination === 'server') { + this.pageFrom = 1 + this.pageTo = data.length + } + + const trFragments = $(document.createDocumentFragment()) + let hasTr = false + + for (let i = this.pageFrom - 1; i < this.pageTo; i++) { + const item = data[i] + const tr = this.initRow(item, i, data, trFragments) + hasTr = hasTr || !!tr + if (tr && typeof tr === 'string') { + trFragments.append(tr) + } + } + + // show no records + if (!hasTr) { + this.$body.html(`${Utils.sprintf('%s', + this.$header.find('th').length, + this.options.formatNoMatches())}`) + } else { + this.$body.html(trFragments) + } + + if (!fixedScroll) { + this.scrollTo(0) + } + + // click to select by column + this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', ({currentTarget, type, target}) => { + const $td = $(currentTarget) + const $tr = $td.parent() + const item = this.data[$tr.data('index')] + const index = $td[0].cellIndex + const fields = this.getVisibleFields() + const field = fields[this.options.detailView && !this.options.cardView ? index - 1 : index] + const column = this.columns[this.fieldsColumnsIndex[field]] + const value = Utils.getItemField(item, field, this.options.escape) + + if ($td.find('.detail-icon').length) { + return + } + + this.trigger(type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td) + this.trigger(type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr, field) + + // if click to select - then trigger the checkbox/radio click + if ( + type === 'click' && + this.options.clickToSelect && + column.clickToSelect && + !this.options.ignoreClickToSelectOn(target) + ) { + const $selectItem = $tr.find(Utils.sprintf('[name="%s"]', this.options.selectItemName)) + if ($selectItem.length) { + $selectItem[0].click() // #144: .trigger('click') bug + } + } + }) + + this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', e => { + e.preventDefault() + + const $this = $(e.currentTarget) // Fix #980 Detail view, when searching, returns wrong row + const $tr = $this.parent().parent() + const index = $tr.data('index') + const row = data[index] + + // remove and update + if ($tr.next().is('tr.detail-view')) { + $this.find('i').attr('class', Utils.sprintf('%s %s', this.options.iconsPrefix, this.options.icons.detailOpen)) + this.trigger('collapse-row', index, row, $tr.next()) + $tr.next().remove() + } else { + $this.find('i').attr('class', Utils.sprintf('%s %s', this.options.iconsPrefix, this.options.icons.detailClose)) + $tr.after(Utils.sprintf('', $tr.find('td').length)) + const $element = $tr.next().find('td') + const content = Utils.calculateObjectValue(this.options, this.options.detailFormatter, [index, row, $element], '') + if ($element.length === 1) { + $element.append(content) + } + this.trigger('expand-row', index, row, $element) + } + this.resetView() + return false + }) + + this.$selectItem = this.$body.find(Utils.sprintf('[name="%s"]', this.options.selectItemName)) + this.$selectItem.off('click').on('click', e => { + e.stopImmediatePropagation() + + const $this = $(e.currentTarget) + this.check_($this.prop('checked'), $this.data('index')) + }) + + this.header.events.forEach((_events, i) => { + let events = _events + if (!events) { + return + } + // fix bug, if events is defined with namespace + if (typeof events === 'string') { + events = Utils.calculateObjectValue(null, events) + } + + const field = this.header.fields[i] + let fieldIndex = this.getVisibleFields().indexOf(field) + + if (fieldIndex === -1) { + return + } + + if (this.options.detailView && !this.options.cardView) { + fieldIndex += 1 + } + + for (const [key, event] of Object.entries(events)) { + this.$body.find('>tr:not(.no-records-found)').each((i, tr) => { + const $tr = $(tr) + const $td = $tr.find(this.options.cardView ? '.card-view' : 'td').eq(fieldIndex) + const index = key.indexOf(' ') + const name = key.substring(0, index) + const el = key.substring(index + 1) + + $td.find(el).off(name).on(name, e => { + const index = $tr.data('index') + const row = this.data[index] + const value = row[field] + + event.apply(this, [e, value, row, index]) + }) + }) + } + }) + + this.updateSelected() + this.resetView() + + this.trigger('post-body', data) + } + + initServer (silent, query, url) { + let data = {} + const index = this.header.fields.indexOf(this.options.sortName) + + let params = { + searchText: this.searchText, + sortName: this.options.sortName, + sortOrder: this.options.sortOrder + } + + if (this.header.sortNames[index]) { + params.sortName = this.header.sortNames[index] + } + + if (this.options.pagination && this.options.sidePagination === 'server') { + params.pageSize = this.options.pageSize === this.options.formatAllRows() + ? this.options.totalRows : this.options.pageSize + params.pageNumber = this.options.pageNumber + } + + if (!(url || this.options.url) && !this.options.ajax) { + return + } + + if (this.options.queryParamsType === 'limit') { + params = { + search: params.searchText, + sort: params.sortName, + order: params.sortOrder + } + + if (this.options.pagination && this.options.sidePagination === 'server') { + params.offset = this.options.pageSize === this.options.formatAllRows() + ? 0 : this.options.pageSize * (this.options.pageNumber - 1) + params.limit = this.options.pageSize === this.options.formatAllRows() + ? this.options.totalRows : this.options.pageSize + if (params.limit === 0) { + delete params.limit + } + } + } + + if (!($.isEmptyObject(this.filterColumnsPartial))) { + params.filter = JSON.stringify(this.filterColumnsPartial, null) + } + + data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data) + + $.extend(data, query || {}) + + // false to stop request + if (data === false) { + return + } + + if (!silent) { + this.$tableLoading.show() + } + const request = $.extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), { + type: this.options.method, + url: url || this.options.url, + data: this.options.contentType === 'application/json' && this.options.method === 'post' + ? JSON.stringify(data) : data, + cache: this.options.cache, + contentType: this.options.contentType, + dataType: this.options.dataType, + success: _res => { + const res = Utils.calculateObjectValue(this.options, + this.options.responseHandler, [_res], _res) + + this.load(res) + this.trigger('load-success', res) + if (!silent) this.$tableLoading.hide() + }, + error: jqXHR => { + let data = [] + if (this.options.sidePagination === 'server') { + data = {} + data[this.options.totalField] = 0 + data[this.options.dataField] = [] + } + this.load(data) + this.trigger('load-error', jqXHR.status, jqXHR) + if (!silent) this.$tableLoading.hide() + } + }) + + if (this.options.ajax) { + Utils.calculateObjectValue(this, this.options.ajax, [request], null) + } else { + if (this._xhr && this._xhr.readyState !== 4) { + this._xhr.abort() + } + this._xhr = $.ajax(request) + } + } + + initSearchText () { + if (this.options.search) { + this.searchText = '' + if (this.options.searchText !== '') { + const $search = this.$toolbar.find('.search input') + $search.val(this.options.searchText) + this.onSearch({currentTarget: $search, firedByInitSearchText: true}) + } + } + } + + getCaret () { + this.$header.find('th').each((i, th) => { + $(th).find('.sortable').removeClass('desc asc') + .addClass($(th).data('field') === this.options.sortName + ? this.options.sortOrder : 'both') + }) + } + + updateSelected () { + const checkAll = this.$selectItem.filter(':enabled').length && + this.$selectItem.filter(':enabled').length === + this.$selectItem.filter(':enabled').filter(':checked').length + + this.$selectAll.add(this.$selectAll_).prop('checked', checkAll) + + this.$selectItem.each((i, el) => { + $(el).closest('tr')[$(el).prop('checked') ? 'addClass' : 'removeClass']('selected') + }) + } + + updateRows () { + this.$selectItem.each((i, el) => { + this.data[$(el).data('index')][this.header.stateField] = $(el).prop('checked') + }) + } + + resetRows () { + for (const row of this.data) { + this.$selectAll.prop('checked', false) + this.$selectItem.prop('checked', false) + if (this.header.stateField) { + row[this.header.stateField] = false + } + } + this.initHiddenRows() + } + + trigger (_name, ...args) { + const name = `${_name}.bs.table` + this.options[BootstrapTable.EVENTS[name]](...args) + this.$el.trigger($.Event(name), args) + + this.options.onAll(name, args) + this.$el.trigger($.Event('all.bs.table'), [name, args]) + } + + resetHeader () { + // fix #61: the hidden table reset header bug. + // fix bug: get $el.css('width') error sometime (height = 500) + clearTimeout(this.timeoutId_) + this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0) + } + + fitHeader () { + if (this.$el.is(':hidden')) { + this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), 100) + return + } + const fixedBody = this.$tableBody.get(0) + + const scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && + fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() + ? Utils.getScrollBarWidth() : 0 + + this.$el.css('margin-top', -this.$header.outerHeight()) + + const focused = $(':focus') + if (focused.length > 0) { + const $th = focused.parents('th') + if ($th.length > 0) { + const dataField = $th.attr('data-field') + if (dataField !== undefined) { + const $headerTh = this.$header.find(`[data-field='${dataField}']`) + if ($headerTh.length > 0) { + $headerTh.find(':input').addClass('focus-temp') + } + } + } + } + + this.$header_ = this.$header.clone(true, true) + this.$selectAll_ = this.$header_.find('[name="btSelectAll"]') + this.$tableHeader.css({ + 'margin-right': scrollWidth + }).find('table').css('width', this.$el.outerWidth()) + .html('').attr('class', this.$el.attr('class')) + .append(this.$header_) + + const focusedTemp = $('.focus-temp:visible:eq(0)') + if (focusedTemp.length > 0) { + focusedTemp.focus() + this.$header.find('.focus-temp').removeClass('focus-temp') + } + + // fix bug: $.data() is not working as expected after $.append() + this.$header.find('th[data-field]').each((i, el) => { + this.$header_.find(Utils.sprintf('th[data-field="%s"]', $(el).data('field'))).data($(el).data()) + }) + + const visibleFields = this.getVisibleFields() + const $ths = this.$header_.find('th') + + this.$body.find('>tr:first-child:not(.no-records-found) > *').each((i, el) => { + const $this = $(el) + let index = i + + if (this.options.detailView && !this.options.cardView) { + if (i === 0) { + this.$header_.find('th.detail').find('.fht-cell').width($this.innerWidth()) + } + index = i - 1 + } + + if (index === -1) { + return + } + + let $th = this.$header_.find(Utils.sprintf('th[data-field="%s"]', visibleFields[index])) + if ($th.length > 1) { + $th = $($ths[$this[0].cellIndex]) + } + + const zoomWidth = $th.width() - $th.find('.fht-cell').width() + $th.find('.fht-cell').width($this.innerWidth() - zoomWidth) + }) + + this.horizontalScroll() + this.trigger('post-header') + } + + resetFooter () { + const data = this.getData() + const html = [] + + if (!this.options.showFooter || this.options.cardView) { // do nothing + return + } + + if (!this.options.cardView && this.options.detailView) { + html.push('
     
    ') + } + + for (const column of this.columns) { + let falign = '' + + let valign = '' + const csses = [] + let style = {} + const class_ = Utils.sprintf(' class="%s"', column['class']) + + if (!column.visible) { + return + } + + if (this.options.cardView && (!column.cardVisible)) { + return + } + + falign = Utils.sprintf('text-align: %s; ', column.falign ? column.falign : column.align) + valign = Utils.sprintf('vertical-align: %s; ', column.valign) + + style = Utils.calculateObjectValue(null, this.options.footerStyle) + + if (style && style.css) { + for (const [key, value] of Object.keys(style.css)) { + csses.push(`${key}: ${value}`) + } + } + + html.push('') + html.push('
    ') + + html.push(Utils.calculateObjectValue(column, column.footerFormatter, [data], ' ') || ' ') + + html.push('
    ') + html.push('
    ') + html.push('
    ') + html.push('') + } + + this.$tableFooter.find('tr').html(html.join('')) + this.$tableFooter.show() + clearTimeout(this.timeoutFooter_) + this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), + this.$el.is(':hidden') ? 100 : 0) + } + + fitFooter () { + clearTimeout(this.timeoutFooter_) + if (this.$el.is(':hidden')) { + this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 100) + return + } + + const elWidth = this.$el.css('width') + const scrollWidth = elWidth > this.$tableBody.width() ? Utils.getScrollBarWidth() : 0 + + this.$tableFooter.css({ + 'margin-right': scrollWidth + }).find('table').css('width', elWidth) + .attr('class', this.$el.attr('class')) + + const $footerTd = this.$tableFooter.find('td') + + this.$body.find('>tr:first-child:not(.no-records-found) > *').each((i, el) => { + const $this = $(el) + + $footerTd.eq(i).find('.fht-cell').width($this.innerWidth()) + }) + + this.horizontalScroll() + } + + horizontalScroll () { + // horizontal scroll event + // TODO: it's probably better improving the layout than binding to scroll event + + this.trigger('scroll-body') + this.$tableBody.off('scroll').on('scroll', ({currentTarget}) => { + if (this.options.showHeader && this.options.height) { + this.$tableHeader.scrollLeft($(currentTarget).scrollLeft()) + } + + if (this.options.showFooter && !this.options.cardView) { + this.$tableFooter.scrollLeft($(currentTarget).scrollLeft()) + } + }) + } + + toggleColumn (index, checked, needUpdate) { + if (index === -1) { + return + } + this.columns[index].visible = checked + this.initHeader() + this.initSearch() + this.initPagination() + this.initBody() + + if (this.options.showColumns) { + const $items = this.$toolbar.find('.keep-open input').prop('disabled', false) + + if (needUpdate) { + $items.filter(Utils.sprintf('[value="%s"]', index)).prop('checked', checked) + } + + if ($items.filter(':checked').length <= this.options.minimumCountColumns) { + $items.filter(':checked').prop('disabled', true) + } + } + } + + getVisibleFields () { + const visibleFields = [] + + for (const field of this.header.fields) { + const column = this.columns[this.fieldsColumnsIndex[field]] + + if (!column.visible) { + continue + } + visibleFields.push(field) + } + return visibleFields + } + + // PUBLIC FUNCTION DEFINITION + // ======================= + + resetView (params) { + let padding = 0 + + if (params && params.height) { + this.options.height = params.height + } + + this.$selectAll.prop('checked', this.$selectItem.length > 0 && + this.$selectItem.length === this.$selectItem.filter(':checked').length) + + if (this.options.height) { + const toolbarHeight = this.$toolbar.outerHeight(true) + const paginationHeight = this.$pagination.outerHeight(true) + const height = this.options.height - toolbarHeight - paginationHeight + + this.$tableContainer.css('height', `${height}px`) + } + + if (this.options.cardView) { + // remove the element css + this.$el.css('margin-top', '0') + this.$tableContainer.css('padding-bottom', '0') + this.$tableFooter.hide() + return + } + + if (this.options.showHeader && this.options.height) { + this.$tableHeader.show() + this.resetHeader() + padding += this.$header.outerHeight() + } else { + this.$tableHeader.hide() + this.trigger('post-header') + } + + if (this.options.showFooter) { + this.resetFooter() + if (this.options.height) { + padding += this.$tableFooter.outerHeight() + 1 + } + } + + // Assign the correct sortable arrow + this.getCaret() + this.$tableContainer.css('padding-bottom', `${padding}px`) + this.trigger('reset-view') + } + + getData (useCurrentPage) { + let data = this.options.data + if (this.searchText || this.options.sortName || !$.isEmptyObject(this.filterColumns) || !$.isEmptyObject(this.filterColumnsPartial)) { + data = this.data + } + + if (useCurrentPage) { + return data.slice(this.pageFrom - 1, this.pageTo) + } + + return data + } + + load (_data) { + let fixedScroll = false + let data = _data + + // #431: support pagination + if (this.options.pagination && this.options.sidePagination === 'server') { + this.options.totalRows = data[this.options.totalField] + } + + fixedScroll = data.fixedScroll + data = Array.isArray(data) ? data : data[this.options.dataField] + + this.initData(data) + this.initSearch() + this.initPagination() + this.initBody(fixedScroll) + } + + append (data) { + this.initData(data, 'append') + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + prepend (data) { + this.initData(data, 'prepend') + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + remove (params) { + const len = this.options.data.length + let i + let row + + if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) { + return + } + + for (i = len - 1; i >= 0; i--) { + row = this.options.data[i] + + if (!row.hasOwnProperty(params.field)) { + continue + } + if (params.values.includes(row[params.field])) { + this.options.data.splice(i, 1) + if (this.options.sidePagination === 'server') { + this.options.totalRows -= 1 + } + } + } + + if (len === this.options.data.length) { + return + } + + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + removeAll () { + if (this.options.data.length > 0) { + this.options.data.splice(0, this.options.data.length) + this.initSearch() + this.initPagination() + this.initBody(true) + } + } + + getRowByUniqueId (_id) { + const uniqueId = this.options.uniqueId + const len = this.options.data.length + let id = _id + let dataRow = null + let i + let row + let rowUniqueId + + for (i = len - 1; i >= 0; i--) { + row = this.options.data[i] + + if (row.hasOwnProperty(uniqueId)) { // uniqueId is a column + rowUniqueId = row[uniqueId] + } else if (row._data && row._data.hasOwnProperty(uniqueId)) { // uniqueId is a row data property + rowUniqueId = row._data[uniqueId] + } else { + continue + } + + if (typeof rowUniqueId === 'string') { + id = id.toString() + } else if (typeof rowUniqueId === 'number') { + if ((Number(rowUniqueId) === rowUniqueId) && (rowUniqueId % 1 === 0)) { + id = parseInt(id) + } else if ((rowUniqueId === Number(rowUniqueId)) && (rowUniqueId !== 0)) { + id = parseFloat(id) + } + } + + if (rowUniqueId === id) { + dataRow = row + break + } + } + + return dataRow + } + + removeByUniqueId (id) { + const len = this.options.data.length + const row = this.getRowByUniqueId(id) + + if (row) { + this.options.data.splice(this.options.data.indexOf(row), 1) + } + + if (len === this.options.data.length) { + return + } + + this.initSearch() + this.initPagination() + this.initBody(true) + } + + updateByUniqueId (params) { + const allParams = Array.isArray(params) ? params : [params] + + for (const params of allParams) { + if (!params.hasOwnProperty('id') || !params.hasOwnProperty('row')) { + continue + } + + const rowId = this.options.data.indexOf(this.getRowByUniqueId(params.id)) + + if (rowId === -1) { + continue + } + $.extend(this.options.data[rowId], params.row) + } + + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + refreshColumnTitle (params) { + if (!params.hasOwnProperty('field') || !params.hasOwnProperty('title')) { + return + } + + this.columns[this.fieldsColumnsIndex[params.field]].title = + this.options.escape ? Utils.escapeHTML(params.title) : params.title + + if (this.columns[this.fieldsColumnsIndex[params.field]].visible) { + const header = this.options.height !== undefined ? this.$tableHeader : this.$header + header.find('th[data-field]').each((i, el) => { + if ($(el).data('field') === params.field) { + $($(el).find('.th-inner')[0]).text(params.title) + return false + } + }) + } + } + + insertRow (params) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { + return + } + this.options.data.splice(params.index, 0, params.row) + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + updateRow (params) { + const allParams = Array.isArray(params) ? params : [params] + + for (const params of allParams) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { + continue + } + $.extend(this.options.data[params.index], params.row) + } + + this.initSearch() + this.initPagination() + this.initSort() + this.initBody(true) + } + + initHiddenRows () { + this.hiddenRows = [] + } + + showRow (params) { + this.toggleRow(params, true) + } + + hideRow (params) { + this.toggleRow(params, false) + } + + toggleRow (params, visible) { + let row + + if (params.hasOwnProperty('index')) { + row = this.getData()[params.index] + } else if (params.hasOwnProperty('uniqueId')) { + row = this.getRowByUniqueId(params.uniqueId) + } + + if (!row) { + return + } + + const index = Utils.findIndex(this.hiddenRows, row) + + if (!visible && index === -1) { + this.hiddenRows.push(row) + } else if (visible && index > -1) { + this.hiddenRows.splice(index, 1) + } + this.initBody(true) + } + + getHiddenRows (show) { + if (show) { + this.initHiddenRows() + this.initBody(true) + return + } + const data = this.getData() + const rows = [] + + for (const row of data) { + if (this.hiddenRows.includes(row)) { + rows.push(row) + } + } + this.hiddenRows = rows + return rows + } + + mergeCells (options) { + const row = options.index + let col = this.getVisibleFields().indexOf(options.field) + const rowspan = options.rowspan || 1 + const colspan = options.colspan || 1 + let i + let j + const $tr = this.$body.find('>tr') + + if (this.options.detailView && !this.options.cardView) { + col += 1 + } + + const $td = $tr.eq(row).find('>td').eq(col) + + if (row < 0 || col < 0 || row >= this.data.length) { + return + } + + for (i = row; i < row + rowspan; i++) { + for (j = col; j < col + colspan; j++) { + $tr.eq(i).find('>td').eq(j).hide() + } + } + + $td.attr('rowspan', rowspan).attr('colspan', colspan).show() + } + + updateCell (params) { + if (!params.hasOwnProperty('index') || + !params.hasOwnProperty('field') || + !params.hasOwnProperty('value')) { + return + } + this.data[params.index][params.field] = params.value + + if (params.reinit === false) { + return + } + this.initSort() + this.initBody(true) + } + + updateCellById (params) { + if (!params.hasOwnProperty('id') || + !params.hasOwnProperty('field') || + !params.hasOwnProperty('value')) { + return + } + const allParams = Array.isArray(params) ? params : [params] + + allParams.forEach(({id, field, value}) => { + const rowId = this.options.data.indexOf(this.getRowByUniqueId(id)) + + if (rowId === -1) { + return + } + this.data[rowId][field] = value + }) + + if (params.reinit === false) { + return + } + this.initSort() + this.initBody(true) + } + + getOptions () { + // Deep copy: remove data + const options = $.extend({}, this.options) + delete options.data + return $.extend(true, {}, options) + } + + getSelections () { + // fix #2424: from html with checkbox + return this.options.data.filter(row => + row[this.header.stateField] === true) + } + + getAllSelections () { + return this.options.data.filter(row => row[this.header.stateField]) + } + + checkAll () { + this.checkAll_(true) + } + + uncheckAll () { + this.checkAll_(false) + } + + checkInvert () { + const $items = this.$selectItem.filter(':enabled') + let checked = $items.filter(':checked') + $items.each((i, el) => { + $(el).prop('checked', !$(el).prop('checked')) + }) + this.updateRows() + this.updateSelected() + this.trigger('uncheck-some', checked) + checked = this.getSelections() + this.trigger('check-some', checked) + } + + checkAll_ (checked) { + let rows + if (!checked) { + rows = this.getSelections() + } + this.$selectAll.add(this.$selectAll_).prop('checked', checked) + this.$selectItem.filter(':enabled').prop('checked', checked) + this.updateRows() + if (checked) { + rows = this.getSelections() + } + this.trigger(checked ? 'check-all' : 'uncheck-all', rows) + } + + check (index) { + this.check_(true, index) + } + + uncheck (index) { + this.check_(false, index) + } + + check_ (checked, index) { + const $el = this.$selectItem.filter(`[data-index="${index}"]`) + const row = this.data[index] + + if ($el.is(':radio') || this.options.singleSelect) { + for (const r of this.options.data) { + r[this.header.stateField] = false + } + this.$selectItem.filter(':checked').not($el).prop('checked', false) + } + + row[this.header.stateField] = checked + $el.prop('checked', checked) + this.updateSelected() + this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el) + } + + checkBy (obj) { + this.checkBy_(true, obj) + } + + uncheckBy (obj) { + this.checkBy_(false, obj) + } + + checkBy_ (checked, obj) { + if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { + return + } + + const rows = [] + this.options.data.forEach((row, i) => { + if (!row.hasOwnProperty(obj.field)) { + return false + } + if (obj.values.includes(row[obj.field])) { + const $el = this.$selectItem.filter(':enabled') + .filter(Utils.sprintf('[data-index="%s"]', i)).prop('checked', checked) + row[this.header.stateField] = checked + rows.push(row) + this.trigger(checked ? 'check' : 'uncheck', row, $el) + } + }) + this.updateSelected() + this.trigger(checked ? 'check-some' : 'uncheck-some', rows) + } + + destroy () { + this.$el.insertBefore(this.$container) + $(this.options.toolbar).insertBefore(this.$el) + this.$container.next().remove() + this.$container.remove() + this.$el.html(this.$el_.html()) + .css('margin-top', '0') + .attr('class', this.$el_.attr('class') || '') // reset the class + } + + showLoading () { + this.$tableLoading.show() + } + + hideLoading () { + this.$tableLoading.hide() + } + + togglePagination () { + this.options.pagination = !this.options.pagination + const button = this.$toolbar.find('button[name="paginationSwitch"] i') + if (this.options.pagination) { + button.attr('class', `${this.options.iconsPrefix} ${this.options.icons.paginationSwitchDown}`) + } else { + button.attr('class', `${this.options.iconsPrefix} ${this.options.icons.paginationSwitchUp}`) + } + this.updatePagination() + } + + toggleFullscreen () { + this.$el.closest('.bootstrap-table').toggleClass('fullscreen') + } + + refresh (params) { + if (params && params.url) { + this.options.url = params.url + } + if (params && params.pageNumber) { + this.options.pageNumber = params.pageNumber + } + if (params && params.pageSize) { + this.options.pageSize = params.pageSize + } + this.initServer(params && params.silent, + params && params.query, params && params.url) + this.trigger('refresh', params) + } + + resetWidth () { + if (this.options.showHeader && this.options.height) { + this.fitHeader() + } + if (this.options.showFooter && !this.options.cardView) { + this.fitFooter() + } + } + + showColumn (field) { + this.toggleColumn(this.fieldsColumnsIndex[field], true, true) + } + + hideColumn (field) { + this.toggleColumn(this.fieldsColumnsIndex[field], false, true) + } + + getHiddenColumns () { + return this.columns.filter(({visible}) => !visible) + } + + getVisibleColumns () { + return this.columns.filter(({visible}) => visible) + } + + toggleAllColumns (visible) { + for (const column of this.columns) { + column.visible = visible + } + + this.initHeader() + this.initSearch() + this.initPagination() + this.initBody() + if (this.options.showColumns) { + const $items = this.$toolbar.find('.keep-open input').prop('disabled', false) + + if ($items.filter(':checked').length <= this.options.minimumCountColumns) { + $items.filter(':checked').prop('disabled', true) + } + } + } + + showAllColumns () { + this.toggleAllColumns(true) + } + + hideAllColumns () { + this.toggleAllColumns(false) + } + + filterBy (columns) { + this.filterColumns = $.isEmptyObject(columns) ? {} : columns + this.options.pageNumber = 1 + this.initSearch() + this.updatePagination() + } + + scrollTo (_value) { + if (typeof _value === 'undefined') { + return this.$tableBody.scrollTop() + } + + let value = _value + if (typeof _value === 'string' && _value === 'bottom') { + value = this.$tableBody[0].scrollHeight + } + this.$tableBody.scrollTop(value) + } + + getScrollPosition () { + return this.scrollTo() + } + + selectPage (page) { + if (page > 0 && page <= this.options.totalPages) { + this.options.pageNumber = page + this.updatePagination() + } + } + + prevPage () { + if (this.options.pageNumber > 1) { + this.options.pageNumber-- + this.updatePagination() + } + } + + nextPage () { + if (this.options.pageNumber < this.options.totalPages) { + this.options.pageNumber++ + this.updatePagination() + } + } + + toggleView () { + this.options.cardView = !this.options.cardView + this.initHeader() + // Fixed remove toolbar when click cardView button. + // this.initToolbar(); + const $icon = this.$toolbar.find('button[name="toggle"] i') + if (this.options.cardView) { + $icon.removeClass(this.options.icons.toggleOff) + $icon.addClass(this.options.icons.toggleOn) + } else { + $icon.removeClass(this.options.icons.toggleOn) + $icon.addClass(this.options.icons.toggleOff) + } + this.initBody() + this.trigger('toggle', this.options.cardView) + } + + refreshOptions (options) { + // If the objects are equivalent then avoid the call of destroy / init methods + if (Utils.compareObjects(this.options, options, true)) { + return + } + this.options = $.extend(this.options, options) + this.trigger('refresh-options', this.options) + this.destroy() + this.init() + } + + resetSearch (text) { + const $search = this.$toolbar.find('.search input') + $search.val(text || '') + this.onSearch({currentTarget: $search}) + } + + expandRow_ (expand, index) { + const $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"]', index)) + if ($tr.next().is('tr.detail-view') === (!expand)) { + $tr.find('> td > .detail-icon').click() + } + } + + expandRow (index) { + this.expandRow_(true, index) + } + + collapseRow (index) { + this.expandRow_(false, index) + } + + expandAllRows (isSubTable) { + if (isSubTable) { + const $tr = this.$body.find(Utils.sprintf('> tr[data-index="%s"]', 0)) + let detailIcon = null + let executeInterval = false + let idInterval = -1 + + if (!$tr.next().is('tr.detail-view')) { + $tr.find('> td > .detail-icon').click() + executeInterval = true + } else if (!$tr.next().next().is('tr.detail-view')) { + $tr.next().find('.detail-icon').click() + executeInterval = true + } + + if (executeInterval) { + try { + idInterval = setInterval(() => { + detailIcon = this.$body.find('tr.detail-view').last().find('.detail-icon') + if (detailIcon.length > 0) { + detailIcon.click() + } else { + clearInterval(idInterval) + } + }, 1) + } catch (ex) { + clearInterval(idInterval) + } + } + } else { + const trs = this.$body.children() + for (let i = 0; i < trs.length; i++) { + this.expandRow_(true, $(trs[i]).data('index')) + } + } + } + + collapseAllRows (isSubTable) { + if (isSubTable) { + this.expandRow_(false, 0) + } else { + const trs = this.$body.children() + for (let i = 0; i < trs.length; i++) { + this.expandRow_(false, $(trs[i]).data('index')) + } + } + } + + updateFormatText (name, text) { + if (this.options[Utils.sprintf('format%s', name)]) { + if (typeof text === 'string') { + this.options[Utils.sprintf('format%s', name)] = () => text + } else if (typeof text === 'function') { + this.options[Utils.sprintf('format%s', name)] = text + } + } + this.initToolbar() + this.initPagination() + this.initBody() + } + } + + BootstrapTable.DEFAULTS = DEFAULTS + BootstrapTable.LOCALES = LOCALES + BootstrapTable.COLUMN_DEFAULTS = COLUMN_DEFAULTS + BootstrapTable.EVENTS = EVENTS + + // BOOTSTRAP TABLE PLUGIN DEFINITION + // ======================= + + const allowedMethods = [ + 'getOptions', + 'getSelections', 'getAllSelections', 'getData', + 'load', 'append', 'prepend', 'remove', 'removeAll', + 'insertRow', 'updateRow', 'updateCell', + 'updateByUniqueId', 'removeByUniqueId', + 'getRowByUniqueId', 'showRow', 'hideRow', 'getHiddenRows', + 'mergeCells', 'refreshColumnTitle', + 'checkAll', 'uncheckAll', 'checkInvert', + 'check', 'uncheck', + 'checkBy', 'uncheckBy', + 'refresh', + 'resetView', + 'resetWidth', + 'destroy', + 'showLoading', 'hideLoading', + 'showColumn', 'hideColumn', + 'getHiddenColumns', 'getVisibleColumns', + 'showAllColumns', 'hideAllColumns', + 'filterBy', + 'scrollTo', + 'getScrollPosition', + 'selectPage', 'prevPage', 'nextPage', + 'togglePagination', + 'toggleView', + 'refreshOptions', + 'resetSearch', + 'expandRow', 'collapseRow', + 'expandAllRows', 'collapseAllRows', + 'updateFormatText', 'updateCellById' + ] + + $.BootstrapTable = BootstrapTable + $.fn.bootstrapTable = function (option, ...args) { + let value + + this.each((i, el) => { + let data = $(el).data('bootstrap.table') + const options = $.extend({}, BootstrapTable.DEFAULTS, $(el).data(), + typeof option === 'object' && option) + + if (typeof option === 'string') { + if (!allowedMethods.includes(option)) { + throw new Error(`Unknown method: ${option}`) + } + + if (!data) { + return + } + + value = data[option](...args) + + if (option === 'destroy') { + $(el).removeData('bootstrap.table') + } + } + + if (!data) { + $(el).data('bootstrap.table', (data = new $.BootstrapTable(el, options))) + } + }) + + return typeof value === 'undefined' ? this : value + } + + $.fn.bootstrapTable.Constructor = BootstrapTable + $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS + $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS + $.fn.bootstrapTable.locales = BootstrapTable.LOCALES + $.fn.bootstrapTable.methods = allowedMethods + $.fn.bootstrapTable.utils = Utils + + // BOOTSTRAP TABLE INIT + // ======================= + + $(() => { + $('[data-toggle="table"]').bootstrapTable() + }) +})(jQuery) diff --git a/js/mColorPicker_min.js b/js/mColorPicker_min.js index a1cb7c0..14b4385 100644 --- a/js/mColorPicker_min.js +++ b/js/mColorPicker_min.js @@ -1,12 +1,12 @@ -/* - mColorPicker - Version: 1.0 r39 - - Copyright (c) 2010 Meta100 LLC. - http://www.meta100.com/ - - Licensed under the MIT license - http://www.opensource.org/licenses/mit-license.php -*/ - +/* + mColorPicker + Version: 1.0 r39 + + Copyright (c) 2010 Meta100 LLC. + http://www.meta100.com/ + + Licensed under the MIT license + http://www.opensource.org/licenses/mit-license.php +*/ + (function($){var b,f,h,l,j=$(document),i=$("
    "),k=$("
    "),n=$("
    "),o=$(""),p=/^rgb[a]?\((\d+),\s*(\d+),\s*(\d+)(,\s*(\d+\.\d+)*)?\)/,q=/([a-f0-9])([a-f0-9])([a-f0-9])/,r=/#[a-f0-9]{3}/,s=/#[a-f0-9]{6}/;$.fn.mColorPicker=function(a){var c=$.fn.mColorPicker.getCookie("swatches");b=$.extend($.fn.mColorPicker.defaults,a);$.fn.mColorPicker.defaults.swatches.concat(b.swatches).slice(-10);f.enhancedSwatches&&c&&(b.swatches=c.split("||").concat(b.swatches).slice(0,10)||b.swatches);$("div#mColorPicker").length||$.fn.mColorPicker.drawPicker();$("#css_disabled_color_picker").length||$("head").prepend('');$("meta[data-remove-me=true]").remove();this.each($.fn.mColorPicker.drawPickerTriggers);return this};$.fn.mColorPicker.init={replace:"[type=color]",index:0,enhancedSwatches:!0,allowTransparency:!0,slogan:"Meta100 - Designing Fun",showLogo:!0};$.fn.mColorPicker.defaults={currentId:!1,currentInput:!1,currentColor:!1,changeColor:!1,color:!1,imageFolder:"http://meta100.github.com/mColorPicker/images/",swatches:"#ffffff,#ffff00,#00ff00,#00ffff,#0000ff,#ff00ff,#ff0000,#4c2b11,#3b3b3b,#000000".split(",")};$.fn.mColorPicker.start=function(){$('input[data-mcolorpicker!="true"]').filter(function(){return"[type=color]"==f.replace?"color"==this.getAttribute("type"):$(this).is(f.replace)}).mColorPicker()};$.fn.mColorPicker.events=function(){$("#mColorPickerBg").live("click",$.fn.mColorPicker.closePicker);$(".mColorPicker").live("keyup",function(){try{$(this).css({"background-color":$(this).val()}).css({color:$.fn.mColorPicker.textColor($(this).css("background-color"))}).trigger("change")}catch(a){}});$(".mColorPickerTrigger").live("click",$.fn.mColorPicker.colorShow);$(".mColor, .mPastColor").live("mousemove",function(a){if(!b.changeColor)return!1;var c=$(this),g=c.offset(),d=b.currentInput,d=d.attr("data-hex")||d.attr("hex");b.color=c.css("background-color");c.hasClass("mPastColor")?b.color=$.fn.mColorPicker.setColor(b.color,d):c.hasClass("mColorTransparent")?b.color="transparent":c.hasClass("mPastColor")||(b.color=$.fn.mColorPicker.whichColor(a.pageX-g.left,a.pageY-g.top,d));b.currentInput.mSetInputColor(b.color)}).live("click",$.fn.mColorPicker.colorPicked);$("#mColorPickerInput").live("keyup",function(a){try{b.color=$(this).val(),b.currentInput.mSetInputColor(b.color),13==a.which&&$.fn.mColorPicker.colorPicked()}catch(c){}}).live("blur",function(){b.currentInput.mSetInputColor(b.color)});$("#mColorPickerWrapper").live("mouseleave",function(){if(!b.changeColor)return!1;var a=b.currentInput;b.currentInput.mSetInputColor($.fn.mColorPicker.setColor(b.currentColor,a.attr("data-hex")||a.attr("hex")))})};$.fn.mColorPicker.drawPickerTriggers=function(){var a=$(this),c=a.attr("id")||"color_"+f.index++,g="hidden"==a.attr("text")||"hidden"==a.attr("data-text")?!0:!1,d=$.fn.mColorPicker.setColor(a.val(),a.attr("data-hex")||a.attr("hex")),e=a.width(),h=a.height(),i=a.css("float"),j=$(""),m=$(""),k="";j.attr({id:"color_work_area","class":"mColorPickerInput"}).appendTo(l);m.attr({id:"mcp_"+c,"class":"mColorPickerTrigger"}).css({display:"inline-block",cursor:"pointer"}).insertAfter(a);$("").attr({src:b.imageFolder+"color.png"}).css({border:0,margin:"0 0 0 3px","vertical-align":"text-bottom"}).appendTo(m);j.append(a);k=j.html().replace(/type=[^a-z ]*color[^a-z //>]*/gi,'type="'+(g?"hidden":"text")+'"');j.html("").remove();a=$(k).attr("id",c).addClass("mColorPicker").val(d).insertBefore(m);g&&m.css({border:"1px solid black","float":i,width:e,height:h}).addClass(a.attr("class")).html(" ");a.mSetInputColor(d);return a};$.fn.mColorPicker.drawPicker=function(){var a=$("
    "),c=$(""),g=$("
    "),d=$("
    ");k.attr({id:"mColorPickerBg"}).css({display:"none",background:"black",opacity:0.01,position:"absolute",top:0,right:0,bottom:0,left:0}).appendTo(l);i.attr({id:"mColorPicker","data-mcolorpicker":!0}).css({position:"absolute",border:"1px solid #ccc",color:"#fff",width:"194px",height:"184px","font-size":"12px","font-family":"times",display:"none"}).appendTo(l);n.attr({id:"mColorPickerTest"}).css({display:"none"}).appendTo(l);d.attr({id:"mColorPickerWrapper"}).css({position:"relative",border:"solid 1px gray"}).appendTo(i);$("
    ").attr({id:"mColorPickerImg","class":"mColor"}).css({height:"136px",width:"192px",border:0,cursor:"crosshair","background-image":"url("+b.imageFolder+"picker.png)"}).appendTo(d);a.attr({id:"mColorPickerSwatches"}).css({"border-right":"1px solid #000"}).appendTo(d);$("
    ").addClass("mClear").css({clear:"both"}).appendTo(a);for(h=9;-1").attr({id:"cell"+h,"class":"mPastColor"+(0").attr({id:"mColorPickerTransparent","class":"mColor mColorTransparent"}).css({"font-size":"16px",color:"#000","padding-right":"30px","padding-top":"3px",cursor:"pointer",overflow:"hidden","float":"right"}).text("transparent").appendTo(g);f.showLogo&&c.attr({href:"http://meta100.com/",title:f.slogan,alt:f.slogan,target:"_blank"}).css({"float":"right"}).appendTo(g);$("").attr({src:b.imageFolder+"meta100.png",title:f.slogan,alt:f.slogan}).css({border:0,"border-left":"1px solid #aaa",right:0,position:"absolute"}).appendTo(c);$(".mNoLeftBorder").css({"border-left":0})};$.fn.mColorPicker.closePicker=function(){k.hide();i.fadeOut()};$.fn.mColorPicker.colorShow=function(){var a=$(this),c=a.attr("id").replace("mcp_",""),g=a.offset(),d=$("#"+c),e=g.top+a.outerHeight(),f=g.left;if(d.attr("disabled"))return!1;b.currentColor=d.css("background-color");b.changeColor=!0;b.currentInput=d;b.currentId=c;e+i.height()>j.height()&&(e=g.top-i.height());f+i.width()>j.width()&&(f=g.left-i.width()+a.outerWidth());i.css({top:e+"px",left:f+"px"}).fadeIn("fast");k.show();b.color=$("#"+c).attr("data-text")?a.css("background-color"):d.css("background-color");b.color=$.fn.mColorPicker.setColor(b.color,d.attr("data-hex")||d.attr("hex"));o.val(b.color)};$.fn.mColorPicker.setInputColor=function(a,c){$("#"+a).mSetInputColor(c)};$.fn.mSetInputColor=function(a){var c=$(this),g={"background-color":a,"background-image":"transparent"==a?"url('"+b.imageFolder+"grid.gif')":"",color:$.fn.mColorPicker.textColor(a)};(c.attr("data-text")||c.attr("text"))&&c.next().css(g);c.val(a).css(g).trigger("change");o.val(a)};$.fn.mColorPicker.textColor=function(a){a=$.fn.mColorPicker.RGBtoHex(a);return"undefined"==typeof a||"transparent"==a?"black":400>parseInt(a.substr(1,2),16)+parseInt(a.substr(3,2),16)+parseInt(a.substr(5,2),16)?"white":"black"};$.fn.mColorPicker.setCookie=function(a,c,b){a=a+"="+escape(c);c=new Date;c.setDate(c.getDate()+b);a+="; expires="+c.toGMTString();document.cookie=a};$.fn.mColorPicker.getCookie=function(a){return(a=document.cookie.match("(^|;) ?"+a+"=([^;]*)(;|$)"))?unescape(a[2]):null};$.fn.mColorPicker.colorPicked=function(){b.changeColor=!1;$.fn.mColorPicker.closePicker();$.fn.mColorPicker.addToSwatch();b.currentInput.trigger("colorpicked")};$.fn.mColorPicker.addToSwatch=function(a){if(!f.enhancedSwatches)return!1;var c=[];h=0;"string"==typeof a&&(b.color=a);"transparent"!=b.color&&(c[0]=$.fn.mColorPicker.hexToRGB(b.color));$(".mPastColor").each(function(){var a=$(this);b.color=$.fn.mColorPicker.hexToRGB(a.css("background-color"));if(b.color!=c[0]&&c.length<10)c[c.length]=b.color;a.css("background-color",c[h++])});f.enhancedSwatches&&$.fn.mColorPicker.setCookie("swatches",c.join("||"),365)};$.fn.mColorPicker.whichColor=function(a,c,b){var d=[255,255,255];32>a?(d[1]=8*a,d[2]=0):64>a?(d[0]=256-8*(a-32),d[2]=0):96>a?(d[0]=0,d[2]=8*(a-64)):128>a?(d[0]=0,d[1]=256-8*(a-96)):160>a?(d[0]=8*(a-128),d[1]=0):(d[1]=0,d[2]=256-8*(a-160));for(var e=0;3>e;e++)64>c?d[e]+=(256-d[e])*(64-c)/64:128>=c?d[e]-=d[e]*(c-64)/64:128a;a++)c+=$.fn.mColorPicker.decToHex(b[a]);return c}return $.fn.mColorPicker.colorTest(a)};$.fn.mColorPicker.hexToRGB=function(a){a=a?a.toLowerCase():!1;return!a?"":p.test(a)?a:r.test(a)?(s.test(a)||(a=a.replace(q,"$1$1$2$2$3$3")),"rgb("+parseInt(a.substr(1,2),16)+", "+parseInt(a.substr(3,2),16)+", "+parseInt(a.substr(5,2),16)+")"):$.fn.mColorPicker.colorTest(a)};f=$.fn.mColorPicker.init;j.ready(function(){l=$("body");$.fn.mColorPicker.events();f.replace&&("function"==typeof $.fn.mDOMupdate?$("input").mDOMupdate($.fn.mColorPicker.start):"function"==typeof $.fn.livequery?$("input").livequery($.fn.mColorPicker.start):($.fn.mColorPicker.start(),j.live("ajaxSuccess.mColorPicker",$.fn.mColorPicker.start)))})})(jQuery); \ No newline at end of file diff --git a/readme.txt b/readme.txt index 65df2e2..93a2c7c 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,11 @@ === WP GPX Maps === -Contributors: bastianonm, Stephan Klein, Michel Selerin, TosattoSimonePio, Kniebremser +Contributors: bastianonm, Stephan Klein, Michel Selerin, TosattoSimonePio, Kniebremser Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8VHWLRW6JBTML Tags: maps, gpx, gps, graph, chart, leaflet, track, garmin, image, nextgen-gallery, nextgen, exif, OpenStreetMap, OpenCycleMap, Hike&Bike, heart rate, heartrate, cadence Requires at least: 4.6.0 -Tested up to: 5.2.1 +Tested up to: 5.2.2 +Requires PHP: 5.6.20 Stable tag: 1.7.00 Draws a GPX track with altitude graph. You can also display your nextgen gallery images in the map. @@ -42,19 +43,19 @@ Try this plugin: www.devfarm.it Support Forum + Would you like to help fix bugs or further develop the plugin? On Github you can contribuite easly with your code. Translations: Translators are welcome to contribute to the plugin. Please use the WordPress translation website. -The language files in the plugin contain 19 translatable texts for 14 languages: +The language files in the plugin contain 18 translatable texts for 13 languages: - Catalan ca - Dutch nl_NL - English (default) - French fr_FR -- German de_DE - Hungarian hu_HU - Italian it_IT - Norwegian nb_NO @@ -71,7 +72,7 @@ The language files in the plugin contain 19 translatable texts for 14 languages: (Many thanks to all guys who helped me with the translations) -Currently are 222 texts are translatable in the plugin. +Currently are 230 texts are translatable in the plugin. With your help, the plugin can be translated into any language. For updating the language file you no longer need to wait for a new version of the plugin. Are 95% WordPress generates a new language file for your language. @@ -107,9 +108,9 @@ Icons made by - .wpgpxmaps { - clear: both; - } - - #content .wpgpxmaps img, - .entry-content .wpgpxmaps img, - .wpgpxmaps img { - max-width: none; - width: none; - padding: 0; - background: none; - margin: 0; - border: none; - } - - .wpgpxmaps .ngimages { - display: none; - } - - .wpgpxmaps .myngimages { - border: 1px solid #fff; - position: absolute; - cursor: pointer; - margin:0; - z-index :1; - } - - .wpgpxmaps_summary .summarylabel { } - .wpgpxmaps_summary .summaryvalue { - font-weight: bold; - } - - .wpgpxmaps .report { - line-height :120%; - } - - .wpgpxmaps .gmnoprint div:first-child { } - .wpgpxmaps .wpgpxmaps_osm_footer { - position: absolute; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 13px; - margin: 0; - z-index: 999; - background: WHITE; - font-size: 12px; - } - - .wpgpxmaps .wpgpxmaps_osm_footer span { - background: WHITE; - padding: 0 6px 6px 6px; - vertical-align: baseline; - position: absolute; - bottom: 0; - } - - - dist[$i]; if ( $uom == '1' ) { - /* miles and feet */ + /* feet / miles */ $_dist *= 0.000621371192; $_ele *= 3.2808399; @@ -247,7 +190,7 @@ function handle_WP_GPX_Maps_folder_Shortcodes( $attr, $content = '' ) { $_dist = (float) ( $_dist / 1000 ); } elseif ( $uom == '3' ) { - /* meters / kilometers / nautical miles */ + /* meters / nautical miles */ $_dist = (float) ( $_dist / 1000 / 1.852 ); } elseif ( $uom == '4' ) { @@ -255,7 +198,7 @@ function handle_WP_GPX_Maps_folder_Shortcodes( $attr, $content = '' ) { $_dist *= 0.000621371192; } elseif ( $uom == '5' ) { - /* meters / kilometers / nautical miles and feet */ + /* feet / nautical miles */ $_dist = (float) ( $_dist / 1000 / 1.852 ); $_ele *= 3.2808399; } @@ -283,7 +226,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $download = wpgpxmaps_findValue( $attr, 'download', 'wpgpxmaps_download', '' ); $usegpsposition = wpgpxmaps_findValue( $attr, 'usegpsposition', 'wpgpxmaps_usegpsposition', false ); /* Print Summary Table */ - $summary = wpgpxmaps_findValue( $attr, 'summary', 'wpgpxmaps_summary', '' ); + $summary = wpgpxmaps_findValue( $attr, 'summary', 'wpgpxmaps_summary', false ); $p_tot_len = wpgpxmaps_findValue( $attr, 'summarytotlen', 'wpgpxmaps_summary_tot_len', false ); $p_max_ele = wpgpxmaps_findValue( $attr, 'summarymaxele', 'wpgpxmaps_summary_max_ele', false ); $p_min_ele = wpgpxmaps_findValue( $attr, 'summaryminele', 'wpgpxmaps_summary_min_ele', false ); @@ -305,7 +248,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $currentIcon = wpgpxmaps_findValue( $attr, 'currenticon', 'wpgpxmaps_map_current_icon', '' ); $waypointIcon = wpgpxmaps_findValue( $attr, 'waypointicon', 'wpgpxmaps_map_waypoint_icon', '' ); /* Diagram - Elevation */ - $showEle = wpgpxmaps_findValue( $attr, 'showele', 'wpgpxmaps_show_elevation', 'true' ); + $showEle = wpgpxmaps_findValue( $attr, 'showele', 'wpgpxmaps_show_elevation', true ); $color_graph = wpgpxmaps_findValue( $attr, 'glinecolor', 'wpgpxmaps_graph_line_color', '#3366cc' ); $uom = wpgpxmaps_findValue( $attr, 'uom', 'wpgpxmaps_unit_of_measure', '0' ); $chartFrom1 = wpgpxmaps_findValue( $attr, 'chartfrom1', 'wpgpxmaps_graph_offset_from1', '' ); @@ -323,8 +266,8 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $showAtemp = wpgpxmaps_findValue( $attr, 'showatemp', 'wpgpxmaps_show_atemp', false ); $color_graph_atemp = wpgpxmaps_findValue( $attr, 'glinecoloratemp', 'wpgpxmaps_graph_line_color_atemp', '#ff77bd' ); /* Diagram - Cadence */ - $showCad = wpgpxmaps_findValue( $attr, 'showcad', 'wpgpxmaps_show_cadence', false ); - $color_graph_cad = wpgpxmaps_findValue( $attr, 'glinecolorcad', 'wpgpxmaps_graph_line_color_cad', '#beecff' ); + $showCad = wpgpxmaps_findValue( $attr, 'showcad', 'wpgpxmaps_show_cadence', false ); + $color_graph_cad = wpgpxmaps_findValue( $attr, 'glinecolorcad', 'wpgpxmaps_graph_line_color_cad', '#beecff' ); /* Diagram - Grade */ $showGrade = wpgpxmaps_findValue( $attr, 'showgrade', 'wpgpxmaps_show_grade', false ); $color_graph_grade = wpgpxmaps_findValue( $attr, 'glinecolorgrade', 'wpgpxmaps_graph_line_color_grade', '#beecff' ); @@ -338,7 +281,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $donotreducegpx = wpgpxmaps_findValue( $attr, 'donotreducegpx', 'wpgpxmaps_donotreducegpx', false ); $allow_users_upload = wpgpxmaps_findValue( $attr, 'wpgpxmaps_allow_users_upload', 'wpgpxmaps_allow_users_view', false ); - $colors_map = "\"" . implode( "\",\"", ( explode( " ", $color_map ) ) ) . "\""; + $colors_map = "\"" . implode( "\",\"", ( explode( ' ', $color_map ) ) ) . "\""; $gpxurl = $gpx; @@ -417,7 +360,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { } } - $isGpxUrl = ( preg_match( '/^(http(s)?\:\/\/)/', trim( $gpx ) ) == 1); + $isGpxUrl = ( preg_match( '/^(http(s)?\:\/\/)/', trim( $gpx ) ) == 1 ); if ( ( ! isset( $points_maps ) || $points_maps == '' ) && $gpx != '' ) { // if (true) { @@ -495,7 +438,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $_dist = (float) $points->dist[$i]; if ( $uom == '1') { - /* miles and feet */ + /* feet / miles */ $_dist *= 0.000621371192; $_ele *= 3.2808399; @@ -504,7 +447,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $_dist = (float) ( $_dist / 1000 ); } elseif ( $uom == '3') { - /* meters / kilometers / nautical miles */ + /* meters / nautical miles */ $_dist = (float) ( $_dist / 1000 / 1.852 ); } elseif ( $uom == '4' ) { @@ -512,7 +455,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $_dist *= 0.000621371192; } elseif ( $uom == '5' ) { - /* meters / kilometers / nautical miles and feet */ + /* feet / nautical miles */ $_dist = (float) ( $_dist / 1000 / 1.852 ); $_ele *= 3.2808399; } @@ -526,25 +469,25 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { } if ( $showHr == true ) { - $points_graph_hr .= number_format( $points->hr[$i], 2, '.', '' ).','; + $points_graph_hr .= number_format( $points->hr[$i], 2, '.', '' ) . ','; } if ( $showAtemp == true ) { - $points_graph_atemp .= number_format( $points->atemp[$i], 1, '.', '' ).','; + $points_graph_atemp .= number_format( $points->atemp[$i], 1, '.', '' ) . ','; } if ( $showCad == true ) { - $points_graph_cad .= number_format( $points->cad[$i], 2, '.', '' ).','; + $points_graph_cad .= number_format( $points->cad[$i], 2, '.', '' ) . ','; } if ( $showGrade == true ) { - $points_graph_grade .= number_format( $points->grade[$i], 2, '.', '' ).','; + $points_graph_grade .= number_format( $points->grade[$i], 2, '.', '' ) . ','; } } } if ( $uom == '1' ) { - /* miles and feet */ + /* feet / miles */ $tot_len = round( $tot_len * 0.000621371192, 2 ) . ' mi'; $max_ele = round( $max_ele * 3.2808399, 0 ) . ' ft'; $min_ele = round( $min_ele * 3.2808399, 0 ) . ' ft'; @@ -560,15 +503,15 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $total_ele_down = round( $total_ele_down, 0 ) . ' m'; } elseif ( $uom == '3' ) { - /* meters / kilometers / nautical miles */ - $tot_len = round( $tot_len / 1000/1.852, 2 ) . ' NM'; + /* meters / nautical miles */ + $tot_len = round( $tot_len / 1000 / 1.852, 2 ) . ' NM'; $max_ele = round( $max_ele, 0 ) . ' m'; $min_ele = round( $min_ele, 0 ) . ' m'; $total_ele_up = round( $total_ele_up, 0 ) . ' m'; $total_ele_down = round( $total_ele_down, 0 ) . ' m'; } elseif ( $uom == '4' ) { - /* meters / kilometers / nautical miles */ + /* meters / miles */ $tot_len = round( $tot_len * 0.000621371192, 2 ) . ' mi'; $max_ele = round( $max_ele, 0 ) . ' m'; $min_ele = round( $min_ele, 0 ) . ' m'; @@ -576,8 +519,8 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $total_ele_down = round( $total_ele_down, 0 ) . ' m'; } elseif ( $uom == '5' ) { - /* meters / kilometers / nautical miles and feet */ - $tot_len = round( $tot_len / 1000/1.852, 2 ) . ' NM'; + /* feet / nautical miles */ + $tot_len = round( $tot_len / 1000 / 1.852, 2 ) . ' NM'; $max_ele = round( $max_ele * 3.2808399, 0 ) . ' ft'; $min_ele = round( $min_ele * 3.2808399, 0 ) . ' ft'; $total_ele_up = round( $total_ele_up * 3.2808399, 0 ) . ' ft'; @@ -599,11 +542,11 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $wpoints = wpgpxmaps_getWayPoints( $gpx ); $waypoints = wp_json_encode( $wpoints ); } - if ( $showEle == 'false' ) { - $points_graph_ele = ""; + if ( $showEle == false ) { + $points_graph_ele = ''; } - $p = "/(,|,null,)$/"; + $p = '/(,|,null,)$/'; $points_maps = preg_replace( $p, '', $points_maps ); @@ -643,11 +586,11 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $ngimgs_data = ''; if ( $ngGalleries != '' || $ngImages != '' ) { $ngimgs = getNGGalleryImages( $ngGalleries, $ngImages, $points_x_time, $points_x_lat, $points_x_lon, $dtoffset, $error ); - $ngimgs_data =''; + $ngimgs_data = ''; foreach ( $ngimgs as $img ) { $data = $img['data']; - $data = str_replace( "\n", "", $data ); + $data = str_replace( '\n', '', $data ); $ngimgs_data .= '' . $data . ''; } } @@ -656,7 +599,7 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $attimgs = wpgpxmaps_getAttachedImages( $points_x_time, $points_x_lat, $points_x_lon, $dtoffset, $error ); foreach ( $attimgs as $img ) { $data = $img['data']; - $data = str_replace( "\n", "", $data ); + $data = str_replace( '\n', '', $data ); $ngimgs_data .= '' . $data . ''; } } @@ -713,55 +656,56 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { jQuery(document).ready(function() { - jQuery("#wpgpxmaps_' . $r . '").wpgpxmaps({ - targetId : "' . $r . '", - mapType : "' . $mt . '", - mapData : [' . $points_maps . '], - graphDist : [' . ( $hideGraph ? '' : $points_graph_dist ) . '], - graphEle : [' . ( $hideGraph ? '' : $points_graph_ele ) . '], - graphSpeed : [' . ( $hideGraph ? '' : $points_graph_speed ) . '], - graphHr : [' . ( $hideGraph ? '' : $points_graph_hr ) . '], - graphAtemp : [' . ( $hideGraph ? '' : $points_graph_atemp ) . '], - graphCad : [' . ( $hideGraph ? '' : $points_graph_cad ) . '], - graphGrade : [' . ( $hideGraph ? '' : $points_graph_grade ) . '], - waypoints : ' . $waypoints . ', - unit : "' . $uom . '", - unitspeed : "' . $uomspeed . '", - color1 : [' . $colors_map . '], - color2 : "' . $color_graph . '", - color3 : "' . $color_graph_speed . '", - color4 : "' . $color_graph_hr . '", - color5 : "' . $color_graph_cad . '", - color6 : "' . $color_graph_grade . '", - color7 : "' . $color_graph_atemp . '", - chartFrom1 : "' . $chartFrom1 . '", - chartTo1 : "' . $chartTo1 . '", - chartFrom2 : "' . $chartFrom2 . '", - chartTo2 : "' . $chartTo2 . '", - startIcon : "' . $startIcon . '", - endIcon : "' . $endIcon . '", - currentIcon : "' . $currentIcon . '", - waypointIcon : "' . $waypointIcon . '", + jQuery( "#wpgpxmaps_' . $r . '" ).wpgpxmaps( { + targetId : "' . $r . '", + mapType : "' . $mt . '", + mapData : [' . $points_maps . '], + graphDist : [' . ( $hideGraph ? '' : $points_graph_dist ) . '], + graphEle : [' . ( $hideGraph ? '' : $points_graph_ele ) . '], + graphSpeed : [' . ( $hideGraph ? '' : $points_graph_speed ) . '], + graphHr : [' . ( $hideGraph ? '' : $points_graph_hr ) . '], + graphAtemp : [' . ( $hideGraph ? '' : $points_graph_atemp ) . '], + graphCad : [' . ( $hideGraph ? '' : $points_graph_cad ) . '], + graphGrade : [' . ( $hideGraph ? '' : $points_graph_grade ) . '], + waypoints : ' . $waypoints . ', + unit : "' . $uom . '", + unitspeed : "' . $uomspeed . '", + color1 : [' . $colors_map . '], + color2 : "' . $color_graph . '", + color3 : "' . $color_graph_speed . '", + color4 : "' . $color_graph_hr . '", + color5 : "' . $color_graph_cad . '", + color6 : "' . $color_graph_grade . '", + color7 : "' . $color_graph_atemp . '", + chartFrom1 : "' . $chartFrom1 . '", + chartTo1 : "' . $chartTo1 . '", + chartFrom2 : "' . $chartFrom2 . '", + chartTo2 : "' . $chartTo2 . '", + startIcon : "' . $startIcon . '", + endIcon : "' . $endIcon . '", + currentIcon : "' . $currentIcon . '", + waypointIcon : "' . $waypointIcon . '", currentpositioncon : "' . $currentpositioncon . '", - usegpsposition : "' . $usegpsposition . '", - zoomOnScrollWheel : "' . $zoomOnScrollWheel . '", - ngGalleries : [' . $ngGalleries . '], - ngImages : [' . $ngImages . '], - pluginUrl : "' . plugins_url() . '", - TFApiKey : "' . get_option( 'wpgpxmaps_openstreetmap_apikey' ) . '", - langs : { altitude : "' . __( 'Altitude', 'wp-gpx-maps' ) . '", - currentPosition : "' . __( 'Current position', 'wp-gpx-maps' ) . '", - speed : "' . __( 'Speed', 'wp-gpx-maps' ) . '", - grade : "' . __( 'Grade', 'wp-gpx-maps' ) . '", - heartRate : "' . __( 'Heart rate', 'wp-gpx-maps' ) . '", - atemp : "' . __( 'Temperature', 'wp-gpx-maps' ) . '", - cadence : "' . __( 'Cadence', 'wp-gpx-maps' ) . '", - goFullScreen : "' . __( 'Go full screen', 'wp-gpx-maps' ) . '", - exitFullFcreen : "' . __( 'Exit full screen', 'wp-gpx-maps' ) . '", - hideImages : "' . __( 'Hide images', 'wp-gpx-maps' ) . '", - showImages : "' . __( 'Show images', 'wp-gpx-maps' ) . '", - backToCenter : "' . __( 'Back to center', 'wp-gpx-maps' ) . '" - } + usegpsposition : "' . $usegpsposition . '", + zoomOnScrollWheel : "' . $zoomOnScrollWheel . '", + ngGalleries : [' . $ngGalleries . '], + ngImages : [' . $ngImages . '], + pluginUrl : "' . plugins_url() . '", + TFApiKey : "' . get_option( 'wpgpxmaps_openstreetmap_apikey' ) . '", + langs : { + altitude : "' . __( 'Altitude', 'wp-gpx-maps' ) . '", + currentPosition : "' . __( 'Current position', 'wp-gpx-maps' ) . '", + speed : "' . __( 'Speed', 'wp-gpx-maps' ) . '", + grade : "' . __( 'Grade', 'wp-gpx-maps' ) . '", + heartRate : "' . __( 'Heart rate', 'wp-gpx-maps' ) . '", + atemp : "' . __( 'Temperature', 'wp-gpx-maps' ) . '", + cadence : "' . __( 'Cadence', 'wp-gpx-maps' ) . '", + goFullScreen : "' . __( 'Go full screen', 'wp-gpx-maps' ) . '", + exitFullFcreen : "' . __( 'Exit full screen', 'wp-gpx-maps' ) . '", + hideImages : "' . __( 'Hide images', 'wp-gpx-maps' ) . '", + showImages : "' . __( 'Show images', 'wp-gpx-maps' ) . '", + backToCenter : "' . __( 'Back to center', 'wp-gpx-maps' ) . '" + } }); }); @@ -769,43 +713,43 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { '; /* Print summary */ - if ( $summary == 'true' && ( $points_graph_speed != '' || $points_graph_ele != '' || $points_graph_dist != '') ) { + if ( $summary == true && ( $points_graph_speed != '' || $points_graph_ele != '' || $points_graph_dist != '' ) ) { $output .= "
    "; - if ( $points_graph_dist != '' && $p_tot_len == 'true' ) { - $output .= "" . __( 'Total distance', 'wp-gpx-maps' ) . ": $tot_len
    "; + if ( $points_graph_dist != '' && $p_tot_len == true ) { + $output .= "" . __( 'Total distance:', 'wp-gpx-maps' ) . " $tot_len
    "; } if ( $points_graph_ele != ' ' ) { - if ( $p_max_ele == 'true' ) - $output .= "" . __( 'Max elevation', 'wp-gpx-maps' ) . ": $max_ele
    "; - if ( $p_min_ele == 'true' ) - $output .= "" . __( 'Min elevation', 'wp-gpx-maps' ) . ": $min_ele
    "; - if ( $p_total_ele_up == 'true' ) - $output .= "" . __( 'Total climbing', 'wp-gpx-maps' ) . ": $total_ele_up
    "; - if ( $p_total_ele_down == 'true' ) - $output .= "" . __( 'Total descent', 'wp-gpx-maps' ) . ": $total_ele_down
    "; + if ( $p_max_ele == true ) + $output .= "" . __( 'Max elevation:', 'wp-gpx-maps' ) . " $max_ele
    "; + if ( $p_min_ele == true ) + $output .= "" . __( 'Min elevation:', 'wp-gpx-maps' ) . " $min_ele
    "; + if ( $p_total_ele_up == true ) + $output .= "" . __( 'Total climbing:', 'wp-gpx-maps' ) . " $total_ele_up
    "; + if ( $p_total_ele_down == true ) + $output .= "" . __( 'Total descent:', 'wp-gpx-maps' ) . " $total_ele_down
    "; } - if ( $points_graph_speed != '' && $p_avg_speed == 'true' ) { - $output .= "" . __( 'Average speed', 'wp-gpx-maps' ) . ": $avg_speed
    "; + if ( $points_graph_speed != '' && $p_avg_speed == true ) { + $output .= "" . __( 'Average speed:', 'wp-gpx-maps' ) . " $avg_speed
    "; } - if ( $points_graph_cad != '' && $p_avg_cad == 'true' ) { - $output .= "" . __( 'Average cadence', 'wp-gpx-maps' ) . ": $avg_cad
    "; + if ( $points_graph_cad != '' && $p_avg_cad == true ) { + $output .= "" . __( 'Average cadence:', 'wp-gpx-maps' ) . " $avg_cad
    "; } - if ( $points_graph_hr != '' && $p_avg_hr == 'true' ) { - $output .= "" . __( 'Average heart rate', 'wp-gpx-maps' ) . ": $avg_hr
    "; + if ( $points_graph_hr != '' && $p_avg_hr == true ) { + $output .= "" . __( 'Average heart rate:', 'wp-gpx-maps' ) . " $avg_hr
    "; } - if ( $points_graph_atemp != '' && $p_avg_temp == 'true' ) { - $output .= "" . __( 'Average temperature', 'wp-gpx-maps' ) . ": $avg_temp
    "; + if ( $points_graph_atemp != '' && $p_avg_temp == true ) { + $output .= "" . __( 'Average temperature:', 'wp-gpx-maps' ) . " $avg_temp
    "; } - if ( $p_total_time == 'true' && $max_time > 0 ) { - $time_diff = date( "H:i:s", ( $max_time - $min_time ) ); - $output .= "" . __( 'Total time', 'wp-gpx-maps' ) . ": $time_diff
    "; + if ( $p_total_time == true && $max_time > 0 ) { + $time_diff = date( 'H:i:s', ( $max_time - $min_time ) ); + $output .= "" . __( 'Total time:', 'wp-gpx-maps' ) . " $time_diff
    "; } - $output .= "
    "; + $output .= '
    '; } /* Print download link */ - if ( $download == 'true' && $gpxurl != '' ) { + if ( $download == true && $gpxurl != '' ) { if ( $isGpxUrl == true ) { } else { @@ -813,25 +757,28 @@ function handle_WP_GPX_Maps_Shortcodes( $attr, $content = '' ) { $dummy = ( defined( 'WP_SITEURL' ) ) ? WP_SITEURL : get_bloginfo( 'url' ); $gpxurl = $dummy . $gpxurl; } - $output .= "" . __( 'Download', 'wp-gpx-maps' ) . ""; + $output .= "" . __( 'Download', 'wp-gpx-maps' ) . ''; } return $output; } function convertSeconds( $s ) { + if ( $s == 0 ) return 0; $s = 1.0 / $s; $_sSecT = $s * 60; // sec/km - $_sMin = floor ( $_sSecT / 60 ); + $_sMin = floor( $_sSecT / 60 ); $_sSec = $_sSecT - $_sMin * 60; return $_sMin + $_sSec / 100; } function convertSpeed( $speed, $uomspeed, $addUom = false ) { + $uom = ''; - if ( $uomspeed == '6' ) { + + if ( $uomspeed == '6' ) { /* min/100 meters */ $speed = 1 / $speed * 100 / 60; $uom = ' min/100m'; @@ -860,6 +807,7 @@ function convertSpeed( $speed, $uomspeed, $addUom = false ) { /* km/h */ $speed *= 3.6; $uom = ' km/h'; + } else { /* dafault m/s */ $uom = ' m/s'; @@ -873,38 +821,31 @@ function convertSpeed( $speed, $uomspeed, $addUom = false ) { } function downloadRemoteFile( $remoteFile ) { + try { $newfname = tempnam( '/tmp', 'gpx' ); - if ( function_exists ( 'file_put_contents' ) ) { + if ( function_exists( 'file_put_contents' ) ) { file_put_contents( $newfname, fopen( $remoteFile, 'r' ) ); return $newfname; } - - $file = fopen ( $remoteFile, 'rb' ); + $file = fopen( $remoteFile, 'rb' ); if ( $file ) { - $newf = fopen ( $newfname, 'wb' ); - + $newf = fopen( $newfname, 'wb' ); if ( $newf ) while ( ! feof( $file ) ) { fwrite( $newf, fread( $file, 1024 * 8 ), 1024 * 8 ); } } - if ( $file ) { fclose( $file ); } - if ( $newf ) { fclose( $newf ); } - return $newfname; - } catch ( Exception $e ) { - print_r( $e ); - return ''; } } @@ -912,7 +853,7 @@ function downloadRemoteFile( $remoteFile ) { function unescape( $value ) { $value = str_replace( "'", "\'", $value ); - $value = str_replace( array( "\n", "\r" ), "", $value ); + $value = str_replace( array( '\n', '\r' ), '', $value ); return $value; } @@ -922,10 +863,22 @@ function WP_GPX_Maps_install() { add_option( 'wpgpxmaps_width', '100%', '', 'yes' ); add_option( 'wpgpxmaps_height', '450px', '', 'yes' ); add_option( 'wpgpxmaps_graph_height', '200px', '', 'yes' ); + add_option( 'wpgpxmaps_distance_type', '0', '', 'yes' ); add_option( 'wpgpxmaps_skipcache', '', '', 'yes' ); add_option( 'wpgpxmaps_download', '', '', 'yes' ); + add_option( 'wpgpxmaps_usegpsposition', '', '', 'yes' ); /* Print Summary Table */ add_option( 'wpgpxmaps_summary', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_tot_len', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_max_ele', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_min_ele', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_total_ele_up', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_total_ele_down', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_avg_speed', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_avg_cad', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_avg_hr', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_avg_temp', '', '', 'yes' ); + add_option( 'wpgpxmaps_summary_total_time', '', '', 'yes' ); /* Map */ add_option( 'wpgpxmaps_map_type', 'HYBRID', '', 'yes' ); add_option( 'wpgpxmaps_map_line_color', '#3366cc', '', 'yes' ); @@ -933,9 +886,11 @@ function WP_GPX_Maps_install() { add_option( 'wpgpxmaps_show_waypoint', '', '', 'yes' ); add_option( 'wpgpxmaps_map_start_icon', '', '', 'yes' ); add_option( 'wpgpxmaps_map_end_icon', '', '', 'yes' ); + add_option( 'wpgpxmaps_currentpositioncon', '', '', 'yes' ); add_option( 'wpgpxmaps_map_current_icon', '', '', 'yes' ); add_option( 'wpgpxmaps_map_waypoint_icon', '', '', 'yes' ); /* Diagram - Elevation */ + add_option( 'wpgpxmaps_show_elevation', 'true', '', 'yes' ); add_option( 'wpgpxmaps_graph_line_color', '#3366cc', '', 'yes' ); add_option( 'wpgpxmaps_unit_of_measure', '0', '', 'yes' ); add_option( 'wpgpxmaps_graph_offset_from1', '', '', 'yes' ); @@ -956,7 +911,8 @@ function WP_GPX_Maps_install() { add_option( 'wpgpxmaps_show_cadence', '', '', 'yes' ); add_option( 'wpgpxmaps_graph_line_color_cad', '#beecff', '', 'yes' ); /* Diagram - Grade */ - + add_option( 'wpgpxmaps_show_grade', '', '', 'yes' ); + add_option( 'wpgpxmaps_graph_line_color_grade', '#beecff', '', 'yes' ); /* Pictures */ add_option( 'wpgpxmaps_map_nggallery', '', '', 'yes' ); /* Advanced */ @@ -970,10 +926,22 @@ function WP_GPX_Maps_remove() { delete_option( 'wpgpxmaps_width' ); delete_option( 'wpgpxmaps_graph_height' ); delete_option( 'wpgpxmaps_height' ); + delete_option( 'wpgpxmaps_distance_type' ); delete_option( 'wpgpxmaps_skipcache' ); delete_option( 'wpgpxmaps_download' ); + delete_option( 'wpgpxmaps_usegpsposition' ); /* Print Summary Table */ delete_option( 'wpgpxmaps_summary' ); + delete_option( 'wpgpxmaps_summary_tot_len' ); + delete_option( 'wpgpxmaps_summary_max_ele' ); + delete_option( 'wpgpxmaps_summary_min_ele' ); + delete_option( 'wpgpxmaps_summary_total_ele_up' ); + delete_option( 'wpgpxmaps_summary_total_ele_down' ); + delete_option( 'wpgpxmaps_summary_avg_speed' ); + delete_option( 'wpgpxmaps_summary_avg_cad' ); + delete_option( 'wpgpxmaps_summary_avg_hr' ); + delete_option( 'wpgpxmaps_summary_avg_temp' ); + delete_option( 'wpgpxmaps_summary_total_time' ); /* Map */ delete_option( 'wpgpxmaps_map_type' ); delete_option( 'wpgpxmaps_map_line_color' ); @@ -981,9 +949,11 @@ function WP_GPX_Maps_remove() { delete_option( 'wpgpxmaps_show_waypoint' ); delete_option( 'wpgpxmaps_map_start_icon' ); delete_option( 'wpgpxmaps_map_end_icon' ); + delete_option( 'wpgpxmaps_currentpositioncon' ); delete_option( 'wpgpxmaps_map_current_icon' ); delete_option( 'wpgpxmaps_map_waypoint_icon' ); /* Diagram - Elevation */ + delete_option( 'wpgpxmaps_show_elevation' ); delete_option( 'wpgpxmaps_graph_line_color' ); delete_option( 'wpgpxmaps_unit_of_measure' ); delete_option( 'wpgpxmaps_graph_offset_from1' ); @@ -1004,12 +974,11 @@ function WP_GPX_Maps_remove() { delete_option( 'wpgpxmaps_show_cadence' ); delete_option( 'wpgpxmaps_graph_line_color_cad' ); /* Diagram - Grade */ - + delete_option( 'wpgpxmaps_show_grade' ); + delete_option( 'wpgpxmaps_graph_line_color_grade' ); /* Pictures */ delete_option( 'wpgpxmaps_map_nggallery' ); /* Advanced */ delete_option( 'wpgpxmaps_pointsoffset' ); delete_option( 'wpgpxmaps_donotreducegpx' ); } - -?> diff --git a/wp-gpx-maps_admin.php b/wp-gpx-maps_admin.php index 52021c9..2e97176 100644 --- a/wp-gpx-maps_admin.php +++ b/wp-gpx-maps_admin.php @@ -1,57 +1,53 @@ __( 'Tracks', 'wp-gpx-maps' ), 'settings' => __( 'Settings', 'wp-gpx-maps' ), 'help' => __( 'Help', 'wp-gpx-maps' ), ); - } elseif ( current_user_can( 'publish_posts' ) ) { + } elseif ( current_user_can( 'publish_posts' ) ) { + /* Access for Editors and Authors */ $tabs = array( 'tracks' => __( 'Tracks', 'wp-gpx-maps' ), 'help' => __( 'Help', 'wp-gpx-maps' ), @@ -61,54 +57,40 @@ function wpgpxmaps_ilc_admin_tabs( $current ) { echo ''; - } - - function WP_GPX_Maps_html_page() { - $realGpxPath = gpxFolderPath(); - - $cacheGpxPath = gpxCacheFolderPath(); - - $relativeGpxPath = relativeGpxFolderPath(); - - $relativeGpxPath = str_replace( "\\","/", $relativeGpxPath ); - + $realGpxPath = gpxFolderPath(); + $cacheGpxPath = gpxCacheFolderPath(); + $relativeGpxPath = relativeGpxFolderPath(); + $relativeGpxPath = str_replace( '\\', '/', $relativeGpxPath ); $relativeGpxCachePath = relativeGpxCacheFolderPath(); - - $relativeGpxCachePath = str_replace( "\\","/", $relativeGpxCachePath ); - - $tab = $_GET['tab']; - + $relativeGpxCachePath = str_replace( '\\', '/', $relativeGpxCachePath ); + $tab = $_GET['tab']; if ( $tab == '' ) $tab = 'tracks'; - ?>

    -

    +

    + +

    '; printf( @@ -119,13 +101,11 @@ function WP_GPX_Maps_html_page() { echo '

    '; } } - if ( file_exists( $cacheGpxPath ) && is_dir( $cacheGpxPath ) ) { /* Directory exist! */ } else { - if ( ! @mkdir( $cacheGpxPath, 0755, true ) ) { echo '

    '; printf( diff --git a/wp-gpx-maps_admin_settings.php b/wp-gpx-maps_admin_settings.php index 5744413..334d974 100644 --- a/wp-gpx-maps_admin_settings.php +++ b/wp-gpx-maps_admin_settings.php @@ -96,9 +96,15 @@ @@ -110,10 +116,7 @@ onchange="this.value = (this.checked)" /> - + @@ -125,10 +128,7 @@ onchange="this.value = (this.checked)" /> - + @@ -140,10 +140,7 @@ onchange="this.value = (this.checked)" /> - + @@ -194,10 +191,7 @@ onchange="this.value = (this.checked)" /> - + @@ -209,10 +203,7 @@ onchange="this.value = (this.checked)" /> - + @@ -224,10 +215,7 @@ onchange="this.value = (this.checked)" /> - + @@ -239,10 +227,7 @@ onchange="this.value = (this.checked)" /> - + @@ -254,10 +239,7 @@ onchange="this.value = (this.checked)" /> - + @@ -269,10 +251,7 @@ onchange="this.value = (this.checked)" /> - + @@ -283,10 +262,7 @@ onchange="this.value = (this.checked)" /> - + @@ -298,10 +274,7 @@ onchange="this.value = (this.checked)" /> - + @@ -313,10 +286,7 @@ onchange="this.value = (this.checked)" /> - + @@ -328,10 +298,7 @@ onchange="this.value = (this.checked)" /> - + @@ -343,10 +310,7 @@ onchange="this.value = (this.checked)" /> - + @@ -379,49 +343,49 @@ >
    >
    >
    >
    >
    >
    >
    >
    @@ -444,10 +408,7 @@ onchange="this.value = (this.checked)" /> - + @@ -459,10 +420,7 @@ onchange="this.value = (this.checked)" /> - + @@ -472,7 +430,7 @@ - + @@ -484,7 +442,7 @@ - + @@ -496,7 +454,7 @@ - + @@ -508,7 +466,7 @@ - + @@ -520,7 +478,7 @@ - + @@ -553,12 +511,9 @@ - onchange="wpgpxmaps_show_elevation.value = this.checked" onload="wpgpxmaps_show_elevation.value = this.checked" /> + onchange="wpgpxmaps_show_elevation.value = this.checked" onload="wpgpxmaps_show_elevation.value = this.checked" /> - + @@ -579,12 +534,42 @@ @@ -595,10 +580,12 @@ - + - - + + + + @@ -607,7 +594,10 @@ - onchange="this.value = (this.checked)" /> + onchange="this.value = (this.checked)" /> + + + @@ -626,13 +616,48 @@ @@ -643,10 +668,12 @@ - + - - + + + + @@ -657,10 +684,7 @@ onchange="this.value = (this.checked)" /> - + @@ -681,10 +705,7 @@ onchange="this.value = (this.checked)" /> - + @@ -705,10 +726,7 @@ onchange="this.value = (this.checked)" /> - + @@ -729,10 +747,7 @@ onchange="this.value = (this.checked)" /> - + @@ -777,10 +792,7 @@ - + @@ -792,10 +804,7 @@ onchange="this.value = (this.checked)" /> - + @@ -805,12 +814,9 @@ - > + /> - + diff --git a/wp-gpx-maps_admin_tracks.php b/wp-gpx-maps_admin_tracks.php index 5e95992..d4fec2d 100644 --- a/wp-gpx-maps_admin_tracks.php +++ b/wp-gpx-maps_admin_tracks.php @@ -8,47 +8,39 @@ $is_admin = current_user_can( 'publish_posts' ); if ( $is_admin != 1 ) return; -$allow_users_upload = get_option( 'wpgpxmaps_allow_users_view' ) === "true"; - -$wpgpxmapsUrl = get_admin_url() . "admin.php?page=WP-GPX-Maps"; - -$gpxRegEx = '/.gpx$/i'; +$allow_users_upload = get_option( 'wpgpxmaps_allow_users_view' ) === 'true'; +$wpgpxmapsUrl = get_admin_url() . 'admin.php?page=WP-GPX-Maps'; +$gpxRegEx = '/.gpx$/i'; if ( current_user_can( 'manage_options' ) ) { - $menu_root = 'options-general.php'; + $menu_root = 'options-general.php'; } elseif ( current_user_can( 'publish_posts' ) ) { - $menu_root = 'admin.php'; + $menu_root = 'admin.php'; } if ( isset( $_POST['clearcache'] ) ) { - - if ( isset( $_GET['_wpnonce'] ) - && - wp_verify_nonce( $_GET['_wpnonce'], 'wpgpx_clearcache_nonce' . $entry ) - ) { + if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'wpgpx_clearcache_nonce' . $entry ) ) { echo '

    '; _e( 'Cache is now empty!', 'wp-gpx-maps' ); echo '

    '; - wpgpxmaps_recursive_remove_directory( $cacheGpxPath, true ); } } if ( is_writable( $realGpxPath ) ) { - ?>
    - '; - ?> + ?>

    '; @@ -57,19 +49,19 @@ if ( is_writable( $realGpxPath ) ) { __( 'The file %1s has been successfully uploaded.', 'wp-gpx-maps' ), '' . esc_html( $uploadingFileName ) . '' ); - echo '

    '; + echo '

    '; + } else { + echo '

    '; + _e( 'There was an error uploading the file, please try again!', 'wp-gpx-maps' ); + echo '

    '; + } } else { - echo '

    '; - _e( 'There was an error uploading the file, please try again!', 'wp-gpx-maps' ); + echo '

    '; + _e( 'The file type is not supported!', 'wp-gpx-maps' ); echo '

    '; } - } else { - echo '

    '; - _e( 'The file type is not supported!', 'wp-gpx-maps' ); - echo '

    '; } } - } ?> @@ -105,21 +97,16 @@ if ( is_writable( $realGpxPath ) ) { $myGpxFileNames = array(); if ( is_readable ( $realGpxPath ) && $handle = opendir( $realGpxPath ) ) { - while ( false !== ( $entry = readdir( $handle ) ) ) { + while ( false !== ( $entry = readdir( $handle ) ) ) { if ( preg_match( $gpxRegEx, $entry ) ) { - - if ( isset($_GET['_wpnonce']) - && - wp_verify_nonce( $_GET['_wpnonce'], 'wpgpx_deletefile_nonce_' . $entry ) - ) { - - if ( file_exists( $realGpxPath . "/" . $entry ) ) { - unlink( $realGpxPath . "/" . $entry ); + if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'wpgpx_deletefile_nonce_' . $entry ) ) { + if ( file_exists( $realGpxPath . '/' . $entry ) ) { + unlink( $realGpxPath . '/' . $entry ); echo '

    '; printf( /* translators: GPX file name */ __( 'The file %1s has been successfully deleted.', 'wp-gpx-maps' ), - '' . esc_html ( $entry ) . '' + '' . esc_html( $entry ) . '' ); echo '

    '; } else { @@ -127,13 +114,12 @@ if ( is_writable( $realGpxPath ) ) { printf( /* translators: GPX file name */ __( 'The file %1s could not be deleted.', 'wp-gpx-maps' ), - '' . esc_html ( $entry ) . '' + '' . esc_html( $entry ) . '' ); - echo '

    '; - + echo '

    '; } } else { - $myFile = $realGpxPath . "/" . $entry; + $myFile = $realGpxPath . '/' . $entry; $myGpxFileNames[] = array( 'name' => $entry, 'size' => filesize( $myFile ), @@ -146,13 +132,13 @@ if ( is_writable( $realGpxPath ) ) { closedir( $handle ); } -if ( is_readable ( $realGpxPath ) && $handle = opendir( $realGpxPath ) ) { - while ( false !== ($entry = readdir( $handle ) ) ) { +if ( is_readable( $realGpxPath ) && $handle = opendir( $realGpxPath ) ) { + while ( false !== ( $entry = readdir( $handle ) ) ) { if ( preg_match( $gpxRegEx, $entry ) ) { - $filenames[] = $realGpxPath . "/" . $entry; + $filenames[] = $realGpxPath . '/' . $entry; } } - closedir( $handle ); + closedir( $handle ); } ?> @@ -237,11 +223,4 @@ if ( is_readable ( $realGpxPath ) && $handle = opendir( $realGpxPath ) ) { }); - - - diff --git a/wp-gpx-maps_help.php b/wp-gpx-maps_help.php index abac852..0067eb0 100644 --- a/wp-gpx-maps_help.php +++ b/wp-gpx-maps_help.php @@ -59,14 +59,15 @@ ?> [sgpx gpx="yourgpxfile.gpx < >"]

    +
    - @@ -104,6 +105,12 @@
    - + +
    +
    + + 100%
    @@ -116,6 +123,12 @@ +
    + + 450px
    @@ -128,6 +141,12 @@ +
    + + 200px
    @@ -173,8 +192,8 @@ - @@ -199,23 +218,56 @@
    - + +
    - HYBRID, ROADMAP, SATELLITE, TERRAIN +
    - OSM1 = +
    - OSM2 = +
    - OSM4 = +
    - OSM5 = +
    - OSM6 = +
    - OSM7 = +
    - OSM9 = +
    - OSM10 = + +
    + + HYBRID
    @@ -317,8 +369,8 @@ - @@ -375,18 +427,41 @@
    - + +
    - 0 = +
    - 1 = +
    - 2 = +
    - 3 = +
    - 4 = +
    - 5 = +
    + + 0
    @@ -450,20 +525,46 @@ - 0 = +
    - 1 = +
    - 2 = +
    - 3 = +
    - 4 = +
    - 5 = +
    - 6 = +
    + + 0
    @@ -624,8 +725,8 @@ - @@ -689,8 +790,8 @@
    - + +
    - @@ -893,8 +994,8 @@
    - + +
    - diff --git a/wp-gpx-maps_utils.php b/wp-gpx-maps_utils.php index 5f12587..95959a5 100644 --- a/wp-gpx-maps_utils.php +++ b/wp-gpx-maps_utils.php @@ -18,7 +18,8 @@ function wpgpxmaps_getAttachedImages( $dt, $lat, $lon, $dtoffset, &$error ) { 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ASC', - )); + ) + ); foreach ( $attachments as $attachment_id => $attachment ) { @@ -27,27 +28,27 @@ function wpgpxmaps_getAttachedImages( $dt, $lat, $lon, $dtoffset, &$error ) { $img_metadata = wp_get_attachment_metadata( $attachment_id ); $item = array(); - $item["data"] = wp_get_attachment_link( $attachment_id, array( 105, 105 ) ); + $item['data'] = wp_get_attachment_link( $attachment_id, array( 105, 105 ) ); if ( is_callable( 'exif_read_data' ) ) { $exif = @exif_read_data( $img_src[0] ); if ( $exif !== false ) { - $item["lon"] = getExifGps( $exif["GPSLongitude"], $exif['GPSLongitudeRef'] ); - $item["lat"] = getExifGps( $exif["GPSLatitude"], $exif['GPSLatitudeRef'] ); - if ( ( $item["lat"] != 0 ) || ( $item["lon"] != 0 ) ) { - $result[] = $item; - } elseif ( isset( $p->imagedate ) ) { - $_dt = strtotime( $p->imagedate ) + $dtoffset; - $_item = findItemCoordinate( $_dt, $dt, $lat, $lon ); + $item['lon'] = getExifGps( $exif['GPSLongitude'], $exif['GPSLongitudeRef'] ); + $item['lat'] = getExifGps( $exif['GPSLatitude'], $exif['GPSLatitudeRef'] ); + if ( ( $item['lat'] != 0 ) || ( $item['lon'] != 0 ) ) { + $result[] = $item; + } elseif ( isset( $p->imagedate ) ) { + $_dt = strtotime( $p->imagedate ) + $dtoffset; + $_item = findItemCoordinate( $_dt, $dt, $lat, $lon ); if ( $_item != null ) { - $item["lat"] = $_item["lat"]; - $item["lon"] = $_item["lon"]; + $item['lat'] = $_item['lat']; + $item['lon'] = $_item['lon']; $result[] = $item; } } } } else { - $error .= "Sorry, exif_read_data function not found! check your hosting..
    "; + $error .= "Sorry, exif_read_data function not found! check your hosting.
    "; } } } catch ( Exception $e ) { @@ -106,8 +107,7 @@ function relativeGpxCacheFolderPath() { function wpgpxmaps_recursive_remove_directory( $directory, $empty = false ) { - if ( substr( $directory, -1 ) == '/' ) - { + if ( substr( $directory, -1 ) == '/' ) { $directory = substr( $directory, 0, -1 ); } if ( ! file_exists( $directory ) || ! is_dir( $directory ) ) { @@ -262,31 +262,31 @@ function wpgpxmaps_parseXml( $filePath, $gpxOffset, $distancetype ) { } } - if ( $lastLat == 0 && $lastLon == 0 ) { + if ( $lastLat == 0 && $lastLon == 0 ) { - /* Base Case */ - array_push( $points->dt, strtotime( $time ) ); - array_push( $points->lat, (float) $lat ); - array_push( $points->lon, (float) $lon ); - array_push( $points->ele, (float) round( $ele, 2 ) ); - array_push( $points->dist, (float) round( $dist, 2 ) ); - array_push( $points->speed, 0 ); - array_push( $points->hr, (float) $hr ); - array_push( $points->atemp, (float) $atemp ); - array_push( $points->cad, (float) $cad ); - array_push( $points->grade, $grade ); + /* Base Case */ + array_push( $points->dt, strtotime( $time ) ); + array_push( $points->lat, (float) $lat ); + array_push( $points->lon, (float) $lon ); + array_push( $points->ele, (float) round( $ele, 2 ) ); + array_push( $points->dist, (float) round( $dist, 2 ) ); + array_push( $points->speed, 0 ); + array_push( $points->hr, (float) $hr ); + array_push( $points->atemp, (float) $atemp ); + array_push( $points->cad, (float) $cad ); + array_push( $points->grade, $grade ); - $lastLat = $lat; - $lastLon = $lon; - $lastEle = $ele; - $lastTime = $time; + $lastLat = $lat; + $lastLon = $lon; + $lastEle = $ele; + $lastTime = $time; } else { - /* Normal Case */ - $offset = calculateDistance( (float) $lat, (float) $lon, (float) $ele, (float) $lastLat, (float) $lastLon, (float) $lastEle, $distancetype ); - $dist = $dist + $offset; + /* Normal Case */ + $offset = calculateDistance( (float) $lat, (float) $lon, (float) $ele, (float) $lastLat, (float) $lastLon, (float) $lastEle, $distancetype ); + $dist = $dist + $offset; - $points->totalLength = $dist; + $points->totalLength = $dist; if ( $speed == 0 ) { $datediff = (float) my_date_diff( $lastTime, $time ); @@ -295,8 +295,8 @@ function wpgpxmaps_parseXml( $filePath, $gpxOffset, $distancetype ) { } } - if ( $ele != 0 && $lastEle != 0 ) { - $deltaEle = (float) ( $ele - $lastEle ); + if ( $ele != 0 && $lastEle != 0 ) { + $deltaEle = (float) ( $ele - $lastEle ); if ( (float) $ele > (float) $lastEle ) { $points->totalEleUp += $deltaEle; @@ -306,98 +306,92 @@ function wpgpxmaps_parseXml( $filePath, $gpxOffset, $distancetype ) { $grade = $deltaEle / $offset * 100; } - array_push( $speedBuffer, $speed ); + array_push( $speedBuffer, $speed ); - if ( ( (float) $offset + (float) $lastOffset ) > $gpxOffset ) { - /* Bigger Offset -> write coordinate */ - $avgSpeed = 0; + if ( ( (float) $offset + (float) $lastOffset ) > $gpxOffset ) { + /* Bigger Offset -> write coordinate */ + $avgSpeed = 0; foreach ( $speedBuffer as $s ) { - $avgSpeed += $s; + $avgSpeed += $s; } - $avgSpeed = $avgSpeed / count( $speedBuffer ); - $speedBuffer = array(); + $avgSpeed = $avgSpeed / count( $speedBuffer ); + $speedBuffer = array(); - $lastOffset = 0; - - array_push( $points->dt, strtotime( $time ) ); - array_push( $points->lat, (float) $lat ); - array_push( $points->lon, (float) $lon ); - array_push( $points->ele, (float) round( $ele, 2 ) ); - array_push( $points->dist, (float) round( $dist, 2 ) ); - array_push( $points->speed, (float) round( $avgSpeed, 1 ) ); - array_push( $points->hr, $hr ); - array_push( $points->atemp, $atemp ); - array_push( $points->cad, $cad ); - array_push( $points->grade, (float) round( $grade, 2 ) ); + $lastOffset = 0; + array_push( $points->dt, strtotime( $time ) ); + array_push( $points->lat, (float) $lat ); + array_push( $points->lon, (float) $lon ); + array_push( $points->ele, (float) round( $ele, 2 ) ); + array_push( $points->dist, (float) round( $dist, 2 ) ); + array_push( $points->speed, (float) round( $avgSpeed, 1 ) ); + array_push( $points->hr, $hr ); + array_push( $points->atemp, $atemp ); + array_push( $points->cad, $cad ); + array_push( $points->grade, (float) round( $grade, 2 ) ); } else { - /* Smoller Offset -> continue.. */ - $lastOffset = (float) $lastOffset + (float) $offset; + /* Smoller Offset -> continue.. */ + $lastOffset = (float) $lastOffset + (float) $offset; } } - $lastLat = $lat; - $lastLon = $lon; - $lastEle = $ele; - $lastTime = $time; - + $lastLat = $lat; + $lastLon = $lon; + $lastEle = $ele; + $lastTime = $time; } + array_push( $points->dt, null ); + array_push( $points->lat, null ); + array_push( $points->lon, null ); + array_push( $points->ele, null ); + array_push( $points->dist, null ); + array_push( $points->speed, null ); + array_push( $points->hr, null ); + array_push( $points->atemp, null ); + array_push( $points->cad, null ); + array_push( $points->grade, null ); - array_push( $points->dt, null ); - array_push( $points->lat, null ); - array_push( $points->lon, null ); - array_push( $points->ele, null ); - array_push( $points->dist, null ); - array_push( $points->speed, null ); - array_push( $points->hr, null ); - array_push( $points->atemp, null ); - array_push( $points->cad, null ); - array_push( $points->grade, null ); - - unset( $trkpts ); - + unset( $trkpts ); } - - unset( $nodes ); + unset( $nodes ); try { + array_pop( $points->dt, null ); + array_pop( $points->lat, null ); + array_pop( $points->lon, null ); + array_pop( $points->ele, null ); + array_pop( $points->dist, null ); + array_pop( $points->speed, null ); + array_pop( $points->hr, null ); + array_pop( $points->atemp, null ); + array_pop( $points->cad, null ); + array_pop( $points->grade, null ); - array_pop( $points->dt, null ); - array_pop( $points->lat, null ); - array_pop( $points->lon, null ); - array_pop( $points->ele, null ); - array_pop( $points->dist, null ); - array_pop( $points->speed, null ); - array_pop( $points->hr, null ); - array_pop( $points->atemp, null ); - array_pop( $points->cad, null ); - array_pop( $points->grade, null ); + $_time = array_filter( $points->dt ); + $_ele = array_filter( $points->ele ); + $_dist = array_filter( $points->dist ); + $points->maxEle = max( $_ele ); + $points->minEle = min( $_ele ); + $points->totalLength = max( $_dist ); + $points->maxTime = max( $_time ); + $points->minTime = min( $_time ); - $_time = array_filter( $points->dt ); - $_ele = array_filter( $points->ele ); - $_dist = array_filter( $points->dist ); - $points->maxEle = max( $_ele ); - $points->minEle = min( $_ele ); - $points->totalLength = max( $_dist ); - $points->maxTime = max( $_time ); - $points->minTime = min( $_time ); + /* Calculating Average Speed */ + $_speed = array_filter( $points->speed ); + $points->avgSpeed = array_sum( $_speed ) / count( $_speed ); - /* Calculating Average Speed */ - $_speed = array_filter( $points->speed ); - $points->avgSpeed = array_sum( $_speed ) / count( $_speed ); + /* Calculating Average Cadence */ + $_cad = array_filter( $points->cad ); + $points->avgCad = (float) round( array_sum( $_cad ) / count( $_cad ), 0 ); - /* Calculating Average Cadence */ - $_cad = array_filter( $points->cad ); - $points->avgCad = (float) round( array_sum( $_cad ) / count( $_cad ), 0 ); + /* Calculating Average Heart Rate */ + $_hr = array_filter( $points->hr ); + $points->avgHr = (float) round( array_sum( $_hr ) / count( $_hr ), 0 ); - /* Calculating Average Heart Rate */ - $_hr = array_filter( $points->hr ); - $points->avgHr = (float) round( array_sum( $_hr ) / count( $_hr ), 0 ); - - /* Calculating Average Temperature */ - $_temp = array_filter( $points->atemp ); - $points->avgTemp = (float) round( array_sum( $_temp ) / count( $_temp ), 1 ); + /* Calculating Average Temperature */ + $_temp = array_filter( $points->atemp ); + $points->avgTemp = (float) round( array_sum( $_temp ) / count( $_temp ), 1 ); } catch ( Exception $e ) { } @@ -568,15 +562,15 @@ function wpgpxmaps_getWayPoints( $gpxPath ) { } array_push($points, array( - "lat" => (float) $lat, - "lon" => (float) $lon, - "ele" => (float) $ele, - "time" => $time, - "name" => $name, - "desc" => $desc, - "sym" => $sym, - "type" => $type, - "img" => $img, + 'lat' => (float) $lat, + 'lon' => (float) $lon, + 'ele' => (float) $ele, + 'time' => $time, + 'name' => $name, + 'desc' => $desc, + 'sym' => $sym, + 'type' => $type, + 'img' => $img, )); } } @@ -638,4 +632,3 @@ function date_getDecimals( $date ) { return 0; } } -?> diff --git a/wp-gpx-maps_utils_nggallery.php b/wp-gpx-maps_utils_nggallery.php index b4ad7e6..c18bd4b 100644 --- a/wp-gpx-maps_utils_nggallery.php +++ b/wp-gpx-maps_utils_nggallery.php @@ -54,7 +54,7 @@ function getNGGalleryImages( $ngGalleries, $ngImages, $dt, $lat, $lon, $dtoffset } } } else { - $error .= "Sorry, exif_read_data function not found! check your hosting..
    "; + $error .= "Sorry, exif_read_data function not found! check your hosting.
    "; } } /* START FIX NEXT GEN GALLERY 2.x */ @@ -72,7 +72,7 @@ function getNGGalleryImages( $ngGalleries, $ngImages, $dt, $lat, $lon, $dtoffset if ( preg_match( "/data-nplmodal-gallery-id=[\"'](.*?)[\"']/", $dummy, $m ) ) { $galid = $m[1]; if ( $galid ) { - for( $i = 0; $i < count( $result ); ++$i ) { + for ( $i = 0; $i < count( $result ); ++$i ) { $result[$i]['data'] = str_replace( '%PRO_LIGHTBOX_GALLERY_ID%', $galid, $result[$i]['data'] ); } } @@ -90,9 +90,12 @@ function getNGGalleryImages( $ngGalleries, $ngImages, $dt, $lat, $lon, $dtoffset function findItemCoordinate( $imgdt, $dt, $lat, $lon ) { foreach ( array_keys( $dt ) as $i ) { - if ( $i!=0 && $imgdt >= $dt[$i-1] && $imgdt <= $dt[$i] ) { + if ( $i != 0 && $imgdt >= $dt[$i - 1] && $imgdt <= $dt[$i] ) { if ( $lat[$i] != 0 && $lon[$i] != 0 ) - return array( 'lat' => $lat[$i], 'lon' => $lon[$i] ); + return array( + 'lat' => $lat[$i], + 'lon' => $lon[$i], + ); } } return null; @@ -105,7 +108,7 @@ function getExifGps( $exifCoord, $hemi ) { $seconds = count( $exifCoord ) > 2 ? gps2Num( $exifCoord[2] ) : 0; $flip = ( $hemi == 'W' or $hemi == 'S' ) ? -1 : 1; - return $flip * ( $degrees + $minutes / 60 + $seconds / 3600); + return $flip * ( $degrees + $minutes / 60 + $seconds / 3600 ); } function gps2Num( $coordPart ) { @@ -121,8 +124,7 @@ function gps2Num( $coordPart ) { $lat = floatval( $parts[0] ); $lon = floatval( $parts[1] ); - if ($lon == 0 ) + if ($lon == 0 ) return $lat; return $lat / $lon; } -?>
    - + +