Local storage has the limitation of being able to store only a single object at a time, rather

This code is designed to store product details in a local storage variable whenever a user visits a product page, with the intention of remembering the last visited products. However, the variable currently only retains one product at a time instead of adding them with "|" separators. Any assistance in resolving this issue would be greatly appreciated. The code appears to be valid.

Best regards

    events.domReady( function() {
      var objLookedAt = {
        'name' : document.getElementById('name').innerHTML.trim(),
        'type' : document.getElementById('type').innerText.trim(),
        'uri' : location.href,
        'imgUri' : document.getElementById('productImg').src,
        'price' : document.querySelectorAll('#prodPrice > span')[0].innerHTML.trim(),
        'quantity' : document.querySelectorAll('#prodPrice > span')[1].innerHTML.trim()
      },
      cRead = window.localStorage.getItem('lvp'),
      stringToSave = JSON.stringify( objLookedAt ),
      obj, ind, currSave = [], seen = false;

      if(cRead) {
        currSave = cRead.split('|');
        for(var i = 0; i < currSave.length; i++) {
          obj = JSON.parse(currSave[i]);
          if(objLookedAt.name === obj.name) {
            seen = true;
            ind = i;
          }
        }
      }
      if( seen ) {
        currSave.splice(ind, 1);
      }
      currSave.reverse().push(stringToSave);
      var cRev = currSave.reverse();
      window.localStorage.setItem('lvp', cRev.slice(0, 4).join('|'));
    });

Answer №1

Alright, this solution should work just fine,
and it's nice that Array.concat() handles both Arrays and single values.

events.domReady( function() {
    var objViewed = {
        'name' : document.getElementById('name').innerHTML.trim(),
        'type' : document.getElementById('type').innerText.trim(),
        'uri' : location.href,
        'imgUri' : document.getElementById('productImg').src,
        'price' : document.querySelectorAll('#prodPrice > span')[0].innerHTML.trim(),
        'quantity' : document.querySelectorAll('#prodPrice > span')[1].innerHTML.trim()
    };

    var lvp = window.localStorage.getItem('lvp');
    var cRev = [ objViewed ].concat(
            tryToParseAsJson( lvp ) || []
        )
        .filter(function(obj){ 
            return obj === objViewed || obj.name !== objViewed.name 
        })
        .slice(0, 4);

    window.localStorage.setItem('lvp', JSON.stringify( cRev ));
});

function tryToParseAsJson(str){
    try {
        return JSON.parse(str);
    }catch(err){}
}

Update: Consider creating an abstraction if multiple parts of the code need to access localStorage, to centralize the serialization/deserialization process.

//utils
var AP = Array.prototype;
function tryToParseAsJson(str){
    try {
        return JSON.parse(str);
    }catch(err){}
}

var store = {
    lvp: {
        get(){
            return AP.concat( tryToParseAsJson( window.localStorage.getItem('lvp') ) || AP );
        },
        set(arr){
            window.localStorage.setItem('lvp', 
                arr == null || typeof arr !== "object"? "": JSON.stringify( arr )
            );
        }
    }
}

Ensure all code uses this module only.

