CSS Sliding views with ui-router - angularjs

I am trying to achieve the same effect of sliding in/out views as found here:
http://dfsq.github.io/ngView-animation-effects/app/#/page/1
Ive created a plunker: http://plnkr.co/edit/ST49iozWWtYRYRdcGGQL?p=preview
But my entire ui-view completely disappears when i copy the CSS from the link above and think it could be down to the position: relative in my container
CSS:
*,
*:after,
*:before {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
font-size: 62.5%;
min-height: 100%;
position: relative;
}
html body {
font-size: 140%;
line-height: 1.5;
margin: 0;
padding: 0 0;
margin-bottom: 60px;
}
.container {
max-width: 430px;
margin: 0 auto;
position: relative;
display: block;
float: none;
overflow: hidden;
}
.l-one-whole {
width: 100%;
}
form {
background: #f0f0f0;
height: 350px;
padding: 10px;
font-size: 1.4em;
}
CSS needed to add:
.slide {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.slide.ng-enter,
.slide.ng-leave {
-webkit-transition: all 1s ease;
transition: all 1s ease;
}
.slide.ng-enter {
left: 100%;
}
.slide.ng-enter-active {
left: 0;
}
.slide.ng-leave {
left: 0;
}
.slide.ng-leave-active {
left: -100%;
}
HTML:
<body ng-controller="MainCtrl">
<ul>
<li>view1
</li>
<li>view2
</li>
</ul>
<main class="l-one-whole">
<section class="container">
<article class="l-one-whole">
<div ui-view class="slide"></div>
</article>
</section>
</main>
</body>
JS:
var app = angular.module('plunker', ['ui.router', 'ngAnimate']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('view1', {
url: '/view1',
templateUrl: 'page1.html'
})
.state('view2', {
url: '/view2',
templateUrl: 'page2.html'
});
$urlRouterProvider.otherwise('/view1');
});
Any help appreciated.

I think this is what you are looking for: Plunkr
I added the following styles to make animations work:
/* Transition effects */
.l-one-whole {
position: relative;
overflow: hidden;
min-height: 400px;
}
.slide {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.slide.ng-enter,
.slide.ng-leave {
transition: all 1s ease;
}
.slide.ng-enter {
transform: translate(100%, 0);
}
.slide.ng-enter-active {
transform: translate(0, 0);
}
.slide.ng-leave {
transform: translate(0, 0);
}
.slide.ng-leave-active {
transform: translate(-100%, 0);
}
I used transform instead of left because AFAIK it enables browser to accelerate animation using GPU increasing performance.
I hope I am not missing anything.

Result: http://plnkr.co/edit/vhGSiA?p=preview
I have use Angular 1.3.15 instead of 1.2.9
Simplified HTML
<section class="container">
<div ui-view class="slide-left"></div>
</section>
and more CSS
.container {
overflow: hidden;
position: relative;
}
.slide-left.ng-enter, .slide-left.ng-leave {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
transition: transform .7s ease-in-out;
}
.slide-left.ng-enter {
z-index: 101;
transform: translateX(100%);
}
.slide-left.ng-enter.ng-enter-active {
transform: translateX(0);
}
.slide-left.ng-leave {
z-index: 100;
transform: translateX(0);
}
.slide-left.ng-leave.ng-leave-active {
transform: translateX(-100%);
}
form { /* contents within ui-view */
position:absolute;
}

Change
<script src="https://raw.github.com/dlukez/ui-router/angular-1.2/release/angular-ui-router.js"></script>
to:
<script src="https://cdn.rawgit.com/dlukez/ui-router/angular-1.2/release/angular-ui-router.js"></script>
Updated plnkr
Detail explaination can be found here:
Link and execute external JavaScript file hosted on GitHub

Related

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.

Circular progress bar with react

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;
}

Animating movement of other items in ng-repeat with ngAnimate

