Vertically align div's but keeping horizontal position intact Vertically align div's but keeping horizontal position intact mysql mysql

Vertically align div's but keeping horizontal position intact


<!DOCTYPE html><html><!--  Created using jsbin.com  Source can be edited via http://jsbin.com/udofoq/26/edit--><head><script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script><meta charset=utf-8 /><title>JS Bin</title><style id="jsbin-css">div.blue {    background-color: #a4dcdf;}div.orange {    background-color: #fd9226;}div.green {    background-color: #88b37e;}div.yellow {    background-color: #d8d03f;}div.red {    background-color: #c16558;}div.grey {    background-color: #cdcdcd;}div.hours1{  top: 0px;  left: 10px;  width: 100px;//(110-10)}div.hours2{  top: 30px;  left: 80px;  width: 50px;}div.hours3{  top: 60px;  left: 120px;  width: 50px;}div.hours4{  top: 90px;  left: 5px;  width: 70px;}div.hours5{  top: 120px;  left: 110px;  width: 30px;}div.hours6{  top: 150px;  left: 130px;  width: 70px;}div.hours {  position: absolute;  height:20px;  color: white;  text-align:center;  border:white;  -webkit-box-shadow: 3px 3px 6px 2px rgba(00, 00, 00, .2);  box-shadow: 3px 3px 6px 2px rgba(00, 00, 00, .2);  font: bold 18px Arial, Helvetica, Geneva, sans-serif;  line-height:20px;     }button{    position:static;    margin-top:200px;}.collapse,.overlap1,.overlap2,.overlap3,reset{    float:left;}</style></head><body>  <div class="hours hours1 orange">A</div><div class="hours hours2 yellow">B</div><div class="hours hours3 blue">C</div><div class="hours hours4 green">D</div><div class="hours hours5 red">E</div><div class="hours hours6 grey">F</div><button class="collapse">collapse</button><button class="overlap1">sort</button><button class="reset">reset</button><script>data1 = [  [1, 10, 110],  [2, 80, 130],  [3, 120, 170],  [4, 5, 70],  [5, 110, 140],  [6, 130, 180]];//just added for console output not neededvar divider="";for (var i = 0; i < 80; i++) {  divider += "_";}console.log(divider);console.log("ORIGINAL ARRAY DATA1:", data1);//add a column to keep track of the row, to start set it to  row 1data1 = $.each(data1, function(index, value) {  value[3] = 0;});console.log(divider);console.log("ORIGINAL dataA WITH ADDED COLUMN:", data1);function timelinesort(dataA){//make a new Array to store the elements in with their new row numbervar dataB = dataA.slice(0, 1);console.log(divider);console.log("INITIALIZED dataB WITH FIRST ELEMENT FROM dataA:", dataB);//initialize the countervar counter = 0;console.log(divider);console.log("INITIALIZED ROUNDS COUNTER:", counter);dataA = $.map(dataA, function(value1, index1) {//increment counter with 1 counter++;console.log(divider);console.log("INCREMENTED ROUNDS COUNTER:", counter);  dataA = $.map(dataA, function(value2, index2) {    //exclude comparing an element with itself    if(value2 != dataB[0]) {      //check to see if elements overlap      if(value2[2] >= dataB[0][1] && value2[1] <= dataB[0][2]) {        console.log(divider);        console.log("Round " + counter  + " from dataA: [" + value2 + "] overlaps with " + dataB[0] + " incrementing row counter with 1");        //increment the value in column 3 (row counter) of the array        value2[3]++;        console.log(divider);        console.log("Now the dataA has changed to this:", dataA);        console.log("Meanwhile data1 has changed to this:", data1);      } else {        //if no overlap occurs check if the element is not already in the dataB array and if not check if it doesn't overlap with the existing elements        if($.inArray(value2, dataB) == -1) {          $.each(dataB, function(index3, value3) {            if(value3[2] >= value2[1] && value3[1] <= value2[2]) {              console.log(divider);              console.log("Round " + counter + " from dataA: [" + value2 + "] overlaps with " + value3 + " incrementing row counter with 1");              dataB.pop();              //increment the value in column 3 (row counter) of the array              value2[3]++;            } else {              //if no overlap occurs add the value to dataB              dataB.push(value2);              console.log(divider);              console.log("Added [" + value2 + "] to dataB and now dataB has changed to this: ", dataB);            }          });        } else {          dataB.push(value2);          console.log("Added [" + value2 + "] to dataB and now dataB has changed to this: ", dataB);        }      }    }    return [value2];  });  dataA = jQuery.grep(dataA, function(item) {    return jQuery.inArray(item, dataB) < 0;  });  if(dataA.length >= 1) {    dataB.unshift(dataA[0]);    dataB = dataB.splice(0, 1);  } else {    dataA = [];  }});}//run the functiontimelinesort(data1);console.log(divider);console.log("Finally the data1 has changed to this:", data1);$(".collapse").click(function() {  $.each(data1, function(index, value) {    $("div.hours" + (index + 1)).animate({      "top": 0    }, "slow");  });});$(".overlap1").click(function() {  $.each(data1, function(index, value) {    console.log("div.hours" + (index + 1) + ":" + (value[3]) * 26);    $("div.hours" + (index + 1)).animate({      "top": (value[3]) * 26    }, "slow");  });});$(".reset").click(function() {  $.each(data1, function(index, value) {    $("div.hours" + (index + 1)).removeAttr('style');  });});</script></body></html>

