I have test where I test drag and drop element. In localhost is everything ok. When I do pull request on github the test falls on the drag and drop movement. Do you have any advice what I can do?I am using this code.
cy.dragAndDrop('[style="width: 843px; height: 230px; position: absolute; transform: translate(10px, 10px); z-index: 0;"] > .rounded-xl > .absolute > .pt-4 > .drag-handle','[style="transform: translate(10px, 490px); width: 843px; height: 230px; position: absolute;"] > .rounded-xl > .flex-col' )
cy.dragAndDrop('[style="transform: translate(10px, 10px); width: 843px; height: 230px; position: absolute; z-index: 0;"] > .rounded-xl > .absolute > .pt-4 > .drag-handle','[style="transform: translate(10px, 250px); width: 843px; height: 230px; position: absolute;"] > .rounded-xl')
here is the commands.ts part:
Cypress.Commands.add('dragAndDrop', (subject, target) => {
Cypress.log({
name: 'DRAGNDROP',
message: `Dragging element ${subject} to ${target}`,
consoleProps: () => {
return {
subject: subject,
target: target
};
}
});
const BUTTON_INDEX = 0;
const SLOPPY_CLICK_THRESHOLD = 10;
cy.get(target)
.first()
.then($target => {
let coordsDrop = $target[0].getBoundingClientRect();
cy.get(subject)
.first()
.then(subject => {
const coordsDrag = subject[0].getBoundingClientRect();
cy.wrap(subject)
.trigger('mousedown', {
button: BUTTON_INDEX,
clientX: coordsDrag.x,
clientY: coordsDrag.y,
force: true
})
.trigger('mousemove', {
button: BUTTON_INDEX,
clientX: coordsDrag.x + SLOPPY_CLICK_THRESHOLD,
clientY: coordsDrag.y,
force: true
});
cy.get('body')
.trigger('mousemove', {
button: BUTTON_INDEX,
clientX: coordsDrop.x,
clientY: coordsDrop.y,
force: true
})
.trigger('mouseup',{force:true});
Related
I've tried different solutions to animate a sidenav bar rise from bottom right corner. This is the last solution, maybe the best one ( because i'm animating the transform scale() ) in the previous ( width / height ) but the animation still sluggish on the cut corner... with the cut line acting with strange squared forms during the animation ... so i'm looking to solve!
Here the scale() example on glitch
https://glitch.com/edit/#!/heady-grey-lantern
Even on w3schools site the simple animation of Side Navigation is little shimmy and flicker
https://www.w3schools.com/howto/howto_js_sidenav.asp
Here the core of animation
// css code
.sidenav {
width: 200vw;
height: 200vh;
width: 200dvw;
height: 200dvh;
position: fixed;
bottom: 0;
/* left: 0; */
right: 0;
/* cut corner */
--cutting: max(100vw, 100vh);
--cutting: max(150dvw, 150dvh);
clip-path: polygon(0 var(--cutting), var(--cutting) 0,100% 0,100% 100%,0 100%);
/* z-index: 1; */
background-color: #111;
/* overflow-x: hidden; */
will-change: transform;
transform: scale(0);
transform-origin: bottom right;
}
// Js code
const sidenav = document.getElementById("mySidenav")
const duration = 500
const openSidenav = [
{ transform: 'scaleX(0) scaleY(0)' },
{ transform: 'scaleX(1) scaleY(1)' }
]
const closeSidenav = [
{ transform: 'scaleX(1) scaleY(1)' },
{ transform: 'scaleX(0) scaleY(0)' }
]
const openNav = () => {
console.log('#NAV >> Open')
// document.getElementById("mySidenav").style.width = '175vw'
// document.getElementById("mySidenav").style.height = '175vh'
sidenav.animate(
openSidenav, {
duration,
iterations: 1,
easing: 'ease-in',
fill: 'forwards'
}
)
}
const closeNav = () => {
console.log('#NAV >> Close')
// document.getElementById("mySidenav").style.width = '0'
// document.getElementById("mySidenav").style.height = '0'
sidenav.animate(
closeSidenav, {
duration,
iterations: 1,
easing: 'ease-in',
fill: 'forwards'
}
)
}
Last, better one!
/* css */
#sidenav {
width: 100vw;
height: 100vh;
width: 100dvw;
height: 100dvh;
position: fixed;
/* cut corner */
--cutting: max(100vw, 100vh);
clip-path: polygon(0 var(--cutting), var(--cutting) 0,100% 0,100% 100%,0 100%);
/* set transition as in WebAnimation API */
transition: all 0.5s;
will-change: transform;
transform: scale(0);
transform-origin: bottom right;
z-index: 11;
background-color: var(--surface1);
display: grid;
justify-items: center;
align-items: center;
/* justify-items: end;
align-items: end; */
}
#sidenav[active] {
--cutting: 0;
transition: all 0.5s;
}
/* --------------- Mobile Nav -------------- */
nav {
/* TODO fallback inline-size: 75vw;
block-size: 75vh; */
inline-size: 75dvw;
block-size: 75dvh;
display: block;
flex-direction: column;
background-color: crimson;
}
// javascript animations
const openSidenav = [
{ transform: 'scale(0)' },
{ transform: 'scale(0.25)' },
{ transform: 'scale(0.5)' },
{ transform: 'scale(0.75)' },
{ transform: 'scale(1)' }
]
const closeSidenav = [
{ transform: 'scale(1)' },
{ transform: 'scale(0.75)' },
{ transform: 'scale(0.5)' },
{ transform: 'scale(0.25)' },
{ transform: 'scale(0)' }
]
const slideIn = [
{ transform: 'translateX(100%)' },
{ transform: 'translateX(0)', opacity: 1 }
]
const slideOut = [
{ transform: 'translateX(0)' },
{ transform: 'translateX(100%)', opacity: 0 }
]
// duration animation
const openSidenavDuration = 500
const closeSidenavDuration = 300
// duration animation per a tag
const slideInDuration = 200
const slideOutDuration = 100
// javascript
openNav (e) {
const sidenav =
this.renderRoot.getElementById('sidenav')
this.sidenavIsOpen = true
const openAnimation = sidenav.animate(
openSidenav, {
duration: openSidenavDuration,
iterations: 1,
easing: 'ease-in',
fill: 'forwards'
}
)
openAnimation.addEventListener('finish', (e) => {
// console.log('#EVENT >> ', e.type)
sidenav.setAttribute('active', '')
// sidenav.style.setProperty('--cutting', 0)
})
}
closeNav (e) {
const sidenav =
this.renderRoot.getElementById('sidenav')
this.sidenavIsOpen = false
sidenav.animate(
closeSidenav, {
duration: closeSidenavDuration,
iterations: 1,
easing: 'ease-in',
fill: 'forwards',
delay: slideOutDuration * 3
}
)
sidenav.removeAttribute('active')
}
I am using latest version of formsflow.ai and I want to create a custom toggle button. How can I do that in formflow.ai. I refer the following documents of formio to do that.
I am expecting to include a custom toggle button in drag and drop mechanism of formsflow.ai
step 1:create the components inside the forms-flow-web in the following order
step 2:Toggle.js code
import React from "react";
import ReactDOM from "react-dom";
import { ReactComponent } from "react-formio";
import settingsForm from "./Toggle.settingsForm";
import ToggleCustomComp from "./Togglechange";
export default class Toggle extends ReactComponent {
/**
* This function tells the form builder about your component. It's name, icon and what group it should be in.
*
* #returns {{title: string, icon: string, group: string, documentation: string, weight: number, schema: *}}
*/
static get builderInfo() {
return {
title: "Toggle",
icon: "square",
group: "basic",
documentation: "",
weight: 120,
schema: Toggle.schema()
};
}
/**
* This function is the default settings for the component. At a minimum you want to set the type to the registered
* type of your component (i.e. when you call Components.setComponent('type', MyComponent) these types should match.
*
* #param sources
* #returns {*}
*/
static schema() {
return ReactComponent.schema({
type: "toggleCustomComp",
label: "ToggleButton"
});
}
/*
* Defines the settingsForm when editing a component in the builder.
*/
static editForm = settingsForm;
/**
* This function is called when the DIV has been rendered and added to the DOM. You can now instantiate the react component.
*
* #param DOMElement
* #returns ReactInstance
*/
attachReact (element) {
let instance;
return ReactDOM.render(
<ToggleCustomComp
ref={(refer) => {instance = refer;}}
component={this.component} // These are the component settings if you want to use them to render the component.
value={this.datavalue} // The starting value of the component.
onChange={this.updateValue}
data={this.data}
disabled={this.disabled}
// The onChange event to call when the value changes.
/>,
element,() => (this.reactInstance = instance)
);
}
/**
* Automatically detach any react components.
*
* #param element
*/
detachReact(element) {
if (element) {
ReactDOM.unmountComponentAtNode(element);
}
}
}
step 3:Toggle.settingsForm.js
import baseEditForm from 'formiojs/components/_classes/component/Component.form';
const settingsForm = (...extend) => {
return baseEditForm([
{
key: 'display',
components: [
{
// You can ignore existing fields.
key: 'placeholder',
ignore: true,
},
]
},
{
key: 'data',
components: [],
},
{
key: 'validation',
components: [],
},
{
key: 'api',
components: [],
},
{
key: 'conditional',
components: [],
},
{
key: 'logic',
components: [],
},
], ...extend);
}
export default settingsForm;
step 4:Togglechange.jsx
import React, {Component} from 'react';
import '../Toggle/toggle.css';
/**
* An example React component this is simply a controlled input element.
*
*/
export default class ToggleCustomComp extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
}
updateCommentData = (event) => {
//const {type} = this.props.component;
this.setState({value: {checked:event.target.checked}}, () => this.props.onChange(this.state.value));
};
render() {
const {disabled, name} = this.props;
let { value } = this.state;
const checked = value?.checked || false;
return (
/*<input type="text" value={value} className={this.props.component.customClassName} onChange={this.setValue}></input>*/
// <input type="checkbox" id="vehicle3" name="vehicle3" value="Boat"></input>
<label class="switch">
<input
name={name}
value={checked}
type="checkbox"
className="form-control"
onChange={(e)=>this.updateCommentData(e)}
disabled={disabled}
/>
<span class="slider round" />
</label>
);
}
};
step 5 :css file
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
step 6:index.js file
import TextAreaWithAnalytics from "./TextAreaWithAnalytics/TextAreaWithAnalytics";
import Toggle from "./Toggle/Toggle";
const components = {
textAreaWithAnalytics: TextAreaWithAnalytics,
toggleCustomComp: Toggle
};
export default components;
I have a map with a layer control that has overlays specified in the baselayer parameter:
var overlays = {
'Layer 1': mylayer1,
'Layer 2': mylayer2
};
L.control.layers( overlays, null, { collapsed: false } ).addTo( map );
I specify my layers as follows:
var mylayer1 = L.esri.featureLayer({
url: 'https://.../MapServer/5'
}).on( 'load', function ( e ) {
...
}).on( 'loading', function ( e ) {
...
}).bindPopup( function ( layer ) {
return L.Util.template( '<p>{_score}</p>', layer.feature.properties );
});
The issue is that when I change layers in the control the bindPopup event no longer gets called.
It's almost like the layer z-index is not updated. Would appreciate any insight on how I can address this.
See: https://codepen.io/jvanulde/pen/LYyOWZo
I see no one has given an answer.
A little around, but it works.
You add the id: x to each layer. Later in the loop you check which layer is active, and all the rest of the layers you add the style display: none.
window.addEventListener('DOMContentLoaded', () => {
let tiles = L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors, Points © 2012 LINZ'
});
let l1 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/1',
id: 0, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 1: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let l2 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/2',
id: 1, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 2: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let map = L.map('map', {
center: [49.2827, -123.1207],
zoom: 12,
layers: [tiles]
});
let overlays = {
'Layer 1': l1,
'Layer 2': l2
};
L.control.layers(overlays, null, {
collapsed: false
}).addTo(map);
l1.addTo(map);
map.on('baselayerchange', function(e) {
const layersCanvas = document.querySelectorAll('.leaflet-overlay-pane > canvas');
layersCanvas.forEach((layer, index) => {
layer.style.display = '';
if (index !== e.layer.options.id) {
layer.style.display = 'none';
}
});
});
});
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100vh;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet#3.0.2/dist/esri-leaflet.js"></script>
<div id="map"></div>
I implemented somethink like on this picture:
if you click on a link popup will appear and you can follow the link.
jQuery(function($){
/**
* add the follow link popup to all TinyMCE instances
*/
if (!window.tinymce) return;
tinymce.on('AddEditor', function( event ) {
tinymce.editors.forEach(function(editor) {
if (!editor.isFollowLinkAdded) {
editor.isFollowLinkAdded = true;
editor.on('blur', function(e) {
jQuery(e.target.contentDocument.body).find('#followLink').remove();
});
editor.on('click', function(e) {
var link = jQuery(e.target).closest('a');
jQuery(e.view.document.body).find('#followLink').remove();
if (link.length) {
e.preventDefault();
var POPUP_WIDTH = 215,
isRightSide = (jQuery(e.view.document).width()-e.pageX) >= POPUP_WIDTH,
boxCss = {
top: e.pageY,
padding: '6px 10px',
position: 'absolute',
backgroundColor: '#ffffff',
border: '1px solid #a8a8a8',
borderRadius: '2px',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.2)',
color: '#666666',
cursor: 'pointer',
whiteSpace: 'nowrap',
zIndex: 502
};
boxCss[(isRightSide) ? 'left' : 'right'] = (isRightSide) ? e.pageX : jQuery(e.view.document).width()-e.pageX;
jQuery('<a/>', {
href: link.attr('href'),
text: link.attr('href'),
target: '_blank'
}).css({
cursor: 'pointer',
display: 'inline-block',
maxWidth: '100px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}).wrap(
jQuery('<p/>', {
text: 'Click to follow: ',
id: 'followLink',
}).on('click', function(){
var win = window.open(link.attr('href'), '_blank');
win.focus();
}).css(boxCss)
).parent().appendTo(e.view.document.body);
}
});
}
});
}, true );
});
The most recent version of TinyMCE 4 (4.5.3) includes the option to open a link in the right click menu of the editor - no need to write your own custom code.
I'm trying to make an animation with velocity.js of a map. I tried 2 different libraries: leaflet, and openlayers3.
Here are the jsfiddles: leaflet, openlayers3
The leaflet animation is smooth on my chrome, but not on firefox, edge, or even qt webview.
I know that invalidateSize()/updateSize() just change the position of the tiles and download new ones but I want them to produce a smooth animation.
wish somebody have seen this kind of animation. Or know how could I solve the issue, thanks.
leaflet
$(document).ready(function() {
var position = {
lat: 43.180176,
lng: 13.792964,
zoomLevel: 4
};
var swBound = L.latLng(-90, -180);
var neBound = L.latLng(90, 180);
var maxBounds = L.latLngBounds(swBound, neBound);
var entityMap = L.map($("#smallMapContainer")[0], {
minZoom: 2,
maxBounds: maxBounds,
zoomControl: false
});
var streetMapURL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
L.tileLayer(streetMapURL, {
maxZoom: 18
}).addTo(entityMap);
//entityMap.fitWorld();
entityMap.setView(L.latLng(position.lat, position.lng), position.zoomLevel);
var nextIndexes = 0;
var aaa = function() {
var smallMapPosition = $("#smallMapContainer").position();
var newW = $("body").width() - 90;
var newH = $("body").height() - 90;
var newX = smallMapPosition.top + newH / 2 - 100;
var newY = smallMapPosition.left + newW / 2 - 150;
$("#smallMapContainer").velocity({
top: newX,
left: newY
}, {
duration: 500,
complete: function() {
$("#smallMapContainer").velocity({
width: newW,
height: newH,
top: smallMapPosition.top,
left: smallMapPosition.left
}, {
duration: 1000,
progress: function() {
entityMap.invalidateSize();
},
complete: function() {
if (nextIndexes++ % 2 == 0) { // with animation
entityMap.setView(L.latLng(55.751674, 37.637059), position.zoomLevel);
} else {
entityMap.setView(L.latLng(43.180176, 13.792964), position.zoomLevel);
}
$("#smallMapContainer").velocity({
width: 300,
height: 200,
top: newX,
left: newY
}, {
delay: 1000,
duration: 1000,
progress: function() {
entityMap.invalidateSize();
},
complete: function() {
$("#smallMapContainer").velocity({
top: smallMapPosition.top,
left: smallMapPosition.left
}, {
duration: 1000
});
}
});
}
});
}
});
}
aaa();
setTimeout(function() {
aaa();
}, 10000);});
openlayers
$(document).ready(function() {
var view = new ol.View({
// the view's initial state
center: ol.proj.fromLonLat([13.792964, 43.180176]),
zoom: 4
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
preload: 4,
source: new ol.source.OSM()
})
],
loadTilesWhileAnimating: true,
target: 'smallMapContainer',
controls: ol.control.defaults({
attributionOptions: ({
collapsible: false
})
}),
view: view
});
nextIndexes = 0;
var animateMap = function() {
var smallMapPosition = $("#smallMapContainer").position();
var newW = $("body").width() - 90;
var newH = $("body").height() - 90;
var newX = smallMapPosition.top + newH / 2 - 100;
var newY = smallMapPosition.left + newW / 2 - 150;
$("#smallMapContainer").velocity({
top: newX,
left: newY
}, {
duration: 500,
complete: function() {
$("#smallMapContainer").velocity({
width: newW,
height: newH,
top: smallMapPosition.top,
left: smallMapPosition.left
}, {
duration: 1000,
progress: function() {
map.updateSize();
},
complete: function() {
if (nextIndexes++ % 2 == 0) {
var pan = ol.animation.pan({
duration: 1000,
source: /** #type {ol.Coordinate} */ (view.getCenter())
});
map.beforeRender(pan);
view.setCenter(ol.proj.fromLonLat([37.637059, 55.751674]));
} else {
var pan = ol.animation.pan({
duration: 1000,
source: /** #type {ol.Coordinate} */ (view.getCenter())
});
map.beforeRender(pan);
view.setCenter(ol.proj.fromLonLat([13.792964, 43.180176]));
}
$("#smallMapContainer").velocity({
width: 300,
height: 200,
top: newX,
left: newY
}, {
delay: 1000,
duration: 1000,
progress: function() {
map.updateSize();
},
complete: function() {
$("#smallMapContainer").velocity({
top: smallMapPosition.top,
left: smallMapPosition.left
}, {
duration: 1000
});
}
});
}
});
}
});
}
animateMap();});
Disclaimer: If you're adament on using Velocity this is in no means a validate answer but i thought i'de throw it in here because i think it's unnecessary to pull in an entire animation library to accomplish something that can easily be done with standard CSS.
You can accomplish the same effect by using CSS keyframe animation, it will run much smoother than using an external animation library:
#leaflet {
width: 300px;
height: 200px;
position: absolute;
top: 55px;
left: 45px;
animation-name: move;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-direction: normal;
animation-timing-function: linear;
}
#keyframes move {
0% {
top: 55px;
left: 45px;
}
25% {
top: calc(50% - (200px / 2));
left: calc(50% - (300px / 2));
width: 300px;
height: 200px;
}
50% {
top: calc(5%);
left: calc(5%);
width: 90%;
height: 90%;
}
75% {
top: calc(50% - (200px / 2));
left: calc(50% - (300px / 2));
width: 300px;
height: 200px;
}
100% {
top: 55px;
left: 45px;
}
}
The only drawback/problem is that somehow (got to look further into this, but i'm low on time at the moment) L.Map's 'resize' event doesn't seem to fire when resizing the map container through CSS animation. So i've used ResizeSensor from CSS Element Queries to be able to call invalidateSize on the map instance when the container gets resized.
Here's a working example on Plunker: http://plnkr.co/edit/EyQFbm?p=preview