On my previous post I asked how I'd get the gradient set up. Now the problem is that the gradient "spreads" out. Here's What I'm using
function generateCSSGradient(colours) {
var l = colours.length, i;
for( i=0; i<l; i++) colours[i] = colours[i].join(" ");
return "linear-gradient( to right, "+colours.join(", ")+")";
}
var cols = [
["red","0%"],
["red","40%"],
["yellow","40%"],
["yellow","60%"],
["green","60%"],
["green","80%"]
];
yourElement.style.background = generateCSSGradient(cols);
With this. What I want to do is say you fill in one input. And the bar goes to 33%, then that could be a red color. Then the next would be a blue and so fourth. Not like this. Any ideas? I'd also avoid using div
I think you want it like this ... See the source code
HTML
I'v edited the HTML code and added another div called colors inside the div top ...
<div class="top">
<div class="colors"></div>
</div>
CSS
Also I edited the CSS of .top and added to it overflow:hidden; and create .colors style
.top{
/*background: #009dff;*/
background:linear-gradient(to right,#009dff 0,#00c8ff 100%);
position:fixed;
z-index:1031;
top:0;
left:0;
height:4px;
transition:all 1s;
width:0;
overflow: hidden;
}
.colors{
width: 100%;
height: 4px;
}
JavsScript
Then edited the JavaScript and made the CSSGradient to colors not top , and let the JavaScript set the width of colors to fit the window width , and changed the colors percentage..
document.querySelector(".colors").style.background = generateCSSGradient(cols);
var window_width = window.innerWidth + "px";
document.querySelector(".colors").style.width = window_width;
var cols = [
["red","0%"],
["red","33.3%"],
["yellow","33.3%"],
["yellow","66.6%"],
["green","66.6%"],
["green","100%"]
];
Hope this will help you ...
Update
if you want to change the color of the bar like this , See the source code ...
just edit the JavaScript to be like this
function cback(e) {
var t = [];
for (var n = inputs.length; n--;) {
if (!inputs[n].value.length) t.push(inputs[n]);
}
var r = t.length;
var i = inputs.length;
var s = document.querySelectorAll(".top");
for (var o = s.length; o--;) {
s[o].style.width = 100 - r / i * 100 + "%";
s[o].style.background = cols[i-r-1];
}
}
var forms = document.querySelectorAll(".form"),
inputs = [];
for (var i = forms.length; i--;) {
var els = forms[i].querySelectorAll("input, textarea, select");
for (var j = els.length; j--;) {
if (els[j].type != "button" && els[j].type != "submit") {
inputs.push(els[j]);
els[j].addEventListener("input", cback, false);
}
}
}
var cols = ["red","yellow","green"];
Related
I have some articles on the block. Some of them cut in the middle of their hight like on the picture:
I tried to fix this problem by using the function below, but it still doesn't work.
const setSameHeightToAll = function() {
const all = document.querySelectorAll('.text_blog')
let maxHeight = 0
var length = all.length
for (var i = 0; i < length; i++) {
if (all[i].getBoundingClientRect().height > maxHeight) {
maxHeight = all[i].getBoundingClientRect().height
}
}
for (var j = 0; j < length; j++) {
all[j].setAttribute('style', 'height:' + maxHeight + 'px')
}
}
in html:(this is pug.js)
.text_blog
!= post.content.full
p.read_more
a(href='/blog/'+post.key) leia mais >>
this is css:
.text_blog {
overflow: hidden;
height: 112px;
}
How can I change my function to work correctly.
You're setting the max-height to 0 in your javascript code.
Not knowing the full context of your code, because you only posted the javascript part, You may either have a constant height for all '.text_blog' elements or use
CSS
.text_blog{
height: auto;
overflow: scroll;
}
OR
JAVASCRIPT
const setSameHeightToAll = function() {
const all = document.querySelectorAll('.text_blog')
//GET HEIGHT OF FIRST ELEMENT AND MAKE IT UNIFORM
let maxHeight = all.firstElementChild.offsetHeight;
//SET CONSTANT HEIGHT
let maxHeight = '500px';
var length = all.length;
for (var i = 0; i < length; i++) {
all[i].setAttribute('style', 'height:' + maxHeight + 'px')
}
}
You are also forgetting to include the closing ';' at the end of some lines.
I'm trying to practice my scripting by making a Battleship game. As seen here.
I'm currently trying to make the board 2D. I was able to make a for-loop in order to make the board, however, due to testing purposes, I'm just trying to make the board, upon clicking a square, it turns red... But, the bottom square always lights up. I tried to debug it by making the c value null, but then it just stops working. I know it's not saving the c value properly, but I'm wondering how to fix this.
Do I have to make 100 squares by my self or can I actually have the script do it?
maincansize = 400;
document.getElementById("Main-Canvas").style.height = maincansize;
document.getElementById("Main-Canvas").style.width = maincansize;
document.getElementById("Main-Canvas").style.position = "relative";
var ize = maincansize * .1;
for (var a = 0; a < 10; a++) {
for (var b = 0; b < 10; b++) {
var c = document.createElement("div");
var d = c;
c.onclick = function() {
myFunction()
};
function myFunction() {
console.log("A square was clicked..." + c.style.top); d.style.backgroundColor = "red";
}
c.style.height = ize;
c.style.width = ize;
c.style.left = b * ize;
c.style.top = a * ize;
c.style.borderColor = "green";
c.style.borderStyle = "outset";
c.style.position = "absolute";
console.log(ize);
document.getElementById('Main-Canvas').appendChild(c);
} //document.getElementById('Main-Canvas').innerHTML+="<br>";
}
#Main-Canvas {
background-color: #DDDDDD;
}
<div>
<div id="header"></div>
<script src="HeaderScript.js"></script>
</div>
<div id="Main-Canvas" style="height:400;width:400;">
</div>
Here's your code with some fixes:
adding 'px' to style assignment
passing the clicked element to myFunction
var maincansize = 400;
document.getElementById("Main-Canvas").style.height = maincansize;
document.getElementById("Main-Canvas").style.width = maincansize;
document.getElementById("Main-Canvas").style.position = "relative";
var ize = maincansize * .1;
for (var a = 0; a < 10; a++) {
for (var b = 0; b < 10; b++) {
var c = document.createElement("div");
c.onclick = function(ev) {
myFunction(ev.currentTarget);
};
function myFunction(el) {
console.log("A square was clicked...");
el.style.backgroundColor = "red";
}
c.style.height = ize+'px';
c.style.width = ize+'px';
c.style.left = (b * ize)+'px';
c.style.top = (a * ize)+'px';
c.style.borderColor = "green";
c.style.borderStyle = "outset";
c.style.position = "absolute";
document.getElementById('Main-Canvas').appendChild(c);
}
}
#Main-Canvas {
background-color: #DDDDDD;
}
<div id="Main-Canvas" style="height:400;width:400;">
</div>
Here's a solution with major revamps. Since you're using a set width for the container element of your board cells you can float the cells and they will wrap to the next line. Absolute positioning tends to be a bit of a bugger. If you want 10 items per row it's as easy as:
<container width> / <items per row> = <width>
Using document fragments is faster than appending each individual element one at a time to the actual DOM. Instead you append the elements to a document fragment that isn't a part of the DOM until you append it. This way you're doing a single insert for all the cells instead of 100.
I moved some of the styling to CSS, but could easily be moved back to JS if you really need to.
function onCellClick() {
this.style.backgroundColor = 'red';
console.log( 'selected' );
}
var main = document.getElementById( 'board' ),
frag = document.createDocumentFragment(),
i = 0,
len = 100;
for ( ; i < len; i++ ) {
div = document.createElement( 'div' );
div.addEventListener( 'click', onCellClick, false );
frag.appendChild( div );
}
main.appendChild( frag );
#board {
width: 500px;
height: 500px;
}
#board div {
float: left;
box-sizing: border-box;
width: 50px;
height: 50px;
border: 1px solid #ccc;
}
<div id="board"></div>
Sorry for the long question.
I have tried to create a meetings on a calendar for a day. I need help to take care of the overlapping intervals.
The code I have written in following :
HTML
<body>
<div id="timeline"></div>
<div id="calendar" class="calendar">
</div>
</body>
CSS
.calendar {
border: 1px solid black;
position: absolute;
width: 600px;
height: 1440px;
left: 60px;
}
.event {
position: absolute;
float: left;
width: 100%;
overflow: auto;
border: 0px solid red;
}
#timeline {
position: absolute;
float: left;
}
JS
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
function creatTimeline(tl) {
var i = 0;
while (i < tl.length) {
var divEl = document.createElement('div');
divEl.style.width = '50px';
divEl.style.height = '120px';
divEl.style.border = '0px solid yellow';
divEl.innerHTML = tl[i];
var timeLine = document.getElementById('timeline');
timeLine.appendChild(divEl);
i++;
}
}
function appendEventDivs(eventArr) {
var i = 0;
while (i < eventArr.length) {
var eventEl = document.createElement('div');
eventEl.className = 'event';
eventEl.style.height = eventArr[i].height;
eventEl.style.top = eventArr[i].top;
eventEl.style.background = eventArr[i].color;
eventEl.style.width = eventArr[i].width;
eventEl.style.left = eventArr[i].left;
eventEl.innerHTML = 'Meeting' + eventArr[i].id;
var cl = document.getElementById('calendar');
cl.appendChild(eventEl);
i++;
}
}
function collidesWith(a, b) {
return a.end > b.start && a.start < b.end;
}
function checkCollision(eventArr) {
for (var i = 0; i < eventArr.length; i++) {
eventArr[i].cols = [];
for (var j = 0; j < eventArr.length; j++) {
if (collidesWith(eventArr[i], eventArr[j])) {
eventArr[i].cols.push(i);
}
}
}
return eventArr;
}
function updateEvents(eventArr) {
eventArr = checkCollision(eventArr);
var arr = [];
arr = eventArr.map(function(el) {
//just to differentiate each event with different colours
el.color = getRandomColor();
el.height = (el.end - el.start) * 2 + 'px';
el.top = (el.start) * 2 + 'px';
el.width = (600 / el.cols.length) + 'px';
return el;
});
return arr;
}
var events = [{
id: 123,
start: 60,
end: 150
}, {
id: 124,
start: 540,
end: 570
}, {
id: 125,
start: 555,
end: 600
}, {
id: 126,
start: 585,
end: 660
}];
var timeline = ['9AM', '10AM', '11AM', '12Noon', '1PM', '2PM', '3PM', '4PM', '5PM', '6PM', '7PM', '8PM', '9PM'];
function getEvents (eventArr) {
eventArr.sort(function(a, b) {
return a.start - b.start;
});
eventArr = updateEvents(eventArr);
appendEventDivs(eventArr);
console.log(eventArr);
//PART 1 - function returning the eventArr with all the required attributes
return eventArr;
};
creatTimeline(timeline);
getEvents(events);
Working fiddle here
Can anybody guide me how to take care of the overlapping intervals so that they appear side-by-side and not on top of each other.
Thanks in advance.
You need to figure out in which column each of the events should be before you can determine their width or left-position. To do this, you need to also store which of the colliding events came before each event:
function checkCollision(eventArr) {
for (var i = 0; i < eventArr.length; i++) {
eventArr[i].cols = [];
eventArr[i].colsBefore=[];
for (var j = 0; j < eventArr.length; j++) {
if (collidesWith(eventArr[i], eventArr[j])) {
eventArr[i].cols.push(j);
if(i>j) eventArr[i].colsBefore.push(j); //also list which of the conflicts came before
}
}
}
return eventArr;
}
Now, we can figure out the column of each event. Once we've done that, we can figure out how wide they should be, and with that, the horizontal positioning should be easy. This should be done inside your updateEvents function. I've got more detailed explanation commented in the comments of the code below.
function updateEvents(eventArr) {
eventArr = checkCollision(eventArr);
var arr=eventArr.slice(0); //clone the array
for(var i=0; i<arr.length; i++){
var el=arr[i];
el.color = getRandomColor();
el.height = (el.end - el.start) * 2 + 'px';
el.top = (el.start) * 2 + 'px';
if(i>0 && el.colsBefore.length>0){ //check column if not the first event and the event has collisions with prior events
if(arr[i-1].column>0){ //if previous event wasn't in the first column, there may be space to the left of it
for(var j=0;j<arr[i-1].column;j++){ //look through all the columns to the left of the previous event
if(el.colsBefore.indexOf(i-(j+2))===-1){ //the current event doesn't collide with the event being checked...
el.column=arr[i-(j+2)].column; //...and can be put in the same column as it
}
}
if(typeof el.column==='undefined') el.column=arr[i-1].column+1; //if there wasn't any free space, but it ito the right of the previous event
}else{
var column=0;
for(var j=0;j<el.colsBefore.length;j++){ //go through each column to see where's space...
if(arr[el.colsBefore[el.colsBefore.length-1-j]].column==column) column++;
}
el.column=column;
}
}else el.column=0;
}
//We need the column for every event before we can determine the appropriate width and left-position, so this is in a different for-loop:
for(var i=0; i<arr.length; i++){
arr[i].totalColumns=0;
if(arr[i].cols.length>1){ //if event collides
var conflictGroup=[]; //store here each column in the current event group
var conflictingColumns=[]; //and here the column of each of the events in the group
addConflictsToGroup(arr[i]);
function addConflictsToGroup(a){
for(k=0;k<a.cols.length;k++){
if(conflictGroup.indexOf(a.cols[k])===-1){ //don't add same event twice to avoid infinite loop
conflictGroup.push(a.cols[k]);
conflictingColumns.push(arr[a.cols[k]].column);
addConflictsToGroup(arr[a.cols[k]]); //check also the events this event conflicts with
}
}
}
arr[i].totalColumns=Math.max.apply(null, conflictingColumns); //set the greatest value as number of columns
}
arr[i].width=(600/(arr[i].totalColumns+1))+'px';
arr[i].left=(600/(arr[i].totalColumns+1)*arr[i].column)+'px';
}
return arr;
}
Working Fiddle: https://jsfiddle.net/ilpo/ftbjan06/5/
I added a few other events to test different scenarios.
Oh, and by the way, absolutely positioned elements can't float.
You already know the top and height of every event, so you could map the calendar and check an event already exist within the area it will occupy, then offset the left value by the number of existing events.
I wrote the code in Javascript but any good alternative would do.
EFFECT: onmousemove over the webpage circles of random colors should create wherever the mouse moves. and they have to be added behind a mask image(circles are visible only in the transparent portion of the image which is a logo. thus creating a color paint to create logo onmousemove.
it doesn't work in jsfidde because of its memory intensiveness.
WORKING LINK: http://goo.gl/DNRxO9
I pasted the exact code you can create a new html file with the following code and IT WORKS PERFECT IN FIREFOX ONLY because of its memory intensiveness(lots of divs added in very short time so DOM becomes very very heavy).
<html>
<head>
<style type="text/css">
body{
padding:0;
margin:0;
overflow: hidden;
}
#mask{
width:100%;
height:auto;
position:absolute;
z-index:10;
}
#logo{
width:50%;
height:50%;
margin:auto;
}
.point{
width:0px;
height:0px;
background-color:#ff0000;
position:absolute;
z-index:5;
left:50px;top:50px;
border-width:50px;
border-style: solid;
border-color:red;
border-radius:50px;
opacity:1;
transition: border-width 3s ease-in-out;
}
.no-border{border-width:0px;}
</style>
<script type="text/javascript">
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
/* OptionalCode: for removing divs after a lot are created */
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = 0, len = this.length; i < len; i++) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
i=0;
function colors(event){
var x=event.clientX;
var y=event.clientY;
var point = document.getElementsByClassName('point');
document.body.innerHTML += "<div class='point'></div>";
point[i].style.borderColor = getRandomColor();
//point[i].className += ' no-border';
point[i].style.left = x + 'px';
point[i].style.top = y + 'px';
i++;
}
function position(){
var ht = window.getComputedStyle(document.getElementById("mask"), null).getPropertyValue("height");
var ht_num = Number(ht.slice(0,ht.length - 2));
margin_top = (Number(document.body.clientHeight) - ht_num)/2;
document.getElementById('mask').style.marginTop = margin_top + "px";
}
</script>
</head>
<body onload="position();" onmousemove="colors(event)">
<img id="mask" src="http://goo.gl/EqfJ0L">
</body>
</html>
There is one HUGE, HUGE, HUGE performance killer in your code:
document.body.innerHTML += "<div class='point'></div>";
This takes your entire document, throws it away and just inserts everything back again. This is horrible! Remember this for all times and never do this again! ;)
Keep the basic rule in mind, to never add Elements via .innerHTML!
The correct way to go is the following:
// create your new div element
var circleElement = document.createElement("div");
// add all the stuff needed
circleElement.classList.add("point");
circleElement.style.borderColor = getRandomColor();
circleElement.style.left = x + 'px';
circleElement.style.top = y + 'px';
// now append the element to the body
document.body.appendChild(circleElement);
This creates a single div and nicely inserts it as a child-element of the body.
Additionally you can decrease the number of divs drawn by introducing a threshhold:
var lastX=0,lastY=0;
function colors(event){
var x=event.clientX;
var y=event.clientY;
if (Math.abs(lastX - x) + Math.abs(lastY - y) <= 10 ) return;
/* do stuff */
lastX = x;lastY = y;
}
As a third measure you can decrease the size of the image to just hold the mask element and trigger the mousemove only on the image (because divs outside the mask are hidden anyway).
Ultimately, you could kill "old" div-elements when you have reached a certain amount.
I have not included these two last optimizations, but look at the already supersmooth example now!
A friend and I are making a God-like Game for the browser. It is VERY early stages, but I already have problems with my code!
It was suggested by someone on Stack Overflow to use a 'matrix' (I think that is what he called it) for organizing the tiles that you can build on. I now have a system for reading and editing the contents of a tile, but I am not sure how I can lay out the matrix in a grid format like this:
tile 1, tile 2, tile 3
tile 4, tile 5, tile 6
tile 7, tile 8, tile 9
It would be ideal if this would work no matter how many rows and columns there were.
Here is my code so far:
var WoodHut = "Woodcutter's hut";
var TownHall = "TownHall";
var Mine = "Iron Mine";
var tiles = [];
var rowCount = 15;
var columnCount = 15;
// Assign the none string to all tiles.
for (var r = 0; r < rowCount; r++)
{
tiles[r] = [];
for (var c = 0; c < columnCount; c++)
{
var currentRow = tiles[r];
currentRow[c] = "--none--";
}
}
// NOTE TO SELF: Arrays are 0-based!
// access row 4, column 2.
// console.log(tiles[3][1]);
// Assign something to row 5 column 3.
// tiles[4][2] = WoodHut
function Build(locX, locY, type){
this.locX = X
this.locY = Y
this.type = type;
tiles[X][Y] = type;
}
function TownMap(){
// HOW DO I DO THIS???????
}
So in summary, I want to be able to call TownMap() and have a grid of tile values displayed in an alert or a console log.
Any Feedback would be great! Thanks in advance!
Wow I'm doing the same thing, only that I started 2 weeks ago.
Any way we could get in contact?
I'll show you how I did the grid:
function setup() {
// Create Grid
var grid = $('#grid');
for (var i = 0; i < tileCount; i++) {
var tile = document.createElement('div');
tile.id = "t" + (i + 1);
tile.className = "tile";
tile.onclick = function () {
deselect();
activeTile = $(this);
$(this).addClass("active");
tilePopup(this);
};
grid.append(tile);
}
//Create Menu
var menu = $('#menu');
for (var i = 0; i < buildings; i++) {
var building = document.createElement('div');
building.id = "b" + (i + 1);
//building.className = "building";
building.innerHTML = "Building " + (i + 1);
building.style.background = "url('images/buildings/" + building.id + ".png') 0 26px / 100% auto no-repeat";
building.onclick = function () {
build(this.id);
};
menu.append(building);
}
}
CSS:
#grid {
position: absolute;
width: 800px;
height: 800px;
left: 400px;
-moz-transform: rotate(-45deg) skew(15deg, 15deg);
-webkit-transform: rotate(-45deg) skew(15deg, 15deg);
-ms-transform: rotate(-45deg) skew(15deg, 15deg);
transform: rotate(-45deg) skew(15deg, 15deg);
background-image: url("images/ground.jpg");
background-size: 100% 100%;
}
.tile {
float: left;
width: 10%;
height: 10%;
outline: 1px ridge rgba(121, 121, 121, 0.8);
transition: 1s;
}