bootstrap-table-cookie.js 17 KB

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