Svelte transition seems to finish too soon - html

I'm trying to build a simple transition in Svelte where I have cards that animate in on page load. I've followed this answer to get it to fire correctly onMount, so that has been ok. However, the transition itself seems to "jump" to the end too quickly, and skips the last few frames.
GIF of problem running on localhost.
Oddly enough, when I copy and paste the same code into the REPL, the visual bug seems to be fixed. I've even downloaded the REPL and run locally, and the bug still appears.
Here is the code.
<script>
import { fly } from 'svelte/transition';
import { onMount } from 'svelte';
const contents = [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
];
let ready = false;
onMount(() => (ready = true));
</script>
<main>
<div class="topBar" />
<div class="container">
{#if ready}
{#each contents as content, i}
<div
class="transCard"
transition:fly={{ y: 80, duration: 1000, delay: i * 200 }}
/>
{/each}
{/if}
</div>
</main>
<style>
main {
background: white;
width: 100vw;
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
}
.container {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
overflow: hidden;
margin-top: 80px;
}
.topBar {
width: 100vw;
height: 80px;
background: black;
position: fixed;
top: 0;
left: 0;
z-index: 9;
}
.transCard {
width: 100%;
height: 200px;
background: gray;
}
</style>

Found the answer myself! Not sure why it fixed it, but for me changing transition to just in seems to have cured the visual bug.

Related

TinyMCE and Drag Conflict Issues

My page reads as follows.
The problem is that when I use draggabilly to drag the move-line, dragging to the left is fine, but when I drag it to the right, it doesn't work in the area where the tinymce compiler is located. How do I fix this problem?
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.all-warp {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
}
.left {
width: 200px;
background-color: burlywood;
}
.move-line {
width: 4px;
background-color: crimson;
cursor:e-resize;
}
.editor-warp {
flex-grow: 2;
}
</style>
<body>
<div class="all-warp">
<div class="left"></div>
<div class="move-line"></div>
<div class="editor-warp">
<textarea id="editor"></textarea>
</div>
</div>
<script>
$(document).ready(function () {
var $draggable = $('.move-line').draggabilly({
axis: 'x',
containment: '.all-warp'
})
});
tinymce.init({
selector: '#editor',
menubar: false,
statusbar: false,
resize: false,
height:500,
});
</script>
</body>
</html>
Without seeing actual running code I cannot say for sure but I would suspect this is because the TinyMCE editing region itself is an iframe? Does the drag code you have work if you replace TinyMCE with a regular iframe? If not that would be your issue.

Initial CSS transition won't play

I've got transition(expand/NotExpand) on the grid cells of my CSS grid which is triggered onClick.
PROBLEM:
The problem is on the initial click, the expansion/transition won't play and the element would simply snap in to place. Of course this also has a reverse transition but since it's the second click of that child cell/element, the transition would play.
~Parent grid~
<template>
<div class="jobGrid myr" id="jobGrid">
<job-cell v-for="job in jobs" :key="job.id" :job="job" />
</div>
</template>
<style scoped>
.jobGrid {
display: grid;
grid-template-columns: 10% 10% 10% 10% 10% 10% 10% ;
grid-template-rows: 25% 25% 25% 25% ;
grid-column-gap: 5%;
grid-row-gap: 3%;
margin: auto;
margin-top: 2%;
width: 90%;
height: 90%;
max-width: 90%;
max-height: 90%;
overflow-x: auto;
}
</style>
~Child cell~
<template>
<div class="scene" #click="toggleJobData($event)" :style="expandCSS" >
<div>
{{job.title}}
</div>
</div>
</template>
<style>
.scene {
background: peru;
transition: left 3s, top 3s, width 3s, height 3s;
}
</style>
<script>
export default {
props: ['job'],
data() {
return {
expand: false,
expandCSS: {zIndex: 1},
}
},
computed: {
gridCSS() {
return this.$store.state.job.jobSelectorCSS
}
},
methods: {
toggleJobData(e) {
let currentPos = e.target.getBoundingClientRect()
let expand = {
position: 'relative',
left: `${this.gridCSS.left - currentPos.left}px`,
top: `${this.gridCSS.top - currentPos.top}px`,
width: `1041%`,
height: `400%`,
//zIndex: 2,
}
let notExpand = {
position: 'relative',
left: '0px',
top: '0px',
width: '100%',
height: '100%',
//zIndex: 1,
}
if(!this.expand) {
this.expand = !this.expand
this.expandCSS = expand
}else{
this.expand = !this.expand
this.expandCSS = notExpand
}
}
}
}
</script>
*** This is what you will get onLoad, or the NotExpand state.
Here, I clicked "Job2" and it will expand beyond its cell to fill up the entire grid.
I assume that the transition is applied immediately after onLoad
I think the "missing transition" is lack of CSS properties for its initial state. Until the first click, there are no properties to transite from.
Try styling your child cell with the initial props, that would be transited, like this:
.scene {
background: peru;
transition: all 3s;
position: relative;
left: 0px; top: 0px;
width: 100%; height: 100%;
}

How to scroll a div to the bottom in componentDidMount(using react.js)?

I'm creating a chat app in react.js and I'm having trouble with setting a div element to be scrolled to bottom every componentDidMount call.
I've tried to use these line but it didn't work:
componentDidMount() {
var objDiv = document.getElementById("scrolling-div");
objDiv.scrollTop = objDiv.scrollHeight;
}
this is the div
<div className="scroll-chat h-def-chat" id="scrolling-div">...</div>
.h-def-chat {
height: calc(100vh - 140px);
}
.scroll-chat {
overflow-y: scroll;
overflow-x: hidden;
float: left;
}
.scroll-chat::-webkit-scrollbar-track {
border-radius: 10px;
background-color: #f2f2f2;
}
.scroll-chat::-webkit-scrollbar {
width: 10px;
background-color: #f2f2f2;
}
.scroll-chat::-webkit-scrollbar-thumb {
border-radius: 3px;
background-color: #ccc;
}
I expect the div to be scrolled down every time the component mounts
is there a solution?
thx, Guy
You simply need to to window.scrollTo function i.e
componentDidMount() {
var objDiv = document.getElementById("scrolling-div");
window.scrollTo(0, objDiv.scrollHeight);
}
It will let you to bottom of your div.
Here i made one codesandbox for refrence.
Note you dont need to add 0 in scrollTo function. Its totally upto you from where you want to scroll.

Toggle 2 classes via Angular

I'm trying to toggle between 2 classes via Angular's ng-Click & ng-Class selectors.
Basically, I want to click 1 line of text, or a button, or whatever, and change the z-index of an element by switching the styles using ng-Click.
I've tried multiple solutions but virtually none of them are working. I'm not entirely sure whether its something I'm doing wrong with Angular, or maybe my CSS?
Angular:
app.controller("naviController",function($scope){
"use strict";
$scope.toggles = [{ state: true }, { state: false }, { state: true }];
});
HTML:
<div ng-controller="naviController">
<div class="nav-container">
<div class="nav-element-block ne-1" ng-click="toggle.state = !toggle.state">Index</div>
<div class="nav-element-block ne-2" ng-click="toggle.state = !toggle.state">About</div>
<div class="nav-element-block ne-3" ng-click="toggle.state = !toggle.state">Dev</div>
</div>
<div id="index-container" ng-class="{'about-container-active' : toggle.state}">Index Container</div>
<div id="about-container" ng-class="{'about-container-active' : toggle.state}">About Container</div>
<div id="dev-container" ng-class="{'about-container-active' : toggle.state}">Dev Container</div>
</div>
CSS:
#index-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #FFF;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
box-sizing: border-box;
padding-left: 5%;
padding-right: 5%;
z-index: 5;
position: fixed;
}
.index-container-active {
z-index: 999;
}
#about-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #f1ffff;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
padding-left: 5%;
padding-right: 5%;
z-index: 4;
position: fixed;
}
.about-container-active {
z-index: 999;
}
#dev-container {
display: table-cell;
width: 100vw;
height: 90vh;
padding-top: 10vh;
background-color: #f1fff1;
overflow: hidden;
animation-name: indexcell;
animation-duration: 500ms;
padding-left: 5%;
padding-right: 5%;
z-index: 3;
position: fixed;
}
.dev-container-active {
z-index: 999;
}
What I'm actually trying to do: I have 5 divs whose class I'd like to change with, lets say 5 links and when I click one of the links I'd like to switch that related class on, and the others off. Like:
Index = Class-1-Active
About = Class-2-Inactive
Dev = Class-3-Inactive
Contact = Class-4-Inactive
Portfolio = Class-5-Inactive
Lets say we click on 'Dev', this then switches class 3 into an active state, by switching classes, and then switches all the other classes to an inactive state. Like so:
Index = Class-1-Inactive
About = Class-2-Inactive
Dev = Class-3-Active
Contact = Class-4-Inactive
Portfolio = Class-5-Inactive
There are multiple errors in your code, as the guys pointed out you're having a typo, but just that won't resolve your issues.
I'd go from start, as everything in angularjs there are many ways to do same thing. This is just one simple proposal, first your html would require ng-click to go in some kind of function in which you will change state of the active:
<button class="nav-element-block ne-1" ng-click="toggleState('index')">Index</button>
<button class="nav-element-block ne-2" ng-click="toggleState('about')">About</button>
<button class="nav-element-block ne-3" ng-click="toggleState('dev')">Dev</button>
next you need to figure out which state is which, so fix your object of states to something like this:
let toggles = [{
name: 'dev',
state: false
}, {
name: 'about',
state: false
}, {
name: 'index',
state: true
}];
and you need to create that function on $scope that you are calling on that div/button click. It will set state to false to all other objects except one named state:
$scope.toggleState = function(state) {
toggles = toggles.map(val => {
if (val.name === state) {
val.state = true;
} else {
val.state = false;
}
return val;
});
};
Then you need to assign function that will check on your divs to trigger a class by a certain div name:
<div id="index-container" ng-class="{'about-container-active' : checkActiveState('index')}">Index Container</div>
<div id="about-container" ng-class="{'about-container-active' : checkActiveState('about')}">About Container</div>
<div id="dev-container" ng-class="{'about-container-active' : checkActiveState('dev')}">Dev Container</div>
And in the end you need a function that will search that div name in your toggles array and return .state of that object and that will actually trigger your class:
$scope.checkActiveState = function(state) {
return toggles.find(x => x.name === state).state;
};
And voila, that's it, if you have any issues let me know, here's fiddle so you can play around with it: https://jsfiddle.net/pegla/mvprL5ap/1/

