【问题标题】:Store user inputs in specific array in local storage将用户输入存储在本地存储中的特定数组中
【发布时间】:2020-12-22 07:40:25
【问题描述】:

我有一个可以动态制作可折叠的程序,然后用户可以将内容输入到他们选择(单击)的可折叠中。当用户将内容添加到特定的可折叠时,我试图将用户输入存储在本地存储中的数组中。我试图这样做:

当用户创建一个新的可折叠对象时,一个新的数组也会随之创建:

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);
    }

这是我正在尝试做的图片:

我不确定这是否可能,或者可能有更简单的方法来尝试我正在尝试做的事情。我想要做的只是:将所选可关闭的输入内容存储在本地存储中,或者以数组或其他任何可以将所选可折叠的输入分组到本地存储中。请要求澄清如果你需要的话。

这是我的完整代码(注释本地存储):

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>

【问题讨论】:

    标签: javascript html jquery arrays


    【解决方案1】:

    今天下午我没有做任何圣诞购物,而是在组装以下应用程序方面进行了一些尝试。作为一个“非 jQuery”用户,它是在 vanilla js 中完成的(当我最初尝试时,我对一些 jQuery 代码感到困惑,所以我把它装箱了)~你应该能够“按原样”复制整个东西“并运行它〜我认为它可以完成您想要做的事情,并且整个过程中有很多 cmets。希望它有所帮助-我相信您可以从中“挑选”位以与您的原始代码相关联。圣诞快乐……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>
    

    【讨论】:

      【解决方案2】:

      如果您想将array 存储在不同的ids 中,您可以在localStorage 中创建如下结构-

      设置localStorage -

      var id = 1;
      var arr = ['a', 'b', 'c'];
      var content = {
            [id]: arr
          };
      var contentString = JSON.stringify(content);
      console.log(contentString);
      //localStorage.setItem("collapsibleContent",contentString);

      这会将您的 arr 与 id 存储为键值对 -

      您可以检索arr -

      var contentString = localStorage.getItem("collapsibleContent");
      var content = JSON.parse(contentString);
      var arr = content[id];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-09-13
        • 1970-01-01
        • 2021-09-29
        • 2015-12-23
        • 2016-10-22
        • 2014-05-10
        • 2016-03-15
        相关资源
        最近更新 更多