2
\$\begingroup\$

I recently launched my first website, and despite being very proud of how far I've come, I know that my code is more "I got it to work" than "It works the best that it can." I'd like some criticism, and insight into how you would accomplish the same effect.

This script shows and hides overlapping Divs to tell a story through text about myself. I want to retain the granular control over how long each div stays visible, but simplify this code.

<script>
    $(document).ready(function(){
     $("button.button").click(function(){
      $("h1.about-title").fadeOut(300, function() {
       $("div.b").delay(500).fadeIn(300).delay(4000).fadeOut(300, function(){
        $("div.c").delay(500).fadeIn(300).delay(4000).fadeOut(300, function(){
         $("div.d").delay(500).fadeIn(300).delay(4000).fadeOut(300, function(){
          $("div.e").delay(500).fadeIn(300).delay(5000).fadeOut(300, function(){
           $("div.f").delay(500).fadeIn(300).delay(5000).fadeOut(300, function(){
            $("div.g").delay(500).fadeIn(300).delay(5000).fadeOut(300, function(){
             $("div.h").delay(500).fadeIn(300).delay(4000).fadeOut(300, function(){

               });         
              });          
             });          
            });   
           });         
          });
         }); 
        });
       }); 
      });
</script>

an example of this running can be found at http://www.erikgratz.com/about.html

I suspect I could have saved a lot of time and code with a loop or some variables. How would you accomplish this same effect?

\$\endgroup\$
  • 2
    \$\begingroup\$ You might want to change the title to "My life story in JavaScript. It might get more interest. You're Javascript code will be reviewed anyway. \$\endgroup\$ – pacmaninbw Jun 15 '18 at 22:38
4
\$\begingroup\$

Explicit question

Criticize my Javascript

So... you have some JavaScript that uses the jQuery library, and there are a lot of nested function calls. Obviously that isn't very flexible, and some might say it looks daunting with all of those nested callbacks.

Implicit question

i.e. How can I simplify this?

There are numerous ways to achieve this... but one way is to use function partials to simplify the callbacks.

Consider the function below, which checks for a next sibling element using .next():

function fadeInOutNext(elementCollection) {
   elementCollection.delay(500).fadeIn(300).delay(getDelayForElement(elementCollection)).fadeOut(300, function() {
     var next = elementCollection.next();
     if (next) {
       fadeInOutNext(next);
     }
   });
 }

With this function, the nested callbacks can be reduced:

$("button.button").click(function(){
 $("h1.about-title").fadeOut(300, fadeInOutNext.bind(null, $("div.b")));
});

As well as the function to get the delay between fading in and out:

function getDelayForElement(elementCollection) {
  if (elementCollection.is('.e, .f, .g')) {
    return 5000;
  }
  return 4000;
}

See the complete code in the snippet below:

 function getDelayForElement(elementCollection) {
  if (elementCollection.is('.e, .f, .g')) {
  	return 5000;
  }
 	return 4000;
 }
 function fadeInOutNext(elementCollection) {
   elementCollection.delay(500).fadeIn(300).delay(getDelayForElement(elementCollection)).fadeOut(300, function() {
     var next = elementCollection.next();
     if (next) {
       fadeInOutNext(next);
     }
   });
 }
 $(document).ready(function() {
   $("button.button").click(function(){
     $("h1.about-title").fadeOut(300, fadeInOutNext.bind(null, $("div.b")));
   });
 });
/* ------------------------------THE RESET----------------------------*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
  display: block;
}

body {
  line-height: 1;
  background-color: black;
}

ol,
ul {
  list-style: none;
}

blockquote,
q {
  quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

/*-----------MY CODE-----------*/

* {
  font-family: Futura, Futura-Medium, "Futura Medium", "Century Gothic", CenturyGothic, "Apple Gothic", AppleGothic, "URW Gothic L", "Avant Garde", sans-serif;
  color: white
}

.frontpage {
  font-family: Futura, Futura-Medium, "Futura Medium", "Century Gothic", CenturyGothic, "Apple Gothic", AppleGothic, "URW Gothic L", "Avant Garde", sans-serif;
  text-transform: uppercase;
  letter-spacing: 8px;
  font-size: 3.5em;
  text-align: center;
  padding-top: 1.25em;
  z-index: 1;
  position: relative;
  color: white;
  text-shadow: 0 0 15px black;
}