Sorry for the vague title, but I couldn't find a fitting short description.
So, I have a list of different items which I'm using ng-repeat to show. Some of them might be removed or added to that list.
I'm using ng-enter etc to animate the transition of the items entering and exiting the view. The problem is, the rest of the items, the ones that are not being added or removed, look like they hop and skip around instead of flowing naturally when items between them are being removed or added.
I made a codepen:
If you click any of the players, you remove them. Click reset to bring them back in. If you remove any of the players in the middle, you can see they jump to the left instantly after the removed item is done with its animation. I would like it to slide over to it's new position instead.
http://codepen.io/utrolig/pen/oxQVVZ
HTML:
<div ng-app="test">
<div ng-controller="AnimateController as vm">
<div class="player" ng-repeat="player in vm.items" ng-click="vm.toggleActiveState(player)" ng-if="player.active">
<div class="imgcont">
<img ng-src="{{player.img}}" />
<div class="jerseyno">
<span>#{{::player.jerseyNumber}}</span>
</div>
</div>
<div class="playername">
<span ng-bind="::player.name"></span>
</div>
</div>
<div class="resetbutton" ng-click="vm.resetActiveState(vm.players)">
<span>Reset</span>
</div>
</div>
</div>
JS:
(function(){
'use strict';
angular
.module('test', ['ngAnimate'])
.controller('AnimateController', AnimateController);
function AnimateController(){
var vm = this;
vm.toggleActiveState = toggleActiveState;
vm.resetActiveState = resetActiveState;
vm.items = [
{
name: "Pavel Bure",
active: true,
team: "Vancouver Canucks",
jerseyNumber: 10,
img: "https://nhl.bamcontent.com/images/headshots/current/168x168/8455738.jpg"
},{
name: "Wayne Gretzky",
jerseyNumber: 99,
active: true,
team: "Vancouver Canucks",
img: "https://nhl.bamcontent.com/images/headshots/current/168x168/8447400.jpg"
},{
name: "Jaromir Jagr",
jerseyNumber: 68,
active: true,
team: "Florida Panthers",
img: "https://nhl.bamcontent.com/images/headshots/current/168x168/8448208.jpg"
},{
name: "Mats Zuccarello",
jerseyNumber: 36,
active: true,
team: "New York Rangers",
img:"https://nhl.bamcontent.com/images/headshots/current/168x168/8475692.jpg"
}
];
//////////////
function toggleActiveState(item){
item.active = item.active ? false : true;
}
function resetActiveState(arr){
for (var i = 0; i < vm.items.length; i++){
vm.items[i].active = true;
}
}
}
})();
CSS:
body, html {
min-height: 100vh;
position: relative;
font-family: 'Arial', sans-serif;
background: #1d1f20;
color: rgba(255,255,255,0.7)
}
.imgcont {
border-radius: 8px;
}
.imgcont img {
border-radius: 8px;
}
.jerseyno {
position: absolute;
top: 6px;
right: 6px;
padding: 4px;
background: rgba(0,0,0,.75);
border-radius: 4px;
}
.resetbutton {
display: block;
float: left;
border-radius: 4px;
margin: 24px;
padding: 24px;
background: rgba(0,0,0,.5);
cursor: pointer;
}
.playername {
position: absolute;
bottom: 6px;
left: 6px;
background: rgba(0,0,0,.75);
padding: 4px;
border-radius: 4px;
}
.player {
float: left;
margin-right: 12px;
position: relative;
cursor: hand;
cursor: pointer;
transition: .5s all;
}
.player.ng-enter {
opacity: 0;
transform: translateY(-50%);
}
.player.ng-enter-active {
opacity: 1;
transform: translateY(0%);
}
.player.ng-leave-active {
opacity: 0;
transform: translateY(-50%);
}
Thanks!

ng-click not working in AngularJS, Cordova

