How to make Airbnb's carousel indicators in Blazor - css

I have a carousel where an arbitrary number of images can be shown.
It currently looks like below, where the problem is that the amount carousel indicators quickly gets out of hand.
I want to try to do something similar to how Airbnb has it, where it only shows a maximum of 5 dots at any given time. I found an example of an implementation of this on codesandbox, but I'm using Blazor and not React, making it kind of hard to directly translate it.
To show what I'm talking about, their carousel looks like this
My current implementation in Blazor looks like his
<span class="progress-dots">
#for (int i = 0; i < Imgs.Count; i++)
{
<span class='progress-dot #( currentImage == i ? "active" : "")'></span>
}
</span>
where currentImage is just tracking the index of the active image. This just couples with some simple css to show which one is active.
.progress-dots {
position: absolute;
bottom: 5px;
left: 5px;
right: 5px;
display: flex;
justify-content: center;
span.progress-dot {
width: 0.45rem;
height: 0.45rem;
border-radius: 50%;
background: rgba(174, 174, 174, 0.453);
margin: 0.2rem 0.15rem;
&.active {
background: #FFF;
}
}
}
Here is a Blazor repl with a stripped down version of my own implementation to test how it works.

You want to take into account the edge cases. The solution I am giving can probably be improved or cleaner, I just focused on a working example.
<div class="img-container">
<span class="progress-dots">
#{
int imgIncMin = 0;
int imgIncMax = Imgs.Count;
int dotsDisplayed = DotsDisplayedAround * 2 + 1;
if(Imgs.Count > dotsDisplayed){
if(currentImage < DotsDisplayedAround){
imgIncMin = 0;
imgIncMax = dotsDisplayed;
}
else if(currentImage + DotsDisplayedAround >= Imgs.Count){
imgIncMin = Imgs.Count - dotsDisplayed;
imgIncMax = Imgs.Count;
}
else{
imgIncMin = currentImage - DotsDisplayedAround;
imgIncMax = currentImage + DotsDisplayedAround + 1;
}
}
}
#for (int i = imgIncMin; i < imgIncMax; i++)
{
<span class='progress-dot #( currentImage == i ? "active" : "")'></span>
}
</span>
</div>
<div class="btn btn-dark" #onclick='() => { currentImage = currentImage - 1 >= 0 ? currentImage - 1 : Imgs.Count - 1 ; }'>Previous</div>
<div class="btn btn-dark" #onclick='() => { currentImage = (currentImage + 1) % Imgs.Count; }'>Next</div>
#code {
const int DotsDisplayedAround = 2;
int currentImage = 0;
List<string> Imgs = new List<string>() { "", "", "", "", "", "", ""};
}
Blazor repl

Related

transition for translateY(0) working, but not translateY(-50px)