.frontname {
  font-size: 2em;
  padding-bottom: .2em;
}

.navbar {
  font-family: Futura, Futura-Medium, "Futura Medium", "Century Gothic", CenturyGothic, "Apple Gothic", AppleGothic, "URW Gothic L", "Avant Garde", sans-serif;
  letter-spacing: 3px;
  background-color: #000;
  position: fixed;
  top: 0;
  width: 100%;
  color: white;
  margin: 0px;
  padding 0px;
}

.name {
  float: left;
  padding: 2em;
  text-transform: uppercase;
}

.links {
  float: right;
  text-decoration: none;
  color: white;
  padding: 2em .45em;
}

.list {
  font-size: .45em;
  list-style-type: none;
  text-decoration: none;
}

a {
  text-decoration: none;
}

.pagetitle {
  text-align: center;
  font-size: 3em;
  text-transform: uppercase;
  letter-spacing: 4px;
}

.SDmain {
  margin-top: 45px;
}

/*----------PAGE SPECIFIC STYLES-----------*/

.contactinfo {
  text-align: center;
  letter-spacing: px;
  font-size: 1.5em;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.contact-social-media-block {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translate(-50%)
}

.sm {}

.contact-social-media {
  height: 8vh;
  width: 8vw;
}

.email-link {
  text-decoration: none;
}

.about-title {
  font-size: 10em;
  text-transform: uppercase;
  text-align: center;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.about-body {
  text-align: center;
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 2em;
}

.b {
  display: none;
}

.c {
  display: none;
}

.d {
  display: none;
}

.e {
  display: none;
  font-size: 1.5em;
}

.f {
  display: none;
}

.g {
  display: none;
}

.h {
  display: none;
}

.article {
  color: white;
  width: 85%;
  margin: auto;
  margin-top: 1em;
}

.article-title {
  font-size: 1.75em;
  text-transform: uppercase;
}

.article-sub,
.article-date,
.port-sub {
  font-family: helvetica;
  font-style: italic;
}

.article-body,
.port-desc {
  text-indent: 1.75em;
  line-height: 1.2em;
}

.port-table {
  display: table;
  margin-top: 1.25em;
}

.port-row {
  display: table-row;
  margin-top: 1.25em;
}

.port-image {
  display: table-cell;
  float: left;
  width: 35%;
  margin: 0 2.5%;
}

.port-text {
  display: table-cell;
  float: right;
  width: 55%;
  margin: 0 2.5%;
}

.port-title {
  font-size: 2em;
  text-transform: uppercase;
}

/*-----------Animations and JQuery---------*/

.button {
  background-color: transparent;
  border: none;
  color: white;
  padding: 10px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  text-align: center;
  position: fixed;
  bottom: 5%;
  left: 50%;
  transform: translate(-50%)
}

.preopen {
  left: 150% !important;
}

.open {
  left: 50% !important;
}

.closed {
  left: -50% !important;
}

.transition {
  -webkit-transition: left 0.3s ease-out;
  -moz-transition: left 0.3s ease-out;
  -o-transition: left 0.3s ease-out;
  transition: left 0.3s ease-out;
}

.preopen2 {
  opacity: 0 !important;
}

.open2 {
  opacity: 1 !important;
}

.closed2 {
  opacity: 0 !important;
}

.transition2 {
  -webkit-transition: opacity 0.3s ease-out;
  -moz-transition: opacity 0.3s ease-out;
  -o-transition: opacity 0.3s ease-out;
  transition: opacity 0.3s ease-out;
}

#text1 {
  min-width: 67vw;
}

/*------------------FERNTS-----------------*/

@font-face {
  font-family: Futura;
  src: url(fonts/futuramedium.otf) format('opentype');
}

@font-face {
  font-family: Futura-Medium;
  src: url(fonts/futural-webfont.svg);
}

/*----------VIDJER---------*/

#myVideo {
  position: fixed;
  right: 0;
  bottom: 0;
  min-width: 100%;
  min-height: 100%;
  z-index: 0;
}

/*-----------MEDIA QUERIES-------------*/

@media all and (min-width: 1800px) {
  .frontname {
    font-size: 5em;
  }
  .list {
    font-size: 1em;
  }
  .break {
    display: none;
  }
  .contactinfo {
    font-size: 4em;
    letter-spacing: 6px;
  }
  .pagetitle {
    padding-top: 1em;
    font-size: 11em;
  }
  .navbar {
    font-size: 3em;
  }
  .about-title {
    font-size: 40em;
  }
  .port-row {
    font-size: 3em;
  }
  .article {
    font-size: 3em;
  }
}

