Stripe creditcard elements not loaded in Safari browser - stripe-payments

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>

Related

Inverted video player's navigation bar when video streaming

I'm building a video chat application using Node, Express, Socket.io, and WebRTC by following this tutorial: Link blog
So on my edge browser, after i enabled the video stream on my application and my webcam is activated, i noticed that when i right click on the video area (video element) and click on show all controls, i found that video player navigation bar is inverted.
Do you have any explication on why the nav bar is inverted? (check theses screenshots for inversed nav bar screenshot 1 & screenshot 2)
Below are my codes:
room.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>videoChatApp</title>
<link rel="stylesheet" href="style.css" />
<script src="/socket.io/socket.io.js"></script>
<script src="https://kit.fontawesome.com/c939d0e917.js"></script>
<script src="https://unpkg.com/peerjs#1.3.1/dist/peerjs.min.js"></script>
<script>
const ROOM_ID = "<%= roomId %>";
</script>
</head>
<body>
<div class="header">
<div class="logo">
<h3>Video Chat</h3>
</div>
</div>
<div class="main">
<div class="main__left">
<div class="videos__group">
<div id="video-grid"></div>
</div>
<div class="options">
<div class="options__left">
<div id="stopVideo" class="options__button">
<i class="fa fa-video-camera"></i>
</div>
<div id="muteButton" class="options__button">
<i class="fa fa-microphone"></i>
</div>
</div>
<div class="options__right">
<div id="inviteButton" class="options__button">
<i class="fas fa-user-plus"></i>
</div>
</div>
</div>
</div>
<div class="main__right">
<div class="main__chat_window">
<div class="messages"></div>
</div>
<div class="main__message_container">
<input
id="chat_message"
type="text"
autocomplete="off"
placeholder="Type message here..."
/>
<div id="send" class="options__button">
<i class="fa fa-plus" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
</body>
<script src="script.js"></script>
</html>
script.js:
let myVideoStream;
const videoGrid = document.getElementById("video-grid");
const myVideo = document.createElement("video");
myVideo.muted = true;
navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
})
.then((stream) => {
myVideoStream = stream;
addVideoStream(myVideo, stream);
});
const addVideoStream = (video, stream) => {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
videoGrid.append(video);
});
};
server.js:
const express = require('express')
const app = express()
const { v4: uuidv4 } = require("uuid");
app.set('view engine', 'ejs')
app.use(express.static('public'));
app.get('/', (req, res) => {
res.redirect(`/${uuidv4()}`);
});
app.get("/:room", (req, res) => {
res.render("room", { roomId: req.param.room });
});
app.listen(3030, () => {
console.log('Server is runing on port 3030');
})
style.css:
#import url("https://fonts.googleapis.com/css2?family=Poppins:wght#400;500;600&display=swap");
:root {
--main-darklg: #1d2635;
--main-dark: #161d29;
--primary-color: #2f80ec;
--main-light: #eeeeee;
font-family: "Poppins", sans-serif;
}
* {
margin: 0;
padding: 0;
}
.header {
display: flex;
justify-content: center;
align-items: center;
height: 8vh;
position: relative;
width: 100%;
background-color: var(--main-darklg);
}
.logo > h3 {
color: var(--main-light);
}
.main {
overflow: hidden;
height: 92vh;
display: flex;
}
.main__left {
flex: 0.7;
display: flex;
flex-direction: column;
}
.videos__group {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
background-color: var(--main-dark);
}
video {
height: 500px;
border-radius: 1rem;
margin: 0.5rem;
width: 900px;
object-fit: cover;
transform: rotateY(180deg);
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
}
.options {
padding: 1rem;
display: flex;
background-color: var(--main-darklg);
}
.options__left {
display: flex;
}
.options__right {
margin-left: auto;
}
.options__button {
display: flex;
justify-content: center;
align-items: center;
background-color: var(--primary-color);
height: 50px;
border-radius: 5px;
color: var(--main-light);
font-size: 1.2rem;
width: 50px;
margin: 0 0.5rem;
}
.background__red {
background-color: #f6484a;
}
.main__right {
display: flex;
flex-direction: column;
flex: 0.3;
background-color: #242f41;
}
.main__chat_window {
flex-grow: 1;
overflow-y: scroll;
}
.main__chat_window::-webkit-scrollbar {
display: none;
}
.main__message_container {
padding: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.main__message_container > input {
height: 50px;
flex: 1;
font-size: 1rem;
border-radius: 5px;
padding-left: 20px;
border: none;
}
.messages {
display: flex;
flex-direction: column;
margin: 1.5rem;
}
.message {
display: flex;
flex-direction: column;
}
.message > b {
color: #eeeeee;
display: flex;
align-items: center;
text-transform: capitalize;
}
.message > b > i {
margin-right: 0.7rem;
font-size: 1.5rem;
}
.message > span {
background-color: #eeeeee;
margin: 1rem 0;
padding: 1rem;
border-radius: 5px;
}
#video-grid {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
#showChat {
display: none;
}
.header__back {
display: none;
position: absolute;
font-size: 1.3rem;
top: 17px;
left: 28px;
color: #fff;
}
#media (max-width: 700px) {
.main__right {
display: none;
}
.main__left {
width: 100%;
flex: 1;
}
video {
height: auto;
width: 100%;
}
#showChat {
display: flex;
}
}
You are applying a 180 degree rotation to the element (i.e. mirroring it)
by using transform: rotateY(180deg) in your CSS file which also rotates the controls.
For WebRTC usage the common approach to solving this is not to use the build-in controls of the video element.