I'm having some trouble with a transition on a transform. I'm making a tic-tac-toe game like in the freecodecamp front-end challenges: https://codepen.io/freeCodeCamp/full/KzXQgy.
I've been able to create most layout things no problem, but am having an issue with my transition on a div that shows which players' turn it is after hitting the reset button. Right now I'm just working on two player mode, so I click two players, then X or O, and then the tic-tac-toe board shows up and a div transform: translateY(-50px) to indicate whether it's Player 1 or Player 2's turn (based on a random number variable I set up). The first time through the div transition's perfectly. Then I hit the Reset All div and it takes me back to the beginning to choose how many players again. And the div transitions the transform: translateY(0) perfectly back to it's starting position. Where I'm struggling is, now when I cycle through the options again, if it's Player 1 or Player 2's turn again, the transition never happens and the div just transforms -50px up with the translateY.
I've tried everything I could think of, JS setting up the transition, resetting the transition, moving the transition to be on different classes, adding and removing a class that only has a transition on it. Can't figure it out, but the weird thing is, whenever I hit the "Reset All", the transform transitions back to 0px normally. Here's my codepen: https://codepen.io/rorschach1234/pen/dZMaJg?editors=0111. I know it's still very rough, but just can't figure out this transition problem. Really appreciate any help. Thanks everyone!
My relevant Html:
<div class="container">
<div class="turns">
<div class="turns__left turns__box"></div>
<div class="turns__right turns__box"></div>
</div>
</div>
My relevant CSS:
.turns {
width: 100%;
display: flex;
position: absolute;
justify-content: space-around;
top: 0;
left: 0;
z-index: -1;
&__box {
width: 40%;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 1.3em;
font-family: sans-serif;
transition: transform 1s .3s ease;
}
&__left {
background-color: $color-turn-left;
//transition: transform 1s .3s ease;
}
&__right {
background-color: $color-turn-right;
//transition: transform 1s .3s ease;
}
}
My Javascript:
let numOfPlayers = document.querySelectorAll(".player .choices h2");
let playerScreen = document.querySelector(".player");
let markerScreen = document.querySelector(".markers");
let singlePlayer = true;
let backBtn = document.querySelector(".markers__back");
let gameScreen = document.querySelector(".game");
let playerOne; let playerTwo; let activePlayer;
let turnBoxes = document.querySelectorAll(".turns__box");
let resetBtn = document.querySelector(".scoreboard__reset");
game();
function game() {
playerModeSelection();
markerSelection();
}
function boardChange(active, inactive) {
inactive.style.opacity = "0";
inactive.style.zIndex = "0";
active.style.opacity = "1";
active.style.zIndex = "1";
}
//One or Two player Selection & transition to Marker Selector
function playerModeSelection() {
for (let i = 0; i < numOfPlayers.length; i++) {
numOfPlayers[i].addEventListener("click", function() {
if(i === 1) {
singlePlayer = false;
}
boardChange(markerScreen, playerScreen);
})
}
}
function markerSelection() {
//Back Button Functionality
backBtn.addEventListener("click", function() {
boardChange(playerScreen, markerScreen);
})
//Listen for choice of X or O
for (let i = 0; i < markers.length; i ++) {
markers[i].addEventListener("click", function() {
boardChange(gameScreen, markerScreen);
if (i === 1) {
playerArr = ["O", "X"];
}
//Starts Two Player Game; Here begin is the function that calls transition
if(!singlePlayer) {
twoPlayerMode();
}
})
}
}
function twoPlayerMode() {
activePlayer = Math.floor(Math.random() * 2);
turnBoxes[activePlayer].textContent = "Go Player " + (activePlayer + 1) + "!";
turnBoxes[activePlayer].style.transform = "translateY(-50px)";
resetBtn.addEventListener("click", function() {
boardChange(playerScreen, gameScreen);
turnBoxes[activePlayer].style.transform = "translateY(0px)";
})
}

asp.net with bootstrap. table-responsive scrolling is broken in panel-body

I have a webpage with the following HTML:
<div class="panel panel-primary" style="width:auto;height:auto;">
<div class="panel-heading" id="ContentHeader" runat="server" style="width:auto;height:auto;">Table</div>
<div class="panel-body" runat="server" style="width:auto;height:auto;">
<div class="table-responsive">
<asp:GridView ID="ExcelContentView" runat="server" class="table table-bordered" >
<HeaderStyle CssClass="info" />
</asp:GridView>
</div>
</div>
</div>
i reference this pages answer.
it works fine only with overflow-x.
however, scroll bar is broken when overflow-x with overflow-y case.
About 53 rows and 15 columns:
vertical scrollbar is not working.
but Left Or Right Key is move scrollbar.
clicking scrollbar is broken i think.
how do i fix scroll bar in overflow x and y case?
here is additional c# code behind
on page load :
{
ExcelContentView.DataSource = ExcelViewManager.Instance.GetExcelViewTable(fileName, historyNum);
ExcelContentView.DataBind();
} // method
and GetExcelViewTable Method
{
DataTable stringTable = new DataTable();
var currType = GameDataFileManager.Instance.GetTypeFromFileName(fileName);
string historyPath = GameDataFileManager.Instance.GetHistoryPathByType(currType);
string fullPath = historyPath + fileName + revNum + ".xlsx";
FileInfo excelFileInfo = new FileInfo(fullPath);
ExcelPackage excel = new ExcelPackage(excelFileInfo);
var workSheet1 = excel.Workbook.Worksheets.First();
int colCount = 0;
//
for (int iCol = 1; iCol <= workSheet1.Dimension.End.Column; ++iCol )
{
stringTable.Columns.Add( workSheet1.Cells[1, iCol].Text, typeof(string) );
++colCount;
} // for
for (int iRow = 3; iRow <= workSheet1.Dimension.End.Row; ++iRow )
{
List<object> objList = new List<object>();
for (int iCol = 1; iCol <= workSheet1.Dimension.End.Column; ++iCol )
{
objList.Add( workSheet1.Cells[iRow, iCol].Text );
} // for
int objCount = objList.Count;
if (colCount != objCount)
{
DotNetMsgBox.Show("Debug");
}
stringTable.Rows.Add(objList.ToArray());
} // for
return stringTable;
}
I solved this.
table-responsive is broken scrollbar when using with simple sidebar
responsive broken when this code.
<li class="sidebar-footer">Made by Me</li>
so, this sidebar-footer code makes problem.
i dont know why this code broken table-responisve sidebar.
i open simple-sidbar.css, and see this codes
.sidebar-nav > .sidebar-footer {
display: block;
text-decoration: none;
color: #fff;
position: fixed;
height: 100px;
bottom: 0;
width: 100%;
}
and i delete code in { }, but still has problem.
so, i delete sidebar-footer in my Master Page. and yes. i solved problem.
anyone tell me why this sidebar-footer broken scrollbar.