how to disable dragend animation in html5

I created a draggable element by setting its draggable attribute. When I drop the element, there is an animation of the element snapping back to its origin position:
How can the snap-back animation be disabled? I tried calling preventDefault() on the dragend event, but it had no effect on the animation.
The following snippet shows the basics:
document.getElementById('test').addEventListener(
'dragend', evt => {
evt.preventDefault();
}
);
#container {
border: 1px solid black;
min-width: 300px;
min-height: 200px;
position: relative;
}
#test {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
top: 25px;
left: 40px;
}
<div id="container">
<div id="test" draggable='true'></div>
</div>
Not every browser will show the dragged #test jumping back to the original position.
In order to prevent the animation, you need the drop event to fire. For the drop event to fire, you need to call preventDefault() in the handler for dragover.
document.addEventListener('dragover', function(e) { e.preventDefault() })
Example in MDN docs shows the same thing: https://developer.mozilla.org/en-US/docs/Web/Events/drop#Example
An old blog post describing the quirks of HTML5 Drag and Drop API: https://www.quirksmode.org/blog/archives/2009/09/the_html5_drag.html
As was said earlier, you need to explicitly describe onDragOver handler on the parent's container (where you will drop your draggable element) and put .preventDefault() on event to prevent this animation.
Here is a simple React code example for better understanding of this mechanic (you can position the box inside the container by dragging it):
App.jsx
import './App.css'
const App = () => {
function handleDragOver(e) {
e.preventDefault()
}
function handleDrop(e) {
let box = document.getElementById('box')
if (box) {
box.style.top = e.clientY + 'px'
box.style.left = e.clientX + 'px'
}
}
return (
<div className="container" onDragOver={handleDragOver} onDrop={handleDrop}>
<div id="box" draggable></div>
</div>
)
}
export default App
App.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100vw;
height: 100vh;
position: relative;
}
#box {
width: 100px;
height: 100px;
background-color: lightgreen;
position: absolute;
}