Circular progress bar with react - reactjs

In my react app I am using a circular progress bar to show time left. The progress bar is using bootstrap 3. The code is working fine when the value is hard coded but when I give a percentage value from a state variable the progress bar is not showing. I copied this code from the net and it uses bootstrap 3. I want to use it to show reverse timer. So the percentage is 100 initially and it decreases every second. The circle shows the initial value at first but as soon as the value of percent changes the circle loses the color and shows basic gray color.
the code in render is
constructor(props){
super(props);
this.state = {
hours: 2,
min: 0,
secs: 0,
fin: false,
percent: 100
}
}
componentDidMount(){
this.myInterval = setInterval(() => {
var {hours,min,secs,fin,percent} = this.state;
if(secs > 0){
secs--;
} else {
secs = 59;
if(min > 0){
min--;
percent = Math.floor(percent - 0.8);
} else {
min = 59;
percent = Math.floor(percent - 0.8);
hours--;
if(hours < 0){
fin = true;
hours = min = secs = 0;
}
}
}
this.setState(prevState => ({
hours, min , secs , fin, percent
}))
}, 1000);
}
<div className="container">
<div className="row">
<div className="col-sm-3 col-md-2">
<div className="progress" data-percentage={this.state.percent}>
<span className="progress-left">
<span className="progress-bar"></span>
</span>
<span className="progress-right">
<span className="progress-bar"></span>
</span>
<div className="progress-value">
<div>
{this.state.hours}:{this.state.min}<br/>
<span>Time Left</span>
</div>
</div>
</div>
</div></div></div>
SASS
$borderWidth: 7px;
$animationTime: 1.5s;
$border-color-default: #eee;
$border-color-fill: #ffb43e;
$size: 150px;
//Create how many steps
$howManySteps: 10; //this needs to be even.
//for fun try using 20 and changine in the HTML the data-percentage to 15 or 85
.progress {
width: $size;
height: $size;
line-height: $size;
background: none;
margin: 0 auto;
box-shadow: none;
position: relative;
&:after {
content: "";
width: 100%;
height: 100%;
border-radius: 50%;
border: $borderWidth solid $border-color-default;
position: absolute;
top: 0;
left: 0;
}
> span {
width: 50%;
height: 100%;
overflow: hidden;
position: absolute;
top: 0;
z-index: 1;
}
.progress-left {
left: 0;
}
.progress-bar {
width: 100%;
height: 100%;
background: none;
border-width: $borderWidth;
border-style: solid;
position: absolute;
top: 0;
border-color: $border-color-fill;
}
.progress-left .progress-bar {
left: 100%;
border-top-right-radius: ($size/2);;
border-bottom-right-radius: ($size/2);;
border-left: 0;
-webkit-transform-origin: center left;
transform-origin: center left;
//animation: loading-2 1.5s linear forwards 1.8s;
}
.progress-right {
right: 0;
.progress-bar {
left: -100%;
border-top-left-radius: ($size/2);;
border-bottom-left-radius: ($size/2);;
border-right: 0;
-webkit-transform-origin: center right;
transform-origin: center right;
//animation: loading-1 1.8s linear forwards;
}
}
.progress-value {
display: flex;
border-radius: 50%;
font-size: 28px;
text-align: center;
line-height: 20px;
align-items: center;
justify-content: center;
height: 100%;
//font-family: $work-sans;
font-weight: 300;
div {
margin-top: 10px;
}
span {
font-size: 12px;
text-transform: uppercase;
}
}
}
/* This for loop creates the necessary css animation names
Due to the split circle of progress-left and progress right, we must use the animations on each side.
*/
#for $i from 1 through $howManySteps {
$stepName: ($i*(100 / $howManySteps));
//animation only the left side if below 50%
#if $i <= ($howManySteps/2) {
.progress[data-percentage="#{$stepName}"] {
.progress-right .progress-bar {
animation: loading-#{$i} $animationTime linear forwards;
}
.progress-left .progress-bar {animation: 0;}
}
}
//animation only the right side if above 50%
#if $i > ($howManySteps/2) {
.progress[data-percentage="#{$stepName}"] {
.progress-right .progress-bar {
animation: loading-#{($howManySteps/2)} $animationTime linear forwards; //set the animation to longest animation
}
.progress-left .progress-bar {
animation: loading-#{$i - ($howManySteps/2)} $animationTime linear forwards $animationTime;
}
}
}
}
//animation
#for $i from 1 through ($howManySteps/2) {
$degrees: (180/($howManySteps/2));
$degrees: ($degrees*$i);
#keyframes loading-#{$i}{
0%{
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100%{
-webkit-transform: rotate($degrees);
transform: rotate(#{$degrees}deg);
}
}
}
//additional styling
.progress {
margin-bottom: 1em;
}