Set animated html5 canvas as the background without interacting with other elements?

I got the canvas working, I'm having issues trying to position it.
Specifically I want to implement them to the same effect as:
html {
background: url(back.jpg) no-repeat center center fixed;
background-size: cover;
}
for static images. Basically no interaction with other elements, and positioned as low as possible with regards to the stacking context. Additionally, I'd like to have the canvas background as compartmentalized / as segmented as possible from the rest of the code.
By segmented, I mean something like this:
<body>
<div id="backgroundContainer">
<canvas id="myCanvas"></canvas>
</div>
<div id="everythingElseContainer">
....
</div>
<script src="canvasAnimation.js"></script>
</body>
or this:
<body>
<div id="container">
<canvas id="myCanvas"></canvas>
<div id="everythingElse">
....
</div>
</div>
<script src="canvasAnimation.js"></script>
</body>
to minimize the possibility of css conflicts.
var WIDTH;
var HEIGHT;
var canvas;
var con;
var g;
var pxs = new Array();
var rint = 60;
$(document).ready(function(){
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
canvas = document.getElementById('canvas');
$(canvas).attr('width', WIDTH).attr('height',HEIGHT);
con = canvas.getContext('2d');
for(var i = 0; i < 100; i++) {
pxs[i] = new Circle();
pxs[i].reset();
}
setInterval(draw,rint);
});
function draw() {
con.clearRect(0,0,WIDTH,HEIGHT);
for(var i = 0; i < pxs.length; i++) {
pxs[i].fade();
pxs[i].move();
pxs[i].draw();
}
}
function Circle() {
this.s = {ttl:8000, xmax:5, ymax:2, rmax:10, rt:1, xdef:960, ydef:540, xdrift:4, ydrift: 4, random:true, blink:true};
this.reset = function() {
this.x = (this.s.random ? WIDTH*Math.random() : this.s.xdef);
this.y = (this.s.random ? HEIGHT*Math.random() : this.s.ydef);
this.r = ((this.s.rmax-1)*Math.random()) + 1;
this.dx = (Math.random()*this.s.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.s.ymax) * (Math.random() < .5 ? -1 : 1);
this.hl = (this.s.ttl/rint)*(this.r/this.s.rmax);
this.rt = Math.random()*this.hl;
this.s.rt = Math.random()+1;
this.stop = Math.random()*.2+.4;
this.s.xdrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
this.s.ydrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
}
this.fade = function() {
this.rt += this.s.rt;
}
this.draw = function() {
if(this.s.blink && (this.rt <= 0 || this.rt >= this.hl)) this.s.rt = this.s.rt*-1;
else if(this.rt >= this.hl) this.reset();
var newo = 1-(this.rt/this.hl);
con.beginPath();
con.arc(this.x,this.y,this.r,0,Math.PI*2,true);
con.closePath();
var cr = this.r*newo;
g = con.createRadialGradient(this.x,this.y,0,this.x,this.y,(cr <= 0 ? 1 : cr));
g.addColorStop(0.0, 'rgba(255,255,255,'+newo+')');
g.addColorStop(this.stop, 'rgba(77,101,181,'+(newo*.6)+')');
g.addColorStop(1.0, 'rgba(77,101,181,0)');
con.fillStyle = g;
con.fill();
}
this.move = function() {
this.x += (this.rt/this.hl)*this.dx;
this.y += (this.rt/this.hl)*this.dy;
if(this.x > WIDTH || this.x < 0) this.dx *= -1;
if(this.y > HEIGHT || this.y < 0) this.dy *= -1;
}
this.getX = function() { return this.x; }
this.getY = function() { return this.y; }
}
html, body, div, button, canvas, .containr {
padding: 0;
border: none;
margin: 0;
}
html, body, .containr{
height: 100%;
width: 100%;
background: none;
}
html, body {
font-size: 13px;
text-decoration: none;
font-family: Verdana, Geneva, sans-serif !important;
}
button {
transition: all 0.24s ease;
}
h1 {
font-size: 4rem;
}
button {
font-size: 5.6rem;
}
#pixie {
position:fixed;
z-index: 0;
background: black;
}
.containr>div {
background: blue;
}
.containr {
overflow:hidden;
color: #ffffff;
z-index: 9;
font-size: 256%;
white-space: nowrap;
display: flex;
flex-flow: column nowrap;
justify-content: space-around;
align-items: center;
align-content: center;
}
.btnz {
margin-left: 2.4%;
margin-right: 2.4%;
background: #ffffff;
background: rgba(0, 0, 0, .36);
text-shadow: 1px 1px 3px #000;
padding: 2rem;
}
.btnz:hover {
background: #3cb0fd;
text-shadow: none;
text-decoration: none;
}
/* Outline Out */
.hvr {
display: inline-block;
vertical-align: middle;
-webkit-transform: translateZ(0);
transform: translateZ(0);
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-moz-osx-font-smoothing: grayscale;
position: relative;
}
.hvr:before {
content: '';
position: absolute;
border: #e1e1e1 solid 5px;
top: -4px;
right: -4px;
bottom: -4px;
left: -4px;
-webkit-transition-duration: 0.3s;
transition-duration: 0.3s;
-webkit-transition-property: top, right, bottom, left;
transition-property: top, right, bottom, left;
}
.hvr:hover:before, .hvr:focus:before, .hvr:active:before {
top: -18px;
right: -18px;
bottom: -18px;
left: -18px;
border: #ffffff solid 8px;
}
<!doctype html>
<html lang="en">
<head datetime="2015-10-31">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="containr">
<canvas id="canvas"></canvas>
<div>
<h1>Main Title</h1>
</div>
<div>
<button class="btnz hvr">
Button Butt
</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="js.js"></script>
</body>
</html>
To move objects down in the visual order use the CSS styling z-index smaller numbers move the element down under other elements, higher numbers bring it up.See MDN z-index for more info.
To set the background of an element to a canvas use
element.style.background= "url(" + canvas.toDataURL() + ")";
To isolate of compartmentalize some code the easiest way is to wrap it in a anonymous function and call it. Everything inside it is isolated. Use 'use strict' directive to ensure you do not accidentally create global scoped variables.
A normal anonymous function does nothing and can not be used.
function(){ console.log(42); }; // does nothing
But if you wrap it in () and then add the function call tokens to the end ( ) you can call it like any function.
(function(){ console.log(42); })(); // send the meaning of life,
// the universe, and everything
// to the console.
The function below wraps up a and nothing can get access to a outside the anonymous function.
(function(){
var a = 1;
})();
But you can easily forget to put var in front of a variable making the variable visible to the entire page.
(function(){
var a = 1;
outThere = 2; // Oh no this is has been placed in
// global scope because it is missing
// the var token.
})();
To stop this use the 'use strict' directive.
(function(){
"use strict"; // this must be the very first line of the function
var a = 1;
outThere = 2; // this will cause the javascript to throw a
// ReferenceError: outThere is not defined
})();
It throws an error and stop the function from running but at least you will know that you have a leak.
Everything inside the anonymous function will manage itself. Deleting itself when not needed any more. Or remaining in memory if the Javascript engine holds an internal reference.
The next function starts up and calls its own function doSomething then exits and is deleted completely including the big array.
(function(){
var bigArray = new Array(100000000);
function doSomething(){
console.log("Whats up?");
}
doSomething();
})();
The next one will create a big array and hold that array in memory for 10 seconds (lifeTime). This is because the setTimeout has given the javascript engine an internal reference to doSomething. As long as that reference exists the bigArray will remain (because of closure). After the timeout the reference his no longer need and thus disposed causing all associated referances to go as well and thus disappear. All done via the magic of garbage collection.
Info on Clouser
Info on Garbage collection MDN is out of date but I am sure a quick search on StackOverflow will help.
(function(){
var bigArray = new Array(100000000);
function doSomething(){
console.log("Big Array has had its time.");
}
setTimeout(doSomething,10000);
})();
Attaching an object to items outside the anonymous function scope will expose data in that object to the global scope.
The next function adds a property to a DOM element. This is visible to the global scope and also means that the lifetime of the function will be as long as that element exists.
(function(){
function Info(){
... create info ..
}
var element = document.getElementById("thisOutsideWorld");
var importantPrivateInfo = new Info();
element.keepThis = importantPrivateInfo;
})();
But this does not apply to primitive types as they are copied not referenced. These are Numbers, Strings, Booleans , Undefined, Null...
So to set the background to a canvas via a compartmentalized function see the following function
(function(){
'use strict';
var myCanvas = document.createElement("canvas");
myCanvas .width = 1024;
myCanvas .height =1024;
var ctx = canvas.getContext("2d");
// toDo
// draw the stuff you want.
var el = document.getElementById("myElement");
if(el !== null){
el.style.background = "url("+canvas.toDataURL()+")";
}
// all done
})(); // once run it will delete the canvas and ctx and leave only the copied dataURL
You may think that this exposes the canvas. But it is safe as the canvas is converted to a string and strings are copied not referenced.
If you need to keep the canvas for some period then use a timer to create an internal reference to the anonymous function
The following function will create a canvas and update it every second for 100 seconds. After that it will be deleted and completely gone.
(function(){
'use strict';
var myCanvas = document.createElement("canvas");
myCanvas .width = 1024;
myCanvas .height =1024;
var lifeCounter = 0;
var ctx = canvas.getContext("2d");
// toDo
// draw the stuff you want.
var el = document.getElementById("myElement");
function update(){
// draw stuff on the canvas
if(el !== null){
el.style.background = "url("+canvas.toDataURL()+")";
}
lifeCounter += 1;
if(lifeCounter < 100){
setTimeout(update,1000);
}
}
update(); //start the updates
// all done
})();
Hope this helps.

