Use ajax data in Gutenberg InspectorControls - json

I am create custom Gutenberg editor block to set YouTube video Id to <button> atribute data-video=""
UPDATE - Added working code to the below
My function.php code
// Include Css and js block files
function designa_youtube_block() {
// Scripts
wp_register_script(
'youtube-block-script', // Handle.
'/wp-content/themes/twentyfifteen/init/block.js',
array( 'wp-blocks', 'wp-element', 'wp-i18n' ),
time()
);
// Styles
wp_register_style(
'youtube-block-editor-style', // Handle.
'/wp-content/themes/twentyfifteen/init/editor.css',
array( 'wp-edit-blocks' ),
time()
);
// Register the block with WP using our namespacing
register_block_type( 'designa/youtube-block', array(
'editor_script' => 'youtube-block-script',
'editor_style' => 'youtube-block-editor-style',
) );
}
add_action( 'init', 'designa_youtube_block' );
My block.js code
( function( editor, components, element ) {
const el = element.createElement;
const registerBlockType = wp.blocks.registerBlockType;
const RichText = wp.editor.RichText;
const BlockControls = wp.editor.BlockControls;
const InspectorControls = wp.editor.InspectorControls;
const AlignmentToolbar = wp.editor.AlignmentToolbar;
const UrlInput = wp.editor.URLInput;
function getVideoId(url) {
if (url) {
let match = url.match(/^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/);
if (match && match[2].length == 11)
return match[2];
else
return false;
} else {
return false;
}
}
registerBlockType( 'designa/youtube-block', {
title: 'YouTube',
description: 'Видео в всплывающем окне.',
icon: 'video-alt3',
category: 'common',
attributes: {
content: {
type: 'string',
},
url: {
type: 'string',
},
alignment: {
type: 'string',
},
},
edit: function( props, isSelected ) {
let attributes = props.attributes,
url = props.attributes.url,
alignment = props.attributes.alignment;
function onChangeAlignment( newAlignment ) {
props.setAttributes( { alignment: newAlignment } );
}
if (url)
videoTitle();
async function videoTitle(){
let id = getVideoId(url);
const response = await fetch( `https://www.googleapis.com/youtube/v3/videos?id=${ id }&key=AIzaSyBUqaVKkqdXzPQnfuuP8VPa-yqOQlJwV-w&fields=items(snippet(title))&part=snippet`, {
cache: 'no-cache',
headers: {
'user-agent': 'WP Block',
'content-type': 'application/json'
},
method: 'GET',
redirect: 'follow',
referrer: 'no-referrer',
})
.then(
returned => {
if (returned.ok) return returned;
throw new Error('Network response was not ok.');
}
);
let data = await response.json();
props.setAttributes( { title: data.items[0].snippet.title} );
};
return [
el( BlockControls, { key: 'controls' },
el( AlignmentToolbar, {
value: alignment,
onChange: onChangeAlignment,
} )
),
el( InspectorControls, { key: 'inspector' },
el( components.PanelBody, {
title: 'Превью видео',
className: 'youtube-preview-block',
initialOpen: true,
},
el( 'div', {
className: 'youtube-preview',
},
el( 'iframe', {
frameborder: '0',
allowfullscreen: 'allowfullscreen',
src: url ? 'https://www.youtube.com/embed/'+getVideoId(url)+'?rel=0&showinfo=0' : ''
},
),
),
el( 'div', { className: !props.attributes.title ? 'sceleton-youtube-title' : '' },
props.attributes.title ? props.attributes.title : ''
),
),
),
el( 'div', { className: alignment ? props.className+' justify-content-'+alignment : props.className },
el( 'svg', { className: 'play-icon', width: '50', height: '50', viewBox: '0 0 70 70' },
el( 'path', { fill: '#f6155e', d: "M35 70C54.33 70 70 54.33 70 35C70 15.67 54.33 0 35 0C15.67 0 0 15.67 0 35C0 54.33 15.67 70 35 70Z" } ),
el( 'path', { fill: '#fff', d: "M48.2988 35L28.6988 44.1L28.6988 25.9L48.2988 35Z" } ),
),
el( 'div', { className: 'youtube-wrap' },
el( RichText, {
tagName: 'div',
placeholder: 'Введите текст кнопки',
keepPlaceholderOnFocus: true,
isSelected: false,
value: props.attributes.content,
onChange: function( content ) {
props.setAttributes( {
content: content,
} );
}
}
),
el( 'div', { className: 'youtube-link-wrap' },
el( 'svg', { className: 'dashicon dashicons-admin-links', width: '20', height: '20' },
el( 'path', { d: "M17.74 2.76c1.68 1.69 1.68 4.41 0 6.1l-1.53 1.52c-1.12 1.12-2.7 1.47-4.14 1.09l2.62-2.61.76-.77.76-.76c.84-.84.84-2.2 0-3.04-.84-.85-2.2-.85-3.04 0l-.77.76-3.38 3.38c-.37-1.44-.02-3.02 1.1-4.14l1.52-1.53c1.69-1.68 4.42-1.68 6.1 0zM8.59 13.43l5.34-5.34c.42-.42.42-1.1 0-1.52-.44-.43-1.13-.39-1.53 0l-5.33 5.34c-.42.42-.42 1.1 0 1.52.44.43 1.13.39 1.52 0zm-.76 2.29l4.14-4.15c.38 1.44.03 3.02-1.09 4.14l-1.52 1.53c-1.69 1.68-4.41 1.68-6.1 0-1.68-1.68-1.68-4.42 0-6.1l1.53-1.52c1.12-1.12 2.7-1.47 4.14-1.1l-4.14 4.15c-.85.84-.85 2.2 0 3.05.84.84 2.2.84 3.04 0z" } ),
),
el( UrlInput, {
tagName: 'div',
value: url,
autoFocus: false,
onChange: function( url ) {
props.setAttributes({
url: url,
title: ''
});
}
}
),
),
),
),
];
},
save: function( props ) {
let attributes = props.attributes;
return (
el( 'div', {
className: (attributes.alignment) ? 'justify-content-'+attributes.alignment : '',
},
el( 'button', {
className: 'video-btn',
'data-video': getVideoId(attributes.url),
}, attributes.content,
),
)
);
},
} );
} )(
window.wp.editor,
window.wp.components,
window.wp.element,
);
My editor.css code
.youtube-wrap {
width: calc(80% - 70px);
}
.wp-block-designa-youtube-block {
display: flex;
align-items: center;
}
.youtube-link-wrap {
display: flex;
align-items: center;
}
.youtube-link-wrap svg {
margin-right: 10px;
fill: #8f98a1;
}
.youtube-wrap {
padding: 0 20px;
}
.youtube-preview {
position: relative;
padding-bottom: 56.25%;
height: 0;
background: #e1e9ee;
margin-bottom: 14px;
}
.gutenberg__editor .youtube-preview iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.justify-content-center {
justify-content: center;
}
.justify-content-left {
justify-content: flex-start;
}
.justify-content-right {
justify-content: flex-end;
}
.sceleton-youtube-title:before, .sceleton-youtube-title:after {
content: "";
display: block;
height: 18px;
width: 100%;
background-color: #f0f4f6;
margin-bottom: 10px;
}
.sceleton-youtube-title:after {
width: 40%;
}
.components-panel__body.youtube-preview-block {
font-weight: bold;
color: #5a5e61;
letter-spacing: 0.015em;
line-height: 22px;
}
In back end I got this result:
Everything works fine, but now I need to get the title and duration of the video from YouTube by ID getId(attributes.url) and insert to InspectorControls block.
If I try to get the title and duration using Ajax, first render all block fields to InspectorControls, and then execute my ajax request. I need something like that on ajax successful push( el( 'p', {}, '**YouTube Title**') )
Tell me how to add the information obtained with Ajax to InspectorControls after rendering and on change?

