Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <body>
    <div id="quote-box"></div>
<!--The script below is used to test the Random Quote Machine submission.  Click on the options block with green bars in upper left of webpage.  Be sure that Random Quote Machine is selected from the drop-down before running the test, then click Tests button for more details.  There is JS code to automatically select the relevant test suite.-->
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
</body>
              
            
!

CSS

              
                body{
  background:rgb(0,128,43);
  color:rgb(0,128,43);
  text-decoration:none;
  display:flex;
  flex-direction:column;
  justify-content:center;
  margin:0;
  padding:0;
  overflow:hidden;
}

#lucky{
  margin:auto;
  margin-top:30px;
  width:200px;
  text-align:center;
  box-shadow:-5px 10px 20px black;
  border-radius:8px;
}

#quootietrap{
  display:flex;
  margin:auto;
  margin-top:30px;
  width:195px;
  text-align:center;
  box-shadow:-5px 10px 20px black;
  border-radius:8px;
  cursor:pointer;
}

#text{
  display:none;
  flex-direction:column;
  background-color:whitesmoke;
  margin:auto;
  width:600px;
  text-align:center;
  box-shadow:-5px 10px 20px black;
  border-radius:8px;
  font-size:1.2em;
}

#tweet-quote{
  display:none;
  background-color:#429cd6;
  color:white;
  height:2.5em;
  width:4em;
  padding:20px;
  border:2px solid #3c87b2;
  background-image:url("data:image/svg+xml;charsetutf-8,%3Csvg xmlns='http://www.w3.org/2000/svg'    viewBox='0 0 72 72'%3E%3Cpath class='icon' fill='%23fff' d='M68.812 15.14a26.189 26.189 0 0 1-7.52 2.06 13.125 13.125 0 0 0 5.757-7.243 26.133 26.133 0 0 1-8.314 3.176A13.066 13.066 0 0 0 49.182 9c-7.23 0-13.092 5.86-13.092 13.093 0 1.026.118 2.02.338 2.98C25.543 24.527 15.9 19.318 9.44 11.396a13.057 13.057 0 0 0-1.77 6.58c0 4.543 2.312 8.552 5.824 10.9a13.05 13.05 0 0 1-5.93-1.64c-.002.056-.002.11-.002.163 0 6.345 4.513 11.638 10.504 12.84-1.1.298-2.256.457-3.45.457-.845 0-1.666-.078-2.464-.23 1.667 5.2 6.5 8.985 12.23 9.09a26.29 26.29 0 0 1-16.26 5.605c-1.055 0-2.096-.06-3.122-.184a37.036 37.036 0 0 0 20.067 5.882c24.083 0 37.25-19.95 37.25-37.25 0-.565-.013-1.133-.038-1.693a26.61 26.61 0 0 0 6.532-6.774z'/%3E%3C/svg%3E");
  background-size:cover;
  background-position:center;
}

#new-quote,#cure{
  display:none;
  background-color:whitesmoke;
  width:8em;
}

#new-quote,#cure,#tweet-quote{
  flex-direction:row;
  margin:auto;
  margin-top:2em;
  text-align:center;
  box-shadow:-5px 10px 20px black;
  border-radius:3px;
  cursor:pointer;
}

#trap{
  stroke-width:0.5px;
  stroke:#000;
  cursor:pointer;
  position:fixed;
  top:10%;
  left:0;
  height:100%;
  width:100%;
}

#tf,#rf,#bf,#lf{
  fill-rule:evenodd;
  stroke-miterlimit:4;
}

.in{
  fill:#99ffe6;
  fill-opacity:1;
}

.out{
  fill:#ffff99;
  fill-opacity:1;
}

#face{
  fill:#aaeeff;
  fill-opacity:1;
  fill-rule:evenodd;
  stroke-linecap:butt;
  stroke-linejoin:miter;
  stroke-miterlimit:4;
}
              
            
!

JS

              
                //auto set tester script to relevant drop-down test suite
const projectName = "random-quote-machine";

