Add a div with cordinates given in another - javascript

I want to put a div in another with cordinates given by input text fields. The added span should be with relative positions to parent's cordinates.
The problem is that it doens't add anything but yet it changes the position of the canvas.
<html>
<head>
<style>
#rectangle { position: relative; }
</style>
<body>
300 x 300 px MAX<br/>
<canvas id="rectangle" width="300" height="300"></canvas>
<br/>
<table>
<tr>
<td>Horizontal starting cordinate:</td>
<td><input type="text" id = "x" value = ""/></td>
</tr>
<tr>
<td>Vertical starting cordinate:</td>
<td><input type="text" id = "y"/></td>
</tr>
<tr>
<td>Width of the rectangle:</td>
<td><input type="text" id = "width"/></td>
</tr>
<tr>
<td>Height of the rectangle:</td>
<td><input type="text" id = "height"/></td>
</tr>
<tr>
<td></td>
<td><input type="button" id = "draw" value = "Click"/></td>
</tr>
</table>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$("#draw").click(function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
var x1 = parseInt($("#x").val());
var y1 = parseInt($("#y").val());
var width = parseInt($("#width").val());
var height = parseInt($("#height").val());
$("#rectangle")
.add("div")
.css("id", "right-zone")
.css("z-index", "5")
.css("position", "absolute")
.css("left", x1)
.css("top", y2)
.css("width", width)
.css("height", height)
.css("background-color", "#FF0000")
.css("border", "solid red 1px");
});
})
</script>
Any ideas what's wrong ?

You should probably be using .append() instead of .add(). .add() will not add a div to the DOM, but an element to a set of matched elements.
Edit: on second thought, I see you are trying to append a div to a canvas element. You might be interested in checking this, where it is stated:
The contents of the canvas element, if any, are the element's fallback
content.
So you should probably replace your canvas element with a div. That, or edit your question to better reflect this detail.

There are a few "bugs" in your code, both html and JS.
Here is a working example: http://jsfiddle.net/kGd2G/1/
I.e. use div instead of canvas
<div id="rectangle" style="width: 300px; height: 300px;"></div>
To simplify JS, I used a "template div" to set some defaults for the rectangle that would be added.

Related

Count Table Rows Hidden In Overflow with Javascript