Related

How to add animation on container changing its width realtime

I am making a form that expands when the user enters any character/key and gets back to its original width when there is no character left, for the plus point, I want to add animation to that expandable form so it gives a smooth look.
Here is the code and I want this action as follows
Not in React but I made an example in Vanilla JS hope it helps. I used CSS variables for changing width and making it smooth.
Instead of removing svg icons completely try scaling it down to 0 or changing it opacity to 0
const btns = Array.from(document.querySelectorAll('.btn'))
const input = document.querySelector('input')
btns.shift() // for leaving first button
input.addEventListener('input', (event) => {
btns.forEach((btn) => {
if (event.target.value.trim().length > 0) {
btn.classList.add('scale-0')
btn.parentElement.classList.add('width-50')
} else {
btn.classList.remove('scale-0')
if (btn.parentElement.classList.contains('width-50')) {
btn.parentElement.classList.remove('width-50')
}
}
})
})
#import 'https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css';
body {
display: grid;
place-items: center;
}
.row {
--column-gap: 1rem; /* 8px */
width: 100%;
display: flex;
max-width: 525px;
column-gap: var(--column-gap);
}
.row input {
flex-grow: 1;
border-radius: 100vmax;
padding: 0.75rem 1.25rem;
border: 1px solid #c1c1c1;
}
.container {
--column-gap: 0.5rem; /* 16px */
--btn-size: 3.125rem; /* 50px */
flex-shrink: 0;
display: inherit;
column-gap: var(--column-gap);
width: calc(var(--column-gap) * 3 + var(--btn-size) * 4);
transition: width 250ms ease;
}
.container.width-50 {
width: var(--btn-size);
}
.container .btn {
width: var(--btn-size);
border-radius: 50%;
aspect-ratio: 1/1;
border: 1px solid #c1c1c1;
transition: transform 250ms ease;
}
.container .btn.scale-0 {
transform: scale(0);
}
<div class="row">
<div class="container">
<button class="btn">1</button>
<button class="btn">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
</div>
<input type="text" />
</div>

Bottom navigation bar animation

I want to make it so that when you click on one of the icons, a certain strip appears under it, which will mean that the person is on this page (something like this)
At the moment, my navbar looks like this
Here's what I have at the moment (HTML):
let marker = document.querySelector('#marker');
let item = document.querySelectorAll('nav a .MuiSvgIcon-root');
function indicator(e) {
marker.style.left = e.offsetLeft + "px";
marker.style.width = e.offsetWidth + "px";
}
item.forEach(link => {
link.addEventListener('click', (e) => {
indicator(e.target)
})
})
body {
position: fixed;
bottom: 0;
left: 0;
background: #f2f2f2;
width: 100%;
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 40px;
border-top: 1px solid lightgray;
z-index: 100;
}
.MuiSvgIcon-root {
font-size: 35px;
cursor: pointer;
transition: 0.3s cubic-bezier(0.1, 0.1, 0.5, 1.4);
:hover {
transform: translateY(-5px);
}
}
#marker {
position: absolute;
height: 4px;
width: 0;
background: #000;
bottom: 8px;
left: 0;
transition: 0.5s;
border-radius: 4px;
}
<div id="marker"></div>
<HomeIcon/>
<TimelineIcon/>
<AccountCircleIcon/>
<ExploreIcon/>
.MuiSvgIcon-root there is defining all icons.
Your js code is correct. You should check your HTML and CSS. Because their structure is important

How to convert from TSX to JSX in this Codesandbox