Related

CSS Show div, detect if end of screen

I am implementing a customized dropdown becuase of the requirements we have, using Vue 2 and typescript (jquery is not an option).
It is working fine, when you click on the main box, it opens the options list downwards.
An improvement I am looking for is that, when at the end of the screen, the options list adds to the page height and thus causing the scrollbar to appear or increase scroll height.
What I am looking for is that, when popping up the div, if there's not enough space at the bottom of the screen, open it upwards instead. How do I achieve this?
(classes are using bootstrat 5)
Opened dropdown &
Closed dropdown
My code:
import Vue, {
PropType
} from 'vue';
import {
Validation
} from 'vuelidate';
let uidc = 0;
export default Vue.extend({
name: 'BaseDropdown',
props: {
value: {
type: [Number, String, Object],
default: () => ''
as string,
},
target: {
type: String,
default: '',
},
label: {
type: String,
default: '',
},
valueIsNumber: {
type: Boolean,
default: false,
},
options: {
type: Array,
default: null,
},
placeholder: {
type: String,
default: '',
},
required: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
validations: {
type: Object as PropType < Validation > ,
default: () => ({
$error: false,
$touch: () => undefined,
$params: {},
}) as Validation,
},
error: {
type: Boolean,
default: false,
},
trackEvent: {
type: String,
default: '',
},
trackField: {
type: String,
default: '',
},
trackPublic: {
type: Boolean,
default: false,
},
padLeft: {
type: Boolean,
default: false,
},
enforceBlackColour: {
type: Boolean,
default: false,
},
customStyled: {
type: Boolean,
default: false,
},
borderBottomWarning: {
type: Boolean,
default: false,
},
},
data(): {
selectedItem: any | null;
menuOpen: boolean;
searchText: string | null;
} {
return {
selectedItem: null,
menuOpen: false,
searchText: null,
};
},
mounted() {
const appElement = document.getElementById('app_home');
(appElement as any).addEventListener('click', this.handleDropdownClickOutside);
this.$nextTick(() => {
if (this.value) {
if (this.valueIsNumber) {
this.selectedItem = this.options.find((x: any) => x.value === Number(this.value)) || null;
} else {
this.selectedItem = this.options.find((x: any) => x.value.toString().toLowerCase() === this.value.toString().toLowerCase()) || null;
}
}
});
},
computed: {
v(): Validation | {} {
return this.validations;
},
errorMessage(): string {
// Validation must be cast to any to access validators
return Object.entries((this.v as Validation).$params).find(([k]) => !(this.v as any)[k]) ? .[1].message;
},
optgroups(): any {
return this.options.reduce((acc: any, o: any) => ({ ...acc,
[o.optgroup]: [...(acc[o.optgroup] || []), o]
}), {});
},
isRequired(): boolean {
return this.required !== false;
},
getSelectedItemText(): string | null {
return this.selectedItem ? this.selectedItem.text : this.placeholder || 'Please select an item';
},
filteredItems(): any[] {
const list: any[] = [];
for (let c = 0; c < 10; c += 1) {
list.push({
text: c,
value: c
});
}
// return this.searchText && this.searchText.length > 0 ? this.options.filter((x: any) => x.text.toLowerCase().indexOf(this.searchText!.toLowerCase()) > -1) : this.options;
return list;
},
},
methods: {
openMenu() {
this.menuOpen = !this.menuOpen;
if (this.menuOpen) {
this.searchText = null;
}
},
selectItem(item: any) {
this.selectedItem = item;
this.$emit('input', item.value);
this.menuOpen = false;
},
setSuppliedSelectedItem() {
this.$nextTick(() => {
if (this.value) {
this.selectedItem = this.options.find((x: any) => x.value === this.value) || null;
}
});
},
handleDropdownClickOutside(event: any): void {
const parent = document.getElementById(`select-${(this as any).uid}`);
const isParent = parent !== event.target && parent ? .contains(event.target);
if (!isParent) {
this.menuOpen = false;
// this.closeOpenendMenu();
// this.searchText = '';
}
},
},
beforeCreate() {
// eslint-disable-next-line no-plusplus
(this as any).uid = uidc++;
},
});
.dropdown {
font-size: 0.7rem;
img {
// float: right;
// padding-right: 10px;
// padding-top: 5px;
position: absolute;
top: 40%;
right: 10px;
}
.fade {
opacity: 0.5;
}
.search-box {
.form-control {
font-size: 12px !important;
height: 30px !important;
margin: 0 10px 5px 10px !important;
width: 95% !important;
}
}
.selected-item {
border-radius: 3px;
border: 1px solid #ced4da;
padding: 10px;
.selected-item-text {
text-overflow: ellipsis;
overflow: hidden;
width: 93%;
/* height: 1.2em; */
white-space: nowrap;
}
}
.items {
border: 1px solid rgb(236, 236, 236);
width: 100%;
z-index: 15;
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
background-color: white;
}
.item {
padding: 10px;
background-color: rgb(240, 240, 240);
cursor: pointer;
&:hover {
background-color: rgb(216, 216, 216);
}
}
}
.hidden {
opacity: 0.2;
}
.disabled {
background-color: #e9ecef;
opacity: 1;
pointer-events: none;
}
<template>
<div class="mt-2" :id="`select-${uid}`">
<label v-show="label" class="mb-2 label-grey" :class="{ 'required': isRequired }" :for="`select-${uid}`">{{ label }}</label>
<div class="dropdown noselect position-relative" :class="{'disabled': disabled}">
<div class="selected-item cursor-pointer" #click="openMenu">
<div class="selected-item-text" :class="{'fade': !selectedItem}">{{getSelectedItemText}}</div>
<img v-if="menuOpen" :src="constants.icons.arrowTop" />
<img v-else :src="constants.icons.arrowDown" />
</div>
<div class="items position-absolute" v-show="menuOpen">
<div v-if="filteredItems && filteredItems.length > 5 || searchText" class="search-box">
<input :size="'sm'" v-model="searchText" />
</div>
<div v-for="item in filteredItems" :key="item.value" #click="selectItem(item)">
<div class="item">
{{item.text}}
</div>
</div>
</div>
</div>
<span v-if="v.$error" class="text-error text-xs font-light">{{ errorMessage }}</span>
</div>
</template>
Suggest to use Floating-ui (well known as Poper)
Floating UI is a low-level library for positioning "floating" elements...intelligently keeping them in view
It's been using widely and cover a lot of edge cases you might encounter when try to create dropdown yourself
You can try with references here
creating-vue-component-dropdown-with-popper-js
floating-vue/dropdown