//data
const quoteData = [
    {
        id: 0,
        quote: 'A wise man can learn more from a foolish question than a fool can learn from a wise answer.',
        author: 'Bruce Lee'
    },
    {
        id: 1,
        quote: 'You must be the change you wish to see in the world.',
        author: 'Mahatma Gandhi'
    },
    {
        id: 2,
        quote: 'A sense of humor is just common sense, dancing.',
        author: 'Clive James'
    },
    {
        id: 3,
        quote: 'So the lover must struggle for words.',
        author: 'T.S. Eliot'
    },
    {
        id: 4,
        quote: 'I am a kind of paranoid in reverse.  I suspect people of plotting to make me happy.',
        author: 'J. D. Salinger'
    },
    {
        id: 5,
        quote: 'I look to the future because that\'s where I\'m going to spend the rest of my life.',
        author: 'George Burns'
    },
    {
        id: 6,
        quote: 'I have not failed.  I\'ve just found 10,000 ways that won\'t work.',
        author: 'Thomas A. Edison'
    },
    {
        id: 7,
        quote: 'Pleasure in the job puts perfection in the work.',
        author: 'Aristotle'
    },
    {
        id: 8,
        quote: 'Life is really simple, but we insist on making it complicated.',
        author: 'Confucius'
    },
    {
        id: 9,
        quote: 'All morons hate it when you call them a moron.',
        author: 'J. D. Salinger'
    },
    {
        id: 10,
        quote: 'Wit is educated insolence.',
        author: 'Aristotle'
    },
    {
        id: 11,
        quote: 'A friend to all is a friend to none.',
        author: 'Aristotle'
    },
    {
        id: 12,
        quote: 'Fear is pain arising from the anticipation of evil.',
        author: 'Aristotle'
    },
    {
        id: 13,
        quote: 'I hear and I forget.  I see and I remember.  I do and I understand.',
        author: 'Confucius'
    },
    {
        id: 14,
        quote: 'Never give a sword to a man who cannot dance.',
        author: 'Confucius'
    },
    {
        id: 15,
        quote: 'Be sure to recycle your white trash.',
        author: 'M. T. Kramer'
    },
    {
        id: 16,
        quote: 'I\'d rather be lucky than good.',
        author: 'Vernon "Lefty" Gomez'
    },
    {
        id: 17,
        quote: 'It is better to travel well than to arrive.',
        author: 'Buddha'
    },
    {
        id: 18,
        quote: 'Everyone you will ever meet knows something you don\'t.',
        author: 'Bill Nye, "The Science Guy"'
    },
    {
        id: 19,
        quote: 'To succeed in life you need three things: a wishbone, a backbone, and a funny bone.',
        author: 'Reba McEntire'
    },
    {
        id: 20,
        quote: 'Laziness is nothing more than the habit of resting before you get tired.',
        author: 'Jules Renard'
    },
    {
        id: 21,
        quote: 'My fake plants died because I didn\'t pretend to water them.',
        author: 'Mitch Hedberg'
    },
    {
        id: 22,
        quote: 'I\'m sorry.  If you were right, I\'d agree with you.',
        author: 'Robin Williams'
    },
    {
        id: 23,
        quote: 'Any girl can be glamorous.  All you have to do is stand still and look stupid.',
        author: 'Hedy Lamarr'
    },
    {
        id: 24,
        quote: 'If I were two-faced, would I be wearing this one?',
        author: 'Abraham Lincoln'
    },
    {
        id: 25,
        quote: 'I never said most of the things I said.',
        author: 'Yogi Berra'
    },
    {
        id: 26,
        quote: 'If you\'re naturally kind, you can attract a lot of people you don\'t like.',
        author: 'William Feather'
    },
    {
        id: 27,
        quote: 'Even Napoleon had his Watergate.',
        author: 'Yogi Berra'
    },
    {
        id: 28,
        quote: 'Instant gratification takes too long.',
        author: 'Carrie Fisher'
    },
    {
        id: 29,
        quote: 'Imagination can often carry us to places that never were.  But without it we go nowhere.',
        author: 'Carl Sagan'
    },
    {
        id: 30,
        quote: 'Absence of evidence is not evidence of absence.',
        author: 'Carl Sagan'
    },
    {
        id: 31,
        quote: 'Most of the people that I deal with are human.  So I\'ve had a lot of experience with that.',
        author: 'Carl Sagan'
    },
    {
        id: 32,
        quote: 'I have a very strict gun control policy: if there\'s a gun around, I want to be in control of it.',
        author: 'Clint Eastwood'
    },
    {
        id: 33,
        quote: 'Nearly all men can stand adversity, but if you want to test a man\'s character, give him power.',
        author: 'Abraham Lincoln'
    },
    {
        id: 34,
        quote: 'Don\'t worry when you are not recognized, but strive to be worthy of recognition.',
        author: 'Abraham Lincoln'
    },
    {
        id: 35,
        quote: 'Do I not destroy my enemies when I make them my friends?',
        author: 'Abraham Lincoln'
    },
    {
        id: 36,
        quote: 'If this is coffee, please bring me some tea; but if this is tea, please bring me some coffee.',
        author: 'Abraham Lincoln'
    },
    {
        id: 37,
        quote: 'My favorite shorts have holes in the knees.',
        author: 'M. T. Kramer'
    },
    {
        id: 38,
        quote: 'I have great respect for the semicolon; it is a mighty handy little fellow.',
        author: 'Abraham Lincoln'
    },
    {
        id: 39,
        quote: 'It is a great piece of folly to attempt to make anything out of my early life.',
        author: 'Abraham Lincoln'
    },
    {
        id: 40,
        quote: 'If you can\'t explain it simply, you don\'t understand it well enough.',
        author: 'Albert Einstein'
    },
    {
        id: 41,
        quote: 'Any man who can drive safely while kissing a pretty girl is not giving the kiss the attention it deserves.',
        author: 'Albert Einstein'
    },
    {
        id: 42,
        quote: 'The only reason for time is so that everything doesn\'t happen at once.',
        author: 'Albert Einstein'
    },
    {
        id: 43,
        quote: 'Figuring things out for yourself is the only freedom anyone really has.  Use that freedom.  Make up your own mind, Rico.',
        author: 'Starship Troopers(1997) - Jean Rasczak (Michael Ironside)'
    },
    {
        id: 44,
        quote: 'The two most important days in your life are the day you are born and the day you find out why.',
        author: 'Mark Twain'
    },
    {
        id: 45,
        quote: 'Be kind, for everyone is fighting a hard battle.',
        author: 'Plato'
    },
    {
        id: 46,
        quote: 'Courage is knowing what not to fear.',
        author: 'Plato'
    },
    {
        id: 47,
        quote: 'To speak another language is to have another soul.',
        author: 'Charlemagne'
    }
];

