简体   繁体   中英

How do I code an upvote bar that stores the information and displays it?

I'm an HTML and CSS newbie. I want to generate an upvote bar which stores the information(in this case, upvotes).

I tried this:

for (const btn of document.querySelectorAll('.vote')) {
  btn.addEventListener('click', event => {
    event.target.classList.toggle('on');
  });
}
.vote {
  display: inline-block;
  overflow: hidden;
  width: 40px;
  height: 25px;
  cursor: pointer;
  background: url('http://i.stack.imgur.com/iqN2k.png');
  background-position: 0 -25px;
} 


.vote.on {
  background-position: 0 2px;
}
Click to vote: <span class="vote"> </span>

I'm not sure if you are trying to loop through buttons. If you have more than one upvote button then you would use the for loop and it would look something like the following:

 const buttons = document.querySelectorAll('.vote'); for(let i = 0; i < buttons.length; i++){ buttons[i].addEventListener('click', function() { buttons[i].classList.toggle('active'); }); }
 .vote.active{ border: 1px solid red; }
 <button class="vote">Vote</button> <button class="vote">Vote</button> <button class="vote">Vote</button>

if you just have one button on your page then you don't need the for loop you can just do:

 const button = document.querySelector('.vote'); button.addEventListener('click', function() { button.classList.toggle('active'); });
 .vote.active{ border: 1px solid red; }
 <button class="vote">Vote</button>

All that said this obviously won't persist when the page is reloaded this will go back to normal state you will need more than just html, css and javascript for that these are front end technologies that will only interact with the browser they do not store information. If you want this to save for future page visits you will obviously need a backend to process the vote and a database to save the information to. I just figured I would state this since you said you were new to html and css and I didn't know the extent of your knowledge or if you were aware of that since you said in your post you wanted to store the information.

There are some improvements you can do here:

  1. Put CSS inside a <style>
  2. Put Javascript inside <script>
  3. You can use the :hover CSS selector. No need for that extra 'on' class.
  4. Set up a variable to store the number of votes so you can reuse later.

Bellow I pasted a code example with these improvements:

<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .vote {
        display: inline-block;
        overflow: hidden;
        width: 40px;
        height: 25px;
        cursor: pointer;
        background: url('http://i.stack.imgur.com/iqN2k.png');
        background-position: 0 -25px;
      }

      .vote:hover {
        background-position: 0 2px;
      }
    </style>
  </head>
  <body>
    Click to vote: <span class="result"></span><span class="vote"></span>
    <script>
      let numVotes = 0;
      document.querySelector('.vote').addEventListener('click', event => {
        document.querySelector('.result').textContent = numVotes++;
      });
    </script>
  </body>
</html>

To store the information ( essentially clicks ) requires some storage mechanism and for this to work and maintain the score for multiple users across time and space would require some server-side storage - most likely a database combined with Ajax to make the request. As no information was given in the question as to the nature of storage I opted here for a simple session based storage and fetch to make the request but this could quite easily be modified to update a database. I appreciate there is probably more here than expected but I hope it'll be of use.

<?php
    session_start();
    /*
        rather than updating a database
        this uses a simple session.
    */
    $svar='upvotes';
    if( empty( $_SESSION[ $svar ] ) )$_SESSION[ $svar ]=array();

    if( $_SERVER['REQUEST_METHOD']=='POST' ){
        ob_clean();

        /* get the POSTed data and decode it */
        $json=json_decode( file_get_contents( 'php://input' ) );
        if( !empty( $json ) ){


            $id=$json->id;
            $direction=$json->direction;

            /* update the vote & save session */
            $votes=array_key_exists( $id, $_SESSION[ $svar ] ) ? intval( $_SESSION[ $svar ][ $id ] ) : 0;
            switch( $direction ){
                case 'up': $votes++; break;
                case 'down': $votes--; break;
            }
            $_SESSION[ $svar ][ $id ]=$votes;
        }

        /* send json response back to callback */
        header('Content-Type: application/json');
        exit( json_encode( $_SESSION[ $svar ] ) );
    }
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>UpVote system</title>
        <script>
            document.addEventListener('DOMContentLoaded',()=>{
                /*
                    A simple `fetch` implementation that sends
                    a POST request with the id of the article
                    ( or whatever is to be upvoted ) and the
                    direction( upvote or downvote )
                */
                const makerequest=function( id,direction ){
                    fetch( location.href,{ method:'post', body:JSON.stringify( { id:id, direction:direction } )} )
                        .then( r=>{ return r.json() } )
                        .then( json=>{
                            /* 
                            iterate through response and 
                            update the display of votes for 
                            each article
                            */
                            Object.keys( json ).map( k=>{
                                let div=document.querySelector( `article[ id="${k}" ] > div.votes` );
                                if( div ) div.dataset.votes=json[ k ];
                            })
                        })
                        .catch( err=>{ alert( err ) } )
                };
                /*
                    event handler bound to the up/down vote icons
                */
                const clickhandler=function(e){
                    if( !this.parentNode.querySelector('span.on') ){

                        let id=this.parentNode.parentNode.id;
                        let dir=this.className.replace('vote ','');

                        makerequest( id, dir );
                        this.classList.add('on');
                    }
                };

                /* assign event handlers */
                Array.from( document.querySelectorAll( '.vote' ) ).forEach( span=>{
                    span.addEventListener( 'click', clickhandler );
                })
            });
        </script>
        <style>
            html *{font-family:monospace; box-sizing:border-box;}
            article{
                width:60%;
                margin:2rem auto;
                padding:1rem;
                border-bottom:1px dotted gray
            }
            article:last-of-type{
                border:none;
            }
            .vote {
                display:inline-block;
                width: 40px;
                height: 25px;
                cursor: pointer;
                background: url( //i.stack.imgur.com/iqN2k.png );
                background-repeat:no-repeat;
                margin:0;
            }
            .votes{
                display:inline-block;
            }
            .up,.down{
                background-position: 0 -25px;
            }
            .down{
                transform:rotate(180deg);
            }
            .vote.on {
                background-position: 0 2px;
            }
            .votes:after{
                content:attr(data-votes);
                display:inline-block;
                min-width:4rem;
                height:25px;
                margin:0;
                text-align:left;
                color:red;
                float:right;
            }
            p{font-style:italic}
        </style>
    </head>
    <body>

        <article id='1'>
            <h1>An article worth reading and voting on quite possibly</h1>
            <div class='votes'>Click to vote: <span class='vote down'></span><span class='vote up'></span></div>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut 
            labore et dolore magna aliqua. Donec luctus odio ac ipsum euismod, eu fermentum justo ullamcorper. 
            Vivamus sollicitudin tellus magna, quis posuere nisi lacinia sed.</p>
        </article>

        <article id='2'>
            <h1>Another well written and noteworthy article</h1>
            <div class='votes'>Click to vote: <span class='vote down'></span><span class='vote up'></span></div>
            <p>Urna et pharetra pharetra massa massa ultricies mi quis. Faucibus pulvinar elementum integer enim.
             Fusce ac odio dui. Aenean turpis sem, elementum eget lacinia eu, auctor vel lorem. Nam tincidunt augue purus, 
             a luctus nibh egestas eu. Quisque eget sapien a orci congue interdum vestibulum et neque.</p>
        </article>

        <article id='3'>
            <h1>Enjoy the wonders of pig-latin</h1>
            <div class='votes'>Click to vote: <span class='vote down'></span><span class='vote up'></span></div>
            <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
            Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
        </article>
    </body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM