So essentially, I am programming a rubiks cube solver where I am using blazor to display the 2D face- I want to add buttons north, east, south and west of the 2D face which are labelled "see left", "see right", "see up" and "see down" which shows the corresponding face. Problem is I have no idea how to position the buttons so they are inline with the middle row of each face? Ive attached my current code (I havent implemented any buttons quite yet) which displays the 2D table- Ive also attached a photo on what i idelaly want it to look like:
<div style="width: 200px;">
<table class="table table-bordered">
<tbody>
#for (var r = 0; r < 3; r++)
{
<tr>
#for (int c = 0; c < 3; c++)
{
<td class="align-middle text-center" style="background-color: #face[r, c]; color: white">#face[r, c]</td>
}
</tr>
}
</tbody>
</table>
</div>
Picture of what I would like it to look like (arrows are not necessary!)
I tried to do make a bigger table and put the 2D table in it and add the buttons around it but it didn't work :( Im quite a new programmer and HTML is not my strong point- I appreciate any help!
RubikButtons.razor
<div class="rubiks-container">
<button class="button-up">⬆️ See up</button>
<button class="button-down">⬇️ See down</button>
<button class="button-left">⬅️ See left</button>
<button class="button-right">➡️ See right</button>
<div class="rubiks-content">
#ChildContent
</div>
</div>
#code {
[Parameter, EditorRequired]
public RenderFragment ChildContent { get; set; } = default!;
}
RubikButtons.razor.css
button {
width: fit-content;
}
.button-up {
background-color: aliceblue;
grid-area: button-up;
justify-self: center;
}
.button-down {
grid-area: button-down;
justify-self: center;
}
.button-left {
grid-area: button-left;
justify-self: end;
}
.button-right {
grid-area: button-right;
}
.rubiks-container {
display: grid;
grid-template:
'button-up button-up button-up'
'button-left rubiks-content button-right'
'button-down button-down button-down';
grid-gap: 10px;
}
Usage
<RubikButtons>
<div>SomeCubeDisplay</div>
</RubikButtons>
Related
I am new to css. How can I add a status button which changes color depending on chat availability on top of another button?
You can use the position property.
See an example code here.
Some resources:
https://www.w3schools.com/css/css_positioning.asp
https://developer.mozilla.org/en-US/docs/Web/CSS/position
From the picture i can tell you don't have to use 2 html elements on top of each other, but you can use css properties like border and background-color to achieve exactly as the button in your picture.
I posted how in the code below with even a little bit of javascript to toogle the button status (not needed for styling, so if you don't know any javascript yet, you can skip that part).
let isOpen = false;
const btn = document.querySelector("#btn");
const dot = document.querySelector(".dot");
const txt = document.querySelector("#text");
btn.addEventListener("click", () => {
if (isOpen) {
dot.style.backgroundColor = "red";
txt.innerHTML = "The chat is now closed";
} else {
dot.style.backgroundColor = "green";
txt.innerHTML = "The chat is now open";
}
isOpen = !isOpen;
});
.dot {
height: 25px;
width: 25px;
background-color: red;
border-radius: 50%;
display: inline-block;
border: 5px solid gray;
}
#wrapper {
border: 1px solid black;
text-align: center;
padding: 10px;
}
#btn {
margin-top: 10px;
}
<div id="wrapper">
<span class="dot"></span>
<p id="text">The chat is now closed</p>
</div>
<button id="btn">Toogle</button>
I'm trying to make a timer; just a simple, HTML timer. Now, I'm trying to get it so that the first button (button1) changes the background colour of the button to #0000FF if var button1 (the variable that determines what the button says) is "Pause" and to #00FF00 if var button1 is anything else. Here's my HTML (note: I am using angular so it might look a little weird):
<!DOCTYPE html>
<html>
<div class="screen">
<div class="timer">
00:00:00
</div>
<div class="buttons">
<button class="button1" id="buuton" onclick="timeout(40, 1)">
{{button1}}
</button>
<button class="button2">
{{button2}}
</button>
</div>
</div>
</html>
Here's my typescript (again might look a little weird):
timeLeft: number //Time left in milliseconds
currTime: number //Time on stopwatch in milliseconds
button1: string //Button 1
button2: string //Button 2
timeout (ms: number, func: number) {
setTimeout(() => {
if (func == 0) {
null
} else if (func == 1) {
if (this.button1 == "Pause") {
document.getElementById("buuton").style.backgroundColor = "#0000ff"
} else {
document.getElementById("buuton").style.backgroundColor = "#00ff00"
}
}
}, ms);
}
And here's my CSS:
.timer {
height: 3.5em;
line-height: 3em;
display: block;
margin-top: 2em;
margin-bottom: 1em;
margin-left: 0.33em;
font-weight: bolder;
}
.buttons {
height: 1em;
line-height: 1.5em;
margin-top: 0.1vh;
margin-bottom: 2em;
margin-left: 0.33em;
}
.screen {
position: fixed;
height: 93.5vh;
width: 99vw;
left: 0.5vw;
top: 0.5vh;
}
I don't know what I'm doing wrong. Can you please help me?
Edit 1 (16 Jun 2020 10:49:39) - No, there were no error messages.
Just as #CodeMonkey mentioned, change your onclick event listener to be (click) instead. When event binding in Angular, we hook an event listener to get notified whenever an event is fired. Angular docs
Since your using Angular, updating the click event listener for your <button> to (click)="timeout(40, 1)" fixes the issue. Wrapping the event listener click inside parentheses indicates that the component property is tied up with the click event.
<!DOCTYPE html>
<html>
<div class="screen">
<div class="timer">
00:00:00
</div>
<div class="buttons">
<button class="button1" id="buuton" (click)="timeout(40, 1)">
{{button1}}
</button>
<button class="button2">
{{button2}}
</button>
</div>
</div>
Here is an example chat app ->
The idea here is to have the .messages-container take up as much of the screen as it can. Within .messages-container, .scroll holds the list of messages, and in case there are more messages then the size of the screen, scrolls.
Now, consider this case:
The user scrolls to the bottom of the conversation
The .text-input, dynamically gets bigger
Now, instead of the user staying scrolled to the bottom of the conversation, the text-input increases, and they no longer see the bottom.
One way to fix it, if we are using react, calculate the height of text-input, and if anything changes, let .messages-container know
componentDidUpdate() {
window.setTimeout(_ => {
const newHeight = this.calcHeight();
if (newHeight !== this._oldHeight) {
this.props.onResize();
}
this._oldHeight = newHeight;
});
}
But, this causes visible performance issues, and it's sad to be passing messages around like this.
Is there a better way? Could I use css in such a way, to express that when .text-input-increases, I want to essentially shift up all of .messages-container
2:nd revision of this answer
Your friend here is flex-direction: column-reverse; which does all you ask while align the messages at the bottom of the message container, just like for example Skype and many other chat apps do.
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
The downside with flex-direction: column-reverse; is a bug in IE/Edge/Firefox, where the scrollbar doesn't show, which your can read more about here: Flexbox column-reverse and overflow in Firefox/IE
The upside is you have ~ 90% browser support on mobile/tablets and ~ 65% for desktop, and counting as the bug gets fixed, ...and there is a workaround.
// scroll to bottom
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
// only shift-up if at bottom
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
In the below code snippet I've added the 2 functions from above, to make IE/Edge/Firefox behave in the same way flex-direction: column-reverse; does.
function addContent () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.value.length > 0) {
msgdiv.innerHTML += msgtxt.value + '<br/>';
msgtxt.value = "";
} else {
msgdiv.innerHTML += 'Long long content ' + (tempCounter++) + '!<br/>';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
function resizeInput () {
var msgdiv = document.getElementById('messages');
var msgtxt = document.getElementById('inputs');
var atbottom = scrollAtBottom(msgdiv);
if (msgtxt.style.height == '120px') {
msgtxt.style.height = 'auto';
} else {
msgtxt.style.height = '120px';
}
/* if at bottom and is IE/Edge/Firefox */
if (atbottom && (!isWebkit || isEdge)) {
updateScroll(msgdiv);
}
}
/* fix for IE/Edge/Firefox */
var isWebkit = ('WebkitAppearance' in document.documentElement.style);
var isEdge = ('-ms-accelerator' in document.documentElement.style);
var tempCounter = 6;
function updateScroll(el){
el.scrollTop = el.scrollHeight;
}
function scrollAtBottom(el){
return (el.scrollTop + 5 >= (el.scrollHeight - el.offsetHeight));
}
html, body { height:100%; margin:0; padding:0; }
.chat-window{
display:flex;
flex-direction:column;
height:100%;
}
.chat-messages{
flex: 1;
height:100%;
overflow: auto;
display: flex;
flex-direction: column-reverse;
}
.chat-input { border-top: 1px solid #999; padding: 20px 5px }
.chat-input-text { width: 60%; min-height: 40px; max-width: 60%; }
/* temp. buttons for demo */
button { width: 12%; height: 44px; margin-left: 5%; vertical-align: top; }
/* begin - fix for hidden scrollbar in IE/Edge/Firefox */
.chat-messages-text{ overflow: auto; }
#media screen and (-webkit-min-device-pixel-ratio:0) {
.chat-messages-text{ overflow: visible; }
/* reset Edge as it identifies itself as webkit */
#supports (-ms-accelerator:true) { .chat-messages-text{ overflow: auto; } }
}
/* hide resize FF */
#-moz-document url-prefix() { .chat-input-text { resize: none } }
/* end - fix for hidden scrollbar in IE/Edge/Firefox */
<div class="chat-window">
<div class="chat-messages">
<div class="chat-messages-text" id="messages">
Long long content 1!<br/>
Long long content 2!<br/>
Long long content 3!<br/>
Long long content 4!<br/>
Long long content 5!<br/>
</div>
</div>
<div class="chat-input">
<textarea class="chat-input-text" placeholder="Type your message here..." id="inputs"></textarea>
<button onclick="addContent();">Add msg</button>
<button onclick="resizeInput();">Resize input</button>
</div>
</div>
Side note 1: The detection method is not fully tested, but it should work on newer browsers.
Side note 2: Attach a resize event handler for the chat-input might be more efficient then calling the updateScroll function.
Note: Credits to HaZardouS for reusing his html structure
You just need one CSS rule set:
.messages-container, .scroll {transform: scale(1,-1);}
That's it, you're done!
How it works: First, it vertically flips the container element so that the top becomes the bottom (giving us the desired scroll orientation), then it flips the content element so that the messages won't be upside down.
This approach works in all modern browsers. It does have a strange side effect, though: when you use a mouse wheel in the message box, the scroll direction is reversed. This can be fixed with a few lines of JavaScript, as shown below.
Here's a demo and a fiddle to play with:
//Reverse wheel direction
document.querySelector('.messages-container').addEventListener('wheel', function(e) {
if(e.deltaY) {
e.preventDefault();
e.currentTarget.scrollTop -= e.deltaY;
}
});
//The rest of the JS just handles the test buttons and is not part of the solution
send = function() {
var inp = document.querySelector('.text-input');
document.querySelector('.scroll').insertAdjacentHTML('beforeend', '<p>' + inp.value);
inp.value = '';
inp.focus();
}
resize = function() {
var inp = document.querySelector('.text-input');
inp.style.height = inp.style.height === '50%' ? null : '50%';
}
html,body {height: 100%;margin: 0;}
.conversation {
display: flex;
flex-direction: column;
height: 100%;
}
.messages-container {
flex-shrink: 10;
height: 100%;
overflow: auto;
}
.messages-container, .scroll {transform: scale(1,-1);}
.text-input {resize: vertical;}
<div class="conversation">
<div class="messages-container">
<div class="scroll">
<p>Message 1<p>Message 2<p>Message 3<p>Message 4<p>Message 5
<p>Message 6<p>Message 7<p>Message 8<p>Message 9<p>Message 10<p>Message 11<p>Message 12<p>Message 13<p>Message 14<p>Message 15<p>Message 16<p>Message 17<p>Message 18<p>Message 19<p>Message 20
</div>
</div>
<textarea class="text-input" autofocus>Your message</textarea>
<div>
<button id="send" onclick="send();">Send input</button>
<button id="resize" onclick="resize();">Resize input box</button>
</div>
</div>
Edit: thanks to #SomeoneSpecial for suggesting a simplification to the scroll code!
Please try the following fiddle - https://jsfiddle.net/Hazardous/bypxg25c/. Although the fiddle is currently using jQuery to grow/resize the text area, the crux is in the flex related styles used for the messages-container and input-container classes -
.messages-container{
order:1;
flex:0.9 1 auto;
overflow-y:auto;
display:flex;
flex-direction:row;
flex-wrap:nowrap;
justify-content:flex-start;
align-items:stretch;
align-content:stretch;
}
.input-container{
order:2;
flex:0.1 0 auto;
}
The flex-shrink value is set to 1 for .messages-container and 0 for .input-container. This ensures that messages-container shrinks when there is a reallocation of size.
I've moved text-input within messages, absolute positioned it to the bottom of the container and given messages enough bottom padding to space accordingly.
Run some code to add a class to conversation, which changes the height of text-input and bottom padding of messages using a nice CSS transition animation.
The JavaScript runs a "scrollTo" function at the same time as the CSS transition is running to keep the scroll at the bottom.
When the scroll comes off the bottom again, we remove the class from conversation
Hope this helps.
https://jsfiddle.net/cnvzLfso/5/
var doScollCheck = true;
var objConv = document.querySelector('.conversation');
var objMessages = document.querySelector('.messages');
var objInput = document.querySelector('.text-input');
function scrollTo(element, to, duration) {
if (duration <= 0) {
doScollCheck = true;
return;
}
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) {
doScollCheck = true;
return;
}
scrollTo(element, to, duration - 10);
}, 10);
}
function resizeInput(atBottom) {
var className = 'bigger',
hasClass;
if (objConv.classList) {
hasClass = objConv.classList.contains(className);
} else {
hasClass = new RegExp('(^| )' + className + '( |$)', 'gi').test(objConv.className);
}
if (atBottom) {
if (!hasClass) {
doScollCheck = false;
if (objConv.classList) {
objConv.classList.add(className);
} else {
objConv.className += ' ' + className;
}
scrollTo(objMessages, (objMessages.scrollHeight - objMessages.offsetHeight) + 50, 500);
}
} else {
if (hasClass) {
if (objConv.classList) {
objConv.classList.remove(className);
} else {
objConv.className = objConv.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
}
}
}
}
objMessages.addEventListener('scroll', function() {
if (doScollCheck) {
var isBottom = ((this.scrollHeight - this.offsetHeight) === this.scrollTop);
resizeInput(isBottom);
}
});
html,
body {
height: 100%;
width: 100%;
background: white;
}
body {
margin: 0;
padding: 0;
}
.conversation {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
position: relative;
}
.messages {
overflow-y: scroll;
padding: 10px 10px 60px 10px;
-webkit-transition: padding .5s;
-moz-transition: padding .5s;
transition: padding .5s;
}
.text-input {
padding: 10px;
-webkit-transition: height .5s;
-moz-transition: height .5s;
transition: height .5s;
position: absolute;
bottom: 0;
height: 50px;
background: white;
}
.conversation.bigger .messages {
padding-bottom: 110px;
}
.conversation.bigger .text-input {
height: 100px;
}
.text-input input {
height: 100%;
}
<div class="conversation">
<div class="messages">
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is a message content
</p>
<p>
This is the last message
</p>
<div class="text-input">
<input type="text" />
</div>
</div>
</div>
You write;
Now, consider this case:
The user scrolls to the bottom of the conversation
The .text-input, dynamically gets bigger
Wouldn't the method that dynamically sets the .text-input be the logical place to fire this.props.onResize().
To whom it may concern,
The answers above did not suffice my question.
The solution I found was to make my innerWidth and innerHeight variable constant - as the innerWidth of the browser changes on scroll to adapt for the scrollbar.
var innerWidth = window.innerWidth
var innerHeight = window.innerHeight
OR FOR REACT
this.setState({width: window.innerWidth, height: window.innerHeight})
In other words, to ignore it, you must make everything constant as if it were never scrolling. Do remember to update these on Resize / Orientation Change !
IMHO current answer is not a correct one:
1/ flex-direction: column-reverse; reverses the order of messages - I didn't want that.
2/ javascript there is also a bit hacky and obsolete
If you want to make it like a PRO use spacer-box which has properties:
flex-grow: 1;
flex-basis: 0;
and is located above messages. It pushes them down to the chat input.
When user is typing new messages and input height is growing the scrollbar moves up, but when the message is sent (input is cleared) scrollbar is back at bottom.
Check my snippet:
body {
background: #ccc;
}
.chat {
display: flex;
flex-direction: column;
width: 300px;
max-height: 300px;
max-width: 90%;
background: #fff;
}
.spacer-box {
flex-basis: 0;
flex-grow: 1;
}
.messages {
display: flex;
flex-direction: column;
overflow-y: auto;
flex-grow: 1;
padding: 24px 24px 4px;
}
.footer {
padding: 4px 24px 24px;
}
#chat-input {
width: 100%;
max-height: 100px;
overflow-y: auto;
border: 1px solid pink;
outline: none;
user-select: text;
white-space: pre-wrap;
overflow-wrap: break-word;
}
<div class="chat">
<div class="messages">
<div class="spacer-box"></div>
<div class="message">1</div>
<div class="message">2</div>
<div class="message">3</div>
<div class="message">4</div>
<div class="message">5</div>
<div class="message">6</div>
<div class="message">7</div>
<div class="message">8</div>
<div class="message">9</div>
<div class="message">10</div>
<div class="message">11</div>
<div class="message">12</div>
<div class="message">13</div>
<div class="message">14</div>
<div class="message">15</div>
<div class="message">16</div>
<div class="message">17</div>
<div class="message">18</div>
</div>
<div class="footer">
<div contenteditable role="textbox" id="chat-input"></div>
</div>
<div>
Hope I could help :)
Cheers
I need to place a star, ★, on a Web page, repeatedly. Is there a way to specify a symbol and how many times it should appear, in HTML or CSS? E.g., something like this, but not necessarily the same syntax, in which an item is specified, along with a quantity:
<repeat n="5">★</repeat>
This will result in:
★★★★★
You could place the star as a repeating background image of an element; and tweak the width of the element via CSS. Something like:
.stars {
display: inline-block;
width: 13px;
height: 13px;
background-image: url(https://i.stack.imgur.com/KaEDC.png);
}
.stars-2 {
width: 26px;
}
.stars-3 {
width: 39px;
}
.stars-4 {
width: 52px;
}
.stars-5 {
width: 65px;
}
<span class="stars"></span><br>
<span class="stars stars-2"></span><br>
<span class="stars stars-3"></span><br>
<span class="stars stars-4"></span><br>
<span class="stars stars-5"></span>
Use content property like this:
Note: that using repeat is not recommended in your case its not a valid html tag, use div, span or a.
Demo
Use SCSS or LESS to generate style sheet like this.
CSS:
<style>
repeat {
display:block;
}
repeat[n="1"]:before {
content: "★";
}
repeat[n="2"]:before {
content: "★★";
}
repeat[n="3"]:before {
content: "★★★";
}
repeat[n="4"]:before {
content: "★★★★";
}
repeat[n="5"]:before {
content: "★★★★★";
}
</style>
HTML:
<repeat n="1"></repeat>
<repeat n="2"></repeat>
<repeat n="5"></repeat>
If you are willing to use jQuery (or just javascript but different code), you could do:
$(document).ready(function() {
$('[repeat]').each(function() {
var toRepeat = $(this).text();
var times = parseInt($(this).attr('repeat'));
var repeated = Array(times+1).join(toRepeat);
$(this).text(repeated).removeAttr('repeat');
});
});
Then when you have
<span repeat="5">★</span>
It will become
<span>★★★★★</span>
Try:
body{
counter-reset: Counter;
}
sameTypeElement::after{
counter-increment: Counter;
content:counter(Counter) " ★";
}
or simpler:
sameTypeElement::after{
content:'★';
}
sameTypeElement siblinging is unknown for different browsers, but must work with any level of nesting tiying to type of selector
If you just want to print the star a certain number of times you can use JavaScript:
for (var i = 0; i < 5; i++) {
document.write("★");
}
Will result in: ★★★★★
If you want to be able to access a particular star, you will need to wrap each star in a span and give it a unique id:
for (var i = 0; i < 6; i++) {
document.write("<span id=\"star" + i + "\">★</span>");
}
This will result in:
<span class="star0">★</span>
<span class="star1">★</span>
<span class="star2">★</span>
<span class="star3">★</span>
<span class="star4">★</span>
I'm building a single page which consists of a list (of div's) on the left and a grid (of div's) on the right. I would like to add the ability for a user to click and drag one of the list items and drop it over one of the grid boxes. I'm not using HTML5, but I know it comes with this native capability. I'm trying to avoid HTML 5 at the moment.
The above illustration shows my basic page layout and the red line shows how things will be dragged/dropped. Any of the list items may be dragged into any of the grid boxes. The grid cells are dynamically sized (resizing the page will resize the grid cells) to where everything always fits in the page at any given time, no scroll bars. Each grid cell has an index starting from 0, counting from left-to-right then top-to-bottom. I need to pair the list item ID (could be any number) with its corresponding grid cell index (0-8 in this case).
I don't know even the first thing I need to do to make this drag/drop possible. I just know the very core basics of HTML - so I need some example to demonstrate this, not just some brief explanation of use this and that, because I won't know what this and that means. All the tutorials I can find are related to either HTML 5 in particular or related to just moving a list item within the same list - but in my case I need to move it outside the list.
Here's the page structure which I am working with below. Note that the list items are dynamically added upon page load...
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>View Cameras</title>
<script type="text/javascript" language="javascript">
var selIndex = 0;
var lastListIndex = 0;
function selBox(index) {
document.getElementById('b' + selIndex).style.backgroundColor = "Black";
selIndex = index;
document.getElementById('b' + selIndex).style.backgroundColor = "Blue";
}
function pageload() {
AddListItem('rtsp://192.168.1.1', 'Test Item 1');
AddListItem('rtsp://192.168.1.2', 'Test Item 2');
AddListItem('rtsp://192.168.1.3', 'Test Item 3');
selBox(0);
camload('');
selBox(1);
camload('');
selBox(2);
camload('');
selBox(3);
camload('');
selBox(4);
camload('');
selBox(5);
camload('');
selBox(6);
camload('');
selBox(7);
camload('');
selBox(8);
camload('');
selBox(0);
}
function AddListItem(address, caption) {
lastListIndex += 1;
var i = lastListIndex;
var h = '<div id="camlistitem' + i + '" class="camlistitem" onclick="camload(\''+address+'\')">';
h += caption;
h += '</div>';
document.getElementById('divCamList').innerHTML += h;
}
function camload(addr) {
var h = '';
if (addr == '') {
h = '<div style="width: 100%; height: 100%; text-align: center; vertical-align: middle;">';
h += ' <img src="Cam.jpg" style="width: 100px; height: 80px;" alt="No Camera Selected"';
h += '</div>';
} else {
h = '<OBJECT classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" ';
h += 'id="player'+selIndex+'" events="True" style="width: 100%; height: 100%;">';
h += '<param name="Src" value="' + addr + '" />';
h += '<param name="ShowDisplay" value="True" />';
h += '<param name="AutoLoop" value="False" />';
h += '<param name="AutoPlay" value="True" />';
h += '<embed id="vcl' + selIndex + '" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" ';
h += 'autoplay="yes" loop="no" target="' + addr + '" style="width: 100%; height: 100%;"></embed></OBJECT>';
}
document.getElementById('divContent' + selIndex).innerHTML = h;
}
</script>
<style type="text/css">
body
{
height: 100%;
}
* { margin: 0px; border: 0px; padding: 0px; }
h3
{
font-size: 14px;
font-weight: bold;
}
div.title
{
height: 40px;
box-sizing: border-box;
overflow: hidden;
}
div.main
{
height: 100%;
}
div.contentmain
{
top: 40px;
bottom: 0;
left: 250px;
right: 0;
overflow: hidden;
position: absolute;
}
div.side
{
top: 40px;
bottom: 0;
width: 250px;
position: absolute;
background: lightgrey;
}
.matrix
{
display: table;
width: 100%;
height: 100%;
}
.row
{
display: table-row;
}
div.contentbox
{
display: table-cell;
width: 33%;
}
table.selecttable
{
width: 200px;
height: 100%;
}
td.selecttable
{
text-align: center;
cursor: pointer;
color: White;
}
div.camlist
{
}
div.camlistitem
{
background-color: Navy;
color: White;
cursor: pointer;
margin-top: 1px;
padding-left: 5px;
}
div.camlistitem:hover
{
background-color: Blue;
}
</style>
</head>
<body onload="pageload()">
<div id="divTitle" class="title">
<h1>View Cameras</h1>
</div>
<div id="divMain" class="main">
<div class="side">
<h3>1) Click box to select view:</h3>
<div style="position: relative; float: left; width: 100%;">
<table class="selecttable" border="1px">
<tr>
<td class="selecttable" id="b0" onclick="selBox(0);" style="background-color: Black;">0<br /></td>
<td class="selecttable" id="b1" onclick="selBox(1);" style="background-color: Black;">1<br /></td>
<td class="selecttable" id="b2" onclick="selBox(2);" style="background-color: Black;">2<br /></td>
</tr>
<tr>
<td class="selecttable" id="b3" onclick="selBox(3);" style="background-color: Black;">3<br /></td>
<td class="selecttable" id="b4" onclick="selBox(4);" style="background-color: Black;">4<br /></td>
<td class="selecttable" id="b5" onclick="selBox(5);" style="background-color: Black;">5<br /></td>
</tr>
<tr>
<td class="selecttable" id="b6" onclick="selBox(6);" style="background-color: Black;">6<br /></td>
<td class="selecttable" id="b7" onclick="selBox(7);" style="background-color: Black;">7<br /></td>
<td class="selecttable" id="b8" onclick="selBox(8);" style="background-color: Black;">8<br /></td>
</tr>
</table>
</div>
<h3>2) Select cam to show in selected box:</h3>
<div style="position: relative; float: left; width: 100%;">
<div id="divCamList" class="camlist">
<div id="camlistitem0" class="camlistitem" onclick="camload('')">
[No Camera]
</div>
</div>
</div>
<h3>3) Can't see the cameras? Click Here.</h3>
</div>
<div class="contentmain">
<div class="matrix">
<div class="row">
<div class="contentbox" id="divContent0"></div>
<div class="contentbox" id="divContent1"></div>
<div class="contentbox" id="divContent2"></div>
</div>
<div class="row">
<div class="contentbox" id="divContent3"></div>
<div class="contentbox" id="divContent4"></div>
<div class="contentbox" id="divContent5"></div>
</div>
<div class="row">
<div class="contentbox" id="divContent6"></div>
<div class="contentbox" id="divContent7"></div>
<div class="contentbox" id="divContent8"></div>
</div>
</div>
</div>
</div>
</body>
</html>
PS - there will be a missing picture Cam.jpg
UPDATE
Thanks to the help of roflmao's effort on the answer below, I got everything working fine now. Just a glitch where when I drag an item, it highlights everything on the page, but that's another story.
Okay, so the first thing you'll want to do right off the bat is use a javascript library, either jQuery or Prototype (jQuery being the more popular one). Manipulating standard JS the way you are is begging for cross-browser compatibility issues.
Once you've put in jQuery, you can just use the jQuery UI library and use the draggable and droppable interfaces. Check this page out.
The code will look something like this:
http://jsfiddle.net/CZNhP/21/
$(function() {
$("#menu li").draggable({reset: true});
$("#container").droppable({
drop: function(event, ui) {
// Here you instantiate your media object.
// You can access the place your object was dropped on with
// "this" and the draggged item with "ui.draggable"
}
});
});