I have a bootstrap 3 dashboard where I am hiding the overflow in a particular div. I need to be able to identify the number of table rows hidden in the overflow that are not visible in the div. jQuery method preferred but vanilla JS also fine.
have been trying to sort this out and have not been able to find any ways so far to count the number of rows that are hidden in overflow.
NB: There is no markup difference between the rows that are visible and those that are not visible as CSS is used to hide the excess rows using overflow: hidden; on the parent DIV.
Thanks.
Additional #1
Here is the HTML I am working with. The height is set by javscript at runtime.
<div id="jobs-list" class="box-body no-padding job-list" style="overflow: hidden;">
<table class="table">
<tbody>
<tr>
<th>Account</th>
<th class="text-center">Due</th>
</tr>
<tr>
<td>
Customer 1 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 2 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 3 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 4 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center">-- TOMORROW --</td>
</tr>
</tbody>
</table>
</div>
<div class="box-footer text-center">
152 More Jobs
</div>
As you can see in the example above I am using a bootstrap 3 box to contain the data. The height of .box-body is set using javascript (which works fine already and is based on the window height). By using the overflow: hidden; CSS rule instead of showing scroll bars on .box-body the overflow is hidden and not visible. I need to be able to adjust the text in .box-footer using javascript to identify the number of rows that are not visible.
Now there is a mathematical approach to this problem, suppose that all the children have the same height (or width, depends on your aligning) :
console.log($('#main div').length - $('#main').height()/$('#main div').height());
#main {
height:200px; /*Suppose 200px*/
overflow:hidden;
}
#main div {
height:100px;
border:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div>
Hello 1
</div>
<div>
Hello 2
</div>
<div>
Hello 3
</div>
<div>
Hello 4
</div>
<div>
Hello 5
</div>
</div>
Thanks for all the answers...
I was able to find a way to do this using jQuery and a jQuery extension by Kevin Marx.
Firstly you need to add the jquery.overflowing.js plugin to the page...
/* Overflowing.js
*
* A plugin based on Elving Rodriguez's Overflowed
* http://elvingrodriguez.com/overflowed
*
*/
(function($){
$.fn.overflowing = function(options, callback){
var self = this
var overflowed = []
var hasCallback = callback && typeof callback === 'function' ? true : false;
var status = false
this.options = options || window
this.each(function(){
var $this = $(this)
elPosition = $this.position()
elWidth = $this.width()
elHeight = $this.height()
var parents = $this.parentsUntil(self.options)
var $parentsTo = $(self.options)
parents.push($parentsTo)
for(var i=0; i<parents.length; i++){
var parentPosition = $(parents[i]).position()
var parentWidth = $(parents[i]).width()
var parentHeight = $(parents[i]).height()
if ( elPosition.top<0
|| elPosition.left<0
|| elPosition.top>(parentHeight+parentPosition.top)
|| elPosition.left>(parentWidth+parentPosition.left)
|| (elPosition.top + elHeight) > (parentHeight+parentPosition.top)
|| (elPosition.left+elWidth) > (parentWidth+parentPosition.left)){
status = true
$(parents[i]).addClass('overflowed')
overflowed.push(parents[i])
if (hasCallback) callback(parents[i])
}
}
if($this.parents(self.options).hasClass('overflowed')) $this.addClass('overflowing')
})
if (!hasCallback) return overflowed.length > 1 ? overflowed : status
}
})(jQuery)
Then you run...
$("tr").overflowing("#jobs-list");
Which through the overflowing plugin adds the class overflowing to each overflowing row (first selector) within the target parent (second selector).
At this point it is a simple case of using jQuery's .length property and a selector to target only the .overflowing classes within the target object you are wanting to calculate for, ie...
var hiddenRows = $("#jobs-list .overflowing").length;
I'm unsure by what you mean by 'hidden by overflow'. Does that mean include stuff that's partially hidden, or things that are fully hidden only? My solution includes partially hidden as 'not hidden'.
Regardless, offset is your best solution.
let jobs = $("#jobs-list");
let offset = jobs.offset().top;
let height = jobs.height();
let tr = $("tr", $("#jobs-list")).toArray();
let stopped = 0;
for (let i in tr)
{
let total_offset = $(tr[i]).offset().top - offset;
if (total_offset >= height)
{
stopped = i;
break;
}
}
console.log("hidden:", tr.length - stopped);
#jobs-list {
height: 80px;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jobs-list" class="box-body no-padding job-list" style="overflow: hidden;">
<table class="table">
<tbody>
<tr>
<th>Account</th>
<th class="text-center">Due</th>
</tr>
<tr>
<td>
Customer 1 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 2 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 3 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center text-green">-- TODAY --</td>
</tr>
<tr>
<td>
Customer 4 (MCB#123456789)<br />
<small>Job name</small>
</td>
<td class="text-center">-- TOMORROW --</td>
</tr>
</tbody>
</table>
</div>
<div class="box-footer text-center">
152 More Jobs
</div>
Found this: Count List Items shown on screen and not overflow
Working jQuery example: https://jsfiddle.net/Twisty/jzmqfeyj/
JavaScript
$(function() {
//Add random count of jobs
var i = 0;
for (i = 0; i < Math.floor(Math.random() * 100); i++) {
$("#jobs-list tbody").append($("#jobs-list table tbody tr:last").clone());
}
console.log("Created", i, "Jobs");
console.log("Total", $("#jobs-list table tbody tr:not('.header')").length, "Jobs");
var mh = $("#jobs-list").height();
var overflowed = $("#jobs-list table tbody tr:not('.header')").filter(function() {
return $(this).position().top + $(this).height() > mh;
});
console.log("Invisible", overflowed.length, "Jobs");
$(".job-number").html(overflowed.length);
});
Since :visible counts only items that are hidden, you can't really use it. We can .filter() on items that are in our "viewport" or not in overflow. We know the height of each element and the div. Anything greater than the height of the div, we count.

showing html table tag name by mouse click or hover

I have written an html code which show a table. Now what i want to do is like that, clicking or hovering mouse over the table then the tag name will show. As i am new in jquery i am unable to organize the logic in jquery.
The following html code generate a simple table
<div class="css">
<table>
<thead>
<tr>
<th>User</th>
<th>Country</th>
<th>City</th>
<th>BithDate</th>
</tr>
</thead>
<tbody>
<tr>
<td>abc</td>
<td>abc</td>
<td>abc</td>
<td>abc</td>
</tr>
<tr>
<td>cdf</td>
<td>cdf</td>
<td>cdf</td>
<td>cdf</td>
</tr>
</tbody>
</table>
</div>
the out put
Now what i want to do is like that when i click on user/country it will show: "thead: th" and when i point mouse on abc or cdf it will show: "tr: td".
what i thought to do is using click event for each tr td . but is there any other way to do that. Thanks in advance!!
Try following,
$('table').click(function(event){
// The event.target property returns which DOM element triggered the event.
//
var elem = event.target.nodeName;
// use this value to display in your way.
})
Demo
Something like this?
var $display = $('<div>TEST</div>');
$display
.css({
position: 'absolute',
background: '#fff',
border: '1px solid #000',
padding: '2px 8px'
})
.appendTo('body');
$(document).mousemove(function(e){
var offset = $display.width() / 2;
$display.css({
top: e.pageY + 20,
left: e.pageX - offset
});
});
$('*').not($display).mouseenter(function(e){
var tags = $(this).parents().map(function(){
return this.tagName;
}).get().reverse().join(': ');
$display.html(tags);
});

HTML drag event does not fire in firefox

I have a table on which I need to implement draggable header columns. I implemented it using Chrome as my browser, and everything worked fine. When I tested it in Firefox (17.0.1), I noticed that the drag event doesn't fire. dragstart does, though. I simplified the problem in the markup below. When loaded in Chrome, the top label updates each time the mouse moves while dragging. In Firefox it remains 0.
<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style>
table,td,th {
border: solid thin black;
}
</style>
<script>
$(document).ready(function() {
$("th").bind("drag", function(event) {
$("#lbl").html(event.originalEvent.offsetX);
});
});
</script>
</head>
<body>
<span id="lbl">0</span>
<table>
<thead>
<tr>
<th draggable="true">Column A</th>
<th draggable="true">Column B</th>
</tr>
</thead>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
</table>
</body>
</html>
I had nightmares fixing this issue for Firefox. I needed to drag a div onto a diary and detect the coordinates of the drop so I knew which date and time the user had selected.
To get the drag event to fire I added the below line to the dragstart event handler:
event.dataTransfer.setData('Text', this.id);
However, the hardest thing to work out was how to get the x and y coordinates when the drag ended, as these are not returned in the dragend event handler in Firefox. I tried using mouse events as mentioned above, but I found that these did not work while the drag is in progress and are only called after the dragend event handler has been called. So, I only used the dragend event to detect when the user had released the div, and then used the next mouse moved event to get the coordinates and do any other work that is required. I found this works in IE, Firefox and Chrome.
Here is the html / javascript of a demo:
<div>
<div id = "todrag" class = "testdiv" draggable="true"><p>Please drag me</p></div>
<div id = "destination" class = "testdiv"><p>To here</p></div>
<p id = "coords"></p>
<p id = "compareords"></p>
</div>
<script>
var down = true;
var m_xcoordDrag = 0;
var m_ycoordDrag = 0;
var m_xcoordMove = 0;
var m_ycoordMove = 0;
var m_dragReleased = false;
var m_coordselement = document.getElementById("coords");
var m_compareordselement = document.getElementById("compareords");
function OnMouseMove(e) {
m_xcoordMove = e.x;
m_ycoordMove = e.y;
m_coordselement.innerHTML = e.x + "," + e.y;
if (m_dragReleased) {
m_compareordselement.innerHTML = "X:" + m_xcoordDrag + ", " + m_xcoordMove + " Y:" + m_ycoordDrag + ", " + m_ycoordMove;
m_dragReleased = false;
}
}
dragstart = function (event) {
event.dataTransfer.setData('Text', this.id);
stop = false;
}
dragend = function (event) {
m_dragReleased = true;
m_xcoordDrag = event.x;
m_ycoordDrag = event.y;
}
document.onmousemove = OnMouseMove;
var toDrag = document.getElementById("todrag");
toDrag.addEventListener('dragstart', dragstart);
toDrag.addEventListener('dragend', dragend);
</script>
I hope this helps!
The bit that has been cut out http://pastebin.com/bD2g3SqL
EDIT:
This does work, however I'm yet to find a way to access the offsetX and offsetY properties, for some reason FF version of the event does not contain them.
<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<style>
table,td,th {
border: solid thin black;
}
</style>
<script>
function Init(){
var n= document.getElementsByTagName("th");
var j=0;
for (var i=0; i<n.length; i++){
n[i].addEventListener('drag', function (e){
document.getElementById("lbl").textContent= j++;
}, false);
}
for (var i=0; i<n.length; i++){
n[i].addEventListener('dragstart', function (e){
e.dataTransfer.setData('text/plain', 'node');
}, false);
}
}
</script>
</head>
<body onload="Init();">
<span id="lbl"></span>
<table>
<thead>
<tr>
<th draggable="true">Column A</th>
<th draggable="true">Column B</th>
</tr>
</thead>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
</table>
</body>
</html>
Apparently, what you need to do is to "initialize" the drag (source.)
EDIT2:
Apparently, there's a bug in the drag event (go figure) which does not update the clientX and clientY properties (source.) They are updated on some other events, like the dragover event, however that event will fire only while the object is being dragged over a plausible drop target. A way out of such a silly situation would be something as crude as this:
<!DOCTYPE html>
<html>
<head>
<title>TH Drag Test</title>
<style>
table,td,th {
border: solid thin black;
}
</style>
<script>
var down= false;
document.onmousemove= OnMouseMove;
function Init(){
var n= document.getElementsByTagName('th');
for (var i=0; i<n.length; i++){
n[i].onmousedown= OnMouseDown;
}
document.onmouseup= OnMouseUp;
}
function OnMouseDown(e){
down= true;
}
function OnMouseUp(e){
down= false;
}
function OnMouseMove(e){
if (!down) return;
document.getElementById('lbl').textContent= e.pageX ? ('x: ' + e.pageX + ' y: ' + e.pageY) : ('x: ' + (e.clientX + document.documentElement.scrollLeft + document.body.scrollLeft) + ' y: ' + (e.clientY + document.documentElement.scrollTop + document.body.scrollTop));
}
</script>
</head>
<body onload="Init();">
<span id="lbl"></span>
<table>
<thead>
<tr>
<th draggable="true">Column A</th>
<th draggable="true">Column B</th>
</tr>
</thead>
<tbody>
<tr>
<td>One</td>
<td>Two</td>
</tr>
<tr>
<td>Three</td>
<td>Four</td>
</tr>
</tbody>
</table>
</body>
</html>
Firefox requires 'something' (that we call 'init' here) to be set in dragstart event to initialize the rest of drag events to occur.
This is probably because all of the DOM elements are draggable="true" by default in XUL. (reference: https://bugzilla.mozilla.org/show_bug.cgi?id=646823#c4)
Example:
<div id="something" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'node');">Drag me</div>
Chrome doesn't require such 'initialization'.

Absolutely Position DIV to the right of the last selected (by class) TD cell in a table row

I have a table like this;
<table class="std-table">
<tbody><tr>
<td>DATA</td><td>DATA</td>
</tr>
<tr class="selected-trial">
<td>DATA</td><td>DATA</td>
</tr>
<tr>
<td>DATA</td><td>DATA</td>
</tr></tbody>
I also have a div on the same level that has an image (arrow) as it's background:
<div class=selected-trial-marker></div>
The CSS is controls the basics of the marker element but what I haven't assigned is top and left values. What I'm trying to do is when the page is ready use JQuery to find out the position of the 'selected' row and position the marker element to the right of it.
This is my code thus far:
$('table.std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('table.std-table tbody tr.selected-trial').offset();
var leftOffset = $('table.std-table').width();
leftOffset += offset.left +42;
var topOffSet = (offset.top);
topOffSet = topOffSet+3;
$('.trial-selection-marker').css({'top':topOffSet+'px', 'left':leftOffset+'px'}).fadeIn('slow');
});
I'm at a loss as my offset keep coming back as null. In my CSS the table has a width of 100% within a cell that is 300px but the TD cells themselves do not have a width assigned to them (does that matter as I'm targetting the row?) Perhaps I've stared at this for too long and the answer is obvious but can anyone please help?
Many thanks in advance.
I see two issues:
jQuery doesn't like having a period in the table class name "table.std-table."
Your selector is missing a period.
var offset= $('.table-std-table tbody tr.selected-trial').offset();
<table class="table-std-table">
<tbody>
<tr>
<td>DATA</td>
<td>DATA</td>
</tr>
<tr class="selected-trial">
<td>DATA</td>
<td>DATA</td>
</tr>
<tr>
<td>DATA</td>
<td>DATA</td>
</tr>
</tbody>
</table>
<div class=.trial-selection-marker></div>
<script>
$('.table-std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('.table-std-table tbody tr.selected-trial').offset();
var leftOffset = $('tablestd-table').width();
leftOffset += offset.left +42;
var topOffSet = (offset.top);
topOffSet = topOffSet+3;
$('.trial-selection-marker').css({'top':topOffSet+'px', 'left':leftOffset+'px'}).fadeIn('slow');
});
</script>
With the help of Tom, here was the code I used in the end;
$('.std-table tbody tr.selected-trial td:last').ready(function(){
var offset= $('.std-table tbody tr.selected-trial').offset();
var topOffSet = (offset.top);
topOffSet = topOffSet-270;
$('.trial-selection-marker').css({'top':topOffSet+'px'}).fadeIn('slow');
});
I realised that the table was within a DIV that was positioned relatively so I did not have to worry about the left or right offset. CSS handled the permanent position of the marker horizontally. The script did the rest!
Thanks Tom for your help.

