I am new to NextJs/ReactJs and I was trying to implement the Responsive slide with Swiperjs which is available in codepen.io
Here is the link to codepen.
Responsive slider timeline with Swiper
Below are my steps I carried out;
Installed JQuery (npm install)
Imported both swiper.min.css and swiper.min.js CDNs to my _Document.js file
Added the css files to Globals.css for time being
Created a TimelineComponent.js to have the swiper component separately.
imported TimelineComponent.js in the index.js
When I run the project it nicely shows you the expected output as below.
But when I resize my browser it behaves abnormally like below
import React, { useEffect } from 'react';
import $ from 'jquery';
function TimeLineComponent() {
function operateTimeline() {
var timelineSwiper = new Swiper('.timeline .swiper-container', {
direction: 'vertical',
loop: false,
speed: 1600,
pagination: '.swiper-pagination',
paginationBulletRender: function (swiper, index, className) {
var year = document
.querySelectorAll('.swiper-slide')
[index].getAttribute('data-year');
return '<span class="' + className + '">' + year + '</span>';
},
paginationClickable: true,
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
breakpoints: {
768: {
direction: 'horizontal',
},
},
});
}
useEffect(() => {
$(window).on('load resize', operateTimeline);
operateTimeline();
return () => {
$(window).off('load resize');
};
}, []);
return (
<div className="timeline-container">
<div className="timeline">
<div className="swiper-container">
<div className="swiper-wrapper">
<div
className="swiper-slide"
style={{
backgroundImage: "url('https://unsplash.it/1920/500?image=11')",
}}
data-year="2011"
>
<div className="swiper-slide-content">
<span className="timeline-year">2011</span>
<h4 className="timeline-title">Our nice super title</h4>
<p className="timeline-text">
Lorem ipsum dolor site amet, consectetur adipscing elit, sed
do eisumod tempor incididut ut labore et dolore magna aliqua.
Ut enim ad mimim venjam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
</div>
</div>
<div
className="swiper-slide"
style={{
backgroundImage: "url('https://unsplash.it/1920/500?image=12')",
}}
data-year="2012"
>
<div className="swiper-slide-content">
<span className="timeline-year">2012</span>
<h4 className="timeline-title">Our nice super title</h4>
<p className="timeline-text">
Lorem ipsum dolor site amet, consectetur adipscing elit, sed
do eisumod tempor incididut ut labore et dolore magna aliqua.
Ut enim ad mimim venjam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</p>
</div>
</div>
</div>
<div className="swiper-button-prev"></div>
<div className="swiper-button-next"></div>
<div className="swiper-pagination"></div>
</div>
</div>
</div>
);
}
export default TimeLineComponent;
Error can be replicated in the above codepen example as well. Most probably this is with the styling
Your help is much appreciated.
Related
I've created an accordion with TailwindCSS and Alpine.js which works fine except that I also want to change the icon in the button that expands the content when it's clicked.
This is what I have:
<div x-data="{selected:null,open:true}">
<dl class="faqs mx-auto max-w-2xl">
<dt>
<span class="faq-q">Question</span>
<button
type="button"
class="faq-toggle"
#click="selected !== 1 ? selected = 1 : selected = null, open = open"
:class="{ 'faq-open': open, 'faq-close': !(open) }"
>
<span>+</span>
<span class="hidden">-</span>
</button>
</dt>
<dd
class="faq-a overflow-hidden transition-all max-h-0 duration-700"
style="" x-ref="container1" x-bind:style="selected == 1 ? 'max-height: ' + $refs.container1.scrollHeight + 'px' : ''"
>
<div class="inner">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure rerum in tempore sit ducimus doloribus quod commodi eligendi ipsam porro non fugiat nisi eaque delectus harum aspernatur recusandae incidunt quasi.
</div>
</dd>
</dl>
</div>
and a link to a CodePen.
What I want to do is toggle the class of the button from faq-open to faq-close when the button is clicked. Although I may actually need to toggle a class on the parent dt too.
At the moment, the accordion expands when you click on the button, but the class doesn't change.
The problem is on this line
#click="selected !== 1 ? selected = 1 : selected = null, open = open"
You never change value of open, it is always the value at initialization, and that is open: true.
You need to switch it:
#click="selected !== 1 ? selected = 1 : selected = null, open = !open"
By the way, you don't need extra variable selected to control the hidden text, just one open variable is enough. Something like this:
<div x-data="{open: true}">
<dl class="faqs mx-auto max-w-2xl">
<dt>
<span class="faq-q">Question</span>
<button
type="button"
class="faq-toggle"
#click="open = !open"
:class="open ? 'faq-open' : 'faq-close'"
>
<span :class="open ? '' : 'hidden'">+</span>
<span :class="open ? 'hidden' : ''">-</span>
</button>
</dt>
<dd
class="faq-a overflow-hidden transition-all max-h-0 duration-700"
style="" x-ref="container1" x-bind:style="open ? 'max-height: ' + $refs.container1.scrollHeight + 'px' : ''"
>
<div class="inner">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iure rerum in tempore sit ducimus doloribus quod commodi eligendi ipsam porro non fugiat nisi eaque delectus harum aspernatur recusandae incidunt quasi.
</div>
</dd>
</dl>
import 'twin.macro';
import React, { useRef, useState } from 'react';
import { BiPlus, BiMinus } from 'react-icons/bi';
const Accordion = ({ title, children }) => {
const [active, setActive] = useState(false);
const [height, setHeight] = useState('0px');
const contentSpace = useRef(null);
function toggleAccordion() {
setActive(!active);
setHeight(active ? '0px' : `${contentSpace.current?.scrollHeight}px`);
}
return (
<div tw="flex flex-col outline-none" role="button" tabIndex={0}>
<div
tw="flex flex-row items-center justify-between py-4 border-b border-t border-black "
onClick={toggleAccordion}>
<h1 tw="cursor-pointer text-base font-bold">{title}</h1>
{active ? <BiMinus /> : <BiPlus />}
</div>
<div
ref={contentSpace}
style={{ maxHeight: `${height}` }}
tw="overflow-auto overflow-y-hidden duration-700 ease-in-out">
<p tw="my-4">{children}</p>
</div>
</div>
);
};
export default Accordion;
I have a modal whose content can be toggled between two different components. It works, but the transition is brutal since the wrapper immediately takes the width of its content.
How to animate this properly? I thought about transform:scale but it did not work.
Here is the code, as well as a sandbox:
import React, {useState} from "react";
import styled from "styled-components"
const Wrapper = styled.div`
background:gainsboro;
width:100%;
height:100%;
border:1px solid lightgrey;
`
const Content1 = () => (
<div>
Lorizzle ipsizzle dolor sit amet, ass adipiscing elizzle. Ass
izzle velizzle, volutpizzle, suscipit quizzle, we gonna chung
vizzle, arcu. Pellentesque egizzle boom shackalack. Fo shizzle
my nizzle erizzle. Pimpin' crunk dolor dapibus rizzle tempizzle
sizzle. Maurizzle fo shizzle mah nizzle fo rizzle, mah home
g-dizzle nibh daahng dawg go to hizzle. Shizznit izzle tortor.
Pellentesque sizzle rhoncizzle shizzlin dizzle. In hizzle
habitasse platea dictumst. For sure fo. Break it down izzle
urna, pretizzle eu, mattis go to hizzle, eleifend black, nunc.
Daahng dawg suscipit. Tellivizzle yo mamma velit sed check
out this.
</div>
)
const Content2 = () => (
<div>
very short content
</div>
)
export default function App() {
const [toggle, setToggle] = useState(false)
return (
<Wrapper>
{toggle ? <Content1 /> : <Content2/>}
<button onClick={()=> setToggle(!toggle)}>toggle content</button>
</Wrapper>
);
}
https://codesandbox.io/s/still-smoke-5ikkg?file=/src/App.js
Thanks!
you can use react-fade-in, not the best, but a fast solution
https://www.npmjs.com/package/react-fade-in
I have been working on a ReactJS project where I create most of the components using flexbox layout. Since with react, we can have deeply nested components, so my layout is having nested flexbox layout.
Now my question is, does this have any issue with performance? On a single page, there are many components and each component have 3 to 4 level nested flexbox layout. Will that cause a performance issue?
Have done a little test. Rendered 100 components, each with 10 nested layout. With and without flexbox. Here are the code snippets:
Component/index.js
#CSSModules(styles, { allowMultiple: true })
export default class TheComponent extends Component {
render() {
const { deepNest, flex } = this.props
return (
<div>{ this.renderComp(deepNest, flex) }</div>
)
}
renderComp(deepNest, flex) {
const flexProperties = [
{ justifyContent: "center", alignItems: "center" },
{ justifyContent: "flex-start", alignItems: "flex-end" },
{ flexDirection: "row" }
]
const content = [
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus interdum quis ligula vel elementum. Integer non rhoncus purus, eget dignissim ante.",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus interdum quis ligula vel elementum. Integer non rhoncus purus, eget dignissim ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus interdum quis ligula vel elementum. Integer non rhoncus purus, eget dignissim ante."
]
if (deepNest > 0 && flex) {
return (
<div styleName="containerFlex" style={flexProperties[deepNest % 3]}>
<div styleName="contentFlex" style={flexProperties[deepNest % 3]}>
{ content[deepNest % 3] }
</div>
<div styleName="nestedFlex" style={flexProperties[deepNest % 3]}>
{ this.renderComp(deepNest - 1, flex) }
</div>
</div>
)
}
if (deepNest > 0 && !flex) {
return (
<div styleName="container">
<div styleName="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus interdum quis ligula vel elementum. Integer non rhoncus purus, eget dignissim ante.
</div>
<div styleName="nested">
{ this.renderComp(deepNest - 1, flex) }
</div>
</div>
)
}
}
}
WithFlex/index.js
import TheComponent from "../Component"
#CSSModules(styles, { allowMultiple: true })
export default class WithFlex extends Component {
constructor(props) {
super(props)
this.state = { render: false }
}
render() {
const {render} = this.state
// number of components to render
const arr = _.range(100)
return (
<div>
<div
style={{ display: "block", padding: 30, lineHeight: "60px" }}
onClick={() => this.setState({render: !render})}>
Start Render
</div>
{ render && arr.map((i) => <TheComponent key={i} deepNest={10} flex={true}/> ) }
</div>
)
}
}
WithoutFlex/index.js
import TheComponent from "../Component"
#CSSModules(styles, { allowMultiple: true })
export default class WithoutFlex extends Component {
constructor(props) {
super(props)
this.state = { render: false }
}
render() {
const {render} = this.state
// number of components to renders
const arr = _.range(100)
return (
<div>
<div
style={{ display: "block", padding: 30, lineHeight: "60px" }}
onClick={() => this.setState({render: !render})}>
Start Render
</div>
{ render && arr.map((i) => <TheComponent key={i} deepNest={10} flex={false}/> ) }
</div>
)
}
}
Results from Chrome dev-tool timeline.
WithFlex
WithoutFlex
Summary
The difference is not that much. Also in flexbox, I put random properties to choose from. So I think it's alright with the performance. Hope it will help other devs.
Old flexbox (display: box) is 2.3x slower than new flexbox (display: flex).
Regular block layout (non-float), will usually be as fast or faster than new flexbox since it’s always single-pass. But new flexbox should be faster than using tables or writing custom JS-base layout code.
For more info
Article1
Article2
I am trying to create my first webapp using google apps script. I am trying to follow the examples but it is not working. I created a stylesheet.html tab along with my main html page. But none of my formatting is working. I thought google appended the files together. FYI, my styles work fine if I include them at the bottom of the main page.
This is my code.gs page:
function doGet() {
return HtmlService.createHtmlOutputFromFile('frontpage')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
This is my main page called frontpage.html :
<!DOCTYPE html>
<html lang="en">
<?!= HtmlService.createHtmlOutputFromFile('stylesheet').getContent(); ?>
<!-- google scripts says to not include header & body tags ?? -->
<meta charset="utf-8">
<title>Borah Physics</title> <!-- google syas not to use title tag need another way to set title.-->
<h1><div style="text-align:center">Physics Homework</div></h1>
<!--List of available assignments. This needs to be updated as assignments are added.
Add assignment name and the ssID of the spreadsheet containing the questions.
when clicked need to return value (ssid) as sheetID.-->
<select id="assignment">
<option sheetID="1ajedscAjuXDsUOcQRzru5-bhUIluGn3fPPsoN-Ww5wU">Kinematics 1</option>
<option sheetID="10mCGpLRwv8ETFbW3RwisI45s_x3-ZItatzq_vU0wacs">Dynamics</option>
</select>
<!--Question should be string variable activeQuestion It will get updated when the question number changes.-->
<div id="question">
<br>
<br>
Question Here
<br>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 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.
<br> <br>
</div>
<!-- If question has an image it will go here.-->
<div id="qImage">
Along with image (if needed)
<br>
</div>
<!-- This is the user inputed answer. It needs to be recorded in the response sheet of the spreadsheet and
compared to the correct answer. (in the comparison we need to add a within x% variable so if the answer
is close it is counted as correct. This accounts for thinks like g=10 m/s^2 vs 9.8 m/s^2.-->
<div id="answer">
<label>Answer:</label>
<input type="text" name="answer"/>
<input type="Submit" value="Submit"/>
<br>
<br>
</div>
<!-- bottom navigation list-->
<ul id="nav">
<li><a> </a></li>
<li><input type="button" onclick="previous()" value="Previous"></li> <!-- goes to previous question (calls previous function)-->
<li><a > Correct: 4/12 </a></li> <!-- need to insert variables #correct & total # questions-->
<li><input type="button" onclick="next()" value="Next"></li> <!-- goes to next question (calls next function).-->
<li><a> </a></li>
</ul>
and finally my stylesheet.html page
<style>
#assignment{
width: 20%; margin: 10 ;
position: absolute;
right: 10px;
}
#question {
width: 90%; margin: 0 auto;
}
#qImage{
width: 90%; margin: 0 auto;
}
#answer {
width: 90%; margin: 0 auto;
}
#nav {
text-align: justify;
min-width: 400px;
}
#nav:after {
content: '';
display: inline-block;
width: 100%;
}
#nav li {
display: inline-block;
}
</style>
My output shows the at the top of the page as if it were text. So I am not connecting the style sheet to the frontpage.
I have not even attempted to understand functions or javascript yet. Lots to learn. (This is a physics homework app I hope to get working before school starts!) All help is appreciated. Any tutors out there?
thanks.
Change createHtmlOutputFromFile to createTemplateFromFile in the doGet() function.
Should be:
return HtmlService
.createTemplateFromFile('frontpage')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
If a file has a scriptlet in it, it's a template. Your frontpage file has a scriptlet in it. The scriptlet is:
<?!= HtmlService.createHtmlOutputFromFile('stylesheet').getContent(); ?>
You can also call a server function from a scriptlet instead of using HtmlService directly inside the scriptlet.
I've I'm trying to build a page which collects together all of the pages on a site and displays them along with their children (if they have any).
So far I've managed to make it loop through all of the top level pages and display them, however I'm getting some difficulty in making it display the child pages in the right place. It seems that I can either retrieve them but have them appear at the end or not retreive them at all.
I would need it to look like this:
<div id="parent" class="guide-item">
<h2>Parent</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
<div id="child" class="guide-item">
<h2>Child</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
</div>
</div>
Here is my controller (including my attempt at getting it to loop through the children:
// Render pages from database
public function sectorAction($sector)
{
$em = $this->getDoctrine()->getManager();
$pages = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:pageSector')
->findBySectorJoinedToUrlTopLevel($sector);
if (!$pages) throw $this->createNotFoundException('Unable to find any matching sectors');
foreach ($pages as $page) {
if ($page->getChildPages()) {
$children = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:pageContent')
->findBySectorAndParent($sector, $page->getPageUrl());
}
}
return $this->render(
'acmeStyleGuideBundle:Page:pages.html.twig',
array(
'Pages' => $pages,
'Children' => $children,
'header' => $sector
)
);
}
Here are the relavent repositories:
public function findBySectorJoinedToUrlTopLevel($sector)
{
$query = $this->getEntityManager()
->createQuery('
SELECT p, s FROM acmeStyleGuideBundle:PageContent p
JOIN p.pageSector s
LEFT JOIN p.pageTypes t
WHERE s.sectorName = :sector
AND t.typeName != :type
AND p.parentPage IS NULL'
)
->setParameter('type', 'Section Headers')
->setParameter('sector', $sector);
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
public function findBySectorAndParent($sector, $pageParent)
{
$query = $this->getEntityManager()
->createQuery('
SELECT p, s, c FROM acmeStyleGuideBundle:PageContent p
JOIN p.pageSector s
LEFT JOIN p.pageTypes t
LEFT JOIN p.parentPage c
WHERE s.sectorName = :sector
AND p.pageUrl = :parent
AND t.typeName != :type'
)
->setParameter('sector', $sector)
->setParameter('parent', $pageParent)
->setParameter('type', 'Section Headers');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
And here is my twig template where I want to output the code:
{% extends 'acmeStyleGuideBundle::landing.html.twig' %}
{% block definition %}
<article class="js-load pageLoad">
<h1>
{% if header is defined %}
{{ header | title }}
{% else %}
{{ Pages[0].pageName }}
{% endif %}
</h1>
{% for pe in Pages %}
<div id="{{ pe.pageUrl | lower}}" class="guide-item">
<h2>{{ pe.pageName }}</h2>
{{ pe.richText | raw }}
</div>
{% endfor %}
</article>
{% endblock %}
I thought that I might hae been able to loop through the children in the controller and then apply it to the twig template as 'children' instead of 'pages' but that didn't seem to work as the following code just constantly repeated the last element in the database which WASN'T a child page.:
{% for ce in Children %}
<div class="childPage">
<div id="{{ ce.pageUrl | lower}}" class="guide-item">
<h2>{{ ce.pageName }}</h2>
{{ ce.richText | raw }}
<div class="explanation">
<div class="card active">
<h3>Example</h3>
{# ce.example | raw#}
</div>
<div class="card">
<h3>Code Example</h3>
<pre name="code" class="{#ce.lang#}">{# ce.example #}</pre>
</div>
</div>
</div>
</div>
{% endfor %}
I've been looking at this problem for a while now so I probably can no longer see the wood for the trees so feel free to pull my code to pieces. I'm a learner at symfony/twig/doctrine anyway so I'll gladly take any feedback you care to give me.
I managed to find a solution.
Instead of trying to do everything in one controller and template, I created a new template called childpages.html.twig and put in this code:
{% for pe in Pages %}
<div id="{{ pe.pageUrl | lower}}" class="guide-item child">
<h2>{{ pe.pageName }}</h2>
{{ pe.richText | raw }}
{{ render(controller('acmeStyleGuideBundle:Page:findCodeExamples', { 'pageParent': pe.codeExample })) }}
</div>
{% endfor %}
I then wrote a new controller:
// Render children from database (Similar to showSubAction but without the $pageUrl requirement)
public function findChildrenAction($pageParent, $sector)
{
$em = $this->getDoctrine()->getManager();
$pages = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:PageSector')
->findBySectorJoinedToParent($sector, $pageParent);
return $this->render(
'acmeStyleGuideBundle:Page:childPages.html.twig',
array(
'Pages' => $pages,
'sector' => $sector
)
);
}
and referenced it in the place I needed it to appear in my original template:
{{
render(controller('acmeStyleGuideBundle:Page:findChildren', {
'pageParent': pe.id,
'sector': 'residential'
}))
}}
Not sure if it's the most elegant solution but it worked.