How to change background color of ul li elements in autosuggest react component?

Iam using react Autosuggest component for city country list. When an input is given the suggested list of cities name with their respective countries is displayed. I am able to change the background color while hovering, but, I want to change when key pressed 'up' or 'down'. Following is the code for reference
Form.js
const getSuggestions = value => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
return inputLength === 0 ? [] : cities.filter(data =>
data.name.toLowerCase().slice(0, inputLength) === inputValue
).slice(0,4);
};
// When suggestion is clicked, Autosuggest needs to populate the input
// based on the clicked suggestion.
const getSuggestionValue = suggestion => suggestion.name
const renderSuggestion = suggestion =>
(
<table className='auto-complete'>
<tbody>
<ArrowTooltip title={suggestion.name + ', ' + countries.getName(suggestion.country,"en")} placement="top">
<tr>
<td style={{ width: '88%' }} dangerouslySetInnerHTML=
{highlight(suggestion.name, suggestion.value)}></td>
<td style={{ width: '12%' }}>{suggestion.country}</td>
</tr>
</ArrowTooltip>
</tbody>
</table>
);
class Form extends React {
constructor() {
super();
this.state = {
value: '',
suggestions: []
};
}
onChange = (event, { newValue, method }) => {
this.setState({
value: newValue,
});
if(method == 'up' || method == 'down') {
// Here the value is triggered when key pressed
console.log('KEY UP/DOWN')
}
};
onSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value)
});
};
// Autosuggest will call this function every time you need to clear suggestions.
onSuggestionsClearRequested = () => {
this.setState({
suggestions: []
});
};
onSuggestionSelected = (event, {suggestion}) => {
const isSuggestion = true
this.props.getWeather(suggestion, isSuggestion)
}
render() {
const { value, suggestions} = this.state;
// Autosuggest will pass through all these props to the input.
const inputProps = {
placeholder: 'Search City...',
value,
onChange: this.onChange
};
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
onSuggestionSelected={this.onSuggestionSelected}
/>
}
}
export default Form
CSS required for suggestions (which is to be styled)
Form.css
.react-autosuggest__suggestions-container {
display: none;
}
.react-autosuggest__suggestions-container--open {
display: block;
perspective: 1000px;
position:absolute;
top: 30px;
width: 180px;
font-family: 'Oxygen';
font-weight: 100;
font-size: 16px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
z-index: 2;
}
#media screen and (max-width: 576px) {
.react-autosuggest__suggestions-container--open, .react-autosuggest__input {
display: block;
width: 220px;
}
}
.react-autosuggest__suggestions-container--open li{
transform-origin: top center;
margin-bottom: 2px;
background: #c7ecee;
}
/* Here the background color is changed on hovering each li */
.react-autosuggest__suggestions-container--open li:hover {
background: #95afc0;
transition: 0.1s ease-in-out;
}
As seen above, when the mouse is hovered over each elements background color changes, but, I want to change when key (up or down) is pressed. Any suggestions or changes??
Just add theme prop. Something like this:
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={
this.onSuggestionsFetchRequested
}
onSuggestionsClearRequested={
this.onSuggestionsClearRequested
}
getSuggestionValue={this.getSuggestionValue}
renderSuggestion={this.renderSuggestion}
inputProps={inputProps}
focusInputOnSuggestionClick={true}
theme={{
container: {
display: "block",
width: "100%",
position: "absolute",
borderTop: "none",
borderBottom: "1px solid #aaa",
borderLeft: "1px solid #aaa",
borderRight: "1px solid #aaa",
backgroundColor: "#fff",
fontFamily: "Helvetica, sans-serif",
fontWeight: 300,
fontSize: "16px",
borderBottomLeftRadius: "4px",
borderBottomRightRadius: "4px",
zIndex: 2,
paddingLeft: 0,
paddingRight: 0,
},
input: {
marginBottom: 0,
display: "block",
width: "100%",
height: "34px",
padding: "6px 12px",
fontSize: "14px",
lineHeight: "1.4285",
color: "#555",
backgroundColor: "#fff",
backgroundImage: "none",
borderRadius: "4px",
border: "1px solid #ccc",
},
suggestionHighlighted: {
backgroundColor: "lightgrey", //magic line
cursor:'pointer'
},
}}
/>

