From 3308c7029995ed88291b9b136a76791576bafed8 Mon Sep 17 00:00:00 2001 From: bastianonm Date: Tue, 2 Jul 2019 06:39:27 +0000 Subject: [PATCH] code reorganization --- css/admin-style.css | 36 +- css/bootstrap-table.css | 337 ++++ css/output-style.css | 65 + js/WP-GPX-Maps.js | 2 +- js/bootstrap-table.js | 3223 +++++++++++++++++++++++++++++++ js/mColorPicker_min.js | 22 +- readme.txt | 31 +- wp-gpx-maps.php | 363 ++-- wp-gpx-maps_admin.php | 88 +- wp-gpx-maps_admin_settings.php | 274 +-- wp-gpx-maps_admin_tracks.php | 79 +- wp-gpx-maps_help.php | 169 +- wp-gpx-maps_utils.php | 229 ++- wp-gpx-maps_utils_nggallery.php | 16 +- 14 files changed, 4310 insertions(+), 624 deletions(-) create mode 100644 css/bootstrap-table.css create mode 100644 css/output-style.css create mode 100644 js/bootstrap-table.js 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; } -?>
    - + +