//components
//word component
class LuckyWord extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            word: ''
        };
    }

    handleChange = (e) => {
        this.setState({ word: e.target.value });
    }

    render() {
        const word = this.state.word;
        return (
            <form id="lucky" onSubmit={() => this.props.handleSubmit(word)}>
                <input
                    onChange={this.handleChange}
                    value={this.state.word}
                    placeholder="Enter Your Lucky Word"
                ></input>
            </form>
        );
    }
}
//share button
//works if you open new tab/window
class ShareButton extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        const tweetHref = 'https://twitter.com/intent/tweet?text=' + encodeURIComponent('"' + this.props.quote + '" ' + this.props.author);
        return (
            <a
                id="tweet-quote"
                href={tweetHref}
                className="twitter-share-button"
                data-size="Large"
                title="Tweet this quote!"
            ></a>
        );
    }
}
//new quote button
class NewQuoteButton extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <button
                id="new-quote"
                onClick={this.props.handleNewQuote}
            >TRAP MORE QUOOTIES?</button>
        );
    }
}
//cure button
class CureButton extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <button
                id="cure"
                onClick={this.props.handleCure}
            >CURE QUOOTIES?</button>
        );
    }
}

//wrapper parent
class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            quotes: quoteData,
            firstQuote: {},
            secondQuote: {},
            thirdQuote: {},
            fourthQuote: {},
            quoteShow: 1,
            wordValue: 0,
            firstOption: {},
            secondOption: {},
        };
    }

    componentDidMount = () => {
        const len = this.state.quotes.length;
        function rand() { return Math.floor(Math.random() * len); }
        const firstQuote = this.state.quotes[rand()];
        this.setState({ firstQuote: firstQuote });
        const secondQuote = this.state.quotes[rand()];
        this.setState({ secondQuote: secondQuote });
        const thirdQuote = this.state.quotes[rand()];
        this.setState({ thirdQuote: thirdQuote });
        const fourthQuote = this.state.quotes[rand()];
        this.setState({ fourthQuote: fourthQuote });
        this.flapChoice();
        spin(3);
    }

    flapChoice = () => {
        this.state.quoteShow === 1 ?
            this.setState(prevState => ({
                firstOption: prevState.firstQuote,
                secondOption: prevState.thirdQuote
            }), () => {  }
            ) :
            this.state.quoteShow === 2 ?
                this.setState(prevState => ({
                    firstOption: prevState.secondQuote,
                    secondOption: prevState.fourthQuote
                }), () => {  }
                ) :
                this.state.quoteShow === 3 ?
                    this.setState(prevState => ({
                        firstOption: prevState.thirdQuote,
                        secondOption: prevState.firstQuote
                    }), () => {  }
                    ) :
                    this.state.quoteShow === 4 ?
                        this.setState(prevState => ({
                            firstOption: prevState.fourthQuote,
                            secondOption: prevState.secondQuote
                        }), () => {  }
                        ) :
                        null;
    }

    handleSubmit = (word) => {
        event.preventDefault();
        const wordValue = word.length;
        this.setState(() => {
            return { wordValue: wordValue };
        },
            () => {
                const quoteShow = this.state.wordValue % 4;
                this.setState(prevState => {
                    return {
                        quoteShow: prevState.quoteShow + quoteShow
                    };
                },
                    () => {
                        this.flapChoice();
                        wordCount(wordValue);
                    }
                )
            }
        )
    }

    onClick = (e) => {
        if (e.target.value === 2) {
            this.setState(prevState => {
                return { firstOption: prevState.secondOption };
            }, () => {
                    $('quootietrap').style.visibility = "hidden";
                    $('trap').style.display = "none";
                    $('text').style.display = "flex";
                    $('new-quote').style.display = "flex";
                    $('cure').style.display = "flex";
                    $('tweet-quote').style.display = "flex";
                }
            );
        }
        $('quootietrap').style.visibility = "hidden";
        $('trap').style.display = "none";
        $('text').style.display = "flex";
        $('new-quote').style.display = "flex";
        $('cure').style.display = "flex";
        $('tweet-quote').style.display = "flex";
    }

    handleNewQuote = () => {
        this.setState(() => {
            return {
                quotes: quoteData,
                firstQuote: {},
                secondQuote: {},
                thirdQuote: {},
                fourthQuote: {},
                quoteShow: 1,
                wordValue: 0,
                firstOption: {},
                secondOption: {},
            };
        },
            () => {
                const len = this.state.quotes.length;
                function rand() { return Math.floor(Math.random() * len); }
                const firstQuote = this.state.quotes[rand()];
                this.setState({ firstQuote: firstQuote });
                const secondQuote = this.state.quotes[rand()];
                this.setState({ secondQuote: secondQuote });
                const thirdQuote = this.state.quotes[rand()];
                this.setState({ thirdQuote: thirdQuote });
                const fourthQuote = this.state.quotes[rand()];
                this.setState({ fourthQuote: fourthQuote });
                this.flapChoice();
                $('trap').style.display = "flex";
                $('trap').style.opacity = "1";
                $('text').style.display = "none";
                $('new-quote').style.display = "none";
                $('cure').style.display = "none";
                $('tweet-quote').style.display = "none";
            }
        );
    }

    handleCure = () => {
        $('trap').style.display = "flex";
        $('text').style.display = "none";
        $('tweet-quote').style.display = "none";
        $('cure').style.display = "none";
        cureQuooties();
    }

    render() {
        console.log('RENDERING!');
        return (
            <main>

                {!this.state.wordValue ? <LuckyWord handleSubmit={this.handleSubmit} /> : null}

                <div id="quootietrap">
                    {this.state.wordValue ? <button
                        onClick={this.onClick}
                        value={1}
                    >Open here?</button> : null}
                    {this.state.wordValue ? <button
                        onClick={this.onClick}
                        value={2}
                    >Or, open here?</button> : null}
                </div>

                <svg id="trap" viewBox="-25 -25 142 125" preserveAspectRatio="xMidYMid meet">
                        <g id="tf">
                            <path id="tf_il" className="in"
                                d="M 46.047,9.745 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="tf_ir" className="in"
                                d="M 46.047,9.745 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="tf_ol" className="out"
                                d="M 46.047,9.745 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="tf_or" className="out"
                                d="M 46.047,9.745 46.047,39.327 46.047,39.327 Z"
                            />
                        </g>
                        <g id="rf">
                            <path id="rf_it" className="in"
                                d="M 77.783,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="rf_ib" className="in"
                                d="M 77.783,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="rf_ot" className="out"
                                d="M 77.783,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="rf_ob" className="out"
                                d="M 77.783,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                        </g>
                        <g id="bf">
                            <path id="bf_ir" className="in"
                                d="M 46.047,69.649 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="bf_il" className="in"
                                d="M 46.047,69.649 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="bf_or" className="out"
                                d="M 46.047,69.649 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="bf_ol" className="out"
                                d="M 46.047,69.649 46.047,39.327 46.047,39.327 Z"
                            />
                        </g>
                        <g id="lf">
                            <path id="lf_ib" className="in"
                                d="M 14.459,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="lf_it" className="in"
                                d="M 14.459,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="lf_ob" className="out"
                                d="M 14.459,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                            <path id="lf_ot" className="out"
                                d="M 14.459,39.327 46.047,39.327 46.047,39.327 Z"
                            />
                        </g>
                        <g id="face">
                            <path id="tl_1" onClick={this.onClick} value={1}
                                d="M 14.459,39.369 C 12.279,35.580 8.985,8.170 11.101,4.487 L 46.047,39.327 Z"
                            />
                            <path id="tl_2"
                                d="M 46.110,9.745 C 42.322,7.564 14.784,2.370 11.101,4.487 L 46.047,39.327 Z"
                            />
                            <path id="tr_1"
                                d="M 46.110,9.745 C 49.899,7.564 77.204,2.370 80.866,4.487 L 46.047,39.327 Z"
                            />
                            <path id="tr_2"
                                d="M 77.783,39.496 C 79.963,35.707 82.983,8.170 80.866,4.487 L 46.047,39.327 Z"
                            />
                            <path id="br_1"
                                d="M 77.783,39.496 C 79.963,43.285 82.983,70.590 80.866,74.252 L 46.047,39.327 Z"
                            />
                            <path id="br_2"
                                d="M 46.047,69.649 C 49.773,71.829 77.204,76.368 80.866,74.252 L 46.047,39.327 Z"
                            />
                            <path id="bl_1"
                                d="M 46.047,69.649 C 42.195,71.829 14.784,76.368 11.101,74.252 L 46.047,39.327 Z"
                            />
                            <path id="bl_2"
                                d="M 14.459,39.369 C 12.279,43.158 8.985,70.590 11.101,74.252 L 46.047,39.327 Z"
                            />
                        </g>
                            </svg>

                <div id="text">
                    <h1>"{this.state.firstOption.quote}"</h1>
                    <h2 id="author">-{this.state.firstOption.author}</h2>
                </div>
                <NewQuoteButton handleNewQuote={this.handleNewQuote} />

                <CureButton handleCure={this.handleCure} />

                <ShareButton quote={this.state.firstOption.quote} author={this.state.firstOption.author} />
            </main>
        );
    }
}
ReactDOM.render(<App />, $('quote-box'));

