bootstrap-table-cookie.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /**
  2. * @author: Dennis Hernández
  3. * @webSite: http://djhvscf.github.io/Blog
  4. * @update zhixin wen <wenzhixin2010@gmail.com>
  5. */
  6. const Utils = $.fn.bootstrapTable.utils
  7. const UtilsCookie = {
  8. cookieIds: {
  9. sortOrder: 'bs.table.sortOrder',
  10. sortName: 'bs.table.sortName',
  11. sortPriority: 'bs.table.sortPriority',
  12. pageNumber: 'bs.table.pageNumber',
  13. pageList: 'bs.table.pageList',
  14. columns: 'bs.table.columns',
  15. cardView: 'bs.table.cardView',
  16. searchText: 'bs.table.searchText',
  17. reorderColumns: 'bs.table.reorderColumns',
  18. filterControl: 'bs.table.filterControl',
  19. filterBy: 'bs.table.filterBy'
  20. },
  21. getCurrentHeader (that) {
  22. return that.options.height ? that.$tableHeader : that.$header
  23. },
  24. getCurrentSearchControls (that) {
  25. return that.options.height ? 'table select, table input' : 'select, input'
  26. },
  27. isCookieSupportedByBrowser () {
  28. return navigator.cookieEnabled
  29. },
  30. isCookieEnabled (that, cookieName) {
  31. return that.options.cookiesEnabled.includes(cookieName)
  32. },
  33. setCookie (that, cookieName, cookieValue) {
  34. if (
  35. !that.options.cookie ||
  36. !UtilsCookie.isCookieEnabled(that, cookieName)
  37. ) {
  38. return
  39. }
  40. return that._storage.setItem(`${that.options.cookieIdTable}.${cookieName}`, cookieValue)
  41. },
  42. getCookie (that, cookieName) {
  43. if (
  44. !cookieName ||
  45. !UtilsCookie.isCookieEnabled(that, cookieName)
  46. ) {
  47. return null
  48. }
  49. return that._storage.getItem(`${that.options.cookieIdTable}.${cookieName}`)
  50. },
  51. deleteCookie (that, cookieName) {
  52. return that._storage.removeItem(`${that.options.cookieIdTable}.${cookieName}`)
  53. },
  54. calculateExpiration (cookieExpire) {
  55. const time = cookieExpire.replace(/[0-9]*/, '') // s,mi,h,d,m,y
  56. cookieExpire = cookieExpire.replace(/[A-Za-z]{1,2}/, '') // number
  57. switch (time.toLowerCase()) {
  58. case 's':
  59. cookieExpire = +cookieExpire
  60. break
  61. case 'mi':
  62. cookieExpire *= 60
  63. break
  64. case 'h':
  65. cookieExpire = cookieExpire * 60 * 60
  66. break
  67. case 'd':
  68. cookieExpire = cookieExpire * 24 * 60 * 60
  69. break
  70. case 'm':
  71. cookieExpire = cookieExpire * 30 * 24 * 60 * 60
  72. break
  73. case 'y':
  74. cookieExpire = cookieExpire * 365 * 24 * 60 * 60
  75. break
  76. default:
  77. cookieExpire = undefined
  78. break
  79. }
  80. if (!cookieExpire) {
  81. return ''
  82. }
  83. const d = new Date()
  84. d.setTime(d.getTime() + cookieExpire * 1000)
  85. return d.toGMTString()
  86. },
  87. initCookieFilters (bootstrapTable) {
  88. setTimeout(() => {
  89. const parsedCookieFilters = JSON.parse(
  90. UtilsCookie.getCookie(bootstrapTable, UtilsCookie.cookieIds.filterControl))
  91. if (!bootstrapTable._filterControlValuesLoaded && parsedCookieFilters) {
  92. const cachedFilters = {}
  93. const header = UtilsCookie.getCurrentHeader(bootstrapTable)
  94. const searchControls = UtilsCookie.getCurrentSearchControls(bootstrapTable)
  95. const applyCookieFilters = (element, filteredCookies) => {
  96. filteredCookies.forEach(cookie => {
  97. const value = element.value.toString()
  98. const text = cookie.text
  99. if (
  100. text === '' ||
  101. element.type === 'radio' &&
  102. value !== text
  103. ) {
  104. return
  105. }
  106. if (
  107. element.tagName === 'INPUT' &&
  108. element.type === 'radio' &&
  109. value === text
  110. ) {
  111. element.checked = true
  112. cachedFilters[cookie.field] = text
  113. } else if (element.tagName === 'INPUT') {
  114. element.value = text
  115. cachedFilters[cookie.field] = text
  116. } else if (
  117. element.tagName === 'SELECT' &&
  118. bootstrapTable.options.filterControlContainer
  119. ) {
  120. element.value = text
  121. cachedFilters[cookie.field] = text
  122. } else if (text !== '' && element.tagName === 'SELECT') {
  123. cachedFilters[cookie.field] = text
  124. for (const currentElement of element) {
  125. if (currentElement.value === text) {
  126. currentElement.selected = true
  127. return
  128. }
  129. }
  130. const option = document.createElement('option')
  131. option.value = text
  132. option.text = text
  133. element.add(option, element[1])
  134. element.selectedIndex = 1
  135. }
  136. })
  137. }
  138. let filterContainer = header
  139. if (bootstrapTable.options.filterControlContainer) {
  140. filterContainer = $(`${bootstrapTable.options.filterControlContainer}`)
  141. }
  142. filterContainer.find(searchControls).each(function () {
  143. const field = $(this).closest('[data-field]').data('field')
  144. const filteredCookies = parsedCookieFilters.filter(cookie => cookie.field === field)
  145. applyCookieFilters(this, filteredCookies)
  146. })
  147. bootstrapTable.initColumnSearch(cachedFilters)
  148. bootstrapTable._filterControlValuesLoaded = true
  149. bootstrapTable.initServer()
  150. }
  151. }, 250)
  152. }
  153. }
  154. $.extend($.fn.bootstrapTable.defaults, {
  155. cookie: false,
  156. cookieExpire: '2h',
  157. cookiePath: null,
  158. cookieDomain: null,
  159. cookieSecure: null,
  160. cookieSameSite: 'Lax',
  161. cookieIdTable: '',
  162. cookiesEnabled: [
  163. 'bs.table.sortOrder', 'bs.table.sortName', 'bs.table.sortPriority',
  164. 'bs.table.pageNumber', 'bs.table.pageList',
  165. 'bs.table.columns', 'bs.table.searchText',
  166. 'bs.table.filterControl', 'bs.table.filterBy',
  167. 'bs.table.reorderColumns', 'bs.table.cardView'
  168. ],
  169. cookieStorage: 'cookieStorage', // localStorage, sessionStorage, customStorage
  170. cookieCustomStorageGet: null,
  171. cookieCustomStorageSet: null,
  172. cookieCustomStorageDelete: null,
  173. // internal variable
  174. _filterControls: [],
  175. _filterControlValuesLoaded: false,
  176. _storage: {
  177. setItem: undefined,
  178. getItem: undefined,
  179. removeItem: undefined
  180. }
  181. })
  182. $.fn.bootstrapTable.methods.push('getCookies')
  183. $.fn.bootstrapTable.methods.push('deleteCookie')
  184. $.extend($.fn.bootstrapTable.utils, {
  185. setCookie: UtilsCookie.setCookie,
  186. getCookie: UtilsCookie.getCookie
  187. })
  188. $.BootstrapTable = class extends $.BootstrapTable {
  189. init () {
  190. if (this.options.cookie) {
  191. if (this.options.cookieStorage === 'cookieStorage' && !UtilsCookie.isCookieSupportedByBrowser()) {
  192. throw new Error('Cookies are not enabled in this browser.')
  193. }
  194. this.configureStorage()
  195. // FilterBy logic
  196. const filterByCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterBy)
  197. if (typeof filterByCookieValue === 'boolean' && !filterByCookieValue) {
  198. throw new Error('The cookie value of filterBy must be a json!')
  199. }
  200. let filterByCookie = {}
  201. try {
  202. filterByCookie = JSON.parse(filterByCookieValue)
  203. } catch (e) {
  204. throw new Error('Could not parse the json of the filterBy cookie!')
  205. }
  206. this.filterColumns = filterByCookie ? filterByCookie : {}
  207. // FilterControl logic
  208. this._filterControls = []
  209. this._filterControlValuesLoaded = false
  210. this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ?
  211. this.options.cookiesEnabled.replace('[', '').replace(']', '')
  212. .replace(/'/g, '').replace(/ /g, '').toLowerCase().split(',') :
  213. this.options.cookiesEnabled
  214. if (this.options.filterControl) {
  215. const that = this
  216. this.$el.on('column-search.bs.table', (e, field, text) => {
  217. let isNewField = true
  218. for (let i = 0; i < that._filterControls.length; i++) {
  219. if (that._filterControls[i].field === field) {
  220. that._filterControls[i].text = text
  221. isNewField = false
  222. break
  223. }
  224. }
  225. if (isNewField) {
  226. that._filterControls.push({
  227. field,
  228. text
  229. })
  230. }
  231. UtilsCookie.setCookie(that, UtilsCookie.cookieIds.filterControl, JSON.stringify(that._filterControls))
  232. }).on('created-controls.bs.table', UtilsCookie.initCookieFilters(that))
  233. }
  234. }
  235. super.init()
  236. }
  237. initServer (...args) {
  238. if (
  239. this.options.cookie &&
  240. this.options.filterControl &&
  241. !this._filterControlValuesLoaded
  242. ) {
  243. const cookie = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.filterControl))
  244. if (cookie) {
  245. return
  246. }
  247. }
  248. super.initServer(...args)
  249. }
  250. initTable (...args) {
  251. super.initTable(...args)
  252. this.initCookie()
  253. }
  254. onSort (...args) {
  255. super.onSort(...args)
  256. if (!this.options.cookie) {
  257. return
  258. }
  259. if (this.options.sortName === undefined || this.options.sortOrder === undefined) {
  260. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
  261. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
  262. } else {
  263. this.options.sortPriority = null
  264. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
  265. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortOrder, this.options.sortOrder)
  266. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortName, this.options.sortName)
  267. }
  268. }
  269. onMultipleSort (...args) {
  270. super.onMultipleSort(...args)
  271. if (!this.options.cookie) {
  272. return
  273. }
  274. if (this.options.sortPriority === undefined) {
  275. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortPriority)
  276. } else {
  277. this.options.sortName = undefined
  278. this.options.sortOrder = undefined
  279. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortName)
  280. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds.sortOrder)
  281. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.sortPriority, JSON.stringify(this.options.sortPriority))
  282. }
  283. }
  284. onPageNumber (...args) {
  285. super.onPageNumber(...args)
  286. if (!this.options.cookie) {
  287. return
  288. }
  289. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  290. }
  291. onPageListChange (...args) {
  292. super.onPageListChange(...args)
  293. if (!this.options.cookie) {
  294. return
  295. }
  296. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageList, this.options.pageSize)
  297. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  298. }
  299. onPagePre (...args) {
  300. super.onPagePre(...args)
  301. if (!this.options.cookie) {
  302. return
  303. }
  304. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  305. }
  306. onPageNext (...args) {
  307. super.onPageNext(...args)
  308. if (!this.options.cookie) {
  309. return
  310. }
  311. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  312. }
  313. _toggleColumn (...args) {
  314. super._toggleColumn(...args)
  315. if (!this.options.cookie) {
  316. return
  317. }
  318. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(this.getVisibleColumns().map(column => column.field)))
  319. }
  320. _toggleAllColumns (...args) {
  321. super._toggleAllColumns(...args)
  322. if (!this.options.cookie) {
  323. return
  324. }
  325. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.columns, JSON.stringify(this.getVisibleColumns().map(column => column.field)))
  326. }
  327. toggleView () {
  328. super.toggleView()
  329. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.cardView, this.options.cardView)
  330. }
  331. selectPage (page) {
  332. super.selectPage(page)
  333. if (!this.options.cookie) {
  334. return
  335. }
  336. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, page)
  337. }
  338. onSearch (event) {
  339. super.onSearch(event, arguments.length > 1 ? arguments[1] : true)
  340. if (!this.options.cookie) {
  341. return
  342. }
  343. if (this.options.search) {
  344. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.searchText, this.searchText)
  345. }
  346. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.pageNumber, this.options.pageNumber)
  347. }
  348. initHeader (...args) {
  349. if (this.options.reorderableColumns && this.options.cookie) {
  350. this.columnsSortOrder = JSON.parse(UtilsCookie.getCookie(this, UtilsCookie.cookieIds.reorderColumns))
  351. }
  352. super.initHeader(...args)
  353. }
  354. persistReorderColumnsState (that) {
  355. UtilsCookie.setCookie(that, UtilsCookie.cookieIds.reorderColumns, JSON.stringify(that.columnsSortOrder))
  356. }
  357. filterBy (...args) {
  358. super.filterBy(...args)
  359. if (!this.options.cookie) {
  360. return
  361. }
  362. UtilsCookie.setCookie(this, UtilsCookie.cookieIds.filterBy, JSON.stringify(this.filterColumns))
  363. }
  364. initCookie () {
  365. if (!this.options.cookie) {
  366. return
  367. }
  368. if ((this.options.cookieIdTable === '') || (this.options.cookieExpire === '')) {
  369. console.error('Configuration error. Please review the cookieIdTable and the cookieExpire property. If the properties are correct, then this browser does not support cookies.')
  370. this.options.cookie = false // Make sure that the cookie extension is disabled
  371. return
  372. }
  373. const sortOrderCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortOrder)
  374. const sortOrderNameCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortName)
  375. let sortPriorityCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.sortPriority)
  376. const pageNumberCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageNumber)
  377. const pageListCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.pageList)
  378. const searchTextCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.searchText)
  379. const cardViewCookie = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.cardView)
  380. const columnsCookieValue = UtilsCookie.getCookie(this, UtilsCookie.cookieIds.columns)
  381. if (typeof columnsCookieValue === 'boolean' && !columnsCookieValue) {
  382. throw new Error('The cookie value of filterBy must be a json!')
  383. }
  384. let columnsCookie = {}
  385. try {
  386. columnsCookie = JSON.parse(columnsCookieValue)
  387. } catch (e) {
  388. throw new Error('Could not parse the json of the columns cookie!', columnsCookieValue)
  389. }
  390. try {
  391. sortPriorityCookie = JSON.parse(sortPriorityCookie)
  392. } catch (e) {
  393. throw new Error('Could not parse the json of the sortPriority cookie!', sortPriorityCookie)
  394. }
  395. if (!sortPriorityCookie) {
  396. // sortOrder
  397. this.options.sortOrder = sortOrderCookie ? sortOrderCookie : this.options.sortOrder
  398. // sortName
  399. this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : this.options.sortName
  400. } else {
  401. this.options.sortOrder = undefined
  402. this.options.sortName = undefined
  403. }
  404. // sortPriority
  405. this.options.sortPriority = sortPriorityCookie ? sortPriorityCookie : this.options.sortPriority
  406. if (this.options.sortOrder || this.options.sortName) {
  407. // sortPriority
  408. this.options.sortPriority = null
  409. }
  410. // pageNumber
  411. this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber
  412. // pageSize
  413. this.options.pageSize = pageListCookie ? pageListCookie === this.options.formatAllRows() ? pageListCookie : +pageListCookie : this.options.pageSize
  414. // searchText
  415. if (UtilsCookie.isCookieEnabled(this, 'bs.table.searchText') && this.options.searchText === '') {
  416. this.options.searchText = searchTextCookie ? searchTextCookie : ''
  417. }
  418. // cardView
  419. this.options.cardView = cardViewCookie === 'true' ? cardViewCookie : false
  420. if (columnsCookie) {
  421. for (const column of this.columns) {
  422. if (!column.switchable) {
  423. continue
  424. }
  425. column.visible = columnsCookie.filter(columnField => {
  426. if (this.isSelectionColumn(column)) {
  427. return true
  428. }
  429. /**
  430. * This is needed for the old saved cookies or the table will show no columns!
  431. * It can be removed in 2-3 Versions Later!!
  432. * TODO: Remove this part some versions later e.g. 1.17.3
  433. */
  434. if (columnField instanceof Object) {
  435. return columnField.field === column.field
  436. }
  437. return columnField === column.field
  438. }).length > 0
  439. }
  440. }
  441. }
  442. getCookies () {
  443. const bootstrapTable = this
  444. const cookies = {}
  445. $.each(UtilsCookie.cookieIds, (key, value) => {
  446. cookies[key] = UtilsCookie.getCookie(bootstrapTable, value)
  447. if (key === 'columns') {
  448. cookies[key] = JSON.parse(cookies[key])
  449. }
  450. })
  451. return cookies
  452. }
  453. deleteCookie (cookieName) {
  454. if (!cookieName) {
  455. return
  456. }
  457. UtilsCookie.deleteCookie(this, UtilsCookie.cookieIds[cookieName])
  458. }
  459. configureStorage () {
  460. const that = this
  461. this._storage = {}
  462. switch (this.options.cookieStorage) {
  463. case 'cookieStorage':
  464. this._storage.setItem = function (cookieName, cookieValue) {
  465. document.cookie = [
  466. cookieName, '=', encodeURIComponent(cookieValue),
  467. `; expires=${UtilsCookie.calculateExpiration(that.options.cookieExpire)}`,
  468. that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
  469. that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
  470. that.options.cookieSecure ? '; secure' : '',
  471. `;SameSite=${ that.options.cookieSameSite}`
  472. ].join('')
  473. }
  474. this._storage.getItem = function (cookieName) {
  475. const value = `; ${document.cookie}`
  476. const parts = value.split(`; ${cookieName}=`)
  477. return parts.length === 2 ? decodeURIComponent(parts.pop().split(';').shift()) : null
  478. }
  479. this._storage.removeItem = function (cookieName) {
  480. document.cookie = [
  481. encodeURIComponent(cookieName), '=',
  482. '; expires=Thu, 01 Jan 1970 00:00:00 GMT',
  483. that.options.cookiePath ? `; path=${that.options.cookiePath}` : '',
  484. that.options.cookieDomain ? `; domain=${that.options.cookieDomain}` : '',
  485. `;SameSite=${ that.options.cookieSameSite}`
  486. ].join('')
  487. }
  488. break
  489. case 'localStorage':
  490. this._storage.setItem = function (cookieName, cookieValue) {
  491. localStorage.setItem(cookieName, cookieValue)
  492. }
  493. this._storage.getItem = function (cookieName) {
  494. return localStorage.getItem(cookieName)
  495. }
  496. this._storage.removeItem = function (cookieName) {
  497. localStorage.removeItem(cookieName)
  498. }
  499. break
  500. case 'sessionStorage':
  501. this._storage.setItem = function (cookieName, cookieValue) {
  502. sessionStorage.setItem(cookieName, cookieValue)
  503. }
  504. this._storage.getItem = function (cookieName) {
  505. return sessionStorage.getItem(cookieName)
  506. }
  507. this._storage.removeItem = function (cookieName) {
  508. sessionStorage.removeItem(cookieName)
  509. }
  510. break
  511. case 'customStorage':
  512. if (
  513. !this.options.cookieCustomStorageSet ||
  514. !this.options.cookieCustomStorageGet ||
  515. !this.options.cookieCustomStorageDelete
  516. ) {
  517. throw new Error('The following options must be set while using the customStorage: cookieCustomStorageSet, cookieCustomStorageGet and cookieCustomStorageDelete')
  518. }
  519. this._storage.setItem = function (cookieName, cookieValue) {
  520. Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageSet, [cookieName, cookieValue], '')
  521. }
  522. this._storage.getItem = function (cookieName) {
  523. return Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageGet, [cookieName], '')
  524. }
  525. this._storage.removeItem = function (cookieName) {
  526. Utils.calculateObjectValue(that.options, that.options.cookieCustomStorageDelete, [cookieName], '')
  527. }
  528. break
  529. default:
  530. throw new Error('Storage method not supported.')
  531. }
  532. }
  533. }