I am learning React and JavaScript and now I have this CodeSandbox but I can't convert it to JavaScript React I have tried this for the Card Component:
import React, { useState } from "react";
const Card = props => {
const [expanded, setExpanded] = useState(false);
const RenderCard = (className) => {
return (
<div
className={`card ${className}${expanded ? " expanded" : ""}`}
onClick={() => {
setExpanded(!expanded);
}}
>
<div className="image">
<img alt="digger" src={props.image} />
</div>
<div className="info">
<div
className="bg1"
style={{ backgroundImage: "url('" + props.image + "')" }}
/>
<div
className="bg2"
style={{ backgroundImage: "url('" + props.image + "')" }}
/>
<div
className="bg3"
style={{ backgroundImage: "url('" + props.image + "')" }}
/>
<h1>JCB OES System</h1>
<h2>Report Number #1</h2>
<h3>Load lifter work area</h3>
<div className="button">Open</div>
</div>
</div>
);
};
return (
<div className={`card-container${expanded ? " expanded" : ""}`}>
{expanded && <div className="background" />}
{<RenderCard className="card1"/>}
{<RenderCard className="card2"/>}
</div>
);
};
export default Card;
And I show the Card like this. It's very simple, it's just that when I click a card it does not pop up like the CodeSandbox does.
import Card from "./Card";
import "./styles.scss";
const CreateContent = () => {
return (
<div className="app">
<link rel="stylesheet" href="https://use.typekit.net/jli8mqj.css" />
<Card image="https://www.thetimes.co.uk/imageserver/image/methode%2Fsundaytimes%2Fprodmigration%2Fweb%2Fbin%2Fbeae8dfb-0a41-4f8e-b076-ffd68417287b.jpg?crop=1024%2C683%2C0%2C0&resize=685" />
<Card image="https://www.virginexperiencedays.co.uk/content/img/product/large/PJCBRA__01.jpg" />
<Card image="https://www.toyfarmers.co.uk/images/britains-jcb-3cx-backhoe-loader.jpg" />
<Card image="https://seatylive.blob.core.windows.net/eventimages/2019-Aug-20-Tue_18-37-31-969.png" />
</div>
);
};
export default CreateContent;
The styles is the same, with no changes: I understand that the expanded background when set to expanded=true using the hook that the scss style for background should be in effect but all I get is a black screen.
.app {
font-family: sans-serif;
text-align: center;
padding: 4em 0;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
border: 0;
}
.card-container {
font-family: niveau-grotesk, sans-serif !important;
position: relative;
z-index: 0;
&.expanded {
z-index: 3;
#keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
.background {
animation: fade-in .3s ease-out;
z-index: 2;
position: fixed;
background: black;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
}
}
.card {
margin: 0 auto;
width: 25em;
cursor: pointer;
border-radius: .5em;
box-shadow: 0 50px 100px -20px rgba(50,50,93,.25),
0 30px 60px -30px rgba(0,0,0,.3),
0 -18px 60px -10px rgba(0,0,0,.03);
margin-bottom: 4em;
&.card2 {
transition: .2s ease-out;
position: absolute;
top: 0;
width: 25em;
left: 50%;
z-index: 4;
transform: translateX(-50%);
&.expanded {
width: 40em;
}
}
.image {
img {
display: block;
border-top-left-radius: .5em;
border-top-right-radius: .5em;
width: 100%;
}
}
$button-color: rgb(87, 87, 228);
&:hover {
.info .button {
color: white;
background: $button-color;
}
}
.info {
background: white;
position: relative;
border-bottom-left-radius: .5em;
border-bottom-right-radius: .5em;
overflow: hidden;
padding: .9em 1.2em;
text-align: left;
$darkness: 0;
&:after {
content: '';
position: absolute;
top: -20%;
left: -20%;
right: -20%;
bottom: -20%;
height: 140%;
width: 140%;
// filter: blur(8px);
// -webkit-filter: blur(8px);
background: linear-gradient(to right,
rgba(0, 0, 0, 0.4) 30%,
rgba(0, 0, 0, 0) 100%);
}
.bg1, .bg2 {
position: absolute;
top: -20%;
left: -20%;
right: -20%;
bottom: -20%;
height: 140%;
width: 140%;
z-index: 0;
background-position: center;
background-repeat: no-repeat;
background-size: 100%;
transform: rotate(180deg);
filter: blur(16px);
}
.bg2 {
background-position: bottom;
transform: rotate(0deg);
opacity:0.4;
}
.bg3 {
background-position: top;
transform: rotate(180deg);
opacity:0.4;
}
.button {
transition: .2s ease-out;
text-transform: uppercase;
line-height: 1.2em;
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 1.8em;
z-index: 1;
background: white;
border-radius: 1em;
padding: .4em 1.1em;
font-weight: 600;
color: $button-color;
}
h1, h2, h3 {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
max-width: 13em;
color: white;
position: relative;
z-index: 1;
text-shadow: 1px 1px 1px rgba(0,0,0,0.8);
}
h1 {
line-height: .8em;
letter-spacing: .03em;
font-size: 1.1em;
font-weight: 900;
padding: .1em 0;
}
h2 {
letter-spacing: .02em;
font-size: 1.0em;
font-weight: 400;
padding: .1em 0;
opacity: 0.6;
}
h3 {
letter-spacing: .02em;
font-size: .9em;
font-weight: 400;
padding: .1em 0;
}
}
}
}
What am I missing?
To swap your Code Sandbox from TypeScript to JavaScript you should just need to:
Remove all typescript specific syntax from your ".ts" and ".tsx" files (interfaces, typings, etc)
Change all the file extensions to their JavaScript equivalent i.e. ".ts" -> ".js" and ".tsx" -> ".jsx".
Update the "main" property of the "package.json" file to point to the renamed entry point. i.e. "src/index.jsx".
I created a quick CodeSandbox with this already done.

