So, I have a project that I've taken on that already has a slick carousel, not familiar with drupal or bootstrap, but from what I can see the current follows documentation. The carousel is triggered upon the breakpoint (as confirmed by the carousel arrows that appear at the breakpoint), However the carousel is not horizontal and the arrows do not work. Please advise.
app.js
explore: function explore() {
$('.explore-carousel').slick({
autoplay:true,
mobileFirst:true,
infinite: false,
dots: false,
slidesToShow: 2,
slidesToScroll: 1,
prevArrow: $('.explore-prev'),
nextArrow: $('.explore-next'),
responsive: [{
breakpoint: 500,
settings: {
slidesToShow: 1
}
}]
});
},
exploreResize: function exploreResize(carousel) {
// https://github.com/kenwheeler/slick/issues/3282
$(window).on('load resize orientationchange', function () {
$(carousel).each(function () {
var $carousel = $(this);
if ($(window).width() > 768) {
if ($carousel.hasClass('slick-initialized')) {
$carousel.slick('unslick');
}
} else {
if (!$carousel.hasClass('slick-initialized')) {
CB.carousel.explore(carousel);
}
}
});
});
},
explore.twig
<section class="explore">
<a class="explore-prev"><img src="../lib/img/icon-carousel-arrow-left.svg"></a>
<a class="explore-next"><img src="../lib/img/icon-carousel-arrow-right.svg"></a>
<div class="explore-carousel grid-x grid-container align-center">
{% for block in entry.exploreMatrix.all() %}
{% set image = block.icon.one() %}
{% set link = block.linkUrl.one() %}
{% set length = loop.length %}
{% set col = 12/length %}
<div class="cell small-12 large-{{ col ? col : 4 }}">
<a class="explore--link" href={{ link.url }}>
<div class="outline">
<img class="explore-image" src="{{ image ? image.url : '' }}">
<div class="hover--container">
<div class="hr"></div>
<h3 class="hover--text">{{ block.linkText }}<span class="button-icon"> {% include 'includes/svg/cta-arrow' %}</span></h3>
</div>
</div>
</a>
</div>
{% endfor %}
</section>
css
.explore {
margin-top: 80px;
#include mq($small) {
margin-top: 0;
}
position: relative;
.explore-prev {
#extend .PrevArrow;
}
.explore-next {
#extend .NextArrow;
}
.explore-carousel {
display: flex;
#include h-padding(rem-calc(50));
// padding-left: rem-calc(50);
// padding-right: rem-calc(50);
#include mq($medium) {
// padding-left: initial;
// padding-right: initial;
#include h-padding(initial);
}
.explore--link {
width: 100%;
}
.outline {
position: relative;
width: rem-calc(250);
border-radius:50%;
transition: all .3s;
margin: 0 auto;
#include spacer(50px, 50px);
&.hover {
background: $offWhite;
}
#include mq($medium) {
width: rem-calc(300);
}
.hover--container {
transition: all .3s;
position: absolute;
left: 0;
right: 0;
margin: 0 auto;
bottom: 5%;
text-align: center;
opacity: 0;
.hover--text {
margin-top:rem-calc(10);
font-size: rem-calc(22);
color: $clay;
letter-spacing: -1px;
}
}
.explore--image {
width: rem-calc(250);
margin: 0 auto;
#include mq($medium) {
width: rem-calc(300);
}
}
}
.hover {
.hover--container {
transition: all .3s;
opacity: 1;
}
}
}
}
Not sure about the 'not horizontal' issue, but i recommend you to remove all css and run slick carousel in a sandbox. When done, add your CSS code.
CSS overrides can be painfull with slick.
About the arrows, i guess you need to register as string HTML markup. Like this:
prevArrow:'<div> my custom prev arrow </div>'
Related
I need a timer in my store, therefore I have taken from the internet a code. Only unfortunately this code is not in the middle or top but at the bottom, under the footer. can someone help me to have the timer on top or in the middle?
{% if end_date != blank %}
<div class="timer">
{% if title != blank %}
<h4 class="timer__title">{{ title }}</h4>
{% endif %}
<div class="timer-display">
<div class="timer-block">
<span class="timer-block__num js-timer-days">00</span>
<span class="timer-block__unit">Days</span>
</div>
<div class="timer-block">
<span class="timer-block__num js-timer-hours">00</span>
<span class="timer-block__unit">Hours</span>
</div>
<div class="timer-block">
<span class="timer-block__num js-timer-minutes">00</span>
<span class="timer-block__unit">Minutes</span>
</div>
<div class="timer-block">
<span class="timer-block__num js-timer-seconds">00</span>
<span class="timer-block__unit">Seconds</span>
</div>
</div>
</div>
<style>
/* styles for timer */
.timer {
background: #f6fafd;
padding: 10px;
margin: 10px 0;
}
.timer--expired {
display: none;
}
.timer__title {
#extend .paragraph;
text-align: center;
}
.timer-display {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
margin-top: 5px;
}
.timer-block {
position: relative;
width: 25%;
padding: 0 10px;
&:not(:last-child):after {
content: ':';
position: absolute;
right: 0;
top: 3px;
}
}
.timer-block__num,
.timer-block__unit {
display: block;
text-align: center;
}
</style>
<script type="text/javascript">
var second = 1000,
minute = second * 60,
hour = minute * 60,
day = hour * 24;
var countDown = new Date('{{- end_date -}}').getTime(),
x = setInterval(function() {
var now = new Date().getTime(),
distance = countDown - now;
document.querySelector('.js-timer-days').innerText = Math.floor(distance / (day)),
document.querySelector('.js-timer-hours').innerText = Math.floor((distance % (day)) / (hour)),
document.querySelector('.js-timer-minutes').innerText = Math.floor((distance % (hour)) / (minute)),
document.querySelector('.js-timer-seconds').innerText = Math.floor((distance % (minute)) / second);
}, second)
</script>
{% endif %}
i want it in the middle or in the top
How its look now
Ive trided to change the code but nothing work
We use stripe v.3 to add creditcard for a customer. It works on all browsers chrome and firefox. But safari returns the following error.
ReferenceError: Can't find variable: elements
Tested on physical iphone device it seems older version cant create the stripe elements leaving the input field, clumpy and not showing the CC information. Check screenshot.
The bug occurs on iOS version 11.3.1 and down. The iframe is showing in the source elements but dont add the class .StripeElement to the dom.
import {
Component,
Inject,
ViewChild,
ElementRef,
AfterViewInit,
OnDestroy,
ChangeDetectorRef,
} from '#angular/core';
import { NgForm } from '#angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '#angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { PaymentService } from '#services/http/payment.service';
import { StateService } from '#services/Logic/state.service';
import { TranslatePipe } from '#app/pipes/translate.pipe';
#Component({
selector: 'app-add-credit-card-dialog',
templateUrl: 'addCreditCard.html',
styleUrls: ['addCreditCard.scss', '../../dialogs.scss'],
})
export class AddCreditCardDialogComponent implements AfterViewInit, OnDestroy {
#ViewChild('cardInfo', { static: true }) cardInfo: ElementRef;
card: any;
cardHandler = this.onChange.bind(this);
error: string;
cardholderName: string;
constructor(
private cd: ChangeDetectorRef,
private toastr: ToastrService,
private translatePipe: TranslatePipe,
private stateService: StateService,
private paymentService: PaymentService,
public dialogRef: MatDialogRef<AddCreditCardDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: any
) {}
ngAfterViewInit() {
this.card = elements.create('card');
this.card.mount(this.cardInfo.nativeElement);
this.card.addEventListener('change', this.cardHandler);
// Force the Element frame to paint once it is visible on the page
setTimeout(() => {
this.forceReflow('.StripeElement');
}, 1000);
}
ngOnDestroy() {
this.card.removeEventListener('change', this.cardHandler);
this.card.destroy();
}
forceReflow(selector) {
const el = document.querySelector(selector);
if (el) {
const initialDisplay = el.style.display;
el.style.display = 'none';
el.offsetHeight;
el.style.display = initialDisplay;
}
}
onChange({ error }) {
if (error) {
this.error = error.message;
} else {
this.error = null;
}
this.cd.detectChanges();
}
async onSubmit(form: NgForm) {
if (!this.cardholderName || this.cardholderName.length === 0) {
return this.toastr.error(this.translatePipe.transform('TOAST_MESSAGES.ERROR.MISSING_CARDHOLDER'));
}
this.stateService.toggleWaitingPage(true);
// create a Setup Intent for this card
const { setupIntent, error } = await stripe.handleCardSetup(
this.data.client_secret,
this.card,
{
payment_method_data: {
billing_details: { name: this.cardholderName },
},
}
);
if (error) {
this.toastr.error(error.message);
this.stateService.toggleWaitingPage(false);
} else {
// create a Payment Method from the previously created Setup Intent and attach it to the Customer
const paymentMethod = await this.paymentService
.attachPaymentMethod({ payment_method: setupIntent.payment_method })
.toPromise();
this.close(paymentMethod);
}
}
close(data: any = null): void {
this.dialogRef.close(data);
}
}
form {
display: flex;
flex-direction: column;
align-items: center;
width: 95%;
margin: auto;
.form-row {
width: 100%;
margin: 0 0 20px;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2);
border-radius: 5px;
padding: 10px;
height: 40px;
#card-errors {
font-size: 12px;
color: #f82e42;
}
}
}
p {
color: #707070;
}
.input_area{
width: 100%;
text-align: center;
padding-bottom: 115px;
}
.body_area{
display: block;
height: 100%;
.attention{
display: flex;
margin: 20px 0px;
height: 100%;
padding: 5px 0px;
background-color: #F6F9FC;
.notranslate {
color: #89b153;
font-size: 18px;
margin-left: 8px;
padding-top: 2px;
padding-right: 5px;
}
p{
text-align: left !important;
margin-bottom: 0px !important;
}
.notranslate{
color: #707070;
place-self: center;
}
}
}
.header_wrapper{
display: block;
height: 100%;
.pinpay{
margin-bottom: unset !important;
font-weight: bold;
font-size: 17px;
color: #4a4a56;
}
.img {
height: 80px;
width: 80px;
margin-top: 10px;
margin: auto;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.16);
border-radius: 500px;
#media (max-width: 320px) and (max-height: 438px) { display: none; }
.image-icon{
height: 60px;
width: 60px;
margin-top: 3px;
margin-left: 8.4px;
}
}
}
#cardholder-name {
width: 95%;
margin-bottom: 20px;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.2);
background: transparent;
border: none;
}
<div class="dialog_container">
<div class="header_row">
<div class="header_left"></div>
<span class="close" (click)="close()">✕</span>
<h5 id="header_title">{{ 'DIALOGS.ADD_CREDIT_CARD.TITLE' | translate }}</h5>
</div>
<div class="header_wrapper">
<div class="img">
</div>
<div style="display: flex; margin-bottom: unset">
<p class="pinpay">PinployPay</p>
<span></span>™
</div>
<p class="pinpay1">Sikker handel</p>
</div>
<div class="body_area">
<div class="attention">
<mat-icon [matTooltip]="'PAGES.SETTINGS.PROFILE.COMPLETION_RATE_INFO' | translate">info</mat-icon>
<p>{{ 'DIALOGS.ADD_CREDIT_CARD.MESSAGE' | translate }}</p>
</div>
<p>
<mat-icon class="notranslate">remove_shopping_cart</mat-icon>{{
'DIALOGS.ADD_CREDIT_CARD.MESSAGE_1' | translate }}
</p>
</div>
<div class="input_area">
<input
id="cardholder-name"
[(ngModel)]="cardholderName"
[placeholder]="'DIALOGS.ADD_CREDIT_CARD.CARDHOLDER' | translate"
/>
<form #checkout="ngForm" (ngSubmit)="onSubmit(checkout)" class="checkout">
<div class="form-row">
<div id="card-info" #cardInfo></div>
<div id="card-errors" role="alert" *ngIf="error">{{ error }}</div>
</div>
<button type="submit" class="pinploy_button_v2_mobile_green">Ok</button>
</form>
</div>
</div>
index.html
<body>
<app-root></app-root>
<script src="https://js.stripe.com/v3/"></script>
<script>
const stripeKey =
window.location.origin === "https://www.pinploy.com"
? "pk_live_******q"
: "pk_test_1P******";
let stripe = Stripe(stripeKey);
let elements = stripe.elements();
</script>
</body>
</html>
I have a TopNav file which displays the items across the top of my page. When the user clicks their icon a dropdown menu appears. When they select "About" from the menu I want a modal dialog to appear with the information in it.
The closest I have managed to get is by using an actual button instead of the dropdown menu item. Also, pressing the button displays a modal only in the small window area with the dropdown instead of the in the center of the screen.
Here is the code for the TopNav.js
import React, { Component } from "react";
import { connect } from "react-redux";
import { logoutUser } from "../../../actions/authActions";
import { Link, withRouter } from "react-router-dom";
import "./TopNav.scss";
import AboutModal from "../MainContent/AboutModal/AboutModal";
class TopNav extends Component {
constructor() {
super();
this.state = {
isShowing: false
}
}
state = {
dropdown: false
};
componentDidMount() {
document.addEventListener("mousedown", this.handleClick, false);
}
componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClick, false);
}
// Close dropdown when click outside
handleClick = e => {
if (this.state.dropdown && !this.node.contains(e.target)) {
this.setState({ dropdown: !this.state.dropdown });
}
};
onLogoutClick = e => {
e.preventDefault();
this.props.logoutUser(this.props.history);
window.location.href = "/";
};
handleProfileClick = e => {
this.setState({ dropdown: !this.state.dropdown });
};
openModalHandler = () => {
this.setState({
isShowing: true
});
}
closeModalHandler = () => {
this.setState({
isShowing: false
});
}
toggleModal = e => {
this.setState({ modal: !this.state.modal });
};
// Show Side Nav
toggleMenu = e => {
let sideNav = document.querySelector(".side");
sideNav.classList.remove("invisibile");
let hamburger = document.querySelector(".hamburger-top-menu");
hamburger.classList.remove("hamburger-visible");
let rightSide = document.querySelector(".right");
rightSide.classList.remove("no-side");
let rightSideRight = document.querySelector(".right-top");
rightSideRight.classList.remove("right-top-visibile");
};
state = {
show: false,
}
showModal = () => {
this.setState({
...this.state,
show: !this.state.show
});
}
render() {
const { name, email } = this.props.auth.user;
return (
<nav className="top-nav" ref={node => (this.node = node)}>
<div className="left-top">
{ this.state.isShowing ? <div onClick={this.closeModalHandler} className="back-drop"></div> : null }
<i
onClick={this.toggleMenu}
className="material-icons hamburger-top-menu"
>
menu
</i>
<Link to="/dashboard">
<h1 className="brand-header">
TowTech Web
</h1>
</Link>
</div>
<ul className="right-top">
<li>
<div className="email">
<p>Signed in as {email}</p>
</div>
</li>
<li>
<div className="profile" onClick={this.handleProfileClick}>
<span>{name !== undefined && name.split("")[0]}</span>
</div>
{this.state.dropdown ? (
<ul className="dropdown">
<p>Hello, {name !== undefined && name.split(" ")[0]}</p>
<Link to="/dashboard">
<li>Home</li>
</Link>
<Link to="/dashboard">
<li>Profile</li>
</Link>
<Link to="/dashboard">
<li>Administration</li>
</Link>
<Link to="/about">
<li>About</li>
</Link>
<button className="open-modal-btn" onClick={this.openModalHandler}>About Button</button>
<AboutModal
className="modal"
show={this.state.isShowing}
close={this.closeModalHandler}>
This is text for the modal dialog. I can't get it to display in the center of the screen, or with the actual drop down menu item.
</AboutModal>
{/*
<Link to="/tasks">
<li>My Tasks</li>
</Link>
*/}
<li onClick={this.onLogoutClick}>Sign Out</li>
</ul>
) : null}
</li>
</ul>
</nav>
);
}
}
const mapStateToProps = state => ({
auth: state.auth
});
export default connect(
mapStateToProps,
{ logoutUser }
)(withRouter(TopNav));
This is the AboutModal.js
import React from 'react';
import './AboutModal.css';
const modal = (props) => {
return (
<div>
<div className="modal-wrapper"
style={{
transform: props.show ? 'translateY(0vh)' : 'translateY(-100vh)',
opacity: props.show ? '1' : '0'
}}>
<div className="modal-header">
<h3>Modal Header</h3>
<span className="close-modal-btn" onClick={props.close}>×</span>
</div>
<div className="modal-body">
<p>
{props.children}
</p>
</div>
<div className="modal-footer">
<button className="btn-cancel" onClick={props.close}>CLOSE</button>
<button className="btn-continue">CONTINUE</button>
</div>
</div>
</div>
)
}
export default modal;
Here is the AboutModal.css
.modal-wrapper {
background: white;
border: 1px solid #d0cccc;
box-shadow: 0 5px 8px 0 rgba(0,0,0,0.2), 0 7px 20px 0 rgba(0,0,0,0.17);
margin: 100px auto 0;
transition: all .8s;
width: 75%;
}
.modal-header {
background: #263238;
height: 40px;
line-height: 40px;
padding: 5px 20px;
text-align: right;
}
.modal-header h3 {
color: white;
float: left;
margin: 0;
padding: 0;
}
.modal-body {
padding: 10px 15px;
text-align: center;
}
.modal-footer {
background: #263238;
height: 35px;
padding: 15px;
}
.close-modal-btn {
color: white;
cursor: pointer;
float: right;
font-size: 30px;
margin: 0;
}
.close-modal-btn:hover {
color: black;
}
.btn-cancel, .btn-continue {
background: coral;
border: none;
color: white;
cursor: pointer;
font-weight: bold;
outline: none;
padding: 10px;
}
.btn-cancel {
background-color: #b71c1c;
float: left;
}
.btn-continue {
background-color: #1b5e20;
float: right;
}
.back-drop {
background-color: rgba(48, 49, 48, 0.42);
height: 100%;
position: fixed;
transition: all 1.3s;
width: 100%;
}
.open-modal-btn {
margin: 15px;
padding: 10px;
font-weight: bold;
}
There are tons of tutorials and samples out there but all of them use a "Open Modal" button on the main page to display a modal.
It solution ended up being passing the function used in the Dashboardjs handler to the props of the TopNav so that it could execute the function to update the state.
Your "modal" is currently just a div rendered within the dropdown, and you haven't specified a position css property on the element, so it defaults to position: static, which means it's positioned within the flow of the elements around it. If you want it to be positioned relative to the window instead, you can give it position: fixed. Alternatively, you can give it position: absolute, which will position it relative to its nearest positioned (i.e. non-static) ancestor. Since elements default to static position, if you haven't specified a position property (besides static) on any of the parent elements, the "nearest positioned ancestor" will be the viewport. Or if you want the modal to always be positioned relative to another container (e.g. the page container, rather than the viewport), you can set the container's position to relative or similar.
A better option in my opinion would be to render both the nav and the modal as children of the nav's parent component (rather than the modal as a child of the nav component), and use the parent state to manage the modal's show/hide prop.
class Container extends Component {
constructor(props) {
super(props);
this.state = {
modalOpen: false
}
}
toggleModal = () => this.setState(prevState => ({ modalOpen: !prevState.modalOpen }))
render() {
return (
<div>
<TopNav toggleModal={toggleModal} />
<AboutModal show={this.state.modalOpen} />
</div>
)
}
}
This way you can position the modal within a page-height container, instead of positioning it within a nav dropdown.
I am using node.js and its framework express to create a movie image gallery. A foreach loop is used to display data onto the page. The image gallery should display 4 images across in each row. For some apparent reason, the layout grid is broken and images are being duplicated when displayed on page. How can I create a grid layout for my image gallery with no duplicated data?
index.ejs
<!-- Photo Grid -->
<div class="row-image">
<% movies.forEach(function(movies) { %>
<div class="column">
<img src="<%= movies.image %>" style="width:100%">
<div class="desc">
<%= movies.name %>
</div>
</div>
<div class="column">
<img src="<%= movies.image %>" style="width:100%">
<div class="desc"><%= movies.name %></div>
</div>
</div>
<% } ); %>
main.css
* {
box-sizing: border-box;
}
.row-image {
display: -ms-flexbox; /* IE10 */
display: flex;
-ms-flex-wrap: wrap; /* IE10 */
flex-wrap: wrap;
padding: 0 14px;
}
/* Create four equal columns that sits next to each other */
.column {
-ms-flex: 25%; /* IE10 */
flex: 25%;
max-width: 25%;
padding: 0 4px 20px;
}
.column img {
margin-top: 8px;
vertical-align: middle;
width: 100%;
border-radius: 9px;
}
.desc a:hover {
text-decoration: none;
color: #b3b3b3;
}
/* Responsive layout - makes a two column-layout instead of four columns */
#media screen and (max-width: 800px) {
.column {
-ms-flex: 50%;
flex: 50%;
max-width: 50%;
}
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
#media screen and (max-width: 600px) {
.column {
-ms-flex: 100%;
flex: 100%;
max-width: 50%;
}
}
I have been struggling with the flexbox column layout. I am trying to create a 3 column layout that stretch vertically all the way to the end of the page (height:100%;). However, 2 of the columns must have specific widths that still scale down on different size screens, is this possible?
CSS:
.container {
display: -webkit-flex;
display: flex;
height: 100%;
}
.initial {
-webkit-flex: initial;
flex: 1;
width: 510px;
min-width: 100px;
}
.flex1 {
-webkit-flex-basis: 28px; /* Safari 6.1+ */
flex-basis: 28px;
}
.flex2 {
-webkit-flex: 2;
flex: 2;
}
HTML
<div class="container">
<section class="elem initial">
<div id="Left">
<h1>Heading</h1>
<p>Lorem Ipsum...</p>
</div>
</section>
<section class="elem flex1">
<div class="col"><img src="img/stripe"/></div>
</section>
<section class="elem flex2">
<div id="Right">
<h2>Header</h2>
<ul>
<li>List item.</li>
</ul>
</div>
</section>
</div>
Here's a working example of what you might be looking for, if I've understood the question correct.
I've commented the important stuff in the code. Take a look at the code, and compare it with your own. You've been using some unnecessary flexbox elements such as flex-basis: 28px; which should just be width: 28px;
HTML
<div class="container">
<section class="elem initial">
<div id="Left">
<h1>Heading</h1>
<p>Lorem Ipsum...</p>
</div>
</section>
<section class="elem flex1">
<div class="col"><img src="img/stripe"/></div>
</section>
<section class="elem flex2">
<div id="Right">
<h2>Header</h2>
<ul>
<li>List item.</li>
</ul>
</div>
</section>
</div>
CSS
html, body {
height: 100%; /* Makes it possible to illustrate the full 100% height */
}
.container {
display: flex; /* Adds flex functionality */
height: 100%;
}
.initial {
width: 510px;
min-width: 100px;
background-color: orange;
}
.flex1 {
width: 28px;
background-color: red;
}
.flex2 {
flex: 1; /* Fills the rest of the available space */
background-color: green;
}
UPDATE
I forked the pen in order to create a new working example based on the comments from the author of this question. He wanted the columns to wrap and the gutter to disappear at a certain size - I've used media queries to accomplish this.
Link to the new forked CodePen
HTML is the same.
CSS
html, body {
height: 100%; /* Makes it possible to illustrate the full 100% height */
}
.container {
display: flex; /* Adds flex functionality */
flex-direction: column;
height: 100%;
}
#media all and (min-width: 768px) {
.container {
flex-direction: row;
}
}
.initial {
width: 510px;
min-width: 100px;
background-color: orange;
}
.flex1 {
display: none;
}
#media all and (min-width: 768px) {
.flex1 {
display: flex;
width: 28px;
background-color: red;
}
}
.flex2 {
flex: 1; /* Fills the rest of the available space */
background-color: green;
}
Remember your vendor-prefixes.