如何修复 'One Closing Button Closes All Modals'
How to Fix 'One Closing Button Closes All Modals'
我正在尝试创建一个 vanilla JavaScript 模态,当从 HTML 实例化它时,它具有由用户自定义的能力文件(或 JS 文件)。但是,在处理关闭模式的 close() 函数时,不是一次关闭一个模式,而是使用它的关闭按钮,第一个模式的关闭按钮关闭页面的所有模式。我不确定我做错了什么...
我研究过其他类似的 vanilla JavaScript,可自定义的模态库,但大多数都使用 jQuery,一些框架,或者包含很多我不熟悉的复杂功能(我还是初学者)。我在 GitHub、CodePen、Google 和此处进行了研究;但我还没有找到满足我需要的解决方案。
由于代码比较长,建议大家直接去我的CodePen账号,那里有完整的代码。
https://codepen.io/jdriviere/pen/zYOyJvv?editors=0011
但这是我的 close() 函数:
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
我希望代码一次关闭一个模态,最好是具有正确 ID 的模态(应由用户分配或默认情况下具有 "NoID" ID)。相反,如果我关闭后续模态,它会关闭它们;但是如果我关闭第一个,它会关闭所有的。另外,有没有办法在您创建模态实例后立即初始化()模态功能(我讨厌手动启动它们)?如果是这样,请在此处也包含您的解决方案,如果没有太多要求的话。
现在已经有一段时间了。非常感谢您的帮助。
谢谢。 :)
您的代码中有几个错误:
- 始终为 HTML 元素使用正确的 ID 模式。您已将
n/a
用于其 options
对象中没有 id
属性 的模态。使用这样的 id
将中断查询 select 或者当您使用 jQuery.
- 因为,您调用了
init()
函数两次,并且在每次调用 init()
时,closeBtn
是 select 两个模式的关闭按钮并分配单击事件处理程序给他们每个人两次。这就是当您单击一个按钮时另一个按钮的单击事件正在执行的原因。因此,您可以做的是,仅将点击函数与调用 init()
函数的模式的关闭按钮关联一次。我在 init()
函数中使用了 let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');
到 select 那个特定的关闭按钮。
总体而言,您的 JS 代码将如下所示:
/**
* Blueprint function (class) that describes a Modal object.
* @param {Object} options Object parameter containing elements that describe the Modal.
* @returns {Object} options Returns options from current modal object.
*/
function Modal(options) {
// If constructor params is available
if (options) {
this.options = options;
} else {
this.options = {};
} // End of IF-ELSE
// Add to options object
if (options.id) {
// Check type of ID entry
if (typeof options.id === 'number') {
this.options.id = options.id.toString();
} else {
this.options.id = options.id;
} // End of IF-ELSE
} else if (options.id === undefined) {
this.options.id = 'NA';
} // End of IF-ELSE
if (options.name) {
this.options.name = options.name;
} // End of IF
if (options.closable) {
this.options.closable = options.closable;
} // End of IF
return this;
};
// Prototypes
/**
* Displays some information concerning the current Modal object.
* @returns {Object} this Returns current modal object.
*/
Modal.prototype.open = function() {
let demo = document.getElementById('demo');
return this;
};
/**
* Creates an instance of a Modal object with the specified object elements.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.create = function() {
// Create Modal Element
let modal = document.createElement('div');
let modalBody = document.createElement('div');
// Create Modal
!modal.classList.contains('modal') ?
modal.classList.add('modal') :
modal.classList.add('');
modal.id = this.options.id || 'noID';
// Create modal body element
!modalBody.classList.contains('modal-body') ?
modalBody.classList.add('modal-body') :
modalBody.classList.add('');document.querySelector('#' + this.options.id + ' .modal-close');
modal.appendChild(modalBody);
// Adding modal sub-elements
if (this.options.title) {
let modalTitle = document.createElement('h2');
!modalTitle.classList.contains('modal-title') ?
modalTitle.classList.add('modal-title') :
modalTitle.classList.add('');
modalTitle.textContent = this.options.title;
modalBody.appendChild(modalTitle);
console.log('Added title!');
} // End of IF
if (this.options.subtitle) {
let modalSubtitle = document.createElement('h4');
!modalSubtitle.classList.contains('modal-subtitle') ?
modalSubtitle.classList.add('modal-subtitle') :
modalSubtitle.classList.add('');
modalSubtitle.textContent = this.options.subtitle;
modalBody.appendChild(modalSubtitle);
console.log('Added subtitle!');
} // End of IF
if (this.options.content) {
let modalContent = document.createElement('p');
!modalContent.classList.contains('modal-content') ?
modalContent.classList.add('modal-content') :
modalContent.classList.add('');
modalContent.textContent = this.options.content;
modalBody.appendChild(modalContent);
console.log('Added contents!');
} // End of IF
if (this.options.closable) {
let modalClose = document.createElement('span');
!modalClose.classList.contains('modal-close') ?
modalClose.classList.add('modal-close') :
modalClose.classList.add('');
modalClose.innerHTML = '×';
modalBody.appendChild(modalClose);
console.log('Close button added!');
} // End of IF
document.body.appendChild(modal);
console.log('Modal created with ID', modal.id);
return this;
};
/**
* Closes the current Modal object.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function(e) {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
// Create a Modal object
let modal1 = new Modal({
id: 'post1',
name: 'modal',
title: 'First Post',
subtitle: 'I contain all the elements',
content: 'This is awesome!',
closable: true
});
let modal2 = new Modal({
title: 'Second Post',
subtitle: 'Trying new things',
content: 'Hehehehehe',
closable: true
});
modal1.open();
modal1.create();
modal1.init();
modal2.open();
modal2.create();
modal2.init();
在你的codepen中替换上面的JS代码试试。它会起作用。
问题出在初始化函数上:
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function() {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let modal = document.getElementById(this.options.id);
let closeBtn = modal.querySelector('.modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
console.log(this.options);
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
如果您没有指定要在当前模态上使用事件监听器,那么它将被设置为两个模态。
我正在尝试创建一个 vanilla JavaScript 模态,当从 HTML 实例化它时,它具有由用户自定义的能力文件(或 JS 文件)。但是,在处理关闭模式的 close() 函数时,不是一次关闭一个模式,而是使用它的关闭按钮,第一个模式的关闭按钮关闭页面的所有模式。我不确定我做错了什么...
我研究过其他类似的 vanilla JavaScript,可自定义的模态库,但大多数都使用 jQuery,一些框架,或者包含很多我不熟悉的复杂功能(我还是初学者)。我在 GitHub、CodePen、Google 和此处进行了研究;但我还没有找到满足我需要的解决方案。
由于代码比较长,建议大家直接去我的CodePen账号,那里有完整的代码。
https://codepen.io/jdriviere/pen/zYOyJvv?editors=0011
但这是我的 close() 函数:
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
我希望代码一次关闭一个模态,最好是具有正确 ID 的模态(应由用户分配或默认情况下具有 "NoID" ID)。相反,如果我关闭后续模态,它会关闭它们;但是如果我关闭第一个,它会关闭所有的。另外,有没有办法在您创建模态实例后立即初始化()模态功能(我讨厌手动启动它们)?如果是这样,请在此处也包含您的解决方案,如果没有太多要求的话。
现在已经有一段时间了。非常感谢您的帮助。
谢谢。 :)
您的代码中有几个错误:
- 始终为 HTML 元素使用正确的 ID 模式。您已将
n/a
用于其options
对象中没有id
属性 的模态。使用这样的id
将中断查询 select 或者当您使用 jQuery. - 因为,您调用了
init()
函数两次,并且在每次调用init()
时,closeBtn
是 select 两个模式的关闭按钮并分配单击事件处理程序给他们每个人两次。这就是当您单击一个按钮时另一个按钮的单击事件正在执行的原因。因此,您可以做的是,仅将点击函数与调用init()
函数的模式的关闭按钮关联一次。我在init()
函数中使用了let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');
到 select 那个特定的关闭按钮。
总体而言,您的 JS 代码将如下所示:
/**
* Blueprint function (class) that describes a Modal object.
* @param {Object} options Object parameter containing elements that describe the Modal.
* @returns {Object} options Returns options from current modal object.
*/
function Modal(options) {
// If constructor params is available
if (options) {
this.options = options;
} else {
this.options = {};
} // End of IF-ELSE
// Add to options object
if (options.id) {
// Check type of ID entry
if (typeof options.id === 'number') {
this.options.id = options.id.toString();
} else {
this.options.id = options.id;
} // End of IF-ELSE
} else if (options.id === undefined) {
this.options.id = 'NA';
} // End of IF-ELSE
if (options.name) {
this.options.name = options.name;
} // End of IF
if (options.closable) {
this.options.closable = options.closable;
} // End of IF
return this;
};
// Prototypes
/**
* Displays some information concerning the current Modal object.
* @returns {Object} this Returns current modal object.
*/
Modal.prototype.open = function() {
let demo = document.getElementById('demo');
return this;
};
/**
* Creates an instance of a Modal object with the specified object elements.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.create = function() {
// Create Modal Element
let modal = document.createElement('div');
let modalBody = document.createElement('div');
// Create Modal
!modal.classList.contains('modal') ?
modal.classList.add('modal') :
modal.classList.add('');
modal.id = this.options.id || 'noID';
// Create modal body element
!modalBody.classList.contains('modal-body') ?
modalBody.classList.add('modal-body') :
modalBody.classList.add('');document.querySelector('#' + this.options.id + ' .modal-close');
modal.appendChild(modalBody);
// Adding modal sub-elements
if (this.options.title) {
let modalTitle = document.createElement('h2');
!modalTitle.classList.contains('modal-title') ?
modalTitle.classList.add('modal-title') :
modalTitle.classList.add('');
modalTitle.textContent = this.options.title;
modalBody.appendChild(modalTitle);
console.log('Added title!');
} // End of IF
if (this.options.subtitle) {
let modalSubtitle = document.createElement('h4');
!modalSubtitle.classList.contains('modal-subtitle') ?
modalSubtitle.classList.add('modal-subtitle') :
modalSubtitle.classList.add('');
modalSubtitle.textContent = this.options.subtitle;
modalBody.appendChild(modalSubtitle);
console.log('Added subtitle!');
} // End of IF
if (this.options.content) {
let modalContent = document.createElement('p');
!modalContent.classList.contains('modal-content') ?
modalContent.classList.add('modal-content') :
modalContent.classList.add('');
modalContent.textContent = this.options.content;
modalBody.appendChild(modalContent);
console.log('Added contents!');
} // End of IF
if (this.options.closable) {
let modalClose = document.createElement('span');
!modalClose.classList.contains('modal-close') ?
modalClose.classList.add('modal-close') :
modalClose.classList.add('');
modalClose.innerHTML = '×';
modalBody.appendChild(modalClose);
console.log('Close button added!');
} // End of IF
document.body.appendChild(modal);
console.log('Modal created with ID', modal.id);
return this;
};
/**
* Closes the current Modal object.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.close = function() {
let modal = document.getElementById(this.options.id);
let modalBody = modal.children[0];
// Delete elements from Modal Body
for (let i = 0; i < modalBody.children.length; i++) {
modalBody.removeChild(modalBody.children[i]);
} // End of LOOP
// Delete Modal Body from Modal
modal.removeChild(modalBody);
// Delete Modal from DOM
modal.style.display = 'none';
document.body.removeChild(modal);
return this;
};
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function(e) {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let closeBtn = document.querySelector('#'+this.options.id + ' .modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
// Create a Modal object
let modal1 = new Modal({
id: 'post1',
name: 'modal',
title: 'First Post',
subtitle: 'I contain all the elements',
content: 'This is awesome!',
closable: true
});
let modal2 = new Modal({
title: 'Second Post',
subtitle: 'Trying new things',
content: 'Hehehehehe',
closable: true
});
modal1.open();
modal1.create();
modal1.init();
modal2.open();
modal2.create();
modal2.init();
在你的codepen中替换上面的JS代码试试。它会起作用。
问题出在初始化函数上:
/**
* Initializes the inner functions of the modal, such as the closing capacity.
* @returns {Object} this Returns current Modal object.
*/
Modal.prototype.init = function() {
// let closeBtnAll = document.querySelectorAll('.modal-close');
let modal = document.getElementById(this.options.id);
let closeBtn = modal.querySelector('.modal-close');
// Assign close() function to all close buttons
closeBtn.addEventListener('click', () => {
console.log(this.options);
if (this.options.closable) {
this.close();
}
})
// Press ESC to close ALL modals
return this;
};
如果您没有指定要在当前模态上使用事件监听器,那么它将被设置为两个模态。