Draw an image as an HTML table - javascript

This is my JSFiddle : http://jsfiddle.net/0r16e802/4/
What I am trying to do is taking the image and draw it as an HTML table
2 big problem in my algorithm
I can seem to be able to draw the images and only the first image is loaded in the first row
big problem in the size and the background-position
var Append="";
$(document).ready(function(){
var row=2;
var ItemPerRow=10;
CreateEmojiTable(row, ItemPerRow);
function CreateEmojiTable(row, ItemsPerRow){
Append+="<table width='99%' style='padding-top:3px;'>";
for(var i=0;i<row;i++)
{
Append+="<tr>";
DrawEmoji(ItemsPerRow, i);
Append+="</tr>";
}
Append+="</table>";
$("#emoji_container").html(Append);
}
function DrawEmoji(ItemsPerRow, r){
var size=16;
for(var i=0;i<ItemsPerRow;i++){
Append+="<td>"
Append+="<div class='emoji' style='background-position:0px -"+parseInt(r*i*size)+"px;'></div>";
Append+="</td>";
}
}
});

EDIT: corrected indexing
As suggested by Jovan, the indexing should be as he says:
(r*ItemsPerRow + i) * size
But it's still misaligned so you'll have to correct it like this:
(r*ItemsPerRow + i) * size - 2
Then, you don't want to go beyond the actual maximum index, which is 262, or you'll have repetitions and misalignments as I told in the comment above.
Here is the full solution. It fixes indexing, alignment and maximum index: http://jsfiddle.net/0r16e802/12/
The emojis in the image are aligned to 17 pixels, not 16.
var size=17;
This aligns them to one another, but you'll still have to solve the border conditions, which are 1 pixel off.
To do this, fix the CSS by 1 pixel:
height:16px;
Finally, fix the size computation by subtracting 1:
parseInt(r*i*size - 1)
Here is the solution: http://jsfiddle.net/0r16e802/5/

I don't think any of the previously posted answers are correct, even if they do happen to work for the first two rows.
The way your sprite is organized, you are looking for:
parseInt( (r*ItemsPerRow + i) * size)

As #pid already said, the sizing was somewhat out by a pixel but also the first row repeats because of i=0 The offset height of the first row ends up being worked out as 0. You also have a 'squidgy' factor for whatever reason of needing to -2 from the height to make them align properly, probably an issue with the original image.
function DrawEmoji(ItemsPerRow, r) {
var size = 17;
for (var i = 0; i < ItemsPerRow; i++) {
Append += "<td>"
Append += "<div class='emoji' style='background-position:0px -" + parseInt((r + 1) * (i + 1) * size - 2) + "px;'></div>";
Append += "</td>";
}
}
});
http://jsfiddle.net/0r16e802/9/

Related

How to set the width of each header cell in a table (with fixed header) to be the same to the biggest in its column, and make the browser respect it?