events.domReady(function() {
    var objViewed = {
        'name' : document.getElementById('name').innerHTML.trim(),
        'type' : document.getElementById('type').innerText.trim(),
        'uri' : location.href,
        'imgUri' : document.getElementById('productImg').src,
        'price' : document.querySelectorAll('#prodPrice > span')[0].innerHTML.trim(),
        'quantity' : document.querySelectorAll('#prodPrice > span')[1].innerHTML.trim()
    };

    function isNotObjViewed(o){
        return o.name !== objViewed.name 
    }

    store.lvp.set( [ objViewed ].concat( store.lvp.get().filter( isNotObjViewed ).slice(0,3) ) );
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to view the list of errors displayed by vscode when opening a JS file exclusively through the terminal?

Is there a default configuration file that vscode uses to display errors and warnings? I want to identify all issues in my JavaScript project. I don't have any jsconfig.json or tsconfig.json files, only using the //@ts-check directive in some files. ...

In JavaScript, what is the best way to target the initial option element in HTML?

As a newcomer to javascript, I'm wondering how to target the first option in the HTML <option value="">Choose an image...</option> without altering the HTML itself? My thought is: memeForm.getElementById('meme-image').getElement ...

Array filtering functions similarly to marketplace filtering tools

In order to make the filter function like a marketplace filter, I want to only see items related to the selected brand and status. For example: partners = [ 0:{ year: "2022" badge_status: "badge-success" sale_date: "01/07/2022&quo ...

Is there a way to remove the initial word from a sentence?

Tue 26-Jul-2011 Looking to remove the initial word "Mon" using javascript with jQuery. Any suggestions on accomplishing this task? ...

Filtering in AngularJS based on a specific ID

Currently, I am dealing with a JSON encoded response from PHP that looks like this... [ {"ID":"149","IDusr":"4","aut_more_info":"good","doc_name":"img1838142879.jpeg","doc_type":"jpg"},{"ID":"149","IDusr":"4","aut_more_info":"good","img5733250433.jpeg","d ...

JS/Docker - The attribute 'user' is not recognized in the context of 'Session & Partial<SessionData>'

I'm attempting to integrate express-session into my Node.js application running within Docker. I've come across several discussions on the topic: Express Session: Property 'signin' does not exist on type 'Session & Partial<Se ...

Upcoming Authentication Update: Enhancing User Profile with Additional Data Points

I recently encountered an issue with my typescript application that uses Next Auth v4 along with GithubProvider and MongoDBAdapter. I needed to add a new field called role to the User schema. Researching online, most solutions suggested adding a function ...

The form will only display results after the "Submit" button is clicked twice

Recently, I built a flask website where the form and results are displayed on the same page. However, there seems to be an issue that arises upon clicking the 'submit' button for the first time after running 'flask run'. The error messa ...

How to declare WinJS.xhr as a global variable in a Windows 8 Metro app

Currently, I am developing a Windows 8 Metro app and facing an issue with a hub page. The problem arises when pushing data dynamically from an XML API using two WinJs.xhr("url") calls; one for headings and the other for section datas. When merging both W ...

Optimal utilization of JSON in JavaScript API: Enhancing Performance, Reinforcing Maintainability, and Optimizing Resources

Currently, I am working on developing an application using Laravel and VueJS (along with Vuex). Although I do not have much experience in working with these frameworks or front-ends, I am curious to know the best practices for utilizing the data received f ...

Using the jqLite .html() method directly as a watch listener in AngularJS

I'm attempting to use the jqLite function element.html directly as a listener for a watcher: angular.module('testApp', []).directive('test', function () { return { restrict: 'A', link: function (scope, element, ...

AngularJS implementation that disables a button when the input field is empty

As I delve into learning angular JS, I am facing a challenge. I want to disable the button using the "ng-disabled" attribute while my input fields for "login" and "password" are empty. However, the default text in the login input is "LOGIN" and in the pass ...

Obtaining numerous data points in a multi-select element within HTML

Struggling with determining the values of multiple <select> tags in an HTML file simultaneously? function knowAllValues(){ var color_element = document.getElementById("color"); var size_element = document.getElementById("size"); ...

How to retrieve a refined selection of items

In my scenario, there are two important objects - dropdownOptions and totalItem https://i.sstatic.net/VreXd.png The requirement is as follows: If 12 < totalItems < 24, then display "Show 12, Show 24" If 24 < totalItems < 36, only show "Show ...

Can the submit ID value be utilized in PHP?

name="submit" functions as expected. if(isset($_POST["submit"])) <input type="submit" ID="asdf" name="submit" value="Save" class="ui blue mini button"> I want to change it to use ...

Store the information in the user interface of React by converting it into a file format

Currently, I am retrieving data from an API and downloading a specific file. My goal is to store this same file in the public directory within my react application. https://i.sstatic.net/bS8Z4.png this.state = { fileDownloadUrl: null, fileName ...

How can I trigger an API call 30 seconds after my React Native app switches to the background?

Seeking assistance with my React Native app: I am trying to make an API call 30 seconds after the app goes into the background. I am using AppState from react-native to detect when the app goes into the background, but I'm not receiving any callback a ...

The POST variable consistently remains void

The approach I am using to handle the data sent with jquery.ajax involves sending an empty string by default. Whenever there is a change, I monitor the input for changes and resend the data. Everything seems to work fine in the console, but in PHP, $this-& ...

The default locale for momentJS is set to zh-tw and I'm having trouble changing it

Currently, I am incorporating the momentJS library into my Angular application by pulling it from a CDN: <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.min.js"></script> Although the default locale should be Engli ...

Ways to align div elements

I am currently in the process of developing my own custom animation player. Utilizing Three.js for object rendering has been successful so far. However, the challenge lies in incorporating control options at the bottom of the player interface (such as play ...