(Axios) HTTP POST request failed after two minutes, Laravel 5 + VueJS

I am trying to replicate data in the database for a specific user. It is almost 1000 rows that should be replicated. But my request gets failed with Empty response after 2 min. you can see in the picture. I am not able to identify the issue. Guide me if anyone has already solved this kind of issue.
My database is hosted on Google Cloud Storage and I am using MySQL.
This is my controller method:
public function createDataForManyToMany (Request $request)
{
$rows = TableA::where('id_analysis',
$request->analysis_id)->get();
$files_data = TableB::Where('id_analysis',
$request->analysis_id)->get();
foreach ($rows as $row)
{
$row->input_files()->saveMany($files_data);
}
return response()->json([
'status' => 'ok',
'analysis_id' => $request->analysis_id
]);
}
My Axios post request:
axios.post('/app/create-det-infiles-data', { '_token': this.csrf_token, 'analysis_id': res.data.analysis_id})
.then( res => {
if (res.data.status === 'ok') {
this.signupTried = false
this.emailSent = true
}
Vue Component:
<template>
<div class="fullwidth-container">
<div class="login-container">
<v-card class="login_form elevation-9">
<form class="login">
<input type="hidden" name="_token" :value="csrf_token"/>
<div class="header">
<h1>PIX2MAP SignUp</h1>
</div>
<v-text-field
color="dark"
prepend-icon="person"
:label="$t('name')"
required
:error-messages="nameErrors"
v-model="name">
</v-text-field>
<v-text-field
color="dark"
prepend-icon="email"
label="Email"
required
:error-messages="emailErrors"
v-model="email">
</v-text-field>
<v-text-field
color="dark"
prepend-icon="vpn_key"
:append_icon="show_pass ? 'visibility_off' : 'visibility'"
:type="show_pass ? 'text' : 'password'"
:error-messages="passwordErrors"
required
:label="$t('password')"
v-model="password"
#click:append="show_pass = !show_pass">
</v-text-field>
<v-text-field
class="pwd-confirm"
color="dark"
:append_icon="show_pass ? 'visibility_off' : 'visibility'"
:type="show_pass2 ? 'text' : 'password'"
:error-messages="repeatPasswordErrors"
required
:label="$t('repeat_password')"
v-model="password2"
#click:append="show_pass = !show_pass">
</v-text-field>
<v-layout row style="margin: 0">
<v-flex shrink style="margin-top: 0">
<v-checkbox
v-model="termsAccepted"
:label="`I accept the `"
:error-messages="acceptAgreementError"
>
</v-checkbox>
</v-flex>
<v-flex grow text-xs-left style="margin-top: 0">
contract
</v-flex>
</v-layout>
<v-btn class="btn-signup" color="accent" #click="doSignup"
:disabled="formFilled"
>Confirm <span class="float-right" :class="{'fas':signupTried, 'fa-spinner':signupTried, 'fa-spin':signupTried}"></span>
</v-btn>
<p class="privacy">{{ $t('form_privacy') }}</p>
</form>
</v-card>
<div class="back">
<v-btn flat #click="$emit('back')"><v-icon>arrow_back</v-icon>{{ $t('back_button') }}</v-btn>
</div>
</div>
<v-dialog
v-model="dialog"
max-width="650"
>
<v-card>
<v-card-title class="headline grey lighten-2">{{ contractTitile }}
<span style="margin-left: auto"><v-icon right #click="dialog = !dialog">fas fa-times</v-icon></span>
</v-card-title>
<v-card-text >
{{ contractBody }}
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-dialog>
<v-snackbar
v-if="signupTried"
v-model="snackbar"
dark
:bottom="y === 'bottom'"
:timeout="timeout"
:left="x === 'left'"
:color="color"
:multi-line="mode === 'multi-line'"
:right="x === 'right'"
:top="y === 'top'"
:vertical="mode === 'vertical'"
>
{{ text }}
</v-snackbar>
<v-snackbar
v-if="emailSent"
v-model="emailSnackbar"
:bottom="y === 'bottom'"
:timeout="timeout"
:left="x === 'left'"
:multi-line="mode === 'multi-line'"
:right="x === 'right'"
:top="y === 'top'"
:color="color"
:vertical="mode === 'vertical'"
>
{{ emailSentMessage }}
</v-snackbar>
</div>
</template>
<script>
import { required, email } from 'vuelidate/lib/validators'
import {TITLE, BODY_TEXT} from '../contract'
import axios from 'axios'
export default {
props: {
csrf_token: String,
name: String,
email: String,
},
data: () => ({
contractTitile: TITLE,
contractBody: BODY_TEXT,
show_pass: false,
show_pass2: false,
name: '',
email: '',
password: '',
password2: '',
signupTried: false,
emailExist: false,
dialog: false,
termsAccepted: false,
snackbar: true,
y: 'bottom',
x: null,
mode: '',
timeout: 10000,
color: '#fff',
text: 'This process will take some time, please! be patience.',
emailSent: false,
emailSnackbar: true,
emailSentMessage: 'We have sent you instructions, please verify your account by visiting your email.'
}),
validations: {
name: {
required
},
email: {
required,
email
},
password: {
required
},
password2: {
required
},
termsAccepted: {
required
}
},
methods: {
async doSignup () {
this.signupTried = true
if (this.$v.name.required && this.$v.email.required && this.$v.email.email && this.$v.password.required && this.termsAccepted ) {
axios.post('/app/register', { '_token': this.csrf_token, 'name': this.name,'email': this.email, 'password': this.password })
.then(res => {
if (res.data.status === 'ok') {
axios.post('/app/create-in-files-data', { '_token': this.csrf_token, 'analysisIds': res.data.analysis_ids})
.then(resp => {
if (resp.data.status === 'ok') {
axios.post('/app/create-mo-files-data', { '_token': this.csrf_token, 'analysisIds': resp.data.analysis_ids})
.then( res => {
if (res.data.status === 'ok') {
// window.location = '/'
// this.signupTried = false
// this.emailSent = true
axios.post('/app/create-det-infiles-data', { '_token': this.csrf_token, 'analysis_id': res.data.analysis_id})
.then( res => {
if (res.data.status === 'ok') {
this.signupTried = false
this.emailSent = true
// await axios.post('/app/create-det-mofiles-data', { '_token': this.csrf_token, 'analysis_id': res.data.analysis_id, demo: true})
// .then(async res => {
// if (res.data.status === 'ok') {
// this.showSpinner = false
// window.location = '/'
// } else {
// console.log('Files not created')
// this.showSpinner = false
// this.$emit('forgotPw', {email: this.email});
// }
// })
// .catch(e => {
// console.log('2nd error', e)
// })
} else {
console.log('Files not created')
this.showSpinner = false
this.$emit('forgotPw', {email: this.email});
}
})
.catch(e => {
console.log('2nd error', e)
})
} else {
console.log('Signup Failed')
this.signupTried = false
this.$emit('forgotPw', {email: this.email});
}
})
.catch(e => {
console.log('2nd error', e)
})
} else {
console.log('Files not created')
this.showSpinner = false
this.$emit('forgotPw', {email: this.email});
}
})
.catch(e => {
console.log('Error: ', e)
})
} else {
this.showSpinner = false
this.$emit('forgotPw', {email: this.email});
}
})
}
},
changeState () {
this.dialog = !this.dialog
}
},
computed: {
nameErrors () {
if (this.signupTried && this.name.length == 0 && !this.$v.name.required) return [this.$t('name_required')]
},
emailErrors () {
const errors = []
if (this.signupTried && !this.$v.email.required) errors.push(this.$t('email_required'))
if (!this.$v.email.email) errors.push(this.$t('not_valid_email'))
if (this.emailExist) errors.push(this.$t('existing_email'))
return errors
},
passwordErrors () {
if (this.signupTried && !this.$v.password.required) return [this.$t('password_required')]
},
repeatPasswordErrors () {
if (this.signupTried && !this.$v.password2.required) return [this.$t('password_required')]
if (this.password2 != this.password) return [this.$t('passwords_not_equal')]
},
acceptAgreementError () {
if (this.signupTried && !this.$v.termsAccepted.required) return [this.$t('agreement_required')]
},
formFilled () {
if (!this.$v.name.required || !this.$v.email.required || !this.$v.password.required || !this.$v.password2.required || !this.termsAccepted || (this.password != this.password2))
{
return true
} else {
return false
}
}
}
}
</script>
<style scoped lang="stylus">
#import '../../stylus/theme.styl'
.fullwidth-container {
width: 100%;
height: 100%;
background: $bg-login;
position: absolute;
top: 0px;
left: 0px;
z-index: 2;
.login-container {
position: relative;
width: 500px;
top: 25px;
margin: auto;
.login_form {
padding: 16pt;
text-align: center;
height: 800px;
* {
margin-top: 24pt;
}
.header {
margin: 24pt;
}
.i-am {
display: flex;
flex-direction: row;
align-items: center;
* {
margin-top: 0pt;
}
span {
width: 8%;
}
.i-am-text {
margin-right: 20px;
}
.i-am-select {
margin-left: 5%;
}
}
.btn-signup {
margin-left: auto;
margin-right: auto;
width: 80%;
}
.privacy {
margin-top: 8pt;
font-style: italic;
}
.pwd-confirm {
margin-left: 7%;
}
.checkboxAccept {
display: inline;
}
.float-right {
margin-top: -3px;
margin-left: 5px;
color: #fff;
font-size: 18px;
}
}
}
}
</style>
This issue might be caused due to MySQL instance is reaching the time out limit for your query.
In Cloud SQL you can try to modify the flag “wait_timeout” and set a bigger value, for example 50000.
Check this link as a reference to set a flag in Cloud SQL instance.

how to call ajax function to update the Highcharts graph dynamically?

I am using Highcharts to plot the graph of temperature vs time. I am having a JSON file wherein data from the backend keep updates the JSON file. I want to call ajax function such that the graphs automatically generates with respect to time. How to do that? I am new to high charts, please help me.
You can use Series.addPoint method.
http://api.highcharts.com/highcharts/Series.addPoint
Here is a example of using Highcharts with live data with GET HTTP requests.
const options = {
chart: {
type: 'spline'
},
title: {
text: 'Live Bitcoin Price'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: 'Price (USD)'
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Live Bitcoint Price [USD]',
data: []
}]
}
const chart = Highcharts.chart('container', options)
// Data
const getData = () => {
setInterval(() => {
window.fetch('https://api.cryptonator.com/api/ticker/btc-usd').then((response) => {
return response.json()
}).then((data) => {
chart.series[0].addPoint({ x: data.timestamp * 1000, y: Number(data.ticker.price) })
})
}, 3000)
}
getData()
#import 'https://code.highcharts.com/css/highcharts.css';
.highcharts-background {
fill: #222;
}
.highcharts-title,
.highcharts-axis-title {
fill: #DDD;
}
.highcharts-credits,
.highcharts-credits:hover {
fill: #222;
}
body {
background-color: #222;
margin 0 !important;
}
#container {
margin: 0;
padding: 0;
border: 0;
background-color: #222;
min-height: 400px;
height:95%;
width:95%;
position:absolute;
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container"></div>
Live example:
https://jsfiddle.net/xpfkx91w/

Why is my zebra-striping CSS not applying to my table rows?

I tried zebra striping my table in a React application here. However, it is not being applied. Here are the relevant styles:
tr:nth-child(even) {
background-color: rgba(0,100,1,0.5)
}
tr:nth-child(odd) {
background-color: rgba(0,100,1,0.3)
}
And the full demo:
'use strict';
var /*var Leaderboard = React.createClass({
getInitialState: function(){
/*var recentCampers= [];
var allTimeCampers= [];*/
//return {toggle30: 'true'};
/*return {recentCampers: [],
allTimeCampers: [],
toggle30: 'true'};
this.recentCampers= this.recentCampers.bind(this);
this.allTimeCampers.bind(this);
this.toggle30= this.toggle30.bind(this); */
/* },
componentDidMount: function(){return axios.all([this.getTopRecentCampers(),this.getTopAlltimeCampers()]).then(function(arr){return {
recentCampers: arr[0].data,
allTimeCampers: arr[1].data};
console.log(this.state.recentCampers[0].username); })},
/*
getTopRecentCampers: function(){return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/recent');},
getTopAlltimeCampers: function(){return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/alltime');},
toggleViewOne: function(){this.setState({toggle30: 'true'});},
toggleViewTwo: function(){this.setState({toggle30: 'false'});},
/* render: function(){return (<div>
<h6>Sort by:</h6> <button onClick={this.toggleViewOne} className="btn">Points in past 30 days <span className="fa fa-sort-desc"> </span></button> <button onClick={this.toggleViewTwo} className="btn"> All time points <span className="fa fa-sort-desc"> </span> </button> <h1> freeCodeCamp <span className="fa fa-free-code-camp"> </span> </h1> <hr></hr> <div className="table-responsive"> <table className="table"> <thead> <tr> <th> <td> # </td> <td> Camper name </td> <td> Points in last month </td> <td> All time points </td> </th> </tr> </thead> <tbody>
//</tbody> </table> </div> </div>);} */
/* });
var Tbody = React.createClass({
render: function(){return (<tbody> {} </tbody>);}
});*/
/*</tr> <tr> <td> gtew</td> </tr> <tr> <td> gffs</td> </tr>this.recentCampers= this.recentCampers.bind(this);
this.allTimeCampers.bind(this) */
/*
ReactDOM.render(<Leaderboard />,document.getElementById('freeCodeCamp'));
---------------------------------------------------------------------------- */Leaderboard = React.createClass({
displayName: 'Leaderboard',
getInitialState: function getInitialState() {
return {
recentCampers: [],
allTimeCampers: [],
toggle: 'recentCampers'
};
},
componentWillMount: function componentWillMount() {
return this.getRequest();
},
getRequest: function getRequest() {
return axios.all([this.getTopRecentCampers(), this.getTopAlltimeCampers()]).then(function (arr) {
this.setState({
recentCampers: arr[0].data,
allTimeCampers: arr[1].data
});
/*var recent= [];
recent= this.state.recentCampers;
for (var i=0;i>=100;i++){return recent[i];};
//console.log(this.state.recentCampers[0].username);*/
}.bind(this));
},
getTopRecentCampers: function getTopRecentCampers() {
return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/recent');
},
getTopAlltimeCampers: function getTopAlltimeCampers() {
return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/alltime');
},
toggleViewOne: function toggleViewOne() {
this.setState({
toggle: 'recentCampers'
});
},
toggleViewTwo: function toggleViewTwo() {
this.setState({
toggle: 'allTimeCampers'
});
},
render: function render() {
return React.createElement(
'div',
null,
' ',
' ',
React.createElement(
'h6',
null,
'Sort by:'
),
' ',
React.createElement(
'button',
{ onClick: this.toggleViewOne, className: 'btn' },
'Points in past 30 days ',
React.createElement(
'span',
{ className: 'fa fa-sort-desc' },
' '
)
),
' ',
React.createElement(
'button',
{ onClick: this.toggleViewTwo, className: 'btn' },
' All time points ',
React.createElement(
'span',
{ className: 'fa fa-sort-desc' },
' '
),
' '
),
' ',
React.createElement(
'h1',
null,
' freeCodeCamp ',
React.createElement(
'span',
{ className: 'fa fa-free-code-camp' },
' '
),
' '
),
' ',
React.createElement('hr', null),
' ',
React.createElement(
'div',
{ className: 'table-responsive' },
' ',
React.createElement(
'table',
{ className: 'table' },
' ',
React.createElement(
'thead',
null,
' ',
React.createElement(
'tr',
null,
' ',
React.createElement(
'th',
null,
' ',
React.createElement(
'td',
{ style: { width: '80px' }, className: 'text-center' },
' # '
),
' ',
React.createElement(
'td',
{ style: { width: '600px' } },
' Camper name '
),
' ',
React.createElement(
'td',
{ style: { width: '400px' }, className: 'text-center' },
' Points in last month '
),
' ',
React.createElement(
'td',
{ style: { width: '400px' }, className: 'text-center' },
' All time points '
),
' '
),
' '
),
' '
),
' ',
React.createElement(
'tbody',
null,
' ',
React.createElement(Map, { data: this.state[this.state.toggle] })
),
' '
),
' '
),
' '
);
}
});
//{<Tbody data={this.state}
/*
-------------------------------------------------------------------------- */
var Map = React.createClass({
displayName: 'Map',
render: function render() {
var rows = this.props.data.map(function (row, index) {
return React.createElement(Tbody, { rank: index + 1, data: row });
});
return React.createElement(
'tbody',
{ id: 'stripe' },
rows
);
}
});
/*
-------------------------------------------------------------------------- */
var Tbody = React.createClass({
displayName: 'Tbody',
render: function render() {
return React.createElement(
'div',
null,
' ',
/*<h1>{this.props.data.username}</h1>*/React.createElement(
'tr',
null,
React.createElement(
'td',
{ style: { width: '80px' }, className: 'text-center' },
this.props.rank + '.'
),
React.createElement(
'td',
{ style: { width: '600px' } },
React.createElement(
'a',
{ target: '_blank', href: 'http://freecodecamp.com/' + this.props.data.username },
React.createElement('img', { src: this.props.data.img }),
' ',
React.createElement(
'span',
null,
this.props.data.username
)
)
),
React.createElement(
'td',
{ id: 'recent', className: 'text-center' },
this.props.data.recent
),
React.createElement(
'td',
{ id: 'all', className: 'text-center' },
this.props.data.alltime
)
),
' '
);
//console.log(JSON.stringify(this.props));*/
}
});
/*
-------------------------------------------------------------------------- */
ReactDOM.render(React.createElement(Leaderboard, null), document.getElementById('freeCodeCamp'));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-image: linear-gradient(161deg, #006401 0%, #FCFFEE 100%);
background-attachment: fixed;
color: #502d17;
margin-left: 20px;
margin-right: 20px;
}
button {
margin: 5px;
background-image: -webkit-linear-gradient(#006401, #FCFFEE);
background-attachment: fixed;
color: #FCFFEE;
box-shadow: inset -1px -3px 10px 1px #515151;
margin-bottom: 20px;
}
button:active {
transform: translate(0, 3px);
box-shadow: none;
text-decoration: none;
outline: none;
}
button:hover, button:active, button:visited {
text-decoration: none;
outline: none;
}
h6 {
margin-left: 10px;
margin-top: 15px;
margin-bottom: 5px;
}
h1 {
color: rgba(245, 245, 245, 0.5);
margin-left: 5px;
}
.fa-free-code-camp {
font-size: 1em;
color: rgba(245, 245, 245, 0.7);
}
table, td {
border: 1px solid grey;
table-layout: fixed;
}
tr:nth-child(even) {
background-color: rgba(0, 100, 1, 0.5);
}
tr:nth-child(odd) {
background-color: rgba(0, 100, 1, 0.3);
}
img {
border-radius: 100%;
height: 60px;
}
a {
text-decoration: none;
color: #502d17;
}
#all {
max-width: 280px;
min-width: 280px;
}
#recent {
max-width: 280px;
min-width: 280px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.8.1/axios.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div id="freeCodeCamp"></div>
As your HTML markup is pulled in within your codepen I'm not sure how useful this is to future users but in the context of your codepen your selectors are incorrect.
Your tbody does not contain tr siblings but each tr is wrapped into a div, hence you need to target those instead.
tbody>div:nth-child(even)
background-color: rgba(0,100,1,0.5)
tbody>div:nth-child(odd)
background-color: rgba(0,100,1,0.3)
See updated CodePen
'use strict';
var /*var Leaderboard = React.createClass({
getInitialState: function(){
/*var recentCampers= [];
var allTimeCampers= [];*/
//return {toggle30: 'true'};
/*return {recentCampers: [],
allTimeCampers: [],
toggle30: 'true'};
this.recentCampers= this.recentCampers.bind(this);
this.allTimeCampers.bind(this);
this.toggle30= this.toggle30.bind(this); */
/* },
componentDidMount: function(){return axios.all([this.getTopRecentCampers(),this.getTopAlltimeCampers()]).then(function(arr){return {
recentCampers: arr[0].data,
allTimeCampers: arr[1].data};
console.log(this.state.recentCampers[0].username); })},
/*
getTopRecentCampers: function(){return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/recent');},
getTopAlltimeCampers: function(){return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/alltime');},
toggleViewOne: function(){this.setState({toggle30: 'true'});},
toggleViewTwo: function(){this.setState({toggle30: 'false'});},
/* render: function(){return (<div>
<h6>Sort by:</h6> <button onClick={this.toggleViewOne} className="btn">Points in past 30 days <span className="fa fa-sort-desc"> </span></button> <button onClick={this.toggleViewTwo} className="btn"> All time points <span className="fa fa-sort-desc"> </span> </button> <h1> freeCodeCamp <span className="fa fa-free-code-camp"> </span> </h1> <hr></hr> <div className="table-responsive"> <table className="table"> <thead> <tr> <th> <td> # </td> <td> Camper name </td> <td> Points in last month </td> <td> All time points </td> </th> </tr> </thead> <tbody>
//</tbody> </table> </div> </div>);} */
/* });
var Tbody = React.createClass({
render: function(){return (<tbody> {} </tbody>);}
});*/
/*</tr> <tr> <td> gtew</td> </tr> <tr> <td> gffs</td> </tr>this.recentCampers= this.recentCampers.bind(this);
this.allTimeCampers.bind(this) */
/*
ReactDOM.render(<Leaderboard />,document.getElementById('freeCodeCamp'));
---------------------------------------------------------------------------- */Leaderboard = React.createClass({
displayName: 'Leaderboard',
getInitialState: function getInitialState() {
return {
recentCampers: [],
allTimeCampers: [],
toggle: 'recentCampers'
};
},
componentWillMount: function componentWillMount() {
return this.getRequest();
},
getRequest: function getRequest() {
return axios.all([this.getTopRecentCampers(), this.getTopAlltimeCampers()]).then(function (arr) {
this.setState({
recentCampers: arr[0].data,
allTimeCampers: arr[1].data
});
/*var recent= [];
recent= this.state.recentCampers;
for (var i=0;i>=100;i++){return recent[i];};
//console.log(this.state.recentCampers[0].username);*/
}.bind(this));
},
getTopRecentCampers: function getTopRecentCampers() {
return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/recent');
},
getTopAlltimeCampers: function getTopAlltimeCampers() {
return axios.get('https://fcctop100.herokuapp.com/api/fccusers/top/alltime');
},
toggleViewOne: function toggleViewOne() {
this.setState({
toggle: 'recentCampers'
});
},
toggleViewTwo: function toggleViewTwo() {
this.setState({
toggle: 'allTimeCampers'
});
},
render: function render() {
return React.createElement(
'div',
null,
' ',
' ',
React.createElement(
'h6',
null,
'Sort by:'
),
' ',
React.createElement(
'button',
{ onClick: this.toggleViewOne, className: 'btn' },
'Points in past 30 days ',
React.createElement(
'span',
{ className: 'fa fa-sort-desc' },
' '
)
),
' ',
React.createElement(
'button',
{ onClick: this.toggleViewTwo, className: 'btn' },
' All time points ',
React.createElement(
'span',
{ className: 'fa fa-sort-desc' },
' '
),
' '
),
' ',
React.createElement(
'h1',
null,
' freeCodeCamp ',
React.createElement(
'span',
{ className: 'fa fa-free-code-camp' },
' '
),
' '
),
' ',
React.createElement('hr', null),
' ',
React.createElement(
'div',
{ className: 'table-responsive' },
' ',
React.createElement(
'table',
{ className: 'table' },
' ',
React.createElement(
'thead',
null,
' ',
React.createElement(
'tr',
null,
' ',
React.createElement(
'th',
null,
' ',
React.createElement(
'td',
{ style: { width: '80px' }, className: 'text-center' },
' # '
),
' ',
React.createElement(
'td',
{ style: { width: '600px' } },
' Camper name '
),
' ',
React.createElement(
'td',
{ style: { width: '400px' }, className: 'text-center' },
' Points in last month '
),
' ',
React.createElement(
'td',
{ style: { width: '400px' }, className: 'text-center' },
' All time points '
),
' '
),
' '
),
' '
),
' ',
React.createElement(
'tbody',
null,
' ',
React.createElement(Map, { data: this.state[this.state.toggle] })
),
' '
),
' '
),
' '
);
}
});
//{<Tbody data={this.state}
/*
-------------------------------------------------------------------------- */
var Map = React.createClass({
displayName: 'Map',
render: function render() {
var rows = this.props.data.map(function (row, index) {
return React.createElement(Tbody, { rank: index + 1, data: row });
});
return React.createElement(
'tbody',
{ id: 'stripe' },
rows
);
}
});
/*
-------------------------------------------------------------------------- */
var Tbody = React.createClass({
displayName: 'Tbody',
render: function render() {
return React.createElement(
'div',
null,
' ',
/*<h1>{this.props.data.username}</h1>*/React.createElement(
'tr',
null,
React.createElement(
'td',
{ style: { width: '80px' }, className: 'text-center' },
this.props.rank + '.'
),
React.createElement(
'td',
{ style: { width: '600px' } },
React.createElement(
'a',
{ target: '_blank', href: 'http://freecodecamp.com/' + this.props.data.username },
React.createElement('img', { src: this.props.data.img }),
' ',
React.createElement(
'span',
null,
this.props.data.username
)
)
),
React.createElement(
'td',
{ id: 'recent', className: 'text-center' },
this.props.data.recent
),
React.createElement(
'td',
{ id: 'all', className: 'text-center' },
this.props.data.alltime
)
),
' '
);
//console.log(JSON.stringify(this.props));*/
}
});
/*
-------------------------------------------------------------------------- */
ReactDOM.render(React.createElement(Leaderboard, null), document.getElementById('freeCodeCamp'));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-image: linear-gradient(161deg, #006401 0%, #FCFFEE 100%);
background-attachment: fixed;
color: #502d17;
margin-left: 20px;
margin-right: 20px;
}
button {
margin: 5px;
background-image: -webkit-linear-gradient(#006401, #FCFFEE);
background-attachment: fixed;
color: #FCFFEE;
box-shadow: inset -1px -3px 10px 1px #515151;
margin-bottom: 20px;
}
button:active {
transform: translate(0, 3px);
box-shadow: none;
text-decoration: none;
outline: none;
}
button:hover, button:active, button:visited {
text-decoration: none;
outline: none;
}
h6 {
margin-left: 10px;
margin-top: 15px;
margin-bottom: 5px;
}
h1 {
color: rgba(245, 245, 245, 0.5);
margin-left: 5px;
}
.fa-free-code-camp {
font-size: 1em;
color: rgba(245, 245, 245, 0.7);
}
table, td {
border: 1px solid grey;
table-layout: fixed;
}
tbody>div:nth-child(even){
background-color: rgba(0, 100, 1, 0.5);
}
tbody>div:nth-child(odd) {
background-color: rgba(0, 100, 1, 0.3);
}
img {
border-radius: 100%;
height: 60px;
}
a {
text-decoration: none;
color: #502d17;
}
#all {
max-width: 280px;
min-width: 280px;
}
#recent {
max-width: 280px;
min-width: 280px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.8.1/axios.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div id="freeCodeCamp"></div>
Just to add, while the above works, I think your JavaScript generates invalid HTML to begin with as I think a div is not allowed as a child inside a tbody wrapping tr elements. If this is your own code, you can update it to use multiple tbody siblings inside the table element, each containing tr elements, instead of nested tbody elements with a div wrapping tr elements. If this is not your own code but the code you got from freeCodeCamp, I would consider switching code camp.
Your table markup is invalid. Your rows shouldn't be wrapped in divs.
The reason nth-child isn't working in this case is because it can only iterate through sibling elements(https://www.w3.org/TR/css3-selectors/#nth-child-pseudo).
Remove your wrapping divs in Leaderboard render function and it should work just fine.