bootstrap-table-cookie.js 20 KB

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