We are writing an application in Ionic, Cordova, AngularJS.
My code is here https://jsfiddle.net/sweety1112/wag7ye4b/1/
My problem is that ui-sref or ng-click is not working as expected. Are there any errors?
$stateProvider
.state('app', {
url: '',
abstract: true,
templateUrl: 'HomePage.html'
})
.state('app.home', {
url: '/home',
templateUrl:'templates/HomeScreen.html',
controller: 'HomePageCtrl'
})
.state('app.scan',
{ parent:'app',
url: '/scan',
templateUrl: 'templates/Scan.html'
// controller: 'SettingsController'
})
.state('app.help', {
url: '/help',
templateUrl:'templates/Help.html'
})
In HTML i have
$scope.funOne=function(){
alert("Button Clicked"); };
Then this should be called from the html
<div> <br/><br/><br/><br/><br/><br/><div ng-click="funOne()"><h1> Home Screen</h1> </div>
<div class="centerButton" ng-click="funOne()">
<a ui-href="app.help"> <img src='assets/img/start_btn.png'/> </a>
<p>START</p>
</div>
ng-click is working from the div which has Home Screen but it is not working on Image. Even ui-sref is not working on the image.
Updated the fiddle with the css classes as well changed the ng-click position. Your css is conflicting with the ng-click and hence needs to be at the parent level.
Updated Fiddle
Css Changed:
.bar-positive {
background-color: #C12537;
border: none;
}
.container {
width:550px;
height:550px;
position:relative;
z-index: -1;
display:block;
}
.container .left, .right div p {
top: 44%;
left: -14%;
}
.container .right {
transform: rotate(90deg);
}
.rotate div p {
position:absolute;
margin:0;
padding:0;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
top:27%;
left:20%;
}
.text {
transform: rotate(360deg);
}
.container img {
position:absolute;
}
.rotate img {
width:100%;
/*-webkit-transform-origin: 70% 105%;*/
z-index: -1;
position:relative;
}
.rotate {
width:72%;
transition: transform 0.5s linear;
transform-origin: 70% 105%;
position:absolute;
}
.bottom img {
/*-webkit-transform: rotate(180deg);*/
z-index: -1;
margin-top: 308px;
margin-left: 141px;
transform: rotate(180deg);
}
.left img {
transform: rotate(270deg);
z-index: -1;
}
.right img {
/*-webkit-transform: rotate(90deg);*/
z-index: -1;
}
.rotate.right div p {
top:22%;
left:9%;
transform: rotate(270deg);
}
.rotate.bottom div p {
position: absolute;
margin: 0;
padding: 0;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
top: 79%;
left: 100%;
}
.rotate.left div p {
top:78%;
left:26%;
transform: rotate(360deg);
}
/*New style**/
.rotate div {
position: absolute;
padding:0;
margin:0;
width:100%;
height:100%;
left:0;
right:0;
top:0;
bottom:0;
transition: transform 0.5s linear;
}
.flex-container {
height: 100%;
padding: 0;
margin: 0;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.centerButton img, .centerButton p {
position:absolute;
width:100%;
top:-50%;
left:-50%;
right:-50%;
bottom:-50%;
margin:auto;
}
.centerButton p {
height:10%;
text-align:center;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
}
.centerButton {
width:50%;
height:50%;
margin:auto;
position:absolute;
top:-45%;
left:-50%;
right:-52%;
bottom:-50%;
}
UPDATE:
Your z-index in the css class was giving the issue. Corrected that in the updated fiddle
CSS for reference:
.bar-positive {
background-color: #C12537;
border: none;
}
.container {
width:550px;
height:550px;
position:relative;
z-index: 9999;
display:block;
}
.container .left, .right div p {
top: 44%;
left: -14%;
}
.container .right {
transform: rotate(90deg);
}
.rotate div p {
position:absolute;
margin:0;
padding:0;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
top:27%;
left:20%;
}
.text {
transform: rotate(360deg);
}
.container img {
position:absolute;
}
.rotate img {
width:100%;
/*-webkit-transform-origin: 70% 105%;*/
z-index: 9999;
position:relative;
}
.rotate p {
z-index:9999;
}
.rotate {
width:72%;
transition: transform 0.5s linear;
transform-origin: 70% 105%;
position:absolute;
}
.bottom img {
/*-webkit-transform: rotate(180deg);*/
z-index: 9999;
margin-top: 308px;
margin-left: 141px;
transform: rotate(180deg);
}
.left img {
transform: rotate(270deg);
z-index: 9999;
}
.right img {
/*-webkit-transform: rotate(90deg);*/
z-index: 9999;
}
.rotate.right div p {
top:22%;
left:9%;
transform: rotate(270deg);
}
.rotate.bottom div p {
position: absolute;
margin: 0;
padding: 0;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
top: 79%;
left: 100%;
}
.rotate.left div p {
top:78%;
left:26%;
transform: rotate(360deg);
}
/*New style**/
.rotate div {
position: absolute;
padding:0;
margin:0;
width:100%;
height:100%;
left:0;
right:0;
top:0;
bottom:0;
transition: transform 0.5s linear;
}
.flex-container {
height: 100%;
padding: 0;
margin: 0;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.centerButton img, .centerButton p {
position:absolute;
width:100%;
top:-50%;
left:-50%;
right:-50%;
bottom:-50%;
margin:auto;
}
.centerButton p {
height:10%;
text-align:center;
font-family:'Roboto';
font-size: 22px;
color: #FFFFFF;
}
.centerButton {
width:50%;
height:50%;
margin:auto;
position:absolute;
top:-45%;
left:-50%;
right:-52%;
bottom:-50%;
}

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