What I did was collapse all rows onto the first row, then check which ones overlapped with the originals of that row and if so increment the row number over the overlapping ones, then go to the next row and repeat the process until all elements are neatly stacked.

You still have to clean up the javascript/jquery stuff and put it in a nice function or so. But as proof of concept it seems to work

working example:


http://jsbin.com/udofoq/26/watch

or

http://jsfiddle.net/stofke/7VP5U/


Check out my fiddle here. I think it does what you need with unlimeted number of blocks. Blocks data is taken from HTML-table.

JS:

var data = [],    rows = [],    chart = $('.wrapper-inner');function DataItem(id, name, start, end){     this.id = id;     this.name = name;     this.start = start;     this.end = end;}$('.data tr').each(function() {    var $this = $(this),        item = new DataItem( $this.find('td:eq(0)').text(),                             $this.find('td:eq(1)').text(),                             $this.find('td:eq(2)').text(),                             $this.find('td:eq(3)').text() );        data.push(item);});function addRow(){    var row = {        el : $('<div class="row"></div>').appendTo(chart),        positions: []    };    rows.push( row );}function checkRow(rowId, item){            var isRowAvailible = true;    for (var i = 0; i < +item.end - +item.start; i++){        if (rows[rowId].positions[+item.start + i]){            isRowAvailible = false;            break;        }    }    return isRowAvailible;}function markRowPositions(rowId, item){    for (var i = 0; i < item.end - item.start; i++){        rows[rowId].positions[+item.start + i] = true;    }}function addItems(){    for (var i = 0; i < data.length; i++){        (function(i){            setTimeout(function() {addItem(data[i])}, 100 * i);        })(i)    }}function addItem(item){    var rowToAdd = false,        itemEl = $('<div class="item"></div>');    for (var i = 0; i < rows.length; i++){        if ( checkRow(i, item) ){            rowToAdd = i;            break;            }    }    if (rowToAdd === false){        addRow();        rowToAdd = rows.length - 1;    }    rows[ rowToAdd ].el.append(itemEl);        console.log(itemEl.css('opacity'))    itemEl.css({        'left': item.start * 30,        'opacity' : 1,        'width': ( ( item.end - item.start ) * 30 ) - 2    });    markRowPositions(rowToAdd, item);}addItems();


your question sounds very naive but it is actually include some complex elements if needed to be resolved in the most OPTIMISED way.

the quick answer of what I probably would do to generate your display -

  1. use the provided function that adds the row number to your table
  2. use your PHP code to generate a DIV container withstyle="display:block" for every row

  3. inside the row generate appropriate size DIV (end-start * scale)with style="display:inline-block; float:left; display:relative" and (EDIT:) add transparent DIV elements to compensate for the white spaces you need. (i.e. from 0 to start and from the end to the start of the next DIV)

  4. add the name field inside the DIV element

use mySchema;drop procedure if exists tileItems;

DELIMITER $$CREATE PROCEDURE tileItems ()BEGINDECLARE p_id, p_start, p_end, p_row int;DECLARE done INT DEFAULT FALSE;DECLARE cur1 CURSOR FOR SELECT id, start, end FROM tasks order by start, id;DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;drop temporary table if exists tiles;create temporary table tiles (row int(11) NOT NULL,id int(11) NOT NULL,end int(11) NOT NULL);-- row field will indicates the row number the task should apearOPEN cur1;next_task: LOOPFETCH cur1 into p_id, p_start, p_end;  IF (done) THEN    LEAVE next_task;  END IF;select min(row) from (select row, max(end) me from tiles t2 group by row) t1   where me < p_start  into p_row;-- take care of row numbering  IF (p_row IS NULL) then  select max(row) from tiles    into p_row;    IF (p_row IS NULL) then      SET p_row = 0;    END IF;    SET p_row=p_row+1;END IF;insert into tiles (id, row, end)  values (p_id,p_row,p_end);END LOOP;-- CLOSE cur1;-- here is your output, on the PHP/.Net code you should loop on the row select tasks.*, tiles.row from tasksinner join tiles on tasks.id = tiles.idorder by tiles.row, tasks.start;END $$DELIMITER ;   

here is the table I used to check it -

CREATE TABLE `tasks` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,  `start` int(11) NOT NULL,  `end` int(11) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=11 ;INSERT INTO `tasks` (`id`, `name`, `start`, `end`) VALUES(1, 'A', 2, 6),(2, 'B', 5, 7),(3, 'C', 8, 10),(4, 'D', 1, 5),(5, 'E', 6, 7);

few words regarding optimisation (one of my favourite subjects :) - in this code there is no optimisation, it means that the task will be allocated to the first available line.in order to minimise the number of lines its possible (but will take some time) to create a function that uses Heuristic method to resolve this problem.

output:

id  name    start   end row4   D   1   5   15   E   6   7   13   C   8   10  11   A   2   6   22   B   5   7   3