Size of the map when redenring mapbox in React

I trying to use mapbox GL to render a map in React.
I've diveide my screen in 4(2 col/crow) with Grid with the following css:
.container {
font-family: sans-serif;
margin: 0;
display: grid;
grid-template-rows: 1fr 7fr;
grid-template-columns: auto;
gap: 5px;
grid-template-areas: "cr1 cr2"
"cr1 cr4";
height: 100vh;
width: 200vh;
background-color: chartreuse;
}
.table {
grid-area: cr1 ;
background-color: aqua;
display: flex;
justify-content: center;
align-items: center;
}
.tank-select {
grid-area: cr2;
background-color: grey;
}
.map {
grid-area: cr4;
display: flex;
justify-content:space-around;
align-items:stretch;
background-color: blueviolet;
}
i would like to have the map in the box cr4 with the following code:
<div className="container">
<div className="table">test</div>
<div className="tank-select">test2</div>
<div className="map">
<Map />
</div>
</div>
The map is compute this way:
const mapContainerRef = useRef(null)
const [lng, setLng] = useState(5)
const [lat, setLat] = useState(34)
const [zoom, setZoom] = useState(1.5)
// Initialize map when component mounts
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [lng, lat],
zoom: zoom,
})
// Add navigation control (the +/- zoom buttons)
map.addControl(new mapboxgl.NavigationControl(), 'top-right')
map.on('move', () => {
setLng(map.getCenter().lng.toFixed(4))
setLat(map.getCenter().lat.toFixed(4))
setZoom(map.getZoom().toFixed(2))
})
// const marker = new mapboxgl.Marker().setLngLat(TankLocationArray).addTo(map)
//
map.on('load', function () {
map.addSource('route', {
type: 'geojson',
data: '../../assets/data/test.geoJSON',
})
map.addLayer({
id: 'route',
type: 'symbol',
source: 'route',
paint: {
'circle-radius': 10,
'circle-color': '#ff0000',
},
})
})
//
// Clean up on unmount
return () => map.remove()
}, []) // eslint-disable-line react-hooks/exhaustive-deps
return (
<div>
<div className="sidebarStyle">
<div>
Longitude: {lng} | Latitude: {lat} | Zoom: {zoom}
</div>
</div>
<div className="map-container" ref={mapContainerRef} />
</div>
With the css:
.map-container {
position:relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sidebarStyle {
display: inline-block;
position: absolute;
top: 0;
left: 0;
margin: 12px;
background-color: #404040;
color: #ffffff;
z-index: 1 !important;
padding: 6px;
font-weight: bold;
}
When i change the map-container position from relative to absolute, the map would take the whole screen, otherwise it's not visible.
I do not know how to style to get the map to appear only in the box .map(cr4).
thanks for the help
solved the issue using React Map GL library.
works really fine. https://www.npmjs.com/package/react-map-gl

How to seperate sender and receiver message on basis of their socket ids in angular12 and nodejs

I want to display the sender and receiver message on different side but i dont know how i can do this
this is app.component.ts code
import { Component } from '#angular/core';
import { ChatService } from './chat.service';
import * as moment from 'moment';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'AngularApp';
constructor(private chatService: ChatService){}
newMessage!: string;
messageList: string[] = [];
ngOnInit(){
this.chatService.getNewMessage().subscribe((message: string) => {
let currentTime = moment().format('hh:mm:ss a');
this.messageList.push(message);
})
}
sendMessage() {
this.chatService.sendMessage(this.newMessage);
this.newMessage = '';
}
}
This is chatservice.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { io } from "socket.io-client";
#Injectable({
providedIn: 'root'
})
export class ChatService {
public message$: BehaviorSubject<string> = new BehaviorSubject('');
constructor() {}
socket = io('http://localhost:3000');
public sendMessage(message:any) {
this.socket.emit('message', message);
}
public getNewMessage = () => {
this.socket.on('message', (message) =>{
this.message$.next(message);
});
return this.message$.asObservable();
};
}
this is my app.component.html code
<div class="container">
<div class="chat-box">
<!-- client -->
<div class="client">
<h2>Simple Chat App</h2>
</div>
<!-- Main Chat Section -->
<div class="chats" *ngFor="let message of messageList">
<div *ngIf="message" class="client-chat">{{message}}</div>
<div *ngIf="message" class="my-chat">{{message}}</div>
</div>
<!-- Input Field -->
<div class="chat-input">
<input type="text" [(ngModel)]="newMessage" (keyup)="$event.keyCode == 13 && sendMessage()" placeholder="Enter Message">
<button (click)="sendMessage()" id="send-btn" class="btn btn-info">
Send
</button>
</div>
this is my app.component.css code
.container{
display: flex;
justify-content: center;
align-items: center;
}
/* Chat Box Section */
.chat-box{
width: 500px;
height: 550px;
background-color: #fff;
overflow: hidden;
border-radius: 10px;
position: relative;
overflow-y: scroll;height: XX px
}
.client{
height: 70px;
background-color: #77b3d4;
padding: 15px;
text-align: center;
}
.client, h2{
color: white;
}
/* Chat Section */
.chats{
width: 100%;
padding: 0 17px;
color: #fff;
position: relative;
font-size: 0.9em;
list-style-position: unset;
}
.client-chat{
width: 60%;
word-wrap: break-word;
background-color: #4f5d73c7;
padding: 7px 10px;
border-radius: 10px 10px 10px 0px;
margin: 10px 0px;
}
.my-chat{
width: 60%;
word-wrap: break-word;
background-color: #77b3d4c7;
padding: 7px 10px;
border-radius: 10px 10px 0px 10px;
margin: 5px 0px 5px auto;
}
/* Input Section */
.chat-input{
display: flex;
align-items: center;
width: 500px;
height: 65px;
background-color: #fff;
padding: 15px;
overflow: hidden;
position: fixed;
bottom: 0;
margin-top: 20px;
}
.chat-input input{
width: calc(100% - 40px);
height: 100%;
background-color: #4f5d7321;
border-radius: 45px;
color: #000;
font-size: 1.2em;
padding: 0 15px;
border: none;
}
#send-btn{
width: 50px;
height: 30px;
/* background-color: transparent; */
margin-left: 3px;
cursor: pointer;
}
this is my nodejs backend code
const app = require('express')();
const httpServer = require('http').createServer(app);
const io = require('socket.io')(httpServer, {
cors: {origin : '*'}
});
const port = process.env.PORT || 3000;
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('message', (message) => {
io.emit('message', `${socket.id.substr(0, 2)} said--${message}`);
});
socket.on('disconnect', () => {
console.log('a user disconnected!');
});
});
httpServer.listen(port, () =>
console.log(`listening on port ${port}`));
This is the screenshot of my code response when i display message i shows two time
Please anyone can solve this problem thanks in advance
In your template you have the following
<div class="chats" *ngFor="let message of messageList">
<div *ngIf="message" class="client-chat">{{message}}</div>
<div *ngIf="message" class="my-chat">{{message}}</div>
</div>
so both client-chat and my-chat will always appear since message is always true (it s the content of the message). You will need a way to know if a message come from yourself or from someone else.
Simple solution would be :
Use socket.id and when sending a message to BE, you send the message + the id.
The BE will then broadcast that message with the id.
In your clients, you will need to check
if the message come from the same socketId we are using, then it is our message so use my-chat
if the message come from a socket that is not ours, then display it as client-chat
then just assign a boolean to the message based on this, self:true if it's our message and false if not
and you simply update
<div class="chats" *ngFor="let message of messageList">
<div *ngIf="!message.self" class="client-chat">{{message}}</div>
<div *ngIf="message.self" class="my-chat">{{message}}</div>
</div>
EDIT :
So, this is a quickly made draft, you should really find the best implementation that suit your case.
you could, In your current BE :
socket.on('message', (message) => {
io.emit('message', `${socket.id.substr(0, 2)} said--${message}`);
});
You only send 2 char of the socketId. you can send it all with
socket.on('message', (message) => {
io.emit('message', `${socket.id} said--${message}`);
});
you can then in your FE just recover the sockedId by retrieving it from inside the string.
so you could do use
const socketId = message.split(' said--')[0]
and compare
socked.id === socketId