css: float blocks to occupy all free space

I'm trying to make an "image mosaic" that consists mostly of images of the same size, and some of them the double height.
They all should align neatly like this:
To make automatic generation of those mosaic as easy as possible, I thought floating them would be the best option. Unfortunately, the big block causes the following ones to flow behind it, but not before:
What can I do - apart from manually positioning them - to get the images to the place I want, and still have it easy to automatically create likewise layouts?
The code I'm currently using is :
FIDDLE
HTML :
<div class="frame">
<div id="p11" class="img">1.1</div>
<div id="p12" class="img h2">1.2</div>
<div id="p13" class="img">1.3</div>
<div id="p21" class="img">2.1</div>
<div id="p22" class="img">2.2</div>
</div>
CSS :
.frame {
background-color: blue;
border: 5px solid black;
width: 670px;
}
.img {
width: 200px;
height: 125px;
background-color: white;
border: 1px solid black;
float: left;
margin: 10px;
}
.h2 {
height: 272px;
}
You need to use Javascript to achieve this effect, I had to do that once and I used http://masonry.desandro.com/ -- worked well!
Pure CSS Solution
Tested in Firefox, IE8+ (IE7 looks like it would need to be targeted to add a top margin added to 2.1 because it overlaps 1.1). See fiddle. This assumes .h2 is the middle div (as your example). If left most div it should not need any change. If right most, you would need to expand the negative margin to also include the third div following.
.h2 + div {
float: right;
margin: 10px 14px 10px 0; /*14px I believe also has to do with borders */
}
.h2 + div + div {
margin-left: -434px; /*need to account for borders*/
clear: right;
}
You can use a column layout like this:
http://jsfiddle.net/KKUZL/
I don't know if that will conflict with your automation process though....
I realize this is not a CSS-only solution, but for what it's worth (JSFiddle):
HTML:
<div id='container'></div>
CSS:
html, body {
margin:0px;
padding:0px;
height:100%;
}
body {
background-color:#def;
}
#container {
margin:0px auto;
width:635px;
min-height:100%;
background-color:#fff;
box-shadow:0px 0px 5px #888;
box-sizing:border-box;
overflow:auto;
}
.widget {
float:left;
box-sizing:border-box;
padding:10px 10px 0px 0px;
}
.widget > div{
height:100%;
box-sizing:border-box;
color:#fff;
font-size:3em;
text-align:center;
padding:.5em;
overflow:hidden;
}
.widget > div:hover {
background-color:purple !important;
}
JS:
////////////////////////////////////////
// ASSUMPTIONS
//
var TWO_COLUMN_WIDGET_COUNT = 1;
var ONE_COLUMN_WIDGET_COUNT = 15;
var NUMBER_OF_COLUMNS = 2;
////////////////////////////////////////
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var colorFactory = (function () {
var colors = [
'#CC9A17',
'#9B2C16',
'#1A8B41',
'#D97114',
'#3B9EE6'];
var index = 0;
return function () {
if (index > 4) {
index = 0;
}
return colors[index++];
}
})();
function widgetFactory(columnSpan) {
return {
'height': rand(10, 30) * 10,
'width': 100 * columnSpan / NUMBER_OF_COLUMNS,
'columnSpan': columnSpan,
'color': colorFactory()
}
}
function getWidgets() {
var widgets = [];
for (var i = 0; i < TWO_COLUMN_WIDGET_COUNT; i++) {
widgets.push(widgetFactory(2));
}
for (var i = 0; i < ONE_COLUMN_WIDGET_COUNT; i++) {
widgets.push(widgetFactory(1));
}
return widgets;
}
function getHighestOffset(offsets){
}
function getHighestSlot(offsets, numOfColumns){
}
$(document).ready(function () {
var container = $('#container');
var widgets = getWidgets();
var col1 = Math.floor(container[0].offsetLeft);
var col2 = Math.floor(container[0].clientWidth / 2 + container[0].offsetLeft);
var offsets = {};
offsets[col1] = 0;
offsets[col2] = 0;
var newLine = true;
for (var i = 0; i < widgets.length; i++) {
var w = widgets[i];
var marginTop = 0;
if (offsets[col1] < offsets[col2]) {
marginTop = (offsets[col2] - offsets[col1]) * -1;
}
if(offsets[col1] <= offsets[col2] || w.columnSpan == 2){
newLine = true;
}
var margin = 'margin-top:' + marginTop + 'px;';
var height = 'height:' + w.height + 'px;';
var color = 'background-color:' + colorFactory() + ';';
var width = 'width:' + w.width + '%;';
var padding = newLine ? "padding-left:10px;" : "";
var component = $('<div class="widget" style="' + padding + margin + height + width + '"><div style="' + color + '">' + i + '</div></div>');
component.appendTo(container);
var c = component[0];
var index = 0;
var minOffset = null;
for(var p in offsets){
if(minOffset == null || offsets[p] < minOffset){
minOffset = offsets[p];
}
if(p == Math.floor(c.offsetLeft)){
index = 1;
}
if(index > 0 && index <= w.columnSpan){
offsets[p] = c.offsetTop + c.offsetHeight;
index++;
}
}
newLine = minOffset >= offsets[col1];
}
});