Here is the infamous table:
My boss wants me, at this time of the year, to make the header of the table fixed, so the user can scroll down the table and continue reading the header. I want to preserve the original precomputed dimensions of the table, I mean, the width that every column has at the moment of its creation (widths aren't established by CSS) and then, adapt the header so its columns match the columns of the body. Following some of the answers I found in Stackoverflow, I started making the header and the body of the table display: block. And after that, I wrote this:
function setTableHeadDimensions() {
var $taskTable = $('.tablaTareas_PEMVISUALIZA'),
$firstRow = $taskTable.find('tbody > tr:first-child'),
$firstRowTds = $firstRow.find('td'),
$firstRowHead = $taskTable.find('thead > tr:first-child'),
$secondRowHead = $taskTable.find('thead > tr:eq(1)'),
$firstRowHeadThs = $firstRowHead.find('th'),
$secondRowHeadThs = $secondRowHead.find('th'),
i = 0,
cells = [];
//We prepare CSS, so we can specify width.
$taskTable
.css('table-layout', 'fixed')
.find('td, th').each(function () {
var $tdh = $(this);
$tdh.css('box-sizing', 'border-box');
$tdh.css('overflow', 'hidden');
});
//Cells of the first row of the table head.
for (i = 0; i < 3; i++) {
cells.push($($firstRowHeadThs[i]));
}
//Cells of the second row of the table head.
for (i = 0; i < $secondRowHeadThs.length; i++) {
cells.push($($secondRowHeadThs[i]));
}
//Rest of the cells for the first row.
for (i = 5; i < $firstRowHeadThs.length; i++) {
cells.push($($firstRowHeadThs[i]));
}
//Try to set the width of the current column's header cell
//to the biggest cell width in the column.
for (i = 0; i < cells.length; i++) {
var maxWidth = 0;
$taskTable.find('td:nth-child(' + (i + 1) + ')').each(function () {
var $el = $(this);
maxWidth = Math.max(maxWidth, $el.width());
});
cells[i].width(maxWidth);
}
}
But, as you can see in the picture, the browser doesn't want to cooperate. What's more, it establishes the width of the cell, but to a number that doesn't match the width of it's corresponding column:
What's more, it doesn't match the width of the row it should match:
So I have two questions:
Why does the browser behave in the way it does?
How can I solve this problem in a way compatible with IE8? (no fancy CSS3 solution, please)
Here's a codepen with the example cut down to the minimum necessary: Codepen example
I solved it. In reality, there were two problems:
The first one is that jQuery.width() returns only the width of the content of the cell, without padding and margin (even if you specify border-sizing: border-box). I found more natural to use jQuery.css('width') and then take borders and padding into account in my calculations, without specifying border-sizing: border-box because retrieving the width with border-sizing: border-box and then setting it in another element with the idea of matching both widths can be error prone (I had problems with it).
The second one is if you use rowspan in the header of the table. In that case, you have to establish the width of the rows envolved doing the proper calculations, not only one of them hopping that the rest of the rows will adapt.
Here's the codepen with the solution: http://codepen.io/PolarKuma/pen/BQXMbO

make both editors in the same size when they autogrowing

I'm using two CKEDITOR's editors in one page, and I them to be in the same size all the time. I'm using the auto grow plugin, so I tried it:
CKEDITOR.plugins.addExternal( 'autogrow', location.href + 'ckeditor/autogrow/', 'plugin.js' );
var e1 = CKEDITOR.replace("heb_editor", {extraPlugins: 'autogrow'});
var e2 = CKEDITOR.replace("eng_editor", {extraPlugins: 'autogrow'});
e1.on("resize", r);
e2.on("resize", r);
function r(){
if($("#cke_1_contents").height() > e2.config.height)
$("#cke_2_contents").height($("#cke_1_contents").height());
else
$("#cke_1_contents").height($("#cke_2_contents").height());
}
it didn't worked. It did resized the second editor to the size of the first one, but it didn't resized the first to the size of the second when it was needed. What to do?
Here is a JSfiddle: http://jsfiddle.net/povw33x7/
Forget all I said before (I deleted it, but you can still see it in the revision history).
Using some code I found on this Web site, you can calculate the height of the box. Now, you just need to apply that to update the box heights on resize:
function getBoxHeight(boxId) {
// using a function to get the height of the box from ==>
var ckeditorFrame = $('#' + boxId + ' iframe');
var innerDoc = (ckeditorFrame.get(0).contentDocument) ? ckeditorFrame.get(0).contentDocument : ckeditorFrame.get(0).contentWindow.document;
var messageHeight = $(innerDoc.body).height();
return messageHeight ? messageHeight : 0;
}
function r() {
if (getBoxHeight("cke_1_contents") > getBoxHeight("cke_2_contents")) {
$("#cke_2_contents").height($("#cke_1_contents").height());
} else {
$("#cke_1_contents").height($("#cke_2_contents").height());
}
}
As you can see on this JSFiddle: http://jsfiddle.net/povw33x7/3/. This solution is cleaner than the other one, although it still has a glitch as it may leave an extra empty space (the height of a line) in one of the boxes.

How to change the left attribute on page resize (jQuery)

I'm having slight troubles with my code. What I'm trying to do is make these element's css property 'left' update according to the difference of it's current left value, and the amount the page resizes. This way, when the page resizes and the background moves over, the elements will move too. Take a look at the code below and I'll describe the issue:
$(window).resize(function() {
var docWidth = $(window).width();
if (docWidth < 1000) {
var difference = 1000-docWidth;
$('#headNav a,#icons div').each(function() {
var left = $(this).position().left;
var newLeft = left - difference;
$(this).css({ 'left' : newLeft });
});
}
});
So the issue that I'm getting is the elements are being given left values of wild numbers, while the value of the variable 'newLeft' is the reasonable, desired value. The each function I think is collecting the sums of these values and running them for each element x amount of times that the elements found exist (so if there's 5 elements it runs 5 times, I mean.) What I want is this code to execute uniquely for each element, but just once each, not each element 10 times! (that's how many elements are in the html).
So my question is, how can this be achieved? I hope I explained myself well enough, this was tough to iterate. Any help is extremely appreciated. Thank you!
Here's a fun trick: Include += in your .css() call:
$(this).css({left: "+=" + difference});
jQuery does the math for you to get the new value.
Try this:
$(window).resize(function() {
var docWidth = $(window).width();
if (docWidth < 1000) {
var difference = 1000-docWidth;
$('#headNav a,#icons div').each(function(iconInst) {
var left = $("#" + iconInst).position().left;
var newLeft = left - difference;
$("#" + iconInst).css({ 'left' : newLeft });
});
}
});

Webpage layout breaking on window resize

The images below illustrate what the actual problem is
So as you can see this is a puzzle, and is being created by javascript. Each row is created like this.
document.write("<div style='float:none'>");
for(i=0; i < 4 ; i++) {
for(j=0; j < 4 ; j++) {
imgArray[i] = "Images/" + x + ".jpg";
document.write("<img id= " + x + " src='Images/" + x + ".jpg' width='120' height='120' style='position:relative;top:50px;left:50px' onclick='checkMove(parseInt(id))'/>");
x = x + 1;
}
document.write("<br>");
}
document.write("</div>");
Even using float style keeps this problem. Is there a way to lock a window not to be resized smaller than x? Could you please point me in the right direction as in what im doing wrong, or not doing.
Have you tried to add a fixed width to your div?
<div style='float:none;width:480px;'>
If you give your div a width (in px), resizing will cause a scrollbar to appear.
document.write("<div style='float:none;width:600px'>");
Just use css to set the width of the container div to the width of 4 images, which should be 480px.
Try putting
white-space: nowrap;
on the style of the div. That should prevent its contents from wrapping. Instead you'll get a horizontal scrollbar.
Also consider min-width http://www.w3schools.com/jsref/prop_style_minwidth.asp and the CSS equivalent.

Javascript to turn an unordered list into multiple columns

There doesn't seem to be an easy way in (well supported) css to do this. I'm looking for a javascript solution, preferably jQuery.
I have an unordered list like this:
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<li>E</li>
...etc
</ul>
I want each column to have a height for example four items and fill vertically rather than horizontally like a css float:
A E
B F
C
D
You will want to use a combination of CSS and jQuery, but in theory it is very simple. Render a complete single list in HTML, then provide a wrapper via jQuery and split the list up as desired. The following function does just that. Be sure to use a more specific selector than just ul when actually using the script. An id would be ideal.
View demo here.
jQuery(function ($) {
var size = 4,
$ul = $("ul"),
$lis = $ul.children().filter(':gt(' + (size - 1) + ')'),
loop = Math.ceil($lis.length / size),
i = 0;
$ul.css('float', 'left').wrap("<div style='overflow: hidden'></div>");
for (; i < loop; i = i + 1) {
$ul = $("<ul />").css('float', 'left').append($lis.slice(i * size, (i * size) + size)).insertAfter($ul);
}
});
See this article:
One of the minor holy grails of XHTML
and CSS is to produce a single,
semantically logical ordered list that
wraps into vertical columns.
I’ll warn you up front. If you want to
present a list in multiple columns,
you’ll have to compromise. You can
sacrifice W3C web standards and use
deprecated markup, you can live with
markup that’s less than semantically
logical, you can tolerate a mixture of
presentation with content, you can say
goodbye to browser compatibility, or
you can use markup that’s heavy with
attributes and styling that’s heavy
with rules. Every road exacts a toll.
http://www.alistapart.com/articles/multicolumnlists/
The "best" solution is subjective, but I'd be inclined towards arbitrary classes.
Doug's solution is nice if you want to split the list up into sub lists.
Instead I chose to position the list elements without changing the dom.
This is a bit messy, basically it puts a left margin on each element which is the column number multiplied by the column width.
This will result in a staircase layout so the next step was to add some negative top margin to bring each element up to the top.
Basically this displays as a grid. I am using this for drop down menus so it worked well. Avoid using this if you need each list item to have a dynamic height. The col_height variable could be set to the height of the largest item to make the code a bit more general purpose.
var col_max_height = 6; //Max Items per column
var col_width = 200; //Pixels
var col_height = 33; //Pixels
$('.header ul li ul').each(function() {
$(this).find('li').each(function(index){
column = parseInt(index/col_max_height);
$(this).css('margin-left', column * col_width + 'px')
if(column > 0) {
$(this).css('margin-top', (index - (col_max_height * column) + 1) * -col_height + 'px').addClass('col_'+column);
}
});
});
#Keyo, thanks for your helpful answer.
Just a few modification needed to make it work on my end.
(Formula was changed, perhaps it could help someone)
var col_max_item = 2; //Max Items per column
var col_width = $('.header ul li').css('width').replace("px", ""); //Pixels, get width from CSS
var col_height = $('.header ul li').css('height').replace("px", ""); //Pixels, get height from CSS
$('.header ul').each(function() {
$(this).find('li').each(function(index){
column = parseInt(index/col_max_item);
$(this).css('margin-left', column * col_width + 'px')
if(column > 0 && (index / col_max_item) == column) {
$(this).css('margin-top', (col_max_item * col_height * -1) + 'px').addClass('col_'+column);
}
});
});
for this I use a plugin called "Easy List Splitter". here is the link:
http://www.madeincima.it/en/articles/resources-and-tools/easy-list-splitter-plugin/
Just a little different moves up the next column instead of each li.
var col_max_height = 6; //Max Items per column
var col_width = 120; //Pixels
var prevCol = 0;
$('.header ul').each(function() {
$(this).find('li').each(function(index){
column = parseInt(index/col_max_height);
$(this).css('margin-left', column * col_width + 'px')
if(prevCol != column) {
$(this).css('margin-top', '-92px').addClass('col_'+column);
prevCol = column;
} else {
$(this).css('margin-top', '0px').addClass('col_'+column);
}
});
});
You can do this really easily with the jQuery-Columns Plugin for example to split a ul with a class of .mylist you would do
$('.mylist').cols(2);
Here's a live example on jsfiddle

Categories

Resources