How to list Items in rows of 3 in React

I have a list of items that I want to display in rows of 3 but it's not displaying in 3 rows. it works in the normal HTML but doesn't work in React.
Here is my Event Component
const Event = (props) => (
<div className="wrap">
<div className="tile">
<img src={props.event.eventImage} />
<div className="text">
<h1>{props.event.title}</h1>
<h2 className="animate-text">More lorem ipsum bacon ipsum.</h2>
<p className="animate-text">{props.event.description}</p>
<div className="dots">
<span />
<span />
<span />
</div>
</div>
</div>
</div>
);
export default class EventsList extends Component {
constructor(props) {
super(props);
this.state = { events: [] };
}
componentDidMount() {
axios
.get("http://localhost:9000/events/")
.then((response) => {
this.setState({ events: response.data });
})
.catch(function (error) {
console.log(error);
});
}
eventList() {
return this.state.events.map(function (currentEvent, i) {
return <Event event={currentEvent} key={i} />;
});
}
render() {
return (
<div>
<div className="row">{this.eventList()}</div>
</div>
);
}
}
and my css
.wrap {
margin: 50px auto 0 auto;
width: 100%;
display: flex;
align-items: space-around;
max-width: 1200px;
}
.tile {
width: 380px;
height: 380px;
margin: 10px;
background-color: #99aeff;
display: inline-block;
background-size: cover;
position: relative;
cursor: pointer;
transition: all 0.4s ease-out;
box-shadow: 0px 35px 77px -17px rgba(0, 0, 0, 0.44);
overflow: hidden;
color: white;
font-family: "Roboto";
}
.tile img {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 0;
transition: all 0.4s ease-out;
}
.tile .text {
/* z-index:99; */
position: absolute;
padding: 30px;
height: calc(100% - 60px);
}
.tile h1 {
font-weight: 300;
margin: 0;
text-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3);
}
.tile h2 {
font-weight: 100;
margin: 20px 0 0 0;
font-style: italic;
transform: translateX(200px);
}
.tile p {
font-weight: 300;
margin: 20px 0 0 0;
line-height: 25px;
/* opacity:0; */
transform: translateX(-200px);
transition-delay: 0.2s;
}
.animate-text {
opacity: 0;
transition: all 0.6s ease-in-out;
}
.tile:hover {
/* background-color:#99aeff; */
box-shadow: 0px 35px 77px -17px rgba(0, 0, 0, 0.64);
transform: scale(1.05);
}
.tile:hover img {
opacity: 0.2;
}
.tile:hover .animate-text {
transform: translateX(0);
opacity: 1;
}
.dots {
position: absolute;
bottom: 20px;
right: 30px;
margin: 0 auto;
width: 30px;
height: 30px;
color: currentColor;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.dots span {
width: 5px;
height: 5px;
background-color: currentColor;
border-radius: 50%;
display: block;
opacity: 0;
transition: transform 0.4s ease-out, opacity 0.5s ease;
transform: translateY(30px);
}
.tile:hover span {
opacity: 1;
transform: translateY(0px);
}
.dots span:nth-child(1) {
transition-delay: 0.05s;
}
.dots span:nth-child(2) {
transition-delay: 0.1s;
}
.dots span:nth-child(3) {
transition-delay: 0.15s;
}
#media (max-width: 1000px) {
.wrap {
flex-direction: column;
width: 400px;
}
}
This is how it's displaying.
But this is what I want to achieve.
I am new to React and I'm learning by building a project.
Here is codepen link of what I want to achieve.
Codepen Link
I have a feeling it's your css, you have your wrap class stretching the whole row width and within it, there is a tile that's only 380px.
Consider making row a grid with three columns.
Ciao, you can use display: 'in-line' like this:
return <Event event={currentEvent} key={i} style={{display: 'in-line'}}/>;