//helper functions
function $(x) { return document.getElementById(x) };

//animation functions
//spin
function spin(rep) {
    const SPD = 2;
    let spinAni = new TimelineMax({ ease: Power4.easeInOut });
    spinAni.to($('trap'), SPD, { rotation: 360 * rep });
    return spinAni;
}
//open vertical
function vertAni() {
    const SPD = .15;
    let vertAni = new TimelineMax({ yoyo: true, repeat: 1, ease: Power4.easeIn });
    vertAni
        //tf
        .to($('tf_il'), SPD, { attr: { d: "M 45.984,4.550 46.047,39.433 46.047,39.433 Z" } }, 0)
        .to($('tf_ol'), SPD, { attr: { d: "M 45.984,4.550 46.047,39.433 46.047,39.433 Z" } }, 0)
        .to($('tf_or'), SPD, { attr: { d: "M 45.984,4.550 46.047,39.433 46.047,39.433 Z" } }, 0)
        //rf                                                                                                   
        .to($('rf_it'), SPD, { attr: { d: "M 80.824,39.369 46.047,39.433 46.047,20.936 Z" } }, 0)
        .to($('rf_ib'), SPD, { attr: { d: "M 80.824,39.369 46.047,39.433 46.047,53.516 Z" } }, 0)
        .to($('rf_ot'), SPD, { attr: { d: "M 80.824,39.369 46.047,39.433 46.047,20.936 Z" } }, 0)
        .to($('rf_ob'), SPD, { attr: { d: "M 80.824,39.369 46.047,39.433 46.047,53.516 Z" } }, 0)
        //bf                                                                                                   
        .to($('bf_ir'), SPD, { attr: { d: "M 46.047,74.209 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('bf_il'), SPD, { attr: { d: "M 46.047,74.209 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('bf_or'), SPD, { attr: { d: "M 46.047,74.209 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('bf_ol'), SPD, { attr: { d: "M 46.047,74.209 46.047,39.327 46.047,39.327 Z" } }, 0)
        //lf                                                                                                   
        .to($('lf_ib'), SPD, { attr: { d: "M 11.165,39.369 46.047,39.327 46.047 53.516 Z" } }, 0)
        .to($('lf_it'), SPD, { attr: { d: "M 11.165,39.369 46.047,39.327 46.047,20.936 Z" } }, 0)
        .to($('lf_ob'), SPD, { attr: { d: "M 11.165,39.369 46.047,39.327 46.047 53.516 Z" } }, 0)
        .to($('lf_ot'), SPD, { attr: { d: "M 11.165,39.369 46.047,39.433 46.047,20.936 Z" } }, 0)
        //face
        .to($('tl_1'), SPD, { attr: { d: "M 11.165,39.369 C 8.985,35.580 -2.343,11.464 0.459,7.781 L 46.047,20.936 Z" } }, 0)
        .to($('tl_2'), SPD, { attr: { d: "M 45.984,4.550 C 42.195,2.370 4.142,5.664 0.459,7.781 L 46.047,20.936 Z" } }, 0)
        .to($('tr_1'), SPD, { attr: { d: "M 45.984,4.550 C 49.773,2.370 81.765,5.411 85.427,7.527 L 46.047,20.936 Z" } }, 0)
        .to($('tr_2'), SPD, { attr: { d: "M 80.824,39.369 C 83.007,35.580 87.544,11.210 85.427,7.527 L 46.047,20.936 Z" } }, 0)
        .to($('br_1'), SPD, { attr: { d: "M 80.824,39.369 C 83.007,43.158 89.824,70.083 87.708,73.745 L 46.047,53.516 Z" } }, 0)
        .to($('br_2'), SPD, { attr: { d: "M 45.984,74.209 C 49.773,76.389 84.046,75.862 87.708,73.745 L 46.047,53.516 Z" } }, 0)
        .to($('bl_1'), SPD, { attr: { d: "M 45.984,74.209 C 42.195,76.389 8.957,74.848 5.274,72.731 L 46.047,53.516 Z" } }, 0)
        .to($('bl_2'), SPD, { attr: { d: "M 11.165,39.369 C 8.985,43.158 3.157,69.070 5.274,72.731 L 46.047,53.516 Z" } }, 0)
        ;
    return vertAni;
}
//open horizontal
function horiAni() {
    const SPD = .15;
    let horiAni = new TimelineMax({ yoyo: true, repeat: 1, ease: Power4.easeIn });
    horiAni
        //tf
        .to($('tf_il'), SPD, { attr: { d: "M 46.047,13.686 46.047,39.327 28.489,39.327 Z" } }, 0)
        .to($('tf_ir'), SPD, { attr: { d: "M 46.047,13.686 46.047,39.327 77.783,39.327 Z" } }, 0)
        .to($('tf_ol'), SPD, { attr: { d: "M 46.047,13.686 46.047,39.327 28.489,39.327 Z" } }, 0)
        .to($('tf_or'), SPD, { attr: { d: "M 46.047,13.686 46.047,39.327 77.783,39.327 Z" } }, 0)
        //rf
        .to($('rf_it'), SPD, { attr: { d: "M 81.008,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('rf_ib'), SPD, { attr: { d: "M 81.008,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('rf_ot'), SPD, { attr: { d: "M 81.008,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('rf_ob'), SPD, { attr: { d: "M 81.008,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        //bf
        .to($('bf_ir'), SPD, { attr: { d: "M 46.047,67.186 46.047,39.327 77.783,39.327 Z" } }, 0)
        .to($('bf_il'), SPD, { attr: { d: "M 46.047,67.186 46.047,39.327 28.489,39.327 Z" } }, 0)
        .to($('bf_or'), SPD, { attr: { d: "M 46.047,67.186 46.047,39.327 77.783,39.327 Z" } }, 0)
        .to($('bf_ol'), SPD, { attr: { d: "M 46.047,67.186 46.047,39.327 28.489,39.327 Z" } }, 0)
        //lf
        .to($('lf_ib'), SPD, { attr: { d: "M 11.234,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('lf_it'), SPD, { attr: { d: "M 11.234,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('lf_ob'), SPD, { attr: { d: "M 11.234,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        .to($('lf_ot'), SPD, { attr: { d: "M 11.234,39.327 46.047,39.327 46.047,39.327 Z" } }, 0)
        //face
        .to($('tl_1'), SPD, { attr: { d: "M 11.234,39.190 C 9.054,35.401 3.431,10.678 5.547,6.995 L 28.489,39.327 Z" } }, 0)
        .to($('tl_2'), SPD, { attr: { d: "M 46.290,13.686 C 42.501,11.506 9.230,4.879 5.547,6.995 L 28.489,39.327 Z" } }, 0)
        .to($('tr_1'), SPD, { attr: { d: "M 46.290,13.686 C 50.078,11.506 81.325,5.058 84.987,7.174 L 69.649,39.327 Z" } }, 0)
        .to($('tr_2'), SPD, { attr: { d: "M 81.008,39.138 C 83.188,35.349 87.104,10.857 84.987,7.174 L 69.649,39.327 Z" } }, 0)
        .to($('br_1'), SPD, { attr: { d: "M 81.008,39.138 C 83.188,42.926 88.895,68.261 86.779,71.922 L 69.649,39.327 Z" } }, 0)
        .to($('br_2'), SPD, { attr: { d: "M 46.047,67.186 C 49.593,68.245 83.117,74.039 86.779,71.922 L 69.649,39.327 Z" } }, 0)
        .to($('bl_1'), SPD, { attr: { d: "M 46.047,67.186 C 42.016,68.245 9.947,72.964 6.264,70.847 L 28.489,39.327 Z" } }, 0)
        .to($('bl_2'), SPD, { attr: { d: "M 11.234,39.190 C 9.054,42.979 4.147,67.186 6.264,70.847 L 28.489,39.327 Z" } }, 0)
        ;
    return horiAni;
}
//open to letter count
function wordCount(rep) {
    function show() { $('quootietrap').style.visibility = "visible"; };
    let wordCount = new TimelineMax({ onComplete: show });
    for (let i = 0; i < rep; i++) {
        if (i % 2 === 0) { wordCount.add(vertAni(), i*.5); };
        if (i % 2 === 1) { wordCount.add(horiAni(), i*.5); };
    }
    return wordCount;
}
//open full ('top','right','bottom','left')
function openAni(which) {
    const SPD = 2;
    let openAni = new TimelineMax({ yoyo: true, ease: Power3.easeInOut });
    //tf
    openAni
        .to($('tf_il'), SPD, { attr: { d: "M 46.110,9.745 46.047,39.433 14.335,9.691 Z" } }, 0)
        .to($('tf_ir'), SPD, { attr: { d: "M 46.110,9.745 46.047,39.433 77.475,8.974 Z" } }, 0)
        .to($('tf_ol'), SPD, { attr: { d: "M 46.110,9.745 46.047,39.433 14.335,9.691 Z" } }, 0)
        .to($('tf_or'), SPD, { attr: { d: "M 46.110,9.745 46.047,39.433 77.475,8.974 Z" } }, 0)
        //rf
        .to($('rf_it'), SPD, { attr: { d: "M 77.783,39.496 45.941,39.433 77.475,8.974 Z" } }, 0)
        .to($('rf_ib'), SPD, { attr: { d: "M 77.783,39.496 45.941,39.433 77.296,69.965 Z" } }, 0)
        .to($('rf_ot'), SPD, { attr: { d: "M 77.783,39.496 45.941,39.433 77.475,8.974 Z" } }, 0)
        .to($('rf_ob'), SPD, { attr: { d: "M 77.783,39.496 45.941,39.433 77.296,69.965 Z" } }, 0)
        //bf
        .to($('bf_ir'), SPD, { attr: { d: "M 45.984,69.649 45.941,39.327 77.296,69.965 Z" } }, 0)
        .to($('bf_il'), SPD, { attr: { d: "M 45.984,69.649 45.941,39.327 13.797,70.323 Z" } }, 0)
        .to($('bf_or'), SPD, { attr: { d: "M 45.984,69.649 45.941,39.327 77.296,69.965 Z" } }, 0)
        .to($('bf_ol'), SPD, { attr: { d: "M 45.984,69.649 45.941,39.327 13.797,70.323 Z" } }, 0)
        //lf
        .to($('lf_ib'), SPD, { attr: { d: "M 14.459,39.369 46.047,39.327 13.797,70.323 Z" } }, 0)
        .to($('lf_it'), SPD, { attr: { d: "M 14.459,39.369 46.047,39.327 14.335,9.691 Z" } }, 0)
        .to($('lf_ob'), SPD, { attr: { d: "M 14.459,39.369 46.047,39.327 13.797,70.323 Z" } }, 0)
        .to($('lf_ot'), SPD, { attr: { d: "M 14.459,39.369 46.047,39.327 14.335,9.691 Z" } }, 0)
        //face
        .to($('tl_1'), SPD, { attr: { d: "M 14.459,39.369 C 27.508,37.551 37.016,38.531 45.941,39.327 L 14.335,9.691 Z" } }, 0)
        .to($('tl_2'), SPD, { attr: { d: "M 46.110,9.745 C 45.188,18.673 44.787,32.910 45.941,39.327 L 14.335,9.691 Z" } }, 0)
        .to($('tr_1'), SPD, { attr: { d: "M 46.110,9.745 C 46.316,14.194 45.431,33.627 46.047,39.327 L 77.475,8.974 Z" } }, 0)
        .to($('tr_2'), SPD, { attr: { d: "M 77.783,39.496 C 72.259,38.753 52.643,39.068 46.047,39.327 L 77.475,8.974 Z" } }, 0)
        .to($('br_1'), SPD, { attr: { d: "M 77.783,39.496 C 66.884,41.493 56.227,40.250 46.047,39.433 L 77.296,69.965 Z" } }, 0)
        .to($('br_2'), SPD, { attr: { d: "M 45.984,69.649 C 46.010,60.899 45.431,44.954 46.047,39.433 L 77.296,69.965 Z" } }, 0)
        .to($('bl_1'), SPD, { attr: { d: "M 45.984,69.649 C 45.241,58.391 43.891,51.045 45.941,39.433 L 13.797,70.323 Z" } }, 0)
        .to($('bl_2'), SPD, { attr: { d: "M 14.459,39.369 C 30.733,39.933 35.404,39.175 45.941,39.433 L 13.797,70.323 Z" } }, 0)
        .to($('face'), 0, { fillOpacity: 0, strokeOpacity: 0 }, .65)
        ;
    //open top
    if (which === 'top') {
        let openTopAni =
            openAni
                .to($('tf_ol'), SPD, { attr: { d: "M 46.110,9.745 46.406,-22.637 14.335,9.691 Z" } }, 2)
                .to($('tf_or'), SPD, { attr: { d: "M 46.110,9.745 46.406,-22.637 77.475,8.974 Z" } }, 2)
                .to($('tf_ol'), 0, { fill: '#99ffe6' }, 2.65)
                .to($('tf_or'), 0, { fill: '#99ffe6' }, 2.65)
            ;
        return openTopAni;
    }
    //open right
    if (which === 'right') {
        let openRightAni =
            openAni
                .to('#rf_ot', SPD, { attr: { d: "M 77.783,39.496 108.292,39.970 77.475,8.974 Z" } }, 2)
                .to('#rf_ob', SPD, { attr: { d: "M 77.783,39.496 108.292,39.970 77.296,69.965 Z" } }, 2)
                .to('#rf_ot,#rf_ob', 0, { fill: '#99ffe6' }, 2.65)
            ;
        return openRightAni;
    }
    //open bottom
    if (which === 'bottom') {
        let openBottomAni =
            openAni
                .to($('bf_or'), SPD, { attr: { d: "M 45.984,69.649 45.762,100.961 77.296,69.965 Z" } }, 2)
                .to($('bf_ol'), SPD, { attr: { d: "M 45.984,69.649 45.762,100.961 13.797,70.323 Z" } }, 2)
                .to($('bf_or'), 0, { fill: '#99ffe6' }, 2.65)
                .to($('bf_ol'), 0, { fill: '#99ffe6' }, 2.65)
            ;
        return openBottomAni;
    }
    //open left
    if (which === 'left') {
        let openLeftAni =
            openAni
                .to($('lf_ob'), SPD, { attr: { d: "M 14.459,39.369 -39.397,39.327 13.797,70.323 Z" } }, 2)
                .to($('lf_ot'), SPD, { attr: { d: "M 14.459,39.369 -39.397,39.327 14.335,9.691 Z" } }, 2)
                .to($('lf_ob'), 0, { fill: '#99ffe6' }, 2.65)
                .to($('lf_ot'), 0, { fill: '#99ffe6' }, 2.65)
            ;
        return openLeftAni;
    }
}
//cure quooties
function cureQuooties() {
    const SPD = 1;
    let tl = new TimelineMax({ repeat: 1, yoyo: true, ease: Power4.easeOut });
    tl
        .to($('tf_il'), SPD, { attr: { d: "M 49.9,-67.7 V -38.2 L 33.8,-54.5 Z" } }, 0)
        .to($('tf_ir'), SPD, { attr: { d: "M 59.4,-57.2 V -27.7 L 74,-32.2 Z" } }, 0)
        .to($('tf_ol'), SPD, { attr: { d: "M 33.8,-54.5 31.9,-83.3 17.6,-60.4 Z" } }, 0)
        .to($('tf_or'), SPD, { attr: { d: "M 66.4,-61.1 69.9,-86.3 85.4,-40.9 Z" } }, 0)
        //rf
        .to($('rf_it'), SPD, { attr: { d: "M 175,23 H 143 L 152,7.89 Z" } }, 0)
        .to($('rf_ib'), SPD, { attr: { d: "M 174,37.2 H 142 L 151,52.4 Z" } }, 0)
        .to($('rf_ot'), SPD, { attr: { d: "M 161,-1.49 188,0.211 166,9.41 Z" } }, 0)
        .to($('rf_ob'), SPD, { attr: { d: "M 169,58.5 196,60 156,78.8 Z" } }, 0)
        //bf
        .to($('bf_ir'), SPD, { attr: { d: "M 57.4,148 V 118 L 78,141 Z" } }, 0)
        .to($('bf_il'), SPD, { attr: { d: "M 50.1,162 V 132 L 32,122 Z" } }, 0)
        .to($('bf_or'), SPD, { attr: { d: "M 54.7,156 66.7,197 84.3,136 Z" } }, 0)
        .to($('bf_ol'), SPD, { attr: { d: "M 41.9,146 24.9,176 12.1,125 Z" } }, 0)
        //lf
        .to($('lf_ib'), SPD, { attr: { d: "M -128,38.1 H -96.1 L -98.2,59.8 Z" } }, 0)
        .to($('lf_it'), SPD, { attr: { d: "M -98.8,29.3 H -67.3 L -72.7,12.2 Z" } }, 0)
        .to($('lf_ob'), SPD, { attr: { d: "M -72.8,47.3 -94.7,49.1 -66.1,61.7 Z" } }, 0)
        .to($('lf_ot'), SPD, { attr: { d: "M -81.5,19.8 -121,16.7 -77.2,1.08 Z" } }, 0)
        //face
        .to($('tl_1'), SPD, { attr: { d: "M -82.6,-19.8 C -84.8,-23.5 -88.1,-51 -86,-54.6 L -51,-19.8 Z" } }, 0)
        .to($('tl_2'), SPD, { attr: { d: "M -8.43,-71.2 C -12.2,-73.4 -39.8,-78.6 -43.4,-76.5 L -8.53,-41.6 Z" } }, 0)
        .to($('tr_1'), SPD, { attr: { d: "M 132,-80.8 C 135,-83 163,-88.1 166,-86 L 132,-51.2 Z" } }, 0)
        .to($('tr_2'), SPD, { attr: { d: "M 188,-29.4 C 191,-33.2 194,-60.7 192,-64.4 L 157,-29.5 Z" } }, 0)
        .to($('br_1'), SPD, { attr: { d: "M 171,96.1 C 173,99.9 176,127 174,131 L 139,96 Z" } }, 0)
        .to($('br_2'), SPD, { attr: { d: "M 117,137 C 120,139 148,143 152,141 L 117,107 Z" } }, 0)
        .to($('bl_1'), SPD, { attr: { d: "M -5.32,139 C -9.22,141 -36.6,145 -40.3,143 L -5.32,109 Z" } }, 0)
        .to($('bl_2'), SPD, { attr: { d: "M -87.9,85.6 C -90.1,89.4 -93.4,117 -91.3,121 L -56.3,85.6 Z" } }, 0)
        ;
    return tl.to($('trap'), 1, { opacity: 0, onComplete: () => $('trap').style.display = "none" }, SPD);
}
              
            
!
999px

Console