jQuery CSS font-size

How do I auto resize the font-size of a <td> if the content goes into second line? I know how to increase/decrease font size using CSS and jquery but how to automatically make the font-size smaller if a particular or all the td's with a specific class name text gets longer then one line.
<div style="overflow: hidden;" id="parentDiv" class="scroll">
<div id="4" >
<table id="t4" class="Table">
<tbody>
<tr>
<td id="b4" class="bY"><table id="inner1" width="100%" cellpadding="3">
<tbody>
<tr>
<td class="code" id="code4" width="172"></td>
<td class="Num" id="Num4" width="50"></td>
<td colspan="2" class="Name" id="Name"></td>
</tr>
<tr>
<td class="code" width="172"> </td>
<td> </td>
<td class="serial" width="110"></td>
<td class="serial" width="322"></td>
</tr>
</tbody>
</table></td>
</tr>
</tbody>
</table>
</div>
You want .filter(). For most elements this should work:
$(".myClass").filter(function()
{
var el = $(this);
el.css("white-space", "nowrap");
var lineHeight = el.height();
el.css("white-space", "");
return el.height() > lineHeight;
}).css("font-size", "10pt");
Dealing with tables, all the cells in a row have the same height, so check the value of a child element. Eg, wrap everything in a div. However, if you must act on a <td> directly:
$(function()
{
$(".myClass td").filter(function()
{
var el = $(this);
el.closest("tr").andSelf().css("white-space", "nowrap");
var lineHeight = el.height();
el.css("white-space", "normal");
var textWraps = el.height() > lineHeight;
el.closest("tr").andSelf().css("white-space", "");
return textWraps;
}).css("font-size", "10pt");
});
There isn't a straightforward way to get the width (in pixels) of text content. You can however get a reasonable estimate by multiplying the number of characters by the average pixel width of each character - this will vary depending on the font, and works best for fixed-width fonts like Courier. This also assumes that all the content is simple text without additional formatting.
Most fonts have a character width less than the height, so assuming width = height will definitely work.
Example:
var fontSize = parseInt($('.my-td-class').css('font-size')); // get default font size
function updateFont() {
var e = $('#some-element');
while (e.text().length * fontSize > e.width()) {
fontSize *= 0.8; // reduce to 80%
e.css('font-size', fontSize + 'px');
}
}
Edit: Based on the other answers, you could apply this technique to the height as well. Just make sure that the width/height comparison reflects the current font size and not any hard-coded value.
var newFontSize = 8
if $('td').filter(function() {
return $(this).height() > 20
}).css("font-size", newFontSize);
Play with the height > 20 and newFontsize to get what you want.

Categories