Fontawesome 5 SVG icons not staying inline with other elements like other icons

Weird issue with fontawesome icons and semantic UI that I can't figure out. If I use the included icons with semantic UI everything works great and displays in the proper place.
If I use the fontawesome react component the icon ends up in some seemingly random place
code sandbox show the example https://codesandbox.io/embed/semantic-ui-example-i7o3w
Any help is much appreciated
It's because font-awesome icons are unstyled SVGs while Semantic-UI looks for a styled i element to display a font specific icon via a string.
To work around it, you'll basically have to do something like this:
<Search
value="FA comp - broken"
icon={
<i className="icon">
<FontAwesomeIcon
style={{ marginTop: 13 }} // alternatively you can do: position: "relative", top: 13
icon="thumbs-down"
/>
</i>
}
/>
Semantic-UI specifically looks for an i.icon element + classname to add styles to it: .ui.icon.input > i.icon. One of the many downsides of using a UI framework is that you're forced to work within its confined architecture.
As follow up to Matt's great help - I dug in to the semantic-ui LESS library and figured out the overrides needed for fontawesome to behave pretty well with it.
here are the icon.overrides and input.overrides with a few notes that are needed for fontawesome to behave nicely.
With the newest fontawesome version (5.10.2) the sizing issues are generally addressed in-library so most display issues that I previous encountered are not a problem.
/* site/elements/input.overrides */
/* just the overrides to replace i for ANYTHING icon so we can use font awesome
semantic always assumes the icon is ONLY an i - that's it - we so far have a link / an A and a span and an svg element
for semantic - SO I'm just going to pull out all the hardcodes and just go with .icon and see how that behaves
just make sure the top level element for the 'icon' has the class 'icon' and you *should* be good don't put icon on every
child element - or rather you don't have to...
SVGs get squared nicely - anything else will need moving
*/
/*--------------------
Loading
---------------------*/
.ui.loading.loading.input > .icon:before {
position: absolute;
content: '';
top: 50%;
left: 50%;
margin: #loaderMargin;
width: #loaderSize;
height: #loaderSize;
border-radius: #circularRadius;
border: #loaderLineWidth solid #loaderFillColor;
}
.ui.loading.loading.input > .icon:after {
position: absolute;
content: '';
top: 50%;
left: 50%;
margin: #loaderMargin;
width: #loaderSize;
height: #loaderSize;
animation: button-spin #loaderSpeed linear;
animation-iteration-count: infinite;
border-radius: #circularRadius;
border-color: #loaderLineColor transparent transparent;
border-style: solid;
border-width: #loaderLineWidth;
box-shadow: 0px 0px 0px 1px transparent;
}
/* Transparent Icon */
.ui.transparent.icon.input > .icon {
width: #transparentIconWidth;
}
/*--------------------
Icon
---------------------*/
.ui.icon.input > .icon {
cursor: default;
position: absolute;
line-height: 1;
text-align: center;
top: 0px;
right: 0px;
margin: 0em;
height: 100%;
width: #iconWidth;
opacity: #iconOpacity;
border-radius: 0em #borderRadius #borderRadius 0em;
transition: #iconTransition;
}
.ui.icon.input > .icon:not(.link) {
pointer-events: none;
}
.ui.icon.input > .icon:before,
.ui.icon.input > .icon:after {
left: 0;
position: absolute;
text-align: center;
top: 50%;
width: 100%;
margin-top: #iconOffset;
}
.ui.icon.input > .link.icon {
cursor: pointer;
}
.ui.icon.input > .circular.icon {
top: #circularIconVerticalOffset;
right: #circularIconHorizontalOffset;
}
/* Left Icon Input */
.ui[class*="left icon"].input > .icon {
right: auto;
left: #borderWidth;
border-radius: #borderRadius 0em 0em #borderRadius;
}
.ui[class*="left icon"].input > .circular.icon {
right: auto;
left: #circularIconHorizontalOffset;
}
/* Focus */
.ui.icon.input > input:focus ~ .icon {
opacity: 1;
}
/* site/elements/icon.overrides */
/*!
refactored these to be a svg rather than i . so they can be svg icons for font awesome
straight copy and paste from https://github.com/Semantic-Org/Semantic-UI-LESS/blob/master/definitions/elements/icon.less
regex find and replace find: \ni. replace \nsvg.
DO NOT COPY THE LAST LINE OF THE FILE - otherwise you'll end up in an endless loop compiling
also don't copy the theme section - it's unneeded
*/
svg.icon {
display: inline-block;
opacity: #opacity;
margin: 0em #distanceFromText 0em 0em;
width: #width;
height: 100%;
font-family: 'Icons';
font-style: normal;
font-weight: #normal;
text-decoration: inherit;
text-align: center;
speak: none;
font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
backface-visibility: hidden;
}
svg.icon:before {
background: none !important;
}
/*******************************
Types
*******************************/
/*--------------
Loading
---------------*/
svg.icon.loading {
height: 1em;
line-height: 1;
animation: icon-loading #loadingDuration linear infinite;
}
#keyframes icon-loading {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/*******************************
States
*******************************/
svg.icon.hover {
opacity: 1 !important;
}
svg.icon.active {
opacity: 1 !important;
}
svg.emphasized.icon {
opacity: 1 !important;
}
svg.disabled.icon {
opacity: #disabledOpacity !important;
}
/*******************************
Variations
*******************************/
/*-------------------
Fitted
--------------------*/
svg.fitted.icon {
width: auto;
margin: 0em !important;
}
/*-------------------
Link
--------------------*/
svg.link.icon, svg.link.icons {
cursor: pointer;
opacity: #linkOpacity;
transition: opacity #defaultDuration #defaultEasing;
}
svg.link.icon:hover, svg.link.icons:hover {
opacity: 1 !important;
}
/*-------------------
Circular
--------------------*/
svg.circular.icon {
border-radius: 500em !important;
line-height: 1 !important;
padding: #circularPadding !important;
box-shadow: #circularShadow;
width: #circularSize !important;
height: #circularSize !important;
}
svg.circular.inverted.icon {
border: none;
box-shadow: none;
}
/*-------------------
Flipped
--------------------*/
svg.flipped.icon,
svg.horizontally.flipped.icon {
transform: scale(-1, 1);
}
svg.vertically.flipped.icon {
transform: scale(1, -1);
}
/*-------------------
Rotated
--------------------*/
svg.rotated.icon,
svg.right.rotated.icon,
svg.clockwise.rotated.icon {
transform: rotate(90deg);
}
svg.left.rotated.icon,
svg.counterclockwise.rotated.icon {
transform: rotate(-90deg);
}
/*-------------------
Bordered
--------------------*/
svg.bordered.icon {
line-height: 1;
vertical-align: baseline;
width: #borderedSize;
height: #borderedSize;
padding: #borderedVerticalPadding #borderedHorizontalPadding !important;
box-shadow: #borderedShadow;
}
svg.bordered.inverted.icon {
border: none;
box-shadow: none;
}
/*-------------------
Inverted
--------------------*/
/* Inverted Shapes */
svg.inverted.bordered.icon,
svg.inverted.circular.icon {
background-color: #black !important;
color: #white !important;
}
svg.inverted.icon {
color: #white;
}
/*-------------------
Colors
--------------------*/
/* Red */
svg.red.icon {
color: #red !important;
}
svg.inverted.red.icon {
color: #lightRed !important;
}
svg.inverted.bordered.red.icon,
svg.inverted.circular.red.icon {
background-color: #red !important;
color: #white !important;
}
/* Orange */
svg.orange.icon {
color: #orange !important;
}
svg.inverted.orange.icon {
color: #lightOrange !important;
}
svg.inverted.bordered.orange.icon,
svg.inverted.circular.orange.icon {
background-color: #orange !important;
color: #white !important;
}
/* Yellow */
svg.yellow.icon {
color: #yellow !important;
}
svg.inverted.yellow.icon {
color: #lightYellow !important;
}
svg.inverted.bordered.yellow.icon,
svg.inverted.circular.yellow.icon {
background-color: #yellow !important;
color: #white !important;
}
/* Olive */
svg.olive.icon {
color: #olive !important;
}
svg.inverted.olive.icon {
color: #lightOlive !important;
}
svg.inverted.bordered.olive.icon,
svg.inverted.circular.olive.icon {
background-color: #olive !important;
color: #white !important;
}
/* Green */
svg.green.icon {
color: #green !important;
}
svg.inverted.green.icon {
color: #lightGreen !important;
}
svg.inverted.bordered.green.icon,
svg.inverted.circular.green.icon {
background-color: #green !important;
color: #white !important;
}
/* Teal */
svg.teal.icon {
color: #teal !important;
}
svg.inverted.teal.icon {
color: #lightTeal !important;
}
svg.inverted.bordered.teal.icon,
svg.inverted.circular.teal.icon {
background-color: #teal !important;
color: #white !important;
}
/* Blue */
svg.blue.icon {
color: #blue !important;
}
svg.inverted.blue.icon {
color: #lightBlue !important;
}
svg.inverted.bordered.blue.icon,
svg.inverted.circular.blue.icon {
background-color: #blue !important;
color: #white !important;
}
/* Violet */
svg.violet.icon {
color: #violet !important;
}
svg.inverted.violet.icon {
color: #lightViolet !important;
}
svg.inverted.bordered.violet.icon,
svg.inverted.circular.violet.icon {
background-color: #violet !important;
color: #white !important;
}
/* Purple */
svg.purple.icon {
color: #purple !important;
}
svg.inverted.purple.icon {
color: #lightPurple !important;
}
svg.inverted.bordered.purple.icon,
svg.inverted.circular.purple.icon {
background-color: #purple !important;
color: #white !important;
}
/* Pink */
svg.pink.icon {
color: #pink !important;
}
svg.inverted.pink.icon {
color: #lightPink !important;
}
svg.inverted.bordered.pink.icon,
svg.inverted.circular.pink.icon {
background-color: #pink !important;
color: #white !important;
}
/* Brown */
svg.brown.icon {
color: #brown !important;
}
svg.inverted.brown.icon {
color: #lightBrown !important;
}
svg.inverted.bordered.brown.icon,
svg.inverted.circular.brown.icon {
background-color: #brown !important;
color: #white !important;
}
/* Grey */
svg.grey.icon {
color: #grey !important;
}
svg.inverted.grey.icon {
color: #lightGrey !important;
}
svg.inverted.bordered.grey.icon,
svg.inverted.circular.grey.icon {
background-color: #grey !important;
color: #white !important;
}
/* Black */
svg.black.icon {
color: #black !important;
}
svg.inverted.black.icon {
color: #lightBlack !important;
}
svg.inverted.bordered.black.icon,
svg.inverted.circular.black.icon {
background-color: #black !important;
color: #white !important;
}
/*-------------------
Sizes
--------------------*/
svg.mini.icon,
svg.mini.icons {
line-height: 1;
font-size: #mini;
}
svg.tiny.icon,
svg.tiny.icons {
line-height: 1;
font-size: #tiny;
}
svg.small.icon,
svg.small.icons {
line-height: 1;
font-size: #small;
}
svg.icon,
svg.icons {
font-size: #medium;
}
svg.large.icon,
svg.large.icons {
line-height: 1;
vertical-align: middle;
font-size: #large;
}
svg.big.icon,
svg.big.icons {
line-height: 1;
vertical-align: middle;
font-size: #big;
}
svg.huge.icon,
svg.huge.icons {
line-height: 1;
vertical-align: middle;
font-size: #huge;
}
svg.massive.icon,
svg.massive.icons {
line-height: 1;
vertical-align: middle;
font-size: #massive;
}
/*******************************
Groups
*******************************/
svg.icons {
display: inline-block;
position: relative;
line-height: 1;
}
svg.icons .icon {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
margin: 0em;
margin: 0;
}
svg.icons .icon:first-child {
position: static;
width: auto;
/* height: auto; */
vertical-align: top;
transform: none;
margin-right: #distanceFromText;
}
/* Corner Icon */
svg.icons .corner.icon {
top: auto;
left: auto;
right: 0;
bottom: 0;
transform: none;
font-size: #cornerIconSize;
text-shadow: #cornerIconShadow;
}
svg.icons .top.right.corner.icon {
top: 0;
left: auto;
right: 0;
bottom: auto;
}
svg.icons .top.left.corner.icon {
top: 0;
left: 0;
right: auto;
bottom: auto;
}
svg.icons .bottom.left.corner.icon {
top: auto;
left: 0;
right: auto;
bottom: 0;
}
svg.icons .bottom.right.corner.icon {
top: auto;
left: auto;
right: 0;
bottom: 0;
}
svg.icons .inverted.corner.icon {
text-shadow: #cornerIconInvertedShadow;
}

