我有这个程序,它可以动态创建可折叠对象,然后用户可以将内容输入到他们选择的可折叠对象中(单击)。当用户将内容添加到特定的可折叠对象时,我正在尝试将用户输入存储在本地存储中的数组中。我正在尝试这样做:
当用户创建新的可折叠对象时,将使用它创建一个新数组:
function addElement() {
/*add closable and it's title*/
//make new array for closables content:
contentArray = new Array();
contentArray.id = "Content array:" + contentArrayNum;
contentArrayNum++
localStorage.setItem("contentArray",JSON.stringify(contentArray));
}
用户可以使用选择框(单击)后附加到可关闭对象的输入框,将内容添加到选定的可折叠对象中。当他们将内容输入到选定的可折叠对象时,我正在尝试将用户输入添加到使用可折叠对象创建的数组中。但是我很困惑如何引用用可折叠对象创建的数组,我尝试了一下(但是(显然)它不起作用):
function selectedColl() {
currentClosable = event.target;
currentContent = currentClosable.nextElementSibling;
currentArray = currentClosable.array; //reference array(that was made with closable) for the selected closable
console.log(currentArray)
document.getElementById("inputTaskDiv").style.display = "block";//shows input box for selected closabales content
var inputTaskDiv = document.getElementById("inputTaskDiv");//appends the input box to the selcted closables
$(currentContent).append(inputTaskDiv);
}
I'm not sure if this is even possible or there might be an easier way to attempt what I'm trying to do. Simply what I want to do is: store the inputted content for a selected closable in local storage either in an array or anything else that can group the inputs for a selected collapsible in local storage. Please ask for clarification if you need it.
Here is my full code (commented local storage):
var currentClosable;
var currentContent;
var currentArray;
var contentArrayNum = 0;
var contentArray;
function selectedColl() {
currentClosable = event.target;
currentContent = currentClosable.nextElementSibling;
//currentArray = currentClosable.array;
//console.log(currentArray)
document.getElementById("inputTaskDiv").style.display = "block";//shows input box for selected closabales content
var inputTaskDiv = document.getElementById("inputTaskDiv");//appends the input box to the selcted closables
$(currentContent).append(inputTaskDiv);
}
var taskCounter = 0;
function addTask() {
var text = document.getElementById("taskInput").value;
// create a new div element and give it a unique id
var newTask = $("<div class='currentTask'><input class='checkbox' type='checkbox'><span class='text'>" + text + "</span></div>");
newTask.id = 'temp' + taskCounter;
taskCounter++;
// and give it some content
var newContent = document.createTextNode(text);
$(currentContent).append(newTask);
// store the content in localStorage
////here
// end of local storage
$(".currentTask").hover(
function() {
var taskCur = event.target;
$(this).find("a").last().remove();
$(taskCur).append($("<a class='taskX'> x</a>"));
function dump() {
$(taskCur).remove();
}
$("a").on("click", dump);
},
function() {
$(this).find("a").last().remove();
});
document.getElementById("taskInput").value = " ";
}
var elementCounter = 0;
var elementCounterContent = 0;
var text;
function addElement() {
text = document.getElementById("input").value;
// create a new div element and give it a unique id
var newDiv = $("<button class='collapsible'><span class='text'>"+text+"</span></button>");
$(newDiv).append("<button class='btnDelete'>Delete</button>");
var newContentOfDiv = $("<div class='content'></div>");
newDiv.id = 'temp' + elementCounter;
newContentOfDiv.id = elementCounterContent;
newDiv.classList = "div";
elementCounter++
elementCounterContent++
// and give it some content
var newContent = document.createTextNode(text);
// add the newly created element and its content into the DOM
document.getElementById("input").value = " ";
$("#divColl").append(newDiv, newContentOfDiv);
// store the closable(s) in localStorage
var arr = [];
arr = $("#divColl").find("button .text")
.map(function() { return this.textContent })
.get();
//array for content of closables
contentArray = new Array();
contentArray.id = "Content array:" + contentArrayNum;
contentArrayNum++
//localStorage.setItem("arr",JSON.stringify(arr));
//localStorage.setItem("contentArray",JSON.stringify(contentArray));
//console.log($("#divColl").find("button .text").map
//(function() { return this.textContent }).get())
// end of local storage
newDiv.click(function() {
selectedColl();
this.classList.toggle("active");
content = this.nextElementSibling;
if (content.style.display === 'block') {
content.style.display = 'none';
} else {
content.style.display = 'block';
}
});
}
$("#divColl").on('click', '.btnDelete', function() {
$(this).closest('.collapsible').remove();
content.style.display = 'none';
});
.collapsible {
background-color: #777;
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #555;
}
.collapsible:after {
content: '\002B';
color: white;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.content {
padding: 0 18px;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.taskX {
color: red;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<!---Add Step --->
<div id="addSteps">
<p>Make a collapsible:</p>
<input id="input" type="text" placeholder="title for collapsible"><button onclick="addElement()">Make collapsible</button>
</div>
<!-- Add content to Collapsable (display:none) --->
<div id="addTasksToSteps" style="display:none">
<div id="inputTaskDiv" style="display:none">
<input id="taskInput" type="text"><button onclick="addTask()">Add content</button>
</div>
</div>
<div id="divColl"></div>
</body>
</html>
我没有在今天下午进行任何圣诞节购物,而是在整理以下应用程序方面发挥了一些作用。作为“非jQuery”用户,它是在普通js中完成的(我一开始尝试时就把一些jQuery代码弄混了,所以我将其装箱了)〜您应该能够按原样复制整个内容并运行它〜我认为它确实可以完成您想要做的事情,并且整个过程中都有很多评论。希望对您有所帮助-我敢肯定您可以从中“挑选”一下您的原始代码。圣诞快乐... 2021年可能会更好!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
html *{ box-sizing:border-box; font-family:calibri,verdana,arial; }
.active,.collapsible:hover { background-color:#555; }
.active:after { content:"\2212"; }
.collapsible { background-color:#777; border:none; color:white; cursor:pointer; font-size:15px; outline:none; padding:18px; text-align:left; width:100%; }
.collapsible:after { color:white; content:'\002B'; float:right; font-weight:bold; margin-left:5px; }
.content { background-color:#f1f1f1; border-bottom:1px solid grey; border-left:1px solid grey; border-radius:0 0 1rem 1rem; border-right:1px solid grey; margin:0 0 2rem 0; padding:0 18px; padding:1rem; transition:max-height 0.2s ease-out; }
.currentTask a { color:red; cursor:pointer; display:inline-block; padding:0 1rem; margin:0 0 0 1rem }
#addSteps{ margin:0 0 2rem 0; }
#deltask{ display:none; }
button > span + button{ margin:0 0 0 5rem; }
</style>
<script>
/* Simple utility to generate semi-random string IDs */
const uniqid=function(l=6){
let t=[];
for(i=0;i<l;i++)t.push(seed());
return t.join('-');
};
const seed=function(){
return Math.floor((1+Math.random())*0x10000).toString(16).substring(1);
};
/*
I wrote this a couple of years ago just to simplify
the process of working with localStorage...
*/
const StoreFactory=function( name, type ){
'use strict';
const engine = !type || type.toLowerCase() === 'local' ? localStorage : sessionStorage;
const set=function( data ){
engine.setItem( name, JSON.stringify( data ) );
};
const get=function(){
return exists( name ) ? JSON.parse( engine.getItem( name ) ) : false;
};
const remove=function(){
engine.removeItem( name );
};
const exists=function(){
return engine.getItem( name )==null ? false : true;
};
const create=function(){
if( !exists() ) set( arguments[0] || {} );
};
const save=function(){
set( get() );
};
return Object.freeze({
set,
get,
save,
exists,
create,
remove
});
};
const create=function(t,a,p){
try{
/*
t:type ~ the DOM Node type. null for default 'div'
a:attributes ~ object literal of attributes to asign to the node
p:parent ~ the parent to which the node will be appended. null to negate.
*/
let el = ( typeof( t )=='undefined' || t==null ) ? document.createElement('div') : document.createElement(t);
let _arr=['innerHTML','innerText','html','text'];
for( let x in a ) if( a.hasOwnProperty( x ) && !~_arr.indexOf( x ) ) el.setAttribute( x, a[ x ] );
if( a.hasOwnProperty('innerHTML') || a.hasOwnProperty('html') ) el.innerHTML=a.innerHTML || a.html;
if( a.hasOwnProperty('innerText') || a.hasOwnProperty('text') ) el.innerText=a.innerText || a.text;
if( p!=null ) typeof( p )=='object' ? p.appendChild( el ) : document.getElementById( p ).appendChild( el );
return el;
}catch( err ){
console.error( err.message );
}
};
/***********************************************************
I know there are many jQuery methods that can be used
for to accomplish the things done here but I don't use
it so I don't know ~ hence using vanilla javascript
*/
document.addEventListener('DOMContentLoaded',function(){
/*************************************************
Create the storage object that will be used
to keep track of "collapsibles" and tasks.
The individual "collapsible" items that the
user creates will be stored within this store
using a unique key defined in the `addelement`
method.
That unique ID is used as a dataset attribute
for certain DOM elements which allows the store
to be used later to reconstruct the "collapsibles"
when the page is reloaded.
The structure for the generated store will be of
the following form:
store={
key1:{title:'The name of the "collapsible',tasks:['an array','of all','the tasks']},
key2:{title:'Another "collapsible"',tasks:['fly','me','to','the','moon']}
}
etc
*/
let oStore=new StoreFactory( 'collapsible' );
oStore.create();
let payload=oStore.get();
let parent=document.getElementById('divColl');
let oText=document.getElementById('input');
let oTask=document.getElementById('inputTaskDiv');
let oBttn=document.querySelector('input#input + button');
const buildElement=function( parent, id, text ){
/*
generate the HTML structure as originally used
and return the "Content" node for chaining to
other calls later.
*/
let bttn=create('button',{'class':'collapsible','data-id':id},parent);
create('span',{'class':'text','text':text},bttn);
create('button',{'class':'btnDelete','text':'Delete'},bttn);
return create('div',{'class':'content','data-id':id},parent);
};
const buildTask=function( parent, id, text ){
/*
Construct the HTML content for individual tasks
and return a refernce to this new content so that
it may be used in chaining if required.
*/
let div=create('div',{'class':'currentTask'},parent);
create('input',{'type':'checkbox','name':'task[]','value':text},div);
create('span',{'class':'text','text':text},div);
return div;
};
function addelement( event ) {
let id=uniqid( 8 );
let text=oText.value.trim();
if( text!='' ){
/* generate new content and append a clone of the input field + button */
appendclone( buildElement( parent,id, text ) );
/* prepare the data to be stored in localStorage */
var payload=oStore.exists() ? oStore.get() : {};
payload[ id ]={ 'title':text, 'tasks':[] };
/* save the data */
oStore.set( payload );
}
oText.value='';
return false;
};
function addtask( event ) {
/* The text data comes from the cloned input element that was inserted */
let input=event.target.previousElementSibling;
let text =input.value.trim();
if( text !='' ){
let parent = event.target.parentNode.parentNode;
let id = parent.dataset.id;
let div=buildTask.call( this, parent, id, text );
/*************************************
Save the task to the appropriate
place within the store. We use the
parentNode to work up the DOM Tree to
find the dataset ID which forms the
key in the store.
*/
let data=oStore.get();
var payload=data.hasOwnProperty( id ) ? data[ id ] : { title:parent.previousElementSibling.querySelector('span').textContent, tasks:[] }
payload.tasks.push( text );
// rebuild data for updating store
data[ id ]=payload;
// save the updated store
oStore.set( data );
/************************************/
input.value='';
return div;
}
return false;
};
/*********************************************
rebuild the display using stored values
...events handled by delegated listeners
*/
Object.keys( payload ).forEach( id => {
let text=payload[ id ].title;
let tasks=payload[ id ].tasks;
// add the "collapsible" to the DOM
let content=buildElement.call( this, parent, id, text );
tasks.forEach( text => {
// Add the tasks to the "collapsible"
buildTask.call( this, content, id, text );
});
});
/*************************************************************************************
Newly generated content has event listeners assigned above in the original jQuery
code. However any content generated on PageLoad as the localStorage is processed
will NOT have these listeners assigned - to my mind using `delegated event handlers`
on a suitable parent container would be a better approach as the same listeners
would work equally well for new content and existing.
*/
function deleteelement(e){
/*
Delete the entire "collapsible" from both
the DOM and from localStorage
*/
let id=e.target.parentNode.dataset.id;
parent.querySelectorAll( '[data-id="'+id+'"]' ).forEach( n=>{
parent.removeChild(n)
});
let data=oStore.get();
delete data[ id ];
oStore.set( data );
};
function deletetask(e){
/*
Delete specific "Task" from a "Collapsible"
- from both the DOM and from localStorage
*/
let id=e.target.parentNode.parentNode.dataset.id;
let task=e.target.parentNode;
// remove the DOM element
task.parentNode.removeChild( task );
// remove this item from the store
let data=oStore.get();
data[ id ].tasks.splice( data[ id ].tasks.indexOf( task ),1 );
// save it
oStore.set( data );
};
function appendclone(n){
/*
Append a cloned version of the
input field and button that are
used to add a new task.
*/
if( !n.querySelector('#newtask') ){
let clone=oTask.cloneNode(true);
clone.id='newtask';
clone.style.display='block';
n.insertBefore(clone,n.firstChild);
}
return true;
};
function appendclonehref(id,n){
/*
Append a cloned version of the hyperlink
that is used to delete and individual task.
The clone is placed at the respective node
in the DOM via the delegated "mouseover"
handler in conjunction with a "mouseout"
*/
if( !n.querySelector( 'a#'+id ) ){
let a=document.getElementById('deltask');
let clone=a.cloneNode( true );
clone.id=id;
clone.addEventListener('click',deletetask)
n.appendChild( clone );
}
};
function displaytasks(e){
/*
Ensure that the "Content" is visible/hidden
dependant upon clicking the button. The cloned
version of the text field + insert button are
added in this method
*/
let content=e.target.nextElementSibling
content.style.display=content.style.display=='block' ? 'none' : 'block';
return appendclone( content );
};
function mouseoverhandler(e){
/*
delegated event handler to intercept and process
the "mouseover[out]" events and modify the DOM
appropriately.
*/
if( e.target.tagName=='DIV' && e.target!=e.currentTarget ){
let id='del-x-task';
let expr='a#'+id;
if( e.target.className=='currentTask' ){
if( e.type=='mouseover' && !e.target.querySelector( expr ) ){
e.target.parentNode.querySelectorAll( expr ).forEach(a=>{
a.parentNode.removeChild(a);
});
appendclonehref( id, e.target );
}
}
if( e.type=='mouseout' && e.target.className!='currentTask' ){
e.target.parentNode.querySelectorAll( expr ).forEach(a=>{
a.parentNode.removeChild(a);
});
}
}
};
function clickhandler(e){
/*
delegated event handler to intercept and process
"Click" events on buttons.
*/
if( e.target.tagName == 'BUTTON' ){
switch( e.target.className ){
case 'btnDelete': return deleteelement.call(this,e);
case 'collapsible': return displaytasks.call(this,e);
case 'addtask': return addtask.call(this,e);
}
}
};
/********************************
Delegated event listeners
*/
parent.addEventListener('click',clickhandler);
parent.addEventListener('mouseover',mouseoverhandler);
parent.addEventListener('mouseout',mouseoverhandler);
/***********************************************************
Because the "Make Collapsible" button is outwith
the Parent DIV we cannot use the same delegated listener
or a listener bound to the same parent
*/
oBttn.addEventListener('click',addelement);
});
</script>
</head>
<body>
<!--- Add Step --->
<div id='addSteps'>
<p>Make a collapsible:</p>
<input id='input' type='text' placeholder='Title for collapsible' />
<button class='addcollapsible'>Make collapsible</button>
</div>
<!-- Add content to Collapsible (display:none) --->
<div id='addTasksToSteps' style='display:none'>
<!-- this will be cloned -->
<div id='inputTaskDiv' style='display:none'>
<input id='taskInput' type='text' />
<button class='addtask'>Add content</button>
</div>
</div>
<!-- this will be cloned -->
<a href='#' id='deltask'>X</a>
<!-- target for generated content -->
<div id='divColl'></div>
</body>
</html>
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句