From 33d4bfd93e5e1b50177f11187c42b46a5a35f180 Mon Sep 17 00:00:00 2001 From: andff Date: Fri, 6 Dec 2024 15:26:59 -0300 Subject: [PATCH] update --- .../index.html | 99 ++++++ .../script.js | 262 ++++++++++++++++ .../style.css | 282 ++++++++++++++++++ 3 files changed, 643 insertions(+) create mode 100644 nested-color-coded-interactive-timeline/index.html create mode 100644 nested-color-coded-interactive-timeline/script.js create mode 100644 nested-color-coded-interactive-timeline/style.css diff --git a/nested-color-coded-interactive-timeline/index.html b/nested-color-coded-interactive-timeline/index.html new file mode 100644 index 0000000..fbe425e --- /dev/null +++ b/nested-color-coded-interactive-timeline/index.html @@ -0,0 +1,99 @@ + + + + + CodePen - Nested & Color Coded Interactive Timeline + + + + + +
+ +
+ + +
+
+

181x-181x

+

1 Lorem ipsum dolor sit amet, consectetur adipisicing.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium doloremque, laboriosam officia facere eligendi quam reiciendis, rem explicabo dolores tenetur libero minus, facilis quibusdam. Consectetur amet beatae fuga, architecto magnam.

+
+
+

182x-182x

+

2 Lorem ipsum dolor sit amet, consectetur adipisicing.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium doloremque, laboriosam officia facere eligendi quam reiciendis, rem explicabo dolores tenetur libero minus, facilis quibusdam. Consectetur amet beatae fuga, architecto magnam.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium doloremque, laboriosam officia facere eligendi quam reiciendis, rem explicabo dolores tenetur libero minus, facilis quibusdam. Consectetur amet beatae fuga, architecto magnam.

+
+
+

183x-183x

+

3 Lorem ipsum dolor sit amet, consectetur adipisicing.

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium doloremque, laboriosam officia facere eligendi quam reiciendis, rem explicabo dolores tenetur libero minus, facilis quibusdam. Consectetur amet beatae fuga, architecto magnam.

+
+
+
+
+ + + +
+ +
+ +
+
+
+ + + +
+
+

1816

+

Lorem ipsum dolor sit amet.

+
+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore vitae sint dolore, officia esse! A recusandae nemo illum rem eos iusto repellendus, voluptatibus tempora nulla voluptatem officia inventore ea modi.

+
+
+
+

1816

+

Lorem ipsum dolor sit amet.

+
+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore vitae sint dolore, officia esse! A recusandae nemo illum rem eos iusto repellendus, voluptatibus tempora nulla voluptatem officia inventore ea modi.

+
+
+
+

1816

+

Lorem ipsum dolor sit amet.

+
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. A tempora blanditiis ut voluptas nisi labore quos iste totam obcaecati modi rerum iusto, voluptate odio commodi ratione amet illum dicta accusamus, ipsum ea vero neque enim, recusandae dignissimos? Quae ea aspernatur dolor atque, ipsum repellendus. Repudiandae culpa magnam, doloribus exercitationem illo impedit quasi officia, veniam vero molestiae sunt dolorem, excepturi ullam dicta sed amet provident ut soluta pariatur magni! Fugiat eveniet suscipit praesentium culpa aperiam ab nulla, exercitationem atque quod, labore, qui quaerat nihil nam laborum aliquam! Nesciunt dignissimos eaque impedit ex, architecto minima ad, temporibus rem possimus consequatur doloremque, fuga?

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore vitae sint dolore, officia esse! A recusandae nemo illum rem eos iusto repellendus, voluptatibus tempora nulla voluptatem officia inventore ea modi.

+
+
+
+

1816

+

Lorem ipsum dolor sit amet.

+
+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore vitae sint dolore, officia esse! A recusandae nemo illum rem eos iusto repellendus, voluptatibus tempora nulla voluptatem officia inventore ea modi.

+
+
+
+

1816

+