Moving items in Dual Listboxes

How can I move items from one list box control to another listbox control using JavaScript in ASP.NET?
If you're happy to use jQuery, it's very, very simple.
$('#firstSelect option:selected').appendTo('#secondSelect');
Where #firstSelect is the ID of the select box.
I've included a working example here:
http://jsbin.com/aluzu (to edit: http://jsbin.com/aluzu/edit)
This code assumes that you have an anchor or that will trigger to movement when it is clicked:
document.getElementById('moveTrigger').onclick = function() {
var listTwo = document.getElementById('secondList');
var options = document.getElementById('firstList').getElementsByTagName('option');
while(options.length != 0) {
listTwo.appendChild(options[0]);
}
}
A library-independent solution:
function Move(inputControl)
{
var left = document.getElementById("Left");
var right = document.getElementById("Right");
var from, to;
var bAll = false;
switch (inputControl.value)
{
case '<<':
bAll = true;
// Fall through
case '<':
from = right; to = left;
break;
case '>>':
bAll = true;
// Fall through
case '>':
from = left; to = right;
break;
default:
alert("Check your HTML!");
}
for (var i = from.length - 1; i >= 0; i--)
{
var o = from.options[i];
if (bAll || o.selected)
{
from.remove(i);
try
{
to.add(o, null); // Standard method, fails in IE (6&7 at least)
}
catch (e)
{
to.add(o); // IE only
}
}
}
}
HTML
<select id="Left" multiple="multiple" size="10">
<option>Some</option>
<option>List</option>
<option>Of</option>
<option>Items</option>
<option>To</option>
<option>Move</option>
<option>Around</option>
</select>
<div id="Toolbar">
<input type="button" value=">" onclick="Move(this)"/>
<input type="button" value=">>" onclick="Move(this)"/>
<input type="button" value="<<" onclick="Move(this)"/>
<input type="button" value="<" onclick="Move(this)"/>
</div>
<select id="Right" multiple="multiple" size="10">
</select>
CSS (example)
select { width: 200px; float: left; }
#Toolbar { width: 50px; float: left; text-align: center; padding-top: 30px; }
#Toolbar input { width: 40px; }
Quick test FF3 and IE6 & 7 only.

Resources