Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/MultipleSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Constants from './constants/index.js'
import VirtualScroll from './virtual-scroll/index.js'
import {
compareObjects,
extend,
findByParam,
getDocumentClickEvent,
removeDiacritics,
Expand All @@ -13,7 +14,7 @@ import {
class MultipleSelect {
constructor ($el, options) {
this.$el = $el
this.options = $.extend({}, Constants.DEFAULTS, options)
this.options = extend({}, Constants.DEFAULTS, options)
}

init () {
Expand Down Expand Up @@ -194,13 +195,13 @@ class MultipleSelect {
this.data = data
}
} else {
$.each(this.$el.children(), (i, elm) => {
for (const [i, elm] of Array.from(this.$el.children()).entries()) {
const row = this.initRow(i, elm)
Comment thread
wenzhixin marked this conversation as resolved.

if (row) {
data.push(this.initRow(i, elm))
data.push(row)
}
})
}

this.options.data = data
this.data = data
Expand Down Expand Up @@ -248,9 +249,9 @@ class MultipleSelect {
row._data = $elm.data()
}

$.each($elm.children(), (j, elem) => {
for (const [j, elem] of Array.from($elm.children()).entries()) {
Comment thread
wenzhixin marked this conversation as resolved.
row.children.push(this.initRow(j, elem, row.disabled))
})
}

return row
}
Expand Down Expand Up @@ -907,18 +908,18 @@ class MultipleSelect {

getOptions () {
// deep copy and remove data
const options = $.extend({}, this.options)
const options = extend({}, this.options)

delete options.data
return $.extend(true, {}, options)
return extend(true, {}, options)
}

refreshOptions (options) {
// If the objects are equivalent then avoid the call of destroy / init methods
if (compareObjects(this.options, options, true)) {
return
}
this.options = $.extend(this.options, options)
this.options = extend(this.options, options)
this.destroy()
this.init()
}
Expand Down
5 changes: 3 additions & 2 deletions src/multiple-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Constants from './constants/index.js'
import MultipleSelect from './MultipleSelect.js'
import { extend } from './utils/index.js'

Comment thread
wenzhixin marked this conversation as resolved.
$.fn.multipleSelect = function (option, ...args) {
let value
Expand All @@ -15,7 +16,7 @@ $.fn.multipleSelect = function (option, ...args) {
const $this = $(el)
let data = $this.data('multipleSelect')

const options = $.extend(
const options = extend(
{},
$this.data(),
typeof option === 'object' && option
Expand All @@ -27,7 +28,7 @@ $.fn.multipleSelect = function (option, ...args) {
}

if (typeof option === 'string') {
if ($.inArray(option, Constants.METHODS) < 0) {
if (!Constants.METHODS.includes(option)) {
throw new Error(`Unknown method: ${option}`)
}
value = data[option](...args)
Expand Down
109 changes: 109 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,111 @@
/**
* Checks if a value is a plain object.
*
* @param {*} obj - The value to check.
* @returns {boolean} True if the value is a plain object, false otherwise.
*/
const isObject = obj => {
if (typeof obj !== 'object' || obj === null) {
return false
}

// Objects with null prototype are considered plain objects (jQuery compatible)
if (Object.getPrototypeOf(obj) === null) {
return true
}

let proto = obj

while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}

return Object.getPrototypeOf(obj) === proto
}
Comment thread
wenzhixin marked this conversation as resolved.

/**
* Merges the contents of two or more objects together into the first object.
* This is a re-implementation of jQuery's extend function.
* Based on: https://github.com/jquery/jquery/blob/3.6.2/src/core.js#L132
*
* @param {boolean|Object} [deep=false] - If true, the merge becomes recursive (deep copy).
* @param {Object} target - The object to extend.
* @param {...Object} objects - The objects to merge into the target.
* @returns {Object} The extended target object.
*/
const extend = (...args) => {
let target = args[0] || {}
let i = 1
let deep = false
let clone

// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target

// Skip the boolean and the target
target = args[i] || {}
i++
}

// Handle case when target is a string or something (possible in deep copy)
if (typeof target !== 'object' && typeof target !== 'function') {
target = {}
}

for (; i < args.length; i++) {
const options = args[i]

// Ignore undefined/null values
if (typeof options === 'undefined' || options === null) {
continue
}

// Extend the base object
// eslint-disable-next-line guard-for-in
for (const name in options) {
const copy = options[name]

// Prevent Object.prototype pollution
// Prevent never-ending loop
if (name === '__proto__' || target === copy) {
continue
}

const copyIsArray = Array.isArray(copy)

// Recurse if we're merging plain objects or arrays
if (deep && copy && (isObject(copy) || copyIsArray)) {
const src = target[name]

if (copyIsArray && Array.isArray(src)) {
if (src.every(it => !isObject(it) && !Array.isArray(it))) {
Comment thread
wenzhixin marked this conversation as resolved.
target[name] = copy.slice()
continue
}
}

Comment thread
wenzhixin marked this conversation as resolved.
if (copyIsArray && !Array.isArray(src)) {
clone = []
} else if (!copyIsArray && !isObject(src)) {
clone = {}
} else {
clone = src
}

// Never move original objects, clone them
target[name] = extend(deep, clone, copy)

// Don't bring in undefined values
} else if (copy !== undefined) {
target[name] = copy
}
}
}

return target
}

const compareObjects = (objectA, objectB, compareLength) => {
const aKeys = Object.keys(objectA)
const bKeys = Object.keys(objectB)
Expand Down Expand Up @@ -178,6 +286,7 @@ const toRaw = proxy => {

export {
compareObjects,
extend,
findByParam,
getDocumentClickEvent,
removeDiacritics,
Expand Down