Why is my node.js etcd client getting html

My etcd instance is running locally and I can perform get and set using the cli
// set
etcdctl set /services/myservice "{\"hostname\": \"127.0.0.1\", \"port\": 3000}"
//get
etcdctl get services/myservice
// results in -> {"hostname": "127.0.0.1", "port": 3000}
but when I use the node-etc module
var Etcd = require('node-etcd');
var etcd = new Etcd(['http://localhost:2379', 'http://localhost:4001']);
etc.get('services/myservice', { wait: true}, function (err, value){
console.log(err, value);
});
I get value is HTML (see below) instead of the same result as the cli. This was working a few weeks ago so I am not sure if I have
I also find that when I don't include hosts and just use new Etcd() I get an internal HTML page with references to proxy issues: "The requested website is blocked by [insert company name] Proxy due to potential malicious activity or other security reasons."
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" data-adblockkey="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKrfIMFkSaoTSqKmC+BrghK0CpDHc0MuVzmMHin8LIORhpXbped+iYhSnZurWnEO0zcKcVIrzp026LVc5pMB9bUCAwEAAQ==_mHzvOc3GBNo9sxVki+5Fe+E9GsbiT2+mBIEtU+yAIW6jw6Uds6VUD5RSkqMfuUSrcw4AYCrFOWaaWSRGDzU8pw==">
<head>
<script type="text/javascript">
var abp;
</script>
<script type="text/javascript" src="http://www.http.com/px.js?ch=1"></script>
<script type="text/javascript" src="http://www.http.com/px.js?ch=2"></script>
<script type="text/javascript">
function handleABPDetect() {
try {
var imglog = document.createElement("img");
imglog.src = "http://www.http.com/rg-logabpstatus.php?a=WVpqOEdZZldDTWo4VWF0M0pNa1pBek0xQnE1WVlqR2VaQ0Frd0V4TUxmcDAvOFN2WnhHYS8weFFEeTZTRHlleTM0UFk3UDhzemxqSWFRdXlFdXpIUGc9PQ==&b=" + abp;
document.body.appendChild(imglog);
} catch (err) {}
}
try {
window.onload = handleABPDetect();
} catch (err) {}
</script>
<title>http.com</title>
<meta http-equiv="Content-Type" content="text/html; charset=">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable = no">
<style type="text/css">
* {
margin: 0;
padding: 0
}
a {
text-decoration: none;
outline: none
}
a:hover {
text-indent: 0;
cursor: pointer
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0
}
* html .clearfix {
zoom: 1
}
*:first-child+html .clearfix {
zoom: 1
}
body {
font-family: Arial, Helvetica, sans-serif;
background: url(http://c.rmgserving.com/rmgpsc/7867/body-bg.gif) 0 0 repeat #000
}
/*.arrows{background:url(http://b.rmgserving.com/rmgpsc/7867/arrows.jpg)}*/
#main-wrap {
background: url(http://a.rmgserving.com/rmgpsc/7867/header-bg.jpg) top center no-repeat;
background-size: 100% 100px
}
.container {
width: 960px;
margin: 0 auto
}
.header {
height: 100px
}
/*commented for new design */
/*.leftblk{float:left; overflow:hidden}
.leftblk img{float: left; margin-top: 23px; padding-right: 15px;}*/
/*.domain_name{float:left; line-height:100px; font-size:26px; font-weight:normal; color:#fff}*/
.searchbox {
float: right;
width: 410px;
* width: 420px;
_width: 420px;
height: 28px !important;
padding-top: 2px;
margin-top: 35px;
/*padding-left:33px;background:url(http://d.rmgserving.com/rmgpsc/7868/srch-bg-caf2.gif) 0 0 no-repeat*/
}
.content {
padding-bottom: 10px;
background: #202020
}
/**RESPOSIVE CHANGES MADE HERE**/
.domain_name {
line-height: normal;
font-size: 26px;
font-weight: normal;
color: #fff;
margin-top: 35px
}
.leftblk {
float: left;
width: 39%;
word-wrap: break-word;
background: url(http://c.rmgserving.com/rmgpsc/7867/logo1.png) no-repeat center left;
padding-left: 70px;
height: 100px;
overflow: hidden;
}
.frt_arr {
float: left;
width: 30%;
height: 425px;
background: url(http://d.rmgserving.com/rmgpsc/7983/frst_arr.jpg);
background-position: 10px 70px;
background-repeat: no-repeat;
background-size: 90%
}
.lst_arr {
float: left;
width: 30%;
height: 425px;
background: url(http://b.rmgserving.com/rmgpsc/7983/last_arr.jpg);
background-position: 0px 70px;
background-repeat: no-repeat;
background-size: 90%
}
.kwd_bloack {
float: left;
width: 40%;
margin-top: 74px
}
/**RESPOSIVE CHANGES END HERE**/
.bottom_bg {
height: 44px;
/*background:#181818; */
margin-top: 34px
}
.bottom_rs {
width: 960px;
height: 44px;
overflow: hidden;
margin: 0 auto;
position: relative
}
#bot_rs {
padding-top: 9px
}
.separator {
position: absolute;
top: 0;
left: 156px;
width: 5px;
height: 44px;
border-left: 2px solid #282828;
background: url(http://a.rmgserving.com/rmgpsc/7867/sep-arw.gif) center center no-repeat
}
.footer-nav {
width: 100%;
height: 74px;
text-align: center;
color: #c0c0c0;
}
.footer-nav a {
font-size: 12px;
line-height: 74px;
color: #c0c0c0;
padding: 0 5px;
text-decoration: underline
}
.footer-nav a:hover {
text-decoration: none
}
.inquire {
text-align: right;
padding-top: 10px;
color: #fff
}
.inquire a {
font-size: 12px;
font-weight: normal;
color: #fff
}
.sale-msg {
background: #fff;
color: #4b4b4b;
text-align: center;
font-size: 14px;
width: 100%;
top: 0;
left: 0
}
.sale-msg a {
text-decoration: none;
color: #079ce9;
font-size: 14px;
}
.sale-msg a:hover,
.bottom_rs ul li a:hover,
.mid_rs ul li a:hover,
.inquire a:hover {
text-decoration: underline
}
#media not all and (min-width: 970px) {
.container {
width: 95%
}
.bottom_bg {
display: none
}
.footer-nav a {
line-height: 45px
}
}
#media not all and (min-width: 840px) {
.frt_arr {
display: none
}
.lst_arr {
display: none
}
.kwd_bloack {
float: none;
width: 95%;
margin: 0 auto;
padding-top: 10px
}
.leftblk {
float: none;
height: 50px;
background-size: 35px;
padding-left: 50px;
width: auto
}
.domain_name {
line-height: normal;
font-size: 20px;
margin-top: 0;
padding-top: 15px
}
.searchbox {
float: none;
margin-top: 10px;
padding-top: 0;
width: auto;
}
}
</style>
<script type="text/javascript" src="http://www.google.com/adsense/domains/caf.js"></script>
</head>
<body onload="" onunload="" onBeforeUnload="">
<noscript>
<meta http-equiv="refresh" content="0;url=http://www.http.com/rg-erdr.php?_rpo=t ntZzFFI&_rdm=9f1NJXf43BJvmfNf4.JvV&p=J1c4gcvmfN9ffFGoFgXoYVa%7C%40%7CbzGzTE%2C5f95zbT%2C5f95Et%7C%40%7CX55g.JvV%7C%40%7C%7C%40%7C%7C%40%7CZzbHzEZHE%7C%40%7CzHZZFTH%7C%40%7CK-%7C%40%7C19c4NW4cGFHzTEtTEGZGzTbT%7C%40%7Ct+nh8llbj%7C%40%7Ct+7zFZKFH&ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&t=gnojs" />
<center>
<p style="padding:1em; font-size:1.5em;">For search results please CLICK HERE.</p>
</center>
</noscript>
<script type="text/javascript" language="javascript">
function __gpup(url, height, width, name) {
sw = window.open(url, name, 'height=' + height + ',width=' + width + ',location=no,toolbar=0,resizable=1,scrollbars=1');
if (window.focus) {
sw.focus()
};
return false;
};
</script>
<script text="text/javascript">
var design = {
'pageOptions': {
'pubId': '',
'resultsPageBaseUrl': '',
'fontFamily': 'arial',
'hl': 'en',
'maxTermLength': 29,
'adtest': 'on',
'clicktrackUrl': '',
'fontFamilyAttribution': 'arial',
'type': 'pageoptions',
'pageLoadedCallback': function(requestAccepted, status) {
document.body.style.visibility = 'visible';
if (!requestAccepted) {}
}
},
'searchboxBlock': {
'container': 'searchbox',
'type': 'searchbox',
'fontSizeSearchInput': 16,
'fontSizeSearchButton': 13,
'widthSearchInput': 215,
'colorSearchButton': '#e2e2e2',
'hideSearchInputBorder': false,
'hideSearchButtonBorder': false
},
'mainrs': {
'container': 'main_rs',
'type': 'relatedsearch',
'colorBackground': 'transparent',
'number': 6,
'fontSizeTitle': 19,
'titleBold': true,
'colorTitleLink': '#079ce9',
'noTitleUnderline': false,
'lineHeightTitle': 30,
'fontFamily': 'arial',
'horizontalAlignment': 'center',
'fontSizeAttribution': 13,
'colorAttribution': '#ababab',
'attributionBold': true,
'attributionUppercase': false,
'attributionSpacingBelow': 36,
'rolloverLinkUnderline': false,
'rolloverLinkColor': '#00c800',
'colorAdSeparator': '#202020'
}
};
</script>
<div id="main-wrap" class="clearfix">
<div class="container clearfix">
<div class="header clearfix">
<div class="leftblk">
<!-- <img src="http://c.rmgserving.com/rmgpsc/7867/logo1.png" /> -->
<h3 class="domain_name">http.com</h3>
</div>
<div class="searchbox clearfix" id="searchbox"></div>
</div>
<div class="content clearfix">
<div class="arrows frt_arr"></div>
<div class="kwd_bloack clearfix" id="main_rs"></div>
<div class="arrows lst_arr"></div>
</div>
</div>
<div class="bottom_bg clearfix">
<div class="bottom_rs clearfix">
<!--<span class="separator"></span>-->
</div>
</div>
<div class="footer-nav">
Privacy Policy </div>
</div>
<script type="text/javascript" language="javascript">
window._debug = false;
window._dumpdata = false;
var _cflp = true;
var pgld = true;
var totRS = -1;
var cntRS = 0;
var _cfstc = false;
var _cfblocker = true;
var _cfrg = true;
var _cfHelp = _cfHelp || {};
_cfHelp.design = design || {};
_cfHelp.servVars = {
"webadfl": "webads.php",
"_clhdl": "http:\/\/www.http.com\/rg-cltrack.php?&gr=%5B%7Crdr_url%7C%5D&gm=1WHI0lwrG0Sxkx4PsD8qyCOUd1dkaI2X1l8SGG1fMSd7bfeWMBF%2FyegsqR%2BZliS%2FkmMLg273bT8VsQ1oofKDtwu2BLulOOE9e9f%2FGbKVB3y9mwzTRLUiokCVqtb5Zk84C2EVcNaF2G3r9Bp3RsH1xfXrZC%2BE8YGoveyKL4ONQKcLbTlODzh%2BgHyFxmaFdMqH&gc=11101851242258318844884&gi=XYb9MaQozttVcq86LfylD8RNPuvlew8QArHjQzucy26g%2BlAY%2F2uHYh%2BA6ff50kcc1PxTBiLUWCU4jHCv3wduaWHfl%2Fk8mkRKtWu8EB0jglLzw7eeSqi3ynxhbG7655Fy%2FLKMke6nBiTt%2FuiCvqlrvF1W%2F0MGzePy07JWvEsPuPqNBujvQaw3gGby3VkjIxfm2atlkRoPbyOyKYholPIgVyyBcIBJQvM3kSCiRXOyaMpxjTprto%2B0LbFQmRT0%2Bv05GchdCqw0KwcBJr1GshmWISk5vXG28qmhuRBFtwmFZTdpEHObgOZuOhjtcRKzp6QcLHJxeH43ucmzlzBBC8rUhA%3D%3D",
"kchst": "http:\/\/www.http.com\/",
"kcpg": "render",
"kcprm": "ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&gqsg=4OVo54jg6Fc8v4dgaRWvLlUoQfiT9l0g4KypdpyKIkp3XttitvahDJPyd8JV8AMP&maxads=0&gerf=NIVtBZ66fMb06L%2FzgSYcSUpDtBcVFLddp21rUKg8Zvs%3D&wait=true",
"jtchdl": "0",
"lkwtkn": null,
"qry": null,
"cntry": "IE",
"prvid": 1566375,
"lgky": "VFJIcUJEQUZtMGQ3dVY0amZaMmFIVi8vL2g2WUVmRkQxNVp6eEJRcSs1WFl3K3cvZFFISS9aN1Y4NE1KamNIUi95TW04Q3p6ek9RejR1N1pRemlJS1hORjIzNEF2Z3d3TGkyUGhGNkJxREdyRDJLNzZoWVMraXd0cFZGK1hiWTY5aGNYRTlmOHlDa3E5bmpLTHRtelJ3PT0%3D",
"_aftrprss": "",
"wclhdl": "http:\/\/www.http.com\/webclk?&gr=%5B%7Crdr_url%7C%5D&gm=N3DjGjxerDa%2B8Ln3%2B884CDaIWdGzXLcE6PGovrvm8cwEqFKj9%2FsSAw13RemOENdu59z53RIAX7qKedB%2BbC7k6lI6gFbOxQR7qkhujpZqsJMhUo0JnsgwBv6eY8R4QxT34RDgzTHG7pSdzqCdYGLMkjkrWeoByyf1I3drNmqLJoXF8CRTdNMoZwb5HxP8G2KL&gc=11101851242258318844501&gi=3asGzSvNXUezIegH6SkVMB9oHMTe%2BRtyB0XjQzqrg%2BegxXIIXBBR%2FNpmg%2FEpOC3SbbpbaUmlcSRdngRk3viiaUqqjkydC5SRcNAQIHAVCSz4CcvOsJgD4kJKepiaVN2MkCXSlbZfRbnV4Lj3QWLNCEpoUpJaD8GoKU2ZiKd%2B2wDKToaj236za8yEZZnAejv7CqvZi7bAnoT7LFHAT4YfVQYDvpwbpObRothY86AABfVVWr%2BDuudu2Z1HgnO7kRUJx945jHKd%2BHgj7szCxsb6xBb7wBlUblacTda5uwQKPLtiF5n7ChXCCJTf%2BYsC%2FDDegcmi71Z8FBC6SLSZ%2FYvsJQ%3D%3D",
"is_webad_enabled": 0,
"loaderimage": "http:\/\/c.rmgserving.com\/rmgisc\/loader.gif",
"_afdad": 1,
"noredir": 0,
"erpub": "oversee11_3ph_adult_xml",
"erch": "372",
"erpubcln": "ca-dp-oversee11_3ph_xml",
"erchcln": "000307",
"ghu": "http:\/\/www.http.com\/rg-erdr.php?_rpo=t ntZzFFI&_rdm=9f1NJXf43BJvmfNf4.JvV&p=J1c4gcvmfN9ffFGoFgXoYVa%7C%40%7CbzGzTE%2C5f95zbT%2C5f95Et%7C%40%7CX55g.JvV%7C%40%7C%7C%40%7C%7C%40%7CZzbHzEZHE%7C%40%7CzHZZFTH%7C%40%7CK-%7C%40%7C19c4NW4cGFHzTEtTEGZGzTbT%7C%40%7Ct+nh8llbj%7C%40%7Ct+7zFZKFH&ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO"
};
_cfHelp.newOpts = {
"pageoptions": {
"kw": "http",
"pubId": "dp-oversee32_3ph_xml",
"channel": "012174,test107,test49",
"hl": "",
"adtest": "off",
"resultsPageBaseUrl": "http:\/\/www.http.com\/?ga=5rKI1sSSBwFmmNY4RDXg%2BB7VS0yzNgnQ9JpHpsLHSsvFu0NyshpFxWu0exObFAo5IdFZQrTZujcZjrXONxp3PxtPV7ezER14zh7kWG69e5lf08niAgSfUKiyBSByBIQgw92X314XjQy5h09a65wi7JIhzrLV0PReUb%2F7SMvquCNLeg70qvVfr7kkYTx9Z4NO&gqsg=4OVo54jg6Fc8v4dgaRWvLlUoQfiT9l0g4KypdpyKIkp3XttitvahDJPyd8JV8AMP&maxads=0&gerf=1NwSv6zgpkznlToCcC1LUPxAge73x0kzNUyoFwPpLQw%3D&wait=true",
"clicktrackUrl": "http:\/\/www.http.com\/rg-cltrack.php?&gr=http%3A%2F%2Fgoogle.com%2F%3FRMGcaf%261437578625&gm=lCHzRGQVmF5GbI%2FoJNvHO9F0H1pK6b4imVg4sD83gr0zwhCg7kUY7A5JisFIua0ovWZYB4g4CbZlK6DDWhXlYS%2FoGwafEe2w6vLAAhtarOqSrags%2FXIb7w%2BHM0BEJgeyKmMXhVQya9xYRoVUupKo7SfWKOP26QW4BeaSRA7pvaleohDknqEJ8irgK41FOPBr&gc=11101851242258318844252&gi=dqJeJ2LIBm6EoVjrQxF%2FslKeVO2MMfAIGz5LwKTbfKTDn9L7haFS7W3vKNwbjSGhC5JthqkexETQM8mEun%2F4M5TCzM0Vphb237zGYUpoBtB1%2BdaJoSRcYUFKnr9lF6i32soKngUvevO7DHx9BHSz7sCMXYPLkJicrRb7WxfYNRWz0plNCCbrW8HYaPbhclR9gVbhSwIUdzpMjwGFrNyh%2B9iqRYF%2BX0wFzLunKbgTnLdmXJuP0Vm%2BjkU%2BC4rprcocV7pcHhlR0%2FKP2vHSKAlWTPcuCA9P04LbPqttMcdlol%2Fpm%2BAeIg79dx%2Bb28yVLKBEpMifhq6%2BT%2B2LndQdLFX%2FCoMvHjee%2BMfVwkRgY8%2F9hqFI%2B9UvBLgcgjCtTYSruCn7",
"domainRegistrant": "as-drid-2351749742621707",
"optimizeTerms": false,
"terms": "[\"Domain Registration\",\"Network Monitoring\",\"Email Hosting\",\"Website Hosting\",\"Network Monitoring Software\",\"High Speed internet\",\"Cable Internet\",\"Broadband Internet\",\"Web Security\",\"Dial-Up Internet\",\"Wireless Internet Providers\",\"Unlimited Broadband\",\"Internet Speed Check\",\"Compare Broadband\",\"Cheap Internet Service\",\"Best Broadband Deals\",\"Internet Solutions\",\"Internet Music\",\"Internet Help\",\"Internet Telephony\",\"Business Internet Providers\",\"Broadband Availability\",\"Prepaid Wireless Internet\",\"Internet Florists\",\"Mobile Wireless Internet\"]",
"uiOptimize": false,
"domainName": "http.com"
},
"relatedsearch": {
"adLoadedCallback": function(cnm, ld) {
if (pgld && !ld && _cfrg && !_cfstc && _cflp) {
cntRS++;
if (cntRS >= totRS && totRS != -1) {
window.location = "http://www.http.com/?_stc_=1"
}
}
}
},
"textads": {
"adLoadedCallback": function(cnm, ld) {}
},
"imagead": {
"adLoadedCallback": function(cnm, ld) {}
},
"ads": {
"adLoadedCallback": function(cnm, ld) {}
}
};
_cfHelp.newOpts.pageoptions["pageLoadedCallback"] = function(requestAccepted, status) {
this.onPageLoad(requestAccepted, status);
_cfblocker = false
};
try {
if (abp) {
_cfHelp.newOpts.pageoptions['channel'] = _cfHelp.newOpts.pageoptions['channel'] + ',test101'
}
} catch (e) {}
</script>
<script type="text/javascript" src="http://a.rmgserving.com/rmgdsc/newcafv2.js?1.1"></script>
</body>
</html>

Resources