I want to add 7 custom lines as helper to user.
Like in that picture, I want to add 7 times "div.moveable-line"
Even rotation change, the lines stayed at suitible position => And I want to add them 7 times.
Can we create a line between T1 and B1 (and for the others)?
Or if you have any other solutions, I am open for them as well.
React Moveable - Github
Warpable - StoryBook
Moveable.warpable - Documentation
Here is a demo link
MY COMPONENT
import React from 'react';
import ReactDOM from 'react-dom';
import Moveable from 'react-moveable';
import { ref } from 'framework-utils';
import { Frame } from 'scenejs';
import './styles.css';
class App extends React.Component {
frame = new Frame({
width: '250px',
height: '200px',
left: '0px',
top: '0px',
transform: {
rotate: '0deg',
scaleX: 1,
scaleY: 1,
matrix3d: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
},
});
state = {
target: null,
container: null,
warpable: true,
stateTransform: [],
totalBoxesTop: 0,
totalBoxesFill: 0,
totalBoxesBottom: 0,
isBoxCreated: false,
};
render() {
const { warpable, target } = this.state;
let k = document.querySelector('.moveable-control-box');
console.log(k, ':44');
if (k !== null) {
// k.appendChild(z);
// k.appendChild(d);
k.style.position = 'relative';
k.style.backgroundColor = '#fff';
}
let topLine = document.querySelector(
'.moveable-direction[data-line-index="0"]'
);
if (topLine !== null) {
topLine.classList.add('myTopLine');
let d = document.createElement('div'); // is a node
d.innerHTML = `T${this.state.totalBoxesTop}`;
d.setAttribute('data-box-position-top', `${this.state.totalBoxesTop}`);
d.classList.add('my-box');
if (this.state.totalBoxesTop < 8) {
// When is this.state.totalBoxes === 1 it means 0 boxes appear
topLine.appendChild(d);
this.setState({ totalBoxesTop: this.state.totalBoxesTop + 1 });
}
console.log(topLine, this.state.totalBoxesTop);
}
let bottomLine = document.querySelector(
'.moveable-direction[data-line-index="3"]'
);
if (bottomLine !== null) {
bottomLine.classList.add('myBottomLine');
let d = document.createElement('div'); // is a node
d.innerHTML = `B${this.state.totalBoxesBottom}`;
d.setAttribute(
'data-box-position-bottom',
`${this.state.totalBoxesBottom}`
);
d.classList.add('my-box');
if (this.state.totalBoxesBottom < 8) {
// When is this.state.totalBoxes === 1 it means 0 boxes appear
bottomLine.appendChild(d);
this.setState({ totalBoxesBottom: this.state.totalBoxesBottom + 1 });
}
console.log(bottomLine, this.state.totalBoxesBottom);
}
return (
<div className="page main">
<Moveable
ref={ref(this, 'moveable')}
target={target}
pinchThreshold={20}
container={document.body}
draggable={true}
warpable={warpable}
rotatable={true}
pinchable={true}
origin={false}
throttleDrag={1}
throttleRotate={0.2}
throttleResize={1}
throttleScale={0.01}
onDrag={this.onDrag}
onWarp={this.onWarp}
onDragEnd={this.onEnd}
onScaleEnd={this.onEnd}
onResizeEnd={this.onEnd}
onWarpEnd={this.onEnd}
onRotateEnd={this.onEnd}
onPinchEnd={this.onEnd}
/>
<div className="moveable">hello</div>
<div className="label" ref={ref(this, 'label')} />
</div>
);
}
componentDidMount() {
this.setState({
target: document.querySelector('.moveable'),
});
window.addEventListener('resize', this.onWindowReisze);
}
componentWillUnmount() {
window.removeEventListener('resize', this.onWindowReisze);
}
onWindowReisze = () => {
this.moveable.updateRect();
};
setTransform(target) {
target.style.cssText = this.frame.toCSS();
}
setLabel(clientX, clientY, text) {
this.label.style.cssText = `
display: block; transform: translate(${clientX}px, ${
clientY - 10
}px) translate(-100%, -100%) translateZ(-100px);`;
this.label.innerHTML = text;
}
onDrag = ({ target, clientX, clientY, top, left, isPinch }) => {
this.frame.set('left', `${left}px`);
this.frame.set('top', `${top}px`);
this.setTransform(target);
if (!isPinch) {
this.setLabel(clientX, clientY, `X: ${left}px<br/>Y: ${top}px`);
}
};
onWarp = ({
target,
clientX,
clientY,
delta,
multiply,
currentTarget,
moveable,
datas,
inputEvent,
transform,
dist,
matrix,
}) => {
console.log(target);
target.style.transform = `matrix3d(${matrix.join(',')})`;
this.setState({ stateTransform: `matrix3d(${matrix.join(',')})` });
this.frame.set(
'transform',
'matrix3d',
multiply(this.frame.get('transform', 'matrix3d'), delta)
);
this.setTransform(target);
this.setLabel(clientX, clientY, `X: ${clientX}px<br/>Y: ${clientY}px`);
};
onEnd = () => {
this.label.style.display = 'none';
};
}
export default App;
#import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600&display=swap");
.moveable {
position: absolute;
width: 250px;
height: 200px;
margin: 0 auto;
background-color: transparent;
top: 0;
left: 0;
}
.my-new-box{
position: relative;
width: 100%;
height: 100%;
background-color: #73a079;
}
.myTopLine,
.myBottomLine{
background-color: #8b270a!important;
display: flex!important;
position: absolute!important;
justify-content: space-between!important;
align-items: flex-end!important;
}
.my-box {
position: relative;
top: 0;
left: 0;
width: 25px;
height: 25px;
/*flex: 1;*/
/*margin: 0 auto;*/
background-color: rgba(0,222,222,0.3);
/*transform: translate3d(42px, -62px, -135px);*/
}
.my-line{
position: relative;
top: 0;
left: 0;
width: 100px;
height: 150px;
background-color: #3a3aa0;
}
.moveable-control-box {
position: relative!important;
background-color: #8b2c62 !important;
}
.label {
position: fixed;
top: 0;
left: 0;
padding: 5px;
border-radius: 5px;
background: #333;
z-index: 3001;
color: #fff;
font-weight: bold;
font-size: 12px;
display: none;
transform: translate(-100%, -100%);
}
.feature .container .left {
position: relative;
width: 300px;
height: 205px;
display: inline-block;
vertical-align: top;
z-index: 2000;
margin-bottom: 20px;
}
.feature .container .right {
position: relative;
display: inline-block;
vertical-align: top;
flex: 1;
}
.feature .right .description {
text-align: left;
margin: 0px 0px 10px;
}
.feature .right .description strong {
font-weight: 600;
}
.draggable,
.resizable,
.scalable,
.rotatable,
.origin,
.warpable,
.pinchable {
position: absolute;
left: 0;
}
.origin {
transform-origin: 30% 50%;
}
pre {
position: relative;
border: 1px solid #ccc;
box-sizing: border-box;
padding: 10px;
max-width: 500px;
}
code.hljs {
padding: 0;
}
.tab {
padding: 10px 12px;
appearance: none;
-webkit-appearance: none;
background: transparent;
border: 1px solid #ccc;
box-shadow: none;
font-weight: bold;
margin: 0;
cursor: pointer;
outline: none;
}
.tab.selected {
background: #333;
color: #fff;
border: 1px solid #333;
}
.panel {
display: none;
}
.panel.selected {
display: block;
}
.page.footer {
font-weight: 400;
}
.page.footer a {
text-decoration: underline;
}
.page.footer span:first-child:before {
content: "";
}
.page.footer span:before {
content: "/";
}
Make Custom Able for Custom Lines
https://stackblitz.com/edit/react-ts-wmy77k?file=index.tsx
Related
previous
<svg
class="get-carousel__prev-svg"
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
viewBox="0 0 512 512"
>
Chevron Back
<button
class="gel-carousel__next get-carousel__buttons_back"
ref="next"
aria-label="next "
#click="nextShift"
type="button"
>
next
Chevron Forward
<div
class="gel-carousel__scrollable"
ref="gallery"
#scroll="carouselScroll"
>
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
Mohtasim Hasan
import { onMounted, ref } from "vue";
let debounced = ref();
const gallery = ref();
const lists = ref();
const previous = ref();
const next = ref();
const buttons = ref();
onMounted(() => {
const slides = document.querySelectorAll("img[data-src]");
buttons.value?.removeAttribute("hidden");
disableEnable();
let observer = new IntersectionObserver(imgSrcSet, {
root: null,
threshold: 0.6,
});
slides.forEach((slide) => {
observer.observe(slide);
});
});
const carouselScroll = () => {
window.clearTimeout(debounced.value);
debounced.value = setTimeout(disableEnable, 250);
};
const disableEnable = function () {
previous.value.disabled = gallery.value?.scrollLeft {
if (entry.intersectionRatio > 0.5) {
entry.target.closest("li").removeAttribute("inert");
console.log(entry);
entry.target.setAttribute("src", entry.target.dataset.src);
entry.target.src = entry.target.dataset.src;
}
if (!entry.isIntersecting) {
entry.target.closest("li").setAttribute("inert", "");
entry.target.closest("li").setAttribute("tabindex", -1);
}
if (entry.isIntersecting) {
entry.target.closest("li").setAttribute("tabindex", 0);
}
});
};
const previousShift = function () {
const scrollPos = ref(gallery.value?.scrollWidth / 4);
gallery.value?.scrollTo(gallery.value?.scrollLeft - scrollPos.value, 0);
};
const nextShift = function () {
const scrollPos = ref(gallery.value?.scrollWidth / 4);
gallery.value?.scrollTo(
gallery.value?.scrollLeft + 400,
gallery.value.scrollTop
);
};
.gel-carousel__buttons {
button {
cursor: pointer;
}
button[disabled] {
cursor: no-drop;
}
}
.gel-carousel__list {
display: flex;
list-style: none;
padding: 0;
margin: 0;
white-space: nowrap;
}
.gel-carousel__list > li {
display: flex;
flex-shrink: 0;
white-space: normal;
width: var(--size-fluid-9); /* standard Promo width */
transition: all 0.5s linear;
position: relative;
figure {
display: flex;
justify-items: space-between;
flex-direction: column;
margin: 0;
padding: 0;
}
figcaption {
margin-block: 2rem;
}
img {
display: block;
width: 100%;
height: var(--size-fluid-8);
background-size: cover;
transition: all 0.3s linear;
}
}
.gel-carousel__list > li[inert] {
opacity: 0.6;
}
ul {
padding: 0;
margin: 0;
}
.gel-carousel__list > li + li {
margin-left: 1rem;
&:not(:last-child) {
margin-left: 0;
}
}
.gel-carousel__scrollable {
width: 50rem;
overflow: auto;
scroll-behavior: smooth;
}
#media (prefers-reduced-motion: reduce) {
.gel-carousel__scrollable {
scroll-behavior: auto;
}
}
.gel-carousel__scrollable::-webkit-scrollbar {
height: 0.8rem;
}
.gel-carousel__scrollable::-webkit-scrollbar-track {
background-color: lightblue;
}
.gel-carousel__scrollable::-webkit-scrollbar-thumb {
background-color: lightpink;
}
.gel-sr:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
I created a vue js carousel app with typescript. But in it shows red squiggly line on both fuction.
I created a simple carousel using HTML, CSS, and Javascript.
Clicking the left button shows the previous slide and the right one shows the next slide.
But my concern is that slide change is not working correctly
when clicking the next button: After the final slide, it won't go to the first slide again.
when clicking the previous button: After the first slide, it won't go again to last the slide again.
So please review my code and let me know my error.
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray=[first,scond,third,fouth];
let index= 0;
let activeSlide= slidesArray[index].classList.add('active');
left.addEventListener('click',()=>{
if (++index > 0) {
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click',()=>{
if (index > 0) {
slidesArray[index].classList.add('deactive');
slidesArray[--index].classList.add('active');
}
});
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
A chained ternary expression can be used to determine the new index number in a single line:
to = to >= size ? 0 : to < 0 ? size - 1 : to;
Details are commented in example
// Reference the buttons
let next = document.querySelector('.next');
let prev = document.querySelector('.prev');
/*
Collect all div.slide into an array
Define the array's size
Define a number value outside of the function
*/
let slides = [...document.querySelectorAll('.slide')];
let size = slides.length;
let index = 0;
// Bind click event to button.prev
prev.onclick = event => move(index - 1);
// Bind click event to button.next
next.onclick = event => move(index + 1);
/*
Pass newest index number
Ternary expression:
If the given number is greater than or equal to size of the array...
...return 0...
...If the given number is less than 0...
...return last index of array...
...otherwise return the given number
Toggle the current .slide.active and new .slide
Assign index as the given number
*/
function move(to) {
to = to >= size ? 0 : to < 0 ? size - 1 : to;
slides[index].classList.toggle("active");
slides[to].classList.toggle("active");
index = to;
}
html {
font: 300 3vmin/1 Consolas;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
main {
display: flex;
justify-content: center;
align-items: center;
position: relative;
max-width: max-content;
min-height: 100vh;
}
.slides {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 420px;
height: 400px;
overflow: hidden;
}
.slide {
display: grid;
place-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 350px;
border-radius: 20px;
font-size: 50px;
font-weight: 600;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
transform: translate(-50%, -50%);
}
.active {
visibility: visible;
}
.slide:first-of-type {
background-color: #F7EC09;
}
.slide:nth-of-type(2) {
background-color: #3EC70B;
}
.slide:nth-of-type(3) {
background-color: #3B44F6;
}
.slide:nth-of-type(4) {
background-color: #A149FA;
}
.ctrl {
display: flex;
justify-content: space-between;
position: absolute;
top: 45%;
left: 45%;
width: 150%;
transform: translate(-50%, -50%);
}
.next,
.prev {
border: none;
font-size: 100px;
font-weight: 700;
background: none;
cursor: pointer;
}
<main>
<section class="slides">
<div class="slide active">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
</section>
<menu class="ctrl">
<button class="prev"><</button>
<button class="next">></button>
</menu>
</main>
You need to reset the index of the slide when you click next and reach to maximum slide you need to reset index to 0 to return to first slide, also when you click prev and you in the first slide, you need to reset index to 3 to return the last slide.
let right = document.querySelector(".nxt");
let left = document.querySelector(".pre");
let slids = document.querySelector(".slids");
let first = document.querySelector(".first");
let scond = document.querySelector(".scond");
let third = document.querySelector(".third");
let fouth = document.querySelector(".fouth");
const elementsArr = [first, scond, third, fouth];
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add("active");
left.addEventListener("click", () => {
if (index === 3) {
index = -1;
}
index++;
resetActiveElements()
});
right.addEventListener("click", () => {
if (index === 0) index = 4;
index--;
resetActiveElements()
});
const resetActiveElements = () => {
elementsArr.forEach((element, i) => {
if (index === i) {
element.classList.add("active");
} else {
element.classList.remove("active");
}
});
}
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
/* <div class="btn">
<button class="pre"><</button>
<button class="nxt">></button>
</div> */
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add('active');
left.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 0) {
index = 3;
slidesArray[index].classList.add('active');
} else {
index--;
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 3) {
index = 0;
slidesArray[index].classList.add('active');
} else {
index++;
slidesArray[index].classList.add('active');
}
});
I did a div that is moveable but unfortunetaly the function that let user move the div also block the highlight of the text in the text area behind.
I would like to keep the possibility to move the div and to highlight the text in textarea like I want.
Ps: I already tried to put the addEventListener on varMoveButtonNotesWindow but it's really ncomfortable to use it like that (we need to keep the cursor in the little box, and I dont want the box to be bigger it wouldn't look good).
Here's the code:
var mousePosition;
var offset = [0,0];
var isDown = false;
var varMoveButtonNotesWindow = document.getElementById('moveButtonNotesWindow');
var varNotesWindow = document.getElementById('notesWindow');
varMoveButtonNotesWindow.addEventListener('mousedown', function(e) {
isDown = true;
offset = [
varNotesWindow.offsetLeft - e.clientX,
varNotesWindow.offsetTop - e.clientY
];
}, true);
document.addEventListener('mouseup', function() {
isDown = false;
}, true);
//The bug occurs here
document.addEventListener('mousemove', function(event) {
event.preventDefault();
if (isDown) {
mousePosition = {
x : event.clientX,
y : event.clientY
};
varNotesWindow.style.left = (mousePosition.x + offset[0]) + 'px';
varNotesWindow.style.top = (mousePosition.y + offset[1]) + 'px';
}
}, true);
//so far
function closeNotesWindow() {
varNotesWindow.classList.remove('show');
}
function openNotesWindow() {
windowsModalContainer.classList.remove('show');
varNotesWindow.classList.add('show');
};
.firstTextarea {
height: 300px;
width: 300px;
}
#notesWindow {
display: block;
position: absolute;
width: 300px;
height: 275px;
top: 0px;
left: 0px;
border: 2px solid #313131;
z-index: 2;
resize: both;
overflow: auto;
}
#headerNotesWindow {
height: 35px;
background-color: black;
}
#moveButtonNotesWindow {
position: absolute;
background-color: blue;
color: white;
width: 20px;
height: 20px;
right: 5px;
z-index: 1;
top: 7.5px;
}
#closeButtonNotesWindow {
position: absolute;
background-color: red;
color: white;
width: 20px;
height: 20px;
right: 30px;
z-index: 1;
top: 7.5px;
}
#divTextareaNotesWindow {
text-align: center;
height: calc(100% - 6px - 35px);
}
#textareaNotesWindow {
resize: none;
width: calc(100% - 6px);
height: 100%;
outline: none;
}
<textarea class="firstTextarea">Pokemon is the best game of my childhood.</textarea>
<div class="divWindow" id="notesWindow">
<div id="headerNotesWindow">
<div id="moveButtonNotesWindow"></div>
<div id="closeButtonNotesWindow" onclick="closeNotesWindow()"></div>
</div>
<div id="divTextareaNotesWindow">
<textarea id="textareaNotesWindow"></textarea>
</div>
</div>
This can do like but not perfact:
RollBack selection when focus back it.
var mousePosition;
var offset = [0,0];
var isDown = false;
var varMoveButtonNotesWindow = document.getElementById('moveButtonNotesWindow');
var varNotesWindow = document.getElementById('notesWindow');
varMoveButtonNotesWindow.addEventListener('mousedown', function(e) {
isDown = true;
offset = [
varNotesWindow.offsetLeft - e.clientX,
varNotesWindow.offsetTop - e.clientY
];
}, true);
document.addEventListener('mouseup', function() {
isDown = false;
}, true);
//The bug occurs here
document.addEventListener('mousemove', function(event) {
event.preventDefault();
if (isDown) {
mousePosition = {
x : event.clientX,
y : event.clientY
};
varNotesWindow.style.left = (mousePosition.x + offset[0]) + 'px';
varNotesWindow.style.top = (mousePosition.y + offset[1]) + 'px';
}
}, true);
//so far
window.addEventListener('load',function(){
var logTextSelection = function(event) {
var tgItem = event.target;
tgItem.setAttribute("lastSelectionStart",tgItem.selectionStart);
tgItem.setAttribute("lastSelectionEnd",tgItem.selectionEnd);
}
var rollBackSelection = function(event){
var tgItem = event.target;
var lastSelectionStart = tgItem.getAttribute("lastSelectionStart");
var lastSelectionEnd = tgItem.getAttribute("lastSelectionEnd");
if((lastSelectionStart !== lastSelectionEnd)){
tgItem.focus();
tgItem.setSelectionRange(lastSelectionStart,lastSelectionEnd);
}
}
var docTextareas = document.getElementsByTagName('textarea');
for (var i = 0; i < docTextareas.length; i++) {
docTextareas[i].addEventListener('select', logTextSelection, true);
docTextareas[i].addEventListener('keyup', logTextSelection, true);
docTextareas[i].addEventListener('focus', rollBackSelection, true);
}
});
function closeNotesWindow() {
varNotesWindow.classList.remove('show');
}
function openNotesWindow() {
windowsModalContainer.classList.remove('show');
varNotesWindow.classList.add('show');
};
.firstTextarea {
height: 300px;
width: 300px;
}
#notesWindow {
display: block;
position: absolute;
width: 300px;
height: 275px;
top: 0px;
left: 0px;
border: 2px solid #313131;
z-index: 2;
resize: both;
overflow: auto;
}
#headerNotesWindow {
height: 35px;
background-color: black;
}
#moveButtonNotesWindow {
position: absolute;
background-color: blue;
color: white;
width: 20px;
height: 20px;
right: 5px;
z-index: 1;
top: 7.5px;
}
#closeButtonNotesWindow {
position: absolute;
background-color: red;
color: white;
width: 20px;
height: 20px;
right: 30px;
z-index: 1;
top: 7.5px;
}
#divTextareaNotesWindow {
text-align: center;
height: calc(100% - 6px - 35px);
}
#textareaNotesWindow {
resize: none;
width: calc(100% - 6px);
height: 100%;
outline: none;
}
<textarea class="firstTextarea">Pokemon is the best game of my childhood.</textarea>
<div class="divWindow" id="notesWindow">
<div id="headerNotesWindow">
<div id="moveButtonNotesWindow"></div>
<div id="closeButtonNotesWindow" onclick="closeNotesWindow()"></div>
</div>
<div id="divTextareaNotesWindow">
<textarea id="textareaNotesWindow"></textarea>
</div>
</div>
OK I found it, i just created a div that replace document for the addeventListener.
Ps I set the color to rgba(0, 175, 0, 0.3) just for you to see how it react and work you can obviously change it to 0.
function start() {
varNotesWindow.classList.add('show');
}
var mousePosition;
var offset = [0,0];
var isDown = false;
var varMoveButtonNotesWindow = document.getElementById('moveButtonNotesWindow');
var varNotesWindow = document.getElementById('notesWindow');
const constAlternativeDocumentForMoveButtonsWindow = document.getElementById('alternativeDocumentForMoveButtonsWindowId');
//Start Move Notes Window
varMoveButtonNotesWindow.addEventListener('mousedown', function(e) {
isDown = true;
offset = [
varNotesWindow.offsetLeft - e.clientX,
varNotesWindow.offsetTop - e.clientY
];
constAlternativeDocumentForMoveButtonsWindow.classList.add('use');
}, true);
constAlternativeDocumentForMoveButtonsWindow.addEventListener('mousemove', function(event) {
event.preventDefault();
if (isDown) {
mousePosition = {
x : event.clientX,
y : event.clientY
};
varNotesWindow.style.left = (mousePosition.x + offset[0]) + 'px';
varNotesWindow.style.top = (mousePosition.y + offset[1]) + 'px';
}
}, true);
constAlternativeDocumentForMoveButtonsWindow.addEventListener('mouseup', function() {
constAlternativeDocumentForMoveButtonsWindow.classList.remove('use');
});
document.addEventListener('mouseup', function() {
isDown = false;
}, true);
//End Move Notes Window
function closeNotesWindow() {
varNotesWindow.classList.remove('show');
}
function openNotesWindow() {
windowsModalContainer.classList.remove('show');
varNotesWindow.classList.add('show');
};
.alternativeDocumentForMoveButtonsWindowClass {
display: none;
}
.alternativeDocumentForMoveButtonsWindowClass.use {
display: block;
position: absolute;
z-index: 3;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: rgba(0, 175, 0, 0.3);
}
#notesWindow {
display: none;
}
#notesWindow.show {
display: block;
position: absolute;
width: 300px;
height: 275px;
top: 0px;
left: 0px;
border: 2px solid #313131;
z-index: 2;
resize: both;
overflow: auto;
}
#headerNotesWindow {
height: 35px;
background-color: black;
}
#moveButtonNotesWindow {
position: absolute;
background-color: blue;
color: white;
width: 20px;
height: 20px;
right: 5px;
z-index: 1;
top: 7.5px;
}
#closeButtonNotesWindow {
position: absolute;
background-color: red;
color: white;
width: 20px;
height: 20px;
right: 30px;
z-index: 1;
top: 7.5px;
}
#divTextareaNotesWindow {
text-align: center;
height: calc(100% - 6px - 35px);
}
#textareaNotesWindow {
resize: none;
width: calc(100% - 6px);
height: 100%;
outline: none;
}
<button onclick='start()'>Let's Go</div>
<div class="alternativeDocumentForMoveButtonsWindowClass" id="alternativeDocumentForMoveButtonsWindowId"></div>
<div class="divWindow" id="notesWindow">
<div id="headerNotesWindow">
<div id="moveButtonNotesWindow"></div>
<div id="closeButtonNotesWindow" onclick="closeNotesWindow()"></div>
</div>
<div id="divTextareaNotesWindow">
<textarea id="textareaNotesWindow"></textarea>
</div>
</div>
I've done a research on this question and found some solutions. However, not every one of them worked. As I understand, async false makes a UI block, which shouldn't be. I could use an overlay until ajax request is completed and on the request success, hide the overlay.
That was my try using a callback argument in the getNewQuote() function (only a small snippet of it):
var getNewQuote = function(callback) {
var quote = {};
setTimeout(function() {
quote.text = 'Example';
quote.author = 'Example';
callback();
return quote;
}, 4000);
};
getNewQuote(function() {
console.log("DONE");
var getRandomColor = function() {
var colors = [
"#ff9966",
"#7f00ff",
"#396afc",
"#0cebeb",
"#06beb6",
"#642b73",
"#36d1dc",
"#cb356b",
"#3a1c71",
"#ef3b36",
"#159957",
"#000046",
"#007991",
"#56ccf2",
"#f2994a",
"#e44d26",
"#4ac29a",
"#f7971e",
"#34e89e",
"#6190e8",
"#3494e6",
"#ee0979"
],
randomNumber = Math.floor(Math.random() * colors.length);
return colors[randomNumber];
};
var updateText = function($t, qt) {
var twitter = "https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=";
twitter += '"' + qt.text + '" ';
twitter += qt.author;
var tumblr = "https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=";
tumblr += qt.author;
tumblr += "&content=";
tumblr += qt.text;
tumblr += "&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button";
var $icon = $("<i class='fa fa-quote-left'>")
.prop("aria-hidden", true);
$t.find(".quote-text").html("").append($icon, qt.text);
$t.find(".quote-author").html("- " + qt.author);
$("#tweet-quote").attr("href", twitter);
$("#tumblr-quote").attr("href", tumblr);
};
var calcNewHeight = function(q) {
var $temp = $("<div>", {
class: "quote-container temp",
}).appendTo($("body"));
$temp.append($("<div>", {
class: "quote-text"
}), $("<div>", {
class: "quote-author"
}));
updateText($temp, q);
var h = $temp.height() + 40;
$temp.remove();
return h;
};
var changeColor = function(newColor) {
$("body, .button:not(#new-quote)").animate({
backgroundColor: newColor
});
$("#new-quote").animate({
color: newColor
});
$(".quote-text, .quote-author").css("color", newColor);
if ($("#modStyle").length === 0) {
$("head").append(
"<style id='modStyle'>#new-quote:before {background:" + newColor + ";}</style>"
);
} else {
$("head style#modStyle").html("#new-quote:before {background:" + newColor + ";}");
}
};
var getQuote = function() {
var nq, nc, nh = 0;
nq = getNewQuote();
nc = getRandomColor();
nh = calcNewHeight(nq);
$(".quote-container").children().css("opacity", 0);
changeColor(nc);
$(".quote-container, #new-quote").animate({
height: nh,
}, {
duration: 1000,
queue: false
});
$(".quote-container").animate({
padding: "2.5em"
}, {
duration: 1000,
queue: false
});
$("#new-quote").animate({
padding: "2.5em .75em"
}, {
duration: 1000,
queue: false
});
updateText($(".quote-container"), nq);
$(".quote-container").children().fadeTo(750, 1);
};
$("#new-quote").on("click", getQuote);
$(".quote-container, #new-quote").css({
visibility: "visible",
height: 0
});
$("#new-quote").css("padding", "0 .75em");
getQuote();
});
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
background: #333;
color: #333;
font-family: sans-serif;
}
.v-wrap {
height: 100%;
text-align: center;
}
.v-wrap:before {
content: "";
display: inline-block;
vertical-align: middle;
width: 0;
height: 100%;
}
.quote-container {
width: 31.25rem;
background: #fff;
margin: 0;
display: inline-block;
vertical-align: middle;
border-radius: 0.1875rem;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
visibility: hidden;
padding: 0 2.5rem;
}
.quote-text {
font-size: 1.625rem;
}
.quote-text i {
margin-right: 0.6rem;
}
.quote-text p {
display: inline;
}
.quote-author {
font-size: 1rem;
margin: 0 0.4rem 2rem 0;
text-align: right;
}
.button {
padding: 0.75rem;
text-align: center;
font-size: 1rem;
color: #fff;
border-radius: .1875rem;
display: inline-block;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
}
.button:not(#new-quote):hover {
opacity: .8 !important;
}
.button:not(#new-quote) {
min-width: 1rem;
min-height: 1rem;
}
.button i {
vertical-align: middle;
}
#new-quote {
white-space: nowrap;
writing-mode: vertical-lr;
height: 50%;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
vertical-align: middle;
background: #fff !important;
margin: 0;
position: relative;
right: 0.25625rem;
color: #333;
visibility: hidden;
}
#new-quote:before {
content: "";
position: absolute;
height: 100%;
width: 0.0625rem;
bottom: 0;
left: 0;
visibility: hidden;
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
#new-quote:hover:before {
visibility: visible;
-webkit-transform: scaleY(1);
transform: scaleY(1);
}
footer {
font-size: 0.85rem;
margin-bottom: 1rem;
}
footer a {
text-decoration: none;
color: #fff;
position: relative;
}
footer a:before {
content: "";
position: absolute;
width: 100%;
height: .0625rem;
bottom: 0;
left: 0;
background: #fff;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all .3s ease-in-out 0s;
transition: all .3s ease-in-out 0s;
}
footer a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="v-wrap">
<div class="quote-container" style="">
<div class="quote-text">
</div>
<div class="quote-author"></div>
<a id="tweet-quote" class="button"><i class="fa fa-twitter"></i></a>
<a id="tumblr-quote" class="button"><i class="fa fa-tumblr"></i></a>
</div>
<div id="new-quote" class="button">New quote</div>
<footer>
Created by LukasLSC
</footer>
</div>
Code output:
As you can see, ajax wasn't success
Uncaught TypeError: callback is not a function and Uncaught TypeError: Cannot read property 'text' of undefined (only in the stack snippet).
I found out this error disappears if I remove the getQuote(); function call. However, I need to call it, overwise, my project won't work. I also tried to use return $.ajax but there was a return quote line so I couldn't use it. The full code can be found here on codepen: https://codepen.io/Kestis500/pen/ZvyxKB?editors=0110.
Then I switched to another method using jQuery promises and used information in this thread: https://stackoverflow.com/a/40658281/8889739. Full code: https://codepen.io/Kestis500/pen/qpjxoq?editors=0110.
var MyFirstFunction = function() {
var getNewQuote = function(callback) {
var quote = {};
setTimeout(function() {
quote.text = 'Example';
quote.author = 'Example';
return quote;
}, 4000);
};
}
var MySecondFunction = function() {
console.log("DONE");
var getRandomColor = function() {
var colors = [
"#ff9966",
"#7f00ff",
"#396afc",
"#0cebeb",
"#06beb6",
"#642b73",
"#36d1dc",
"#cb356b",
"#3a1c71",
"#ef3b36",
"#159957",
"#000046",
"#007991",
"#56ccf2",
"#f2994a",
"#e44d26",
"#4ac29a",
"#f7971e",
"#34e89e",
"#6190e8",
"#3494e6",
"#ee0979"
],
randomNumber = Math.floor(Math.random() * colors.length);
return colors[randomNumber];
};
var updateText = function($t, qt) {
var twitter = "https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=";
twitter += '"' + qt.text + '" ';
twitter += qt.author;
var tumblr = "https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes,freecodecamp&caption=";
tumblr += qt.author;
tumblr += "&content=";
tumblr += qt.text;
tumblr += "&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fbuttons&shareSource=tumblr_share_button";
var $icon = $("<i class='fa fa-quote-left'>")
.prop("aria-hidden", true);
$t.find(".quote-text").html("").append($icon, qt.text);
$t.find(".quote-author").html("- " + qt.author);
$("#tweet-quote").attr("href", twitter);
$("#tumblr-quote").attr("href", tumblr);
};
var calcNewHeight = function(q) {
var $temp = $("<div>", {
class: "quote-container temp",
}).appendTo($("body"));
$temp.append($("<div>", {
class: "quote-text"
}), $("<div>", {
class: "quote-author"
}));
updateText($temp, q);
var h = $temp.height() + 40;
$temp.remove();
return h;
};
var changeColor = function(newColor) {
$("body, .button:not(#new-quote)").animate({
backgroundColor: newColor
});
$("#new-quote").animate({
color: newColor
});
$(".quote-text, .quote-author").css("color", newColor);
if ($("#modStyle").length === 0) {
$("head").append(
"<style id='modStyle'>#new-quote:before {background:" + newColor + ";}</style>"
);
} else {
$("head style#modStyle").html("#new-quote:before {background:" + newColor + ";}");
}
};
var getQuote = function() {
var nq, nc, nh = 0;
nq = getNewQuote();
nc = getRandomColor();
nh = calcNewHeight(nq);
$(".quote-container").children().css("opacity", 0);
changeColor(nc);
$(".quote-container, #new-quote").animate({
height: nh,
}, {
duration: 1000,
queue: false
});
$(".quote-container").animate({
padding: "2.5em"
}, {
duration: 1000,
queue: false
});
$("#new-quote").animate({
padding: "2.5em .75em"
}, {
duration: 1000,
queue: false
});
updateText($(".quote-container"), nq);
$(".quote-container").children().fadeTo(750, 1);
};
$("#new-quote").on("click", getQuote);
$(".quote-container, #new-quote").css({
visibility: "visible",
height: 0
});
$("#new-quote").css("padding", "0 .75em");
getQuote();
}
MyFirstFunction().done(MySecondFunction);
html,
body {
height: 100%;
width: 100%;
}
body {
margin: 0;
padding: 0;
background: #333;
color: #333;
font-family: sans-serif;
}
.v-wrap {
height: 100%;
text-align: center;
}
.v-wrap:before {
content: "";
display: inline-block;
vertical-align: middle;
width: 0;
height: 100%;
}
.quote-container {
width: 31.25rem;
background: #fff;
margin: 0;
display: inline-block;
vertical-align: middle;
border-radius: 0.1875rem;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
visibility: hidden;
padding: 0 2.5rem;
}
.quote-text {
font-size: 1.625rem;
}
.quote-text i {
margin-right: 0.6rem;
}
.quote-text p {
display: inline;
}
.quote-author {
font-size: 1rem;
margin: 0 0.4rem 2rem 0;
text-align: right;
}
.button {
padding: 0.75rem;
text-align: center;
font-size: 1rem;
color: #fff;
border-radius: .1875rem;
display: inline-block;
cursor: pointer;
-webkit-user-select: none;
user-select: none;
}
.button:not(#new-quote):hover {
opacity: .8 !important;
}
.button:not(#new-quote) {
min-width: 1rem;
min-height: 1rem;
}
.button i {
vertical-align: middle;
}
#new-quote {
white-space: nowrap;
writing-mode: vertical-lr;
height: 50%;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
vertical-align: middle;
background: #fff !important;
margin: 0;
position: relative;
right: 0.25625rem;
color: #333;
visibility: hidden;
}
#new-quote:before {
content: "";
position: absolute;
height: 100%;
width: 0.0625rem;
bottom: 0;
left: 0;
visibility: hidden;
-webkit-transform: scaleY(0);
transform: scaleY(0);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
#new-quote:hover:before {
visibility: visible;
-webkit-transform: scaleY(1);
transform: scaleY(1);
}
footer {
font-size: 0.85rem;
margin-bottom: 1rem;
}
footer a {
text-decoration: none;
color: #fff;
position: relative;
}
footer a:before {
content: "";
position: absolute;
width: 100%;
height: .0625rem;
bottom: 0;
left: 0;
background: #fff;
visibility: hidden;
-webkit-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: all .3s ease-in-out 0s;
transition: all .3s ease-in-out 0s;
}
footer a:hover:before {
visibility: visible;
-webkit-transform: scaleX(1);
transform: scaleX(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="v-wrap">
<div class="quote-container" style="">
<div class="quote-text">
</div>
<div class="quote-author"></div>
<a id="tweet-quote" class="button"><i class="fa fa-twitter"></i></a>
<a id="tumblr-quote" class="button"><i class="fa fa-tumblr"></i></a>
</div>
<div id="new-quote" class="button">New quote</div>
<footer>
Created by LukasLSC
</footer>
</div>
Code output:
It broke everything, the gray screen is because of the default codepen background
Uncaught TypeError: Cannot read property 'done' of undefined
You're using return from the asynchronous operation's callback. That just sets the return value of that callback (which is ignored in the case of setTimeout's or XHR's callback), it doesn't set the return value of your function.
You can't return the value from your function, which is why you're adding a callback. Instead:
var getNewQuote = function(callback) {
var quote = {};
setTimeout(function() {
quote.text = 'Example';
quote.author = 'Example';
callback(quote); // <====
}, 4000);
};
...and use the parameter of the callback, e.g.:
getNewQuote(function(quote) {
// Use quote here...
});
Live Example:
var getNewQuote = function(callback) {
var quote = {};
setTimeout(function() {
quote.text = 'Example';
quote.author = 'Example';
callback(quote); // <====
}, 1000);
};
getNewQuote(function(quote) {
console.log("quote:", quote);
});
Having a slider with images implementation from array, cant figure out why images dont want to be shown up from array, tryed to make a path but it didnt work.I want this code to reflect this image every time a push the button: fpoimg.com/100x100.
Im trying to fix it only with clean javascript.
Here is a sandbox
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame:0,
set:function(image){
path = path || 'http://fpoimg.com/';
document.getElementById('scr').style.backgroundImage ="url ("+path+ image+")";
},
init:function() {
this.set(this.slides[this.frame]);
},
left:function() {
this.frame--;
if(frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right:function() {
if(this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
},5000);
};
.scr {
margin:20px auto;
width: 600px;
height: 320px;
margin-top:20px;
background-color: white;
background-size:cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background:none;
border:none;
}
.left {
left:25px;
}
.right {
right:25px;
}
<body>
<button class="left" onclick="slider.left();"><</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();">></button>
</body>
On Line 6 of your Javascript, you have used getElementById('scr'). You have no element with an Id or scr, you needed to use getElementsByClassName('scr')
Your new code:
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame: 0,
set: function(image) {
path = path || 'http://fpoimg.com/';
document.getElementsByClassName('scr').style.backgroundImage = "url (" + path + image + ")";
},
init: function() {
this.set(this.slides[this.frame]);
},
left: function() {
this.frame--;
if (frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right: function() {
if (this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
}, 5000);
};
.scr {
margin: 20px auto;
width: 600px;
height: 320px;
margin-top: 20px;
background-color: white;
background-size: cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background: none;
border: none;
}
.left {
left: 25px;
}
.right {
right: 25px;
}
<body>
<button class="left" onclick="slider.left();">
</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();"></button>
</body>
It seems you've got getElementById() when you meant getElementsByClassName()