Left hand side and right hand side listboxes with add one, add all, remove one, remove all buttons in the middle

I have a left-hand side (lhs) list box and right-hand side (rhs) list box I want to be able to select items in the lhs listbox and add one or all of them to the rhs listbox. Then I'd also like a remove one or all from the rhs returning them to the lhs. How would I accomplish this? So far, I can only manage getting the index value of the lhs box to the right but it won't take the actual item name for some reason. This is the code that does that:
private void SelectOne_Click(object sender, RoutedEventArgs e)
{
listBoxFin.ItemsSource = listBoxStart.SelectedIndex.ToString();
}
Hi this is not the final solution but this will help you lot.
Working DEMO.
HTML
<div class="wrapper">
<div class="selectbox alignleft">
<ul id="selection" class="cf">
<li>One <span class="desc">Description</span></li>
<li>...</li>
<li>...</li>
</ul>
</div>
<div class="movebutton alignleft">
<input class="button mover" value=">>" type="button" />
</div>
<div id="moving" class="movebox alignleft">
<ul class="cf">
<li>One <span class="desc">Description</span>
</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</div>
<div class="alignleft">
<input class="button" id="move-up" type="button" value="Up" />
<input class="button" id="move-down" type="button" value="Down" />
</div>
CSS
.cf:before, .cf:after {
content:"";
display: table;
}
.cf:after {
clear: both;
}
/* For IE 6/7 (trigger hasLayout) */
.cf {
zoom: 1;
}
/* general purpose classes */
.nodisplay {
display: none;
}
.nodisplay_strict {
display: none !important;
}
.alignleft {
float: left;
}
.alignright {
float: right;
}
.button {
cursor: pointer;
background: #eee;
border: 0;
min-width: 116px;
padding: 5px 0;
margin-bottom: 2px;
display: block;
}
body {
padding: 25px;
font-family:Verdana, Geneva, sans-serif;
font-size: 12px;
}
li {
display: block;
cursor: pointer;
padding: 5px;
font-weight: bold;
position: relative;
border-bottom: 1px solid #fff;
}
li.active {
background: #000;
color: #fff;
}
.wrapper {
width: 960px;
margin: 0 auto;
}
.selectbox {
border: 1px solid;
width: 150px;
min-height: 199px;
max-height: 199px;
overflow-y: auto;
position: relative;
}
.movebox {
border: 1px solid;
width: 200px;
min-height: 199px;
max-height: 199px;
overflow-y: auto;
position:relative;
margin-left: 10px;
margin-right: 10px;
}
span.desc {
display: block;
padding-top: 5px;
color: #7a7a7a;
font-weight: normal;
font-style: italic;
}
li.active span.desc {
color: #ccc;
}
.movebox .delete, .movebox .unmoved {
display: inline-block;
position: absolute;
right: 5px;
top: 5px;
z-index: 999;
background:url(icon-close.png) no-repeat 0 0 red;
width: 10px;
height: 10px;
text-indent: -99999px;
}
.movebutton {
margin-left: 10px;
}
.movebutton .mover {
background: url(icon_right.png) no-repeat 0 0 #eee;
height: 48px;
margin: 65px auto 0;
min-width: 0;
text-align: center;
width: 48px;
}
.moved {
background: #d9fffe;
}
#move-up {
background: url("icon_up.png") no-repeat 0 0 #eee;
height: 48px;
margin: 0px auto 0;
min-width: 0;
text-align: center;
width: 48px;
}
#move-down {
background: url("icon_down.png") no-repeat 0 0 #eee;
height: 48px;
margin: 15px auto 0;
min-width: 0;
text-align: center;
width: 48px;
}
JavaScript
// JavaScript Document
$(document).ready(function (e) {
$('.selectbox li, .movebox li').click(function () {
$(this).addClass('active').siblings().removeClass('active');
});
$('.mover').click(function () {
$('.selectbox li.active').addClass('moved').prependTo('.movebox ul').prepend('<span class="delete alignright" onclick="moveToLHS(this);">DELETE</span>');
});
$('.mover').click(function () {
$('.selectbox li.active').addClass('moved');
$('.movebox li.active').removeClass('active');
setTimeout(function () {
$('.movebox li').removeClass('moved');
}, 1500);
});
$('.movebox ul li').each(function () {
$(this).prepend('<span class="unmoved alignright" onclick="deleteFromRHS(this);">DELETE</span>');
});
$("#move-up").click(moveUp);
$("#move-down").click(moveDown);
$("#reset-list").click(resetList);
});
//DELETE
function moveToLHS(t) {
$(t).parent().remove().prependTo('.selectbox ul');
$('.selectbox li').click(function () {
$(this).addClass('active').siblings().removeClass('active');
});
//deleting span
$('.selectbox ul li .delete').each(function () {
$(this).remove();
});
}
function deleteFromRHS(d) {
$(d).parent().remove();
}
// LI Up Down
function moveUp() {
$("#moving li.active").each(function () {
var listItem = $(this);
var listItemPosition = $("#moving li").index(listItem) + 1;
if (listItemPosition == 1) return false;
listItem.insertBefore(listItem.prev());
});
}
function moveDown() {
var itemsCount = $("#moving li").length;
$($("#moving li.active").get().reverse()).each(function () {
var listItem = $(this);
var listItemPosition = $("#moving li").index(listItem) + 1;
if (listItemPosition == itemsCount) return false;
listItem.insertAfter(listItem.next());
});
}
function resetList() {
$("#moving").html(originalItems);
}
Working DEMO
As H.B. noted, there are many ways this could be accomplished. Probably the most widely acclaimed architecture for WPF is MVVM, so I'll try to outline a solution with respect to my understanding of that architecture.
The ViewModel will expose a few different properties: LHSList, LHSSelectedItem, RHSList, RHSSelectedItem (collections are ObservableCollections here) as well as a few commands - MoveLHSSelectedToRHS, MoveLHSToRHS, MoveRHSSelectedToRHS, MoveRHSToLHS.
The lists are simple bindings to the ListViews in the View, and the SelectedItem's of those ListViews are also bound accordingly. The commands simply operate on the lists and the selected items. For example, MoveLHSSelectedToRHS would be a command with an action something like:
public void OnMoveLHSSelectedToRHS()
{
if(LHSSelectedItem==null)
return;
RHSList.Add(LHSSelectedItem);
LHSList.Remove(LHSSelectedItem);
LHSSelectedItem=null;
}
Unfortunately, it looks like you are using code behind at the moment. If you are not familiar with MVVM, I'd suggest looking into Josh Smith's WPF articles - they're a great place to start!

Resources