@media all and (min-width: 1200px) and (max-width: 1799px) {
  .frontname {
    font-size: 3em;
  }
  .list {
    font-size: 1em;
  }
  .break {
    display: none;
  }
  .contactinfo {
    font-size: 2em;
    letter-spacing: 6px;
  }
  .pagetitle {
    padding-top: 1em;
    font-size: 5em;
  }
  .navbar {
    font-size: 1.4em;
  }
}

@media all and (min-width: 900px) and (max-width: 1199px) {
  .break {
    display: none;
  }
  .contactinfo {
    font-size: 1em;
    letter-spacing: 4px;
  }
  .pagetitle {
    padding-top: 1em;
    font-size: 4.5em;
  }
  .navbar {
    font-size: 1em;
  }
}

@media all and (min-width: 600px) and (max-width: 899px) {
  .frontname {
    font-size: 2em;
  }
  .list {
    font-size: .6em
  }
  .contactinfo {
    letter-spacing: 4px;
  }
  .pagetitle {
    padding-top: 1em;
    font-size: 4.5em;
  }
  .navbar {
    font-size: 1em;
  }
}

@media all and (max-width: 599px) {
  .frontname {
    font-size: 1.4em
  }
  .list {
    font-size: .6em
  }
  .contactinfo {
    font-size: 1em;
    letter-spacing: 2px;
  }
  .pagetitle {
    font-size: 3em;
  }
  .navbar {
    font-size: .5em;
  }
  .about-title {
    font-size: 4em;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main class="SDmain">
  <h2 class="pagetitle"></h2>
  <h1 class="about-title" id="text0">Hello</h1>
  <div class="about-body b" id="text1">
    <p>Welcome.<br>My name is Erik. <br>I enjoy Minimalism.</p>
  </div>
  <div class="about-body c">
    <p>I made this happen with<br>Javascript and JQuery.
    </p>
  </div>
  <div class="about-body d">
    <p>I like Java as well.<br>Programs just make sense to me.
    </p>
  </div>
  <div class="about-body e">
    <p>I have made apps for android, websites for my friends, and I am looking for new projects.<br>You can find my other works in the Portfolio.
    </p>
  </div>
  <div class="about-body f">
    <p>I write about my life occasionally. If that interests you, it drains out of my head into my Blog.
    </p>
  </div>
  <div class="about-body g">
    <p>I am currently seeking my first job in Software Development.<br><br>My Resume can be found on the Contact page.
    </p>
  </div>
  <div class="about-body h">
    <p>Thank you for reading.
    </p>
  </div>
  <button class="button" id="b"> Play </button>
</main>

\$\endgroup\$
2
\$\begingroup\$

I have an alternative solution, which uses CSS animation.

Since the rest of divs (from ".b" to ".h") have the same effects, I added it to an animation name called intro, and the hello is using a fade animation called fade, and last thing is to use JavaScript to add the ani class to each div for different timing.

add the code below to style.css:

@keyframes fade{
    from{
        opacity: 1
    }
    to{
        opacity:0;
    }
}
@keyframes intro{
    0%{
        opacity:0;
    }
    30%,70%{
        opacity:1;
    }
    100%{
        opacity:0;
    }
}
.SDmain>*{
    animation-fill-mode: forwards;
    animation-timing-function: ease;
}
.about-title.ani{
    animation-name: fade;
    animation-duration: 1s;
}
.about-body.ani{
    display:block;
    animation-name: intro;
    animation-duration: 3s;
}

Then JavaScript can be as simple as:

let startingTime=-1500;
const gap=3000;
const startAniWhen=selector=>{
    setTimeout(()=>{
        $(selector).addClass("ani");
    },startingTime+=gap);
}

$(".button").click(()=>{
    $(".about-title").addClass("ani");
    for(let x of [".b",".c",".d",".e",".f",".g",".h"]) startAniWhen(x);
});

see example fiddle

\$\endgroup\$
  • 1
    \$\begingroup\$ I think using css is for best practice and better performance(this might be subtle to see) \$\endgroup\$ – Chase Jun 16 '18 at 1:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.