Lorem ipsum dolor sit amet.

+
+ +

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Tempore vitae sint dolore, officia esse! A recusandae nemo illum rem eos iusto repellendus, voluptatibus tempora nulla voluptatem officia inventore ea modi.

+
+
+
+ + +
+ +
+ + + + + diff --git a/nested-color-coded-interactive-timeline/script.js b/nested-color-coded-interactive-timeline/script.js new file mode 100644 index 0000000..48e8387 --- /dev/null +++ b/nested-color-coded-interactive-timeline/script.js @@ -0,0 +1,262 @@ +"use strict"; +class PRESTimeline { + constructor(target, color) { + // this.__process_stylesheet(document.styleSheets[0]); + this.base = target; + this.color = color; + // console.log(this.color) + this.periodContainer = $(this.base).find('.periods-container'); + this.cardContainer = $(this.base).find('.cards-container'); + this.timelineNodeContainer = $(this.base).find('.timeline-container .timeline'); + // this.activePeriod = $(this.base).find('.periods-container section.active') + this._parseData(); + this._initialColor(); + this._generateTimeline(); + this._setStateClasses(); + this._assignBtn(); + this._adjustPeriodContainer(); + this._adjustCardContainer(); + // console.log(this.cardData) + } + _parseData() { + let base = this.base; + let periods = $(base).find('.periods-container section'); + for (let section of periods) { + section.period = $(section).attr('period'); + section.index = $(section).index(); + } + // console.log(periods) + this.periodData = periods; + let data = $(base).find('.cards-container section'); + // console.log(data) + for (let section of data) { + section.period = $(section).attr('period'); + section.index = $(section).index(); + } + // console.log(data) + this.cardData = data; + // #assign initial entry point (active items) + this.activePeriod = this.periodData[0]; + this.activePeriodIndex = 0; + this.activeCard = this.cardData[0]; + this.activeCardIndex = 0; + } + _setStateClasses() { + // # periods + $(this.base).find('.periods-container section.active').removeClass('active'); + $(this.base).find('.periods-container section.prev').removeClass('prev'); + $(this.base).find('.periods-container section.next').removeClass('next'); + // console.log("setclass: " + this.activePeriod.index) + $(this.activePeriod).addClass('active'); + // console.log(this.activePeriod.index) + // this.activePeriodIndex = this.activePeriod.index + if ($(this.activePeriod).prev().length != 0) { + $(this.activePeriod).prev().addClass('prev'); + $(this.base).find('.periods-container .btn-back').removeClass('hide'); + } + else { + $(this.base).find('.periods-container .btn-back').addClass('hide'); + } + if ($(this.activePeriod).next().length != 0) { + $(this.activePeriod).next().addClass('next'); + $(this.base).find('.periods-container .btn-next').removeClass('hide'); + } + else { + $(this.base).find('.periods-container .btn-next').addClass('hide'); + } + // ## cards + $(this.base).find('.cards-container section.active').removeClass('active'); + $(this.base).find('.cards-container section.prev').removeClass('prev'); + $(this.base).find('.cards-container section.next').removeClass('next'); + $(this.activeCard).addClass('active'); + // this.activeCardIndex - this.activeCard.index + if ($(this.activeCard).prev().length != 0) { + $(this.activeCard).prev().addClass('prev'); + } + if ($(this.activeCard).next().length != 0) { + $(this.activeCard).next().addClass('next'); + } + // ## timeline + $(this.base).find('.timeline li.active').removeClass('active'); + // let findNode = $(this.base).find('.timeline ol li')[this.activeCard.index] + $(this.timelineData[this.activeCard.index]).addClass('active'); + let timelineB = $(this.base).find('.timeline-container .btn-back'); + let timelineN = $(this.base).find('.timeline-container .btn-next'); + // console.log($(timelineN)) + if (this.activeCardIndex === 0) { + timelineB.addClass('hide'); + } + else { + timelineB.removeClass('hide'); + } + if (this.activeCardIndex >= this.cardData.length - 1) { + timelineN.addClass('hide'); + } + else { + timelineN.removeClass('hide'); + } + } + // ## timeline generater + _generateTimeline() { + // ## create node list + let htmlWrap = '
    '; + $(this.timelineNodeContainer).append(htmlWrap); + let wrap = $(this.timelineNodeContainer).find('ol'); + let numNode = this.cardData.length; + for (let i = 0; i < numNode; i++) { + let c = this.cardData[i].color; + let el = wrap.append('
  1. '); + } + // ## width of timeline + let nodeW = 200; + wrap.css('width', nodeW * numNode - 16); + let nodeList = $(this.base).find('.timeline ol li'); + this.timelineData = nodeList; + } + // ## assign button actions + _assignBtn() { + let periodPrev = $(this.base).find('.periods-container .btn-back'); + let periodNext = $(this.base).find('.periods-container .btn-next'); + periodPrev.click(() => { + if (this.activePeriodIndex > 0) { + // console.log('prev') + this.activePeriodIndex -= 1; + this.activePeriod = this.periodData[this.activePeriodIndex]; + this._chainActions('period'); + this._setStateClasses(); + } + this._adjustPeriodContainer(); + }); + periodNext.click(() => { + if (this.activePeriodIndex < this.periodData.length - 1) { + // console.log('next' + this.activePeriodIndex) + this.activePeriodIndex += 1; + this.activePeriod = this.periodData[this.activePeriodIndex]; + this._chainActions('period'); + this._setStateClasses(); + } + this._adjustPeriodContainer(); + }); + let timelinePrev = $(this.base).find('.timeline-container .btn-back'); + let timelineNext = $(this.base).find('.timeline-container .btn-next'); + timelinePrev.click(() => { + if (this.activeCardIndex > 0) { + this.activeCardIndex -= 1; + this.activeCard = this.cardData[this.activeCardIndex]; + this._chainActions('timeline'); + this._setStateClasses(); + } + this._adjustCardContainer(); + this._adjustPeriodContainer(); + }); + timelineNext.click(() => { + if (this.activeCardIndex < this.cardData.length - 1) { + this.activeCardIndex += 1; + this.activeCard = this.cardData[this.activeCardIndex]; + this._chainActions('timeline'); + this._setStateClasses(); + } + this._adjustCardContainer(); + this._adjustPeriodContainer(); + }); + // ## assign each timeline li + for (let i = 0; i < this.timelineData.length; i++) { + $(this.timelineData[i]).click(() => { + this.activeCardIndex = this.cardData[i].index; + this.activeCard = this.cardData[this.activeCardIndex]; + this._chainActions('timeline'); + this._setStateClasses(); + this._adjustCardContainer(); + this._shiftTimeline(); + }); + } + } + // ## color ## + _initialColor() { + for (let i = 0; i < this.periodData.length; i++) { + let p = this.periodData[i].period; + this.periodData[i].color = this.color[p]; + let temp = this.periodData[i]; + $(temp).css('border-color', temp.color); + $(temp).find('.year').css('color', temp.color); + // ## color for timeline items, this part utilize the period name as class which will be add to the li later + // ### cross browser bug fix + let sbstyle = document.createElement("style"); + document.head.appendChild(sbstyle); + // let sheet = document.styleSheets[0] + sbstyle.sheet.insertRule('li.' + p + '.active { background-color: ' + this.color[p] + ' !important } ', 0); + sbstyle.sheet.insertRule('li.' + p + '::before { background-color: ' + this.color[p] + ' } ', 0); + sbstyle.sheet.insertRule('li.' + p + '::after { background-color: ' + this.color[p] + ' } ', 0); + } + for (let i = 0; i < this.cardData.length; i++) { + let p = this.cardData[i].period; + this.cardData[i].color = this.color[p]; + let temp = this.cardData[i]; + $(temp).css('border-color', temp.color); + $(temp).find('.year').css('color', temp.color); + } + } + _adjustPeriodContainer() { + let activeH = $(this.activePeriod).outerHeight(); + $(this.periodContainer).height(activeH); + console.log('top adjusted'); + } + _adjustCardContainer() { + let activeH = $(this.activeCard).outerHeight() + 24; + $(this.cardContainer).height(activeH); + console.log('bot adjusted'); + } + _shiftTimeline() { + // #### We need to fix this part if using this component in different sizes #### + let timelineW = $(this.base).find('.timeline-container').outerWidth(); + let timelinePadding = 210; + let timelineCenter = 300; + let liWidth = 16; + let activeNodeX = $(this.timelineData[this.activeCardIndex]).position().left; + let finalPos = -activeNodeX + timelinePadding; + $(this.timelineNodeContainer).css('left', finalPos); + console.log(activeNodeX); + } + _chainActions(state) { + switch (state) { + case 'period': + console.log('period'); + if (this.activePeriod.period != this.activeCard.period) { + // ## find the closest li with the active period + let ta = []; + for (let i = 0; i < this.cardData.length; i++) { + let temp = this.cardData[i]; + if (this.activePeriod.period === temp.period) + ta.push(temp); + } + this.activeCard = ta[0]; + this.activeCardIndex = ta[0].index; + } + break; + case 'timeline': + console.log('timeline'); + if (this.activeCard.period != this.activePeriod.period) { + let ta; + for (let i = 0; i < this.periodData.length; i++) { + let temp = this.periodData[i]; + if (this.activeCard.period === temp.period) + ta = temp; + } + this.activePeriod = ta; + this.activePeriodIndex = ta.index; + } + break; + } + this._shiftTimeline(); + this._adjustCardContainer(); + } +} +// ## document load ## +$(document).ready(function () { + let colorcode = { + 'period1': '#fec541', + 'period2': '#36d484', + 'period3': '#32ccf4' + }; + let timeline = new PRESTimeline($('#this-timeline'), colorcode); +}); \ No newline at end of file diff --git a/nested-color-coded-interactive-timeline/style.css b/nested-color-coded-interactive-timeline/style.css new file mode 100644 index 0000000..d78141b --- /dev/null +++ b/nested-color-coded-interactive-timeline/style.css @@ -0,0 +1,282 @@ +body { + margin: 0; +} + +.body-wrap { + background-color: #fff; + width: 600px; + min-height: 500px; + margin: 0 auto; + font-size: 12px; +} + +.pres-timeline { + font-family: roboto, helvetica, sans-serif; + font-size: 12px; + color: #4A4A4A; + width: 100%; + margin: 30px 0; +} +.pres-timeline > div > div { + padding: 1em 0; + box-sizing: border-box; +} +.pres-timeline .periods-container, .pres-timeline .cards-container { + overflow: hidden; + box-sizing: border-box; + position: relative; + min-height: 100px; + transition: height 0.5s ease-in-out; + background-color: #FFF; +} +.periods-container:before { + background-image: linear-gradient(left, #FFF, rgba(248, 248, 248, 0)); + left: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.periods-container:after { + background-image: linear-gradient(right, #FFF, rgba(248, 248, 248, 0)); + right: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.periods-container .btn-back, .periods-container .btn-next { + display: inline-block; + width: 15%; + height: 100%; + position: absolute; + cursor: pointer; + z-index: 10; + transition: 0.3s ease-in-out; +} +.periods-container .btn-back:hover, .periods-container .btn-next:hover { + background-color: rgba(0, 0, 0, 0.05); +} +.periods-container .btn-back.hide, .periods-container .btn-next.hide { + display: none; +} +.periods-container .btn-back { + left: 0; +} +.periods-container .btn-next { + right: 0; +} +.periods-container section { + width: 70%; + height: 0; + position: absolute; + margin-left: 15%; + border-bottom: 5px solid #dfe3e6; + padding: 1.5em; + box-sizing: border-box; + transition: transform 0.3s ease-in-out, opacity 0.2s ease, height 0.3s ease; + bottom: 0; + opacity: 0; + background-color: #fff; +} +.periods-container section.active { + height: auto; + opacity: 1; + transform: translateX(0); + z-index: 5; +} +.periods-container section.active .title, .periods-container section.active p { + display: block; +} +.periods-container section.prev { + height: auto; + opacity: 0.4; + transform: translateX(-100%); + z-index: 0; +} +.periods-container section.prev .year { + text-align: right; +} +.periods-container section.next { + height: auto; + opacity: 0.4; + transform: translateX(100%); + z-index: 0; +} +.periods-container section .year { + font-size: 20px; + font-weight: 400; +} +.periods-container section .title { + color: #4A4A4A; + font-size: 28px; + font-weight: 400; + display: none; +} +.periods-container section p { + display: none; +} + +.timeline-container { + position: relative; + width: 100%; + height: 50px; + overflow: hidden; +} +.timeline-container:before { + background-image: linear-gradient(left, #FFF, rgba(248, 248, 248, 0)); + left: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.timeline-container:after { + background-image: linear-gradient(right, #FFF, rgba(248, 248, 248, 0)); + right: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.timeline-container .timeline { + position: absolute; + display: block; + height: 50px; + transition: left 0.3s ease-in-out; +} +.timeline-container .timeline ol { + display: block; + width: 100%; + height: 2px; + background-color: #dfe3e6; + list-style: none; + padding-left: 210px; + padding-right: 300px; +} +.timeline-container .timeline ol li { + display: inline-block; + padding: 5px; + margin-top: -11px; + margin-left: 80px; + border-radius: 50%; + border: 3px solid #7f9298; + background-color: #FFF; + position: relative; + cursor: pointer; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); +} +.timeline-container .timeline ol li.active { + box-shadow: none; +} +.timeline-container .timeline ol li.active:before { + content: ""; + display: block; + height: 25px; + width: 1px; + position: absolute; + top: -25px; + transition: opacity 0.3s ease-in-out; +} +.timeline-container .timeline ol li.active:after { + content: ""; + display: block; + height: 25px; + width: 1px; + position: absolute; + bottom: -25px; + transition: opacity 0.3s ease-in-out; +} +.timeline-container .btn-back, .timeline-container .btn-next { + display: inline-block; + position: absolute; + cursor: pointer; + margin-top: -2px; + z-index: 11; + transition: all 0.3s ease; +} +.timeline-container .btn-back.hide, .timeline-container .btn-next.hide { + display: none; +} +.timeline-container .btn-back:hover, .timeline-container .btn-next:hover { + border-color: #7f9298; +} +.timeline-container .btn-back { + left: 1em; +} +.timeline-container .btn-next { + right: 1em; +} + +.cards-container:before { + background-image: linear-gradient(left, #FFF, rgba(248, 248, 248, 0)); + left: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.cards-container:after { + background-image: linear-gradient(right, #FFF, rgba(248, 248, 248, 0)); + right: 0; + content: ""; + position: absolute; + z-index: 2; + top: 0; + height: 100%; + width: 100px; +} +.cards-container section { + width: 70%; + position: absolute; + margin-left: 15%; + margin-bottom: 2em; + border: 1px solid #f5f7f6; + padding: 1.5em; + box-sizing: border-box; + transition: transform 0.3s ease-in-out; + top: 0; + opacity: 0; + border-radius: 8px; + background-color: #fff; + box-shadow: 0 10px 15px rgba(0, 0, 0, 0.15); +} +.cards-container section.active { + height: auto; + opacity: 1; + transform: translateX(0); + z-index: 5; +} +.cards-container section.prev { + height: auto; + opacity: 0.4; + transform: translateX(-105%); + z-index: 0; +} +.cards-container section.next { + height: auto; + opacity: 0.4; + transform: translateX(105%); + z-index: 0; +} +.cards-container section .year { + text-align: center; + font-size: 16px; + margin: 0; +} +.cards-container section .title { + font-weight: 400; +} +.cards-container section img { + width: 100%; +} \ No newline at end of file