getClientBoundingRect for conditionally rendered element with animation in Svelte - svelte-3

Given conditionally rendered div with drop-down menu. In order to calculate its position (to open it to up or down) I need to get its height and width.
Of course element doesn't get correct dimensions before the transition is done.
So question is - how do I turn off transition programmatically? Or how do I get future position of element without showing it?
{#if isOpened}
<div
bind:this={thisMenu}
use:clickOutside
on:click_outside={closeHandler}
class="dropdown absolute left-100p text-gray-600 z-10 w-full animated
rounded-lg"
style={finalStyle}
{isInit ? null : transition:slide }>
<slot name="list" />
</div>
{/if}

slide-transition uses getComputedStyle, so maybe that’s what you need. The following is copied from slide function in svelte’s repository (src/runtime/transition/index.ts). Slide-function sets those values from zero to initial value and back.
const style = getComputedStyle(node);
const opacity = +style.opacity;
const height = parseFloat(style.height);
const padding_top = parseFloat(style.paddingTop);
const padding_bottom = parseFloat(style.paddingBottom);
const margin_top = parseFloat(style.marginTop);
const margin_bottom = parseFloat(style.marginBottom);
const border_top_width = parseFloat(style.borderTopWidth);
const border_bottom_width = parseFloat(style.borderBottomWidth);
EDIT:
#bobfanger explained in comments how to make a custom mySlide-function and within that function there are those initial size values available. Here is a working example:
<script>
import {slide} from "svelte/transition"
let show=false
let d
function mySlide(el) {
let s=window.getComputedStyle(d)
console.log("mySlide",s.height)
return slide(el, {duration:2000})
}
</script>
<h1 on:click={()=>show=show?false:true}>Click me</h1>
{#if show}
<div bind:this={d} transition:mySlide
style="background-color:yellow;padding:10px;border:10px solid;">
<p>test</p>
</div>
{/if}
This is much simpler than to use onMount and visibility hacks.

Related

Making an asterisk in a label red

I have the following .html markup
.html
<paper-button
raised
active
toggles
on-tap = "toggler"
class = "bold">Patient *
<iron-icon
icon = ""
id = "fe-icon"></iron-icon>
</paper-button>
</div>
How can I make the * in Patient * red without the entire label being red, and also make the asterisk larger?
Just wrap it with a <span> like >Patient <span class="asterisk">*</span></iron-icon> then you can style it individually.

jQuery animate() on Chrome 37.0.2062.120 m / Webkit?

This is my first question here on SO, so bear with me. I am developing a small project and I recently discovered one particular problem that I did not have before.
In my project I have a small map used for selection of different regions of my country, Romania. I implemented this with Raphael.js library and jQuery/UI. It looks like this:
http://s28.postimg.org/pzg3gaiod/output_Cuap_Ye.gif
The idea is when you select a region it gets dynamically coloured and added to a vector of regions. Simple. So for every region (that is declared as a path for the Raphael library to understand and paint) I have a small function:
function clickableMinimapRegions(st, regio) {
st[0].style.cursor = "pointer";
st[0].onclick = function () {
if ($.inArray(regio, regions) != -1) {
regions.splice($.inArray(regio, regions), 1);
st.animate({
fill: "#FFFFFF"
}, 0);
} else {
regions.push(regio);
st.animate({
fill: "#e6e6e6"
}, 0);
}
};
}
Then I have this HTML:
<ul class="element-menu drop-up">
<li>
<a id="toggle" class="dropdown-toggle bg-lime text-shadow button shadow">
<img src="../img/regions.png">
</a>
<div id="content" class="dropdown-menu bg-steel" data-role="dropdown">
<div id="minimap" class="minimap"></div>
</div>
</li>
</ul>
I use Metro UI CSS library, it's a simple drop-down menu. But it's behaviour is to autoclose on click. So for that I did:
$("#minimap").click(function (event) {
event.stopPropagation();
});
http://s28.postimg.org/trltqsu19/Captura3.png
This menu is at the bottom of the screen over a leaflet map, the map is the background and this drop-down is over the map. The thing is, if the map is not loaded, than it works fine. If the map tiles are loaded, something is happening that prevents the regions to be coloured when clicked.
Thank you.
SOLUTION FOUND:
Force DOM redraw/refresh on Chrome/Mac
The second parameter in jQuery's .animate() is the duration, in milliseconds. Having set it to 0, I'd rather say the behaviour you see in other browsers is wrong, and you should expect to have the property changed immediately with no animation.
st.animate({
fill: "#FFFFFF"
}, 0);
// ^---- duration
Try changing that to a bigger value (400 ms is the default)
Here's a fiddle showing the difference: http://jsfiddle.net/exrj973b/

How to programmatically clear PaperInput and have the floating label drop down to the input line

I have the following markup:
<paper-input id="alias-input" floatingLabel label="Person Alias (eg: King, Eldest Son, Mooch, etc.)"></paper-input>
<paper-input id="birth-year-input" floatingLabel label="Birth Year (eg: 1969)" validate="^[12][0-9][0-9][0-9]$"></paper-input>
<div center horizontal layout>
<paper-button id="add-button" on-click="{{addPerson}}" class="add" label="Add Person"></paper-button>
</div>
To go along with this markup I have an addButton method which does:
addPerson(_) {
// Add the person
// ...
// Clear the inputs
($['alias-input'] as PaperInput)..inputValue = ''..commit()..blur();
($['birth-year-input'] as PaperInput)..inputValue = ''..commit()..blur();
}
This correctly clears the contents of the inputs, which I want. But I also want the PaperInput help label to drop down onto the line as it is when the control is first loaded. My hope was that the call to blur() would do that. Is there some other call to achieve this?
It seems you need to call blur on the actual <input id='input'> element inside <paper-input> not the <paper-input> itself.
I got it working with
import 'dart:js' as js;
var inp = $['alias-input'] as PaperInput;
inp.inputValue = '';
new js.JsObject.fromBrowserObject(inp).callMethod('inputBlurAction', []);
alternatively you can do it like
var inp = $['alias-input'] as PaperInput;
inp.inputValue = '';
inp.querySelector('* /deep/ #input') // not yet supported with polyfills
..focus() // blur doesn't work when the field doesn't have the focus
..blur();

Get scroll position of panel using SplitView (JQuery Mobile)

I have implemented a WebApp using SplitView - http://asyraf9.github.com/jquery-mobile/ - (and that seems to use the ScrollView component) together with jQuery Mobile. Everything works fine ...
Within the panel I have got a list of elements that should dynamically add elements when scrolling reaches the end of the list. On the iPhone I do not use SplitView but iScroll - http://cubiq.org/iscroll - and the following code to achieve this (and it is working).
HTML:
<div data-role="panel" data-id="menu" data-hash="crumbs" style="z-index: 10000;" id="Panel">
<div data-role="page" id="Root" class="Login" onscroll="console.log('onscroll');">
<div data-role="content" data-theme="d" onscroll="console.log('onscroll');">
<div class="sub">
<ul data-role="listview" data-theme="d" data-dividertheme="a" class="picListview" id="PortfolioList">
<!-- Content added dynamically -->
</ul>
</div>
</div>
</div>
</div>
Javascript:
var defaultIScrollOptions = {
useTransition: true,
onScrollStart: function() {
this.refresh();
},
onScrollEnd: function() {
if (this.elem && this.id) {
possiblyDisplayNextDocuments(this.y, this.elem, this.id);
}
}
};
iScrolls.push(new iScroll(document.getElementById("searchResults").parentNode, defaultIScrollOptions));
But when using SplitView I do not really know which event and which element to bind the listener on or how to get the scroll position. I already tried several combinations, but did not achieve good results. The best one was the following:
$("#PortfolioList").scrollstop(function(event) {
console.log("scrollstop: "+$("#PortfolioList").scrollTop());
});
My question is: Am I using the right event listener (since it already fires althgough the scrolling animation is still in use) and how do I get the scroll position?
dont use the scrollview plugin. its buggy. Use iscroll for both iOS phonegap apps as well as android. It works fine on both.
For detecting the scroll and loading new elements into the list, listen to the the 'onScrollMove' event of iscroll.
In the iscroll-wrapper.js add this-
options.onScrollMove = function(){
that.triggerHandler('onScrollMove', [this]);
};
then in your code attach a event handler to the onScrollMove event and handle adding new rows in that. onScrollMove will fire whenever you scroll.
In the handler you can find how many rows are there in your list and that which row is on the top of your view port using something like
iscrollScrollEventHandler:function(event){
var contentDiv= $('div:jqmData(id="main") .ui-page-active div[data-role*="content"] ul li' );
var totalItemsonList = contentDiv.length;
var cont =$('div:jqmData(id="main") .ui-page-active div:jqmData(role="content")');
var itemToScrollOn = totalItemsonList - x; // x is the item no. from the top u want to scroll on. u need to keep updating i guess
var docViewBottom = $(cont).scrollTop() + $(cont).height();
var itemOffset = $(contentDiv[itemToScrollOn]).offset();
if(itemOffset){
var elemTop = itemOffset.top;
if (elemTop <= docViewBottom){
event.data.callback();
}
}
}
and in the callback add the code to add new rows. hope that helps.

Buttons in Jquery Ui having some problem with the change of a Label

I have a little problem, and I can't figure out where does it come from.
I'm using jQuery UI (and of course jQuery)
I have the following HTML:
<input type="checkbox" id="test" value="test"/>
<label for="test">Show Test</label>
<div id="checkedDiv"></div>
and the following JS:
function clickChange() {
var currentText = this.nextSibling.innerHTML;
this.nextSibling.innerHTML =
(this.checked) ? currentText.replace("Show","Hide") :
currentText.replace("Hide", "Show");
$("#checkedDiv").text(this.nextSibling.innerHTML);
}
var test=document.getElementById("test")
test.onclick=clickChange;
$("#test").button();
The problem is that on the first click, the innerHTML doesn't change. After that it works.
And to be a little more disappointed, the nextSibling seems to change (at least from what is seen in the #checkedDiv), but doesn't appear on the DOM Tree on firefox/firebug.
Am I missing something ?
Thanks
(if you want to try it yourself, it's here: http://jsfiddle.net/nvNKW/3/ )
EDIT:
The (or at least one) solution is to use label as suggested by Aziz Shaikh:
function clickChange() {
var currentText = $(this).button( "option","label");
$(this).button( "option","label",(this.checked)? currentText.replace("Show","Hide") : currentText.replace("Hide", "Show"));
}
And there is no need to change the html or the button initialisation.
Try setting the label using $("#test").button({ label: newText }); instead of this.nextSibling.innerHTML
Edit: So your fixed JS function would be:
function clickChange() {
var currentText = this.nextSibling.firstChild.innerHTML;
var newText = (this.checked) ? currentText.replace("Show","Hide") : currentText.replace("Hide", "Show");
$("#test").button("option", "label", newText);
$("#checkedDiv").text(this.nextSibling.innerHTML);
}
It's because nextSibling() also returns text nodes. You are changing the blank empty space after the input, not the next tag.
jQuery makes it easy, do
$(this).next('label').html()

Resources