I'd like to create a numbered grid.The user puts in the number and the grid is generated. I'd like to do it in CSS, HTML or Jquery Mobile. This is for an ipad project. I'm not sure how to approach the problem. I would like the following result:
As it stands now, I have a div that repeats a grid image across the page. I have to regenerate an image for each background. i.e.: user wants a 40X60 feet area, I will have to generate a 40X60 image. (100px=5 feet on the grid) I'd much rather have the user input two numbers and have the grid and numbers auto generated.
<div style="background-image:url(/images/linegrid100.png);
width:980px;height:700px;
border:1px solid black;padding:10px;">
I've looked at a serious number of grid generators. I've thought about using a table rather than an image. Would that be better? How do I approach the math for the number generation? Seems like this should all be pretty straight forward, but I can't find much information. (Googled for a couple of days now) These kinds of grids are done all of the time in graphics programs and CAD programs.
Any help would be appreciated.
TIA -Rachel
OK. Here is the result of your code. It is running :-) but not as expected. I've been working with the code all day. It is making more sense now, but I'm still lost with the loops and math. Any ideas? So nice to have help and this is fun. Thanks again -R
The code that seems to impact things is :
w = parseInt($square.css('width'), 10) + 2; //the width of each square + 2 pixels for the borders;
If I leave it just as you have it:
If I change the 10 to 100:
Let's assume you have the following form where users enter the two numbers:
<form>
<input type="text" id="x">
<input type="text" id="y">
</form>
Then you can use jQuery to generate your grid as follows:
var x = parseInt($('#x').val(), 10),
y = parseInt($('#y').val(), 10);
grid(x, y);
function grid(x, y) {
var i = -1,
j = -1,
step = 5, //assuming that each grid unit = 5
$grid = $('<div>', {'id':'grid'}),
$square = $('<div>', {'class':'square'}),
$label,
w = parseInt($square.css('width'), 10) + 2; //the width of each square + 2 pixels for the borders;
$grid.width(w * x);
while(++i < x) {
while(++j < y) {
if(j === 0) {
$label = $('<span>', {'class':'label'});
$label.css('top', j * w).css('left', i * w).html(i * step);
}
if(i === 0 && j > 0) {
$label = $('<span>', {'class':'label'});
$label.css('top', j * w).css('left', i * w).html(j * step);
}
$grid.append($square.clone(), $label);
}
j = -1;
}
$('body').append($grid);
}
CSS:
#grid { overflow: hidden; border-left: 1px solid #000; border-top: 1px solid #000; position: relative; }
div.square { width: 50px; height: 50px; float: left; border-bottom: 1px dotted #000; border-right: 1px dotted #000; }
span.label { position: absolute; background: #fff; font-weight: bold; z-index: 10; }
Let's say here's our overlay (dialog box):
<div>
<input type="text" id="x">
<input type="text" id="y">
<button id="build-grid" type="button">Build grid</button>
</div>
Then, you attach an onclick event to the build-grid button. So, when the button is clicked, we read the x and y values and build the grid.
$('#build-grid').on('click', function(e){
e.preventDefault();
var x = parseInt($('#x').val(), 10), //get our values from the input fields
y = parseInt($('#y').val(), 10);
grid(x, y); // build the grid
});
Related
I have the problem that I have a circle that adjusts according to the content of the text. However, I would like the font size to adjust to the circle and not have the circle change size.
How is it possible to implement this in CSS?
I use react 18 and styled-components.
Examples of how it should not be.
Please note that the circle should remain a circle on any device.
I hope for your ideas
E10 (cicle)
Diesel (not a cicle)
I think you are going to need a bit of avaScript for this.
Here's a simple example. The size of the text is gradually increased until it is wider than you want, then decreased by 1 for the texts in each circle.
const tester = document.createElement('div');
tester.setAttribute('class', 'tester');
document.body.append(tester);
const circles = document.querySelectorAll('.circle');
circles.forEach(circle => {
let fs = 2; // 1px is the smallest we can go
tester.innerHTML = circle.innerHTML;
tester.style.fontSize = fs + 'px';
let w = window.getComputedStyle(tester).width.replace('px', '');
while (w < 40) { //allow for some space left and right so not the full 50
fs++;
tester.style.fontSize = fs + 'px';
w = window.getComputedStyle(tester).width.replace('px', '');
};
circle.style.fontSize = (fs - 1) + 'px';
});
tester.remove();
.circle {
color: white;
background-color: darkblue;
border-radius: 50%;
width: 50px;
aspect-ratio: 1 / 1;
display: flex;
justify-content: center;
align-items: center;
}
.tester {
width: fit-content;
position: absolute;
}
<div class="circle">text</div>
<div class="circle">longer text</div>
So I created a count down timer that starts when the person clicks on the button. the countdown timer works but the issue i an running into are two things:
if a person click on the button a second time it speeds up the timers
If a person click on the button after the timer finish it starts to show a negative number.
I am still learning Java and cannot figure this one out.
<button
style="
background:#f1b005;
margin-bottom: 25px;
border:0px;
color: White;
text-align: center;
text-decoration: none;
display: inline-block;
height:50px;
width:125px;
border-radius: 5px;
align:center;
cursor: pointer;"
onclick="onTimer()">
120 Sec Rest
</button>
<div
style="60px;
font-size:30px;
text-align:center;
color:#f1b005;"
id="mycounter">
</div>
<script>
i = 120;
function onTimer() {
document.getElementById('mycounter').innerHTML = i;
i--;
if (i < 0) {
alert('Times Up! Lets Get It!');
clearInerval(i);
}
else {
setTimeout(onTimer, 1000);
}
}
</script>
You have multiple mistakes.
You wrote clearInerval(i) instead of clearInterval(i).
You put the definition of i outside the function - so it's set once, and every time it's clicked, it does the function but does not reset i.
It speeds down because you are doing i--, which makes the value of i one lower.
The major problem is that you set i outside the function.
Try this:
<script>
function onTimer() {
i = 120;
document.getElementById('mycounter').innerHTML = i;
i--;
if (i < 0) {
alert('Times Up! Lets Get It!');
clearInterval(i);
}
else {
setTimeout(onTimer, 1000);
}
}
</script>
Look here for an example of nicer code, just change i++ to i-- to make it count down instead of up in this example: Javascript Second Counter
I'm just curious as to what the maximum value you can enter for something like absolute positioning and for it to still be fully honoured by the browser (let's say modern-ish, so IE8+):
.foo {
left: 9999px;
}
After having a search around I stumbled across this answer which say's there is (virtually) no limit to what you can have as a z-index value, however I would think that these two properties work differently.
Also, what impact might this have on performance?
According to the test below, all Firefox, Chrome and IE8 have the same problem, but at different values.
The serious problem starts more or less at
Chrome: 33554430
Firefox: 17895700
IE8: 1193050
But, on Firefox and Chrome, much before that number, some elements are shifted one or two pixels to the left or to the right. I didn't see that on IE8.
Moreover, on Chrome, the inputs can stop working around 33553900.
var num = document.getElementById('num'),
init = document.getElementById('init'),
render = document.getElementById('render'),
result = document.getElementById('result');
render.onclick = function() {
result.innerHTML = '';
var from = +init.value,
to = from + +num.value;
for(var i=from; i<to; ++i) {
var wrapper = document.createElement('div');
wrapper.className = 'wrapper';
wrapper.style.marginLeft = -i + 'px';
var first = document.createElement('div');
first.style.left = i + 'px';
first.setAttribute('data-num', i);
var last = document.createElement('div');
last.style.left = i+10 + 'px';
last.setAttribute('data-num', i+10);
wrapper.appendChild(first);
wrapper.appendChild(last);
result.appendChild(wrapper);
}
}
.wrapper {
margin: 10px 0;
}
.wrapper > div {
position: relative;
width: 10px;
height: 10px;
background: red;
}
.wrapper > div:after {
content: attr(data-num);
font-size: 10px;
line-height: 10px;
float: left;
margin-left: 15px;
}
Render <input type="number" id="num" value="100" /> elements
starting with <input type="number" id="init" value="0" />
<input type="button" id="render" value="Render" />
<div id="result"></div>
How can i position my dropdown at cursor position inside a textarea? I have found this question was already asked here many times but i cant able figure out the correct solution ..
this is the JSBIN
please help me with your suggestions
Thanks in advance
I know it isn't an exact answer on the question (this solution doesn't use a textarea, but a contentEditable div), but I don't think there is any way of getting x-y-coordinates using either the event, an attribute or function on the textarea or an attribute or function on the Selection object.
I have meshed up an example on JSBin. Please note that I haven't bothered testing for compatibility in other browsers and that it won't return the caret to where you left off. I can't figure out the code for that. I believe window.getSelection() will not work in IE, and in IE8- it would be completely different. You probably want to make sure too, that the menu will not be displayed right from the edge of the screen.
The HTML
<div id="target" contentEditable="true">Type # to see the dropdown.... </div>
<div class="dropdown">
<ul id="dropdown" class="dropdown-menu hide" role="menu" aria-labelledby="dropdownMenu">
<li><a>One</a> </li>
<li><a>Two</a></li>
<li><a>Three</a></li>
<li><a>Four</a> </li>
</ul>
</div>
The CSS
#target {
height: 100px;
border: 1px solid black;
margin-top: 50px;
}
#dummy {
display: inline-block;
}
.dropdown {
position: absolute;
top: 0;
left: 0;
}
The Javascript & JQuery
$("#target").keydown( function(e) {
if(e.which === 50 && e.shiftKey === true ) {
//Prevent this event from actually typing the #
e.preventDefault();
//console.log( window.getSelection() );
var sel = window.getSelection();
var offset = sel.baseOffset;
var node = sel.focusNode.parentNode;
//Get the text before and after the caret
var firsttext = node.innerHTML.substr(0,sel.baseOffset);
var nexttext = (sel.baseOffset != sel.focusNode.length ) ? node.innerHTML.substr( sel.baseOffset, sel.focusNode.length) : "";
//Add in # + dummy, because # is not in there yet on keydown
node.innerHTML = firsttext + '#<div id="dummy"></div>' + nexttext;
//Transfer all relevant data to the dropdown menu
$('.dropdown').css('left', $('#dummy')[0].offsetLeft).css('top', $('#dummy')[0].offsetTop).prop('x-custom-offset', offset + 1);
//Delete the dummy to keep it clean
//This will split the contents into two text nodes, which we don't want
//$('#dummy').remove();
node.innerHTML = firsttext + '#' + nexttext;
//Put the caret back in place where we left off
//...I can't seem to figure out how to correctly set the range correctly...
$('#dropdown').removeClass('hide').addClass('show');
} else {
$('#dropdown').removeClass('show').addClass('hide');
$('.dropdown').removeProp('x-custom-offset');
}
});
$('#dropdown').on( 'click', 'li a', function( e ) {
e.preventDefault();
$('#target').html( function( i, oldtext ) {
var firsttext = oldtext.substr( 0, $('.dropdown').prop('x-custom-offset') );
var nexttext = oldtext.substr( $('.dropdown').prop('x-custom-offset'), oldtext.length );
console.log( e );
var inserttext = e.target.innerText;
//Cleanup
$('#dropdown').removeClass('show').addClass('hide');
return firsttext + inserttext + nexttext;
} );
} );
The explanation
This example works based on that you can insert an element in a contentEditable and retrieve it's offset to the top and the left of the screen. When shift + key 50 is pressed, the event handler will prevent the # from being written and instead inserts the # + dummy object itself. Then we retrieve the offset from this object and move the dropdown menu to that offset. Furthermore, we save the character-offset as a custom property x-custom-offset of the menu, so that we can insert a value at that specific location. We then need to remove the dummy div, but if we would remove the dummy with $('#dummy').remove() the text node before the dummy and the text node behind the dummy will not merge. This will delete the last textnode if we were to put an other # somewhere and/or place it in the wrong location. Therefore, we simply replace the contents of the editable div again. Last, the caret must be set back to it's original position. I cannot figure out how to do this properly though.
The second handler is to insert text into the textbox. The code should be self-explanatory. The x-custom-offset property we set earlier is used here to insert the text into the correct place in the textbox. $('#dropdown').on( 'click', 'li a', function( e ) { ... } ); will attach the click event to the ul instead of the li's, so that it will keep working if you dynamically create the li's (but it will only fire if you click the link part).
You can get the position of the mouse and then move the drop-down list to this position.
You just need to ensure the popup content has a higher z-index than the element you'd like it occlude, and that it's position is set to absolute.
Here's a small test sample I wrote once.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function toggleClass(element, newStr)
{
index=element.className.indexOf(newStr);
if ( index == -1)
element.className += ' '+newStr;
else
{
if (index != 0)
newStr = ' '+newStr;
element.className = element.className.replace(newStr, '');
}
}
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
window.addEventListener('load', mInit, false);
function mInit()
{
}
function onShowBtn(e)
{
var element = byId('popup');
element.className = element.className.replace(' hidden', '');
var str = '';//'border-radius: 32px; border: solid 5px;';
e = e||event;
str += "left: " + e.pageX + "px; top:"+e.pageY+"px;"
element.setAttribute('style',str);
}
function onHideBtn()
{
var element = byId('popup');
if (element.className.indexOf(' hidden') == -1)
element.className += ' hidden';
}
</script>
<style>
#controls
{
display: inline-block;
padding: 16px;
border-radius: 6px;
border: solid 1px #555;
background: #AAA;
}
#popup
{
border: solid 1px #777;
border-radius: 4px;
padding: 12px;
background: #DDD;
display: inline-block;
z-index: 2;
position: absolute;
}
#popup.hidden
{
visibility: hidden;
}
</style>
</head>
<body>
<div id='controls'>
<input type='button' value='show' onclick='onShowBtn()'>
<input type='button' value='hide' onclick='onHideBtn()'>
</div>
<br>
<div id='popup'>
<p>This is some assorted
text</p>
<hr>
<ul>
<li>item a</li>
<li>item 2</li>
<li>item iii</li>
</ul>
</div>
</body>
</html>
I have two CSS classes:
.class1 {
height: 100%;
width: 300px;
border: 1px none #B0B0B0;
position: relative;
display: inline;
left: 10px;
}
.class2 {
height: 100%;
width: 200px;
position: relative;
display: inline;
margin-left: 15px;
background-color: #00CCCC;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-right-style: solid;
border-bottom-style: solid;
border-left-style: solid;
}
Now, as you can see, they're both set to display in a line (no line breaks in between elements). Which works correctly. But for some reason, ever since I set the display to inline, the Padding, the Positioning and the Margin CSS have all just stopped working. I can add a margin-left 10inches and nothing will happen. Same with padding and positioning.
Can anyone explain how to fix this?
Also, I have the relative position set on both classes, yet when viewing the page in a browser, .class2 over laps .class1 when its supposed to be just after .class1.
Any ideas?
EDIT:
Okay, so I've done a JSFiddle, but it seems to be playing up even more there....
Looks like the Width is not working....
here it is:
http://jsfiddle.net/zYbwh/1/
You need to use
display: inline-block;
instead. margin doesn't work with display: inline elements, however with inline-block it does. You can then have an inline element with margins and explicit widths/heights.
To make this work in IE7, add these two lines:
*display: inline;
zoom: 1;
It's horrible, but it works.
I know this is quite a late answer but I wrote a jQuery plugin which support padding on inline elements (with word breaking) see this JSfiddle:
http://jsfiddle.net/RxKek/
Plugin Code:
$.fn.outerHTML = function () {
// IE, Chrome & Safari will comply with the non-standard outerHTML, all others (FF) will have a fall-back for cloning
return (!this.length) ? this : (this[0].outerHTML || (
function (el) {
var div = document.createElement('div');
div.appendChild(el.cloneNode(true));
var contents = div.innerHTML;
div = null;
return contents;
})(this[0]));
};
/*
Requirements:
1. The container must NOT have a width!
2. The element needs to be formatted like this:
<div>text</div>
in stead of this:
<div>
text
</div>
*/
$.fn.fixInlineText = function (opt) {
return this.each(function () {
//First get the container width
var maxWidth = opt.width;
//Then get the width of the inline element
//To calculate the correct width the element needs to
//be 100% visible that's why we make it absolute first.
//We also do this to the container.
$(this).css("position", "absolute");
$(this).parent().css("position", "absolute").css("width", "200%");
var width = $(this).width();
$(this).css("position", "");
$(this).parent().css("position", "").css("width", "");
//Don't do anything if it fits
if (width < maxWidth) {
return;
}
//Check how many times the container fits within the box
var times = Math.ceil(width / maxWidth);
//Function for cleaning chunks
var cleanChunk = function (chunk) {
var thisChunkLength = chunk.length - 1;
if (chunk[0] == " ") chunk = chunk.substring(1);
if (chunk[thisChunkLength] == " ") chunk = chunk.substring(0, thisChunkLength);
return chunk;
};
//Divide the text into chunks
var text = $(this).html();
var textArr = text.split(" ");
var chunkLength = Math.ceil((textArr.length - 1) / times);
var chunks = [];
var curChunk = "";
var curChunkCount = 0;
var isParsingHtml = false;
//Loop through the text array and split it into chunks
for (var i in textArr) {
//When we are parsing HTML we don't want to count the
//spaces since the user doesn't see it.
if (isParsingHtml) {
//Check for a HTML end tag
if (/<\/[a-zA-Z]*>/.test(textArr[i]) || /[a-zA-Z]*>/.test(textArr[i])) {
isParsingHtml = false;
}
} else {
//Check for a HTML begin tag
if (/<[a-zA-Z]*/.test(textArr[i])) {
isParsingHtml = true;
}
}
//Calculate chunks
if (curChunkCount == (chunkLength - 1) && !isParsingHtml) {
curChunk += textArr[i] + " ";
chunks.push(cleanChunk(curChunk));
curChunk = "";
curChunkCount = -1;
} else if ((i == (textArr.length - 1))) {
curChunk += textArr[i];
chunks.push(cleanChunk(curChunk));
break;
} else {
curChunk += textArr[i] + " ";
}
if (!isParsingHtml) {
curChunkCount++;
}
}
//Convert chunks to new elements
var el = $($(this).html("").outerHTML());
for (var x in chunks) {
var new_el = el.clone().html(chunks[x]).addClass("text-render-el");
var new_el_container = $("<div/>").addClass("text-render-container");
new_el_container.append(new_el);
$(this).before(new_el_container);
}
//Finally remove the current element
$(this).remove();
});
};
Thats the problem you get when using templates, ive programmed a site in php, but the design is killing me.
So i try'd some rocket fuel for webdesigners.
And this is the problems i keep getting every step of the way...
Inline-block does not work for me, nothing works, becouse it is not my design and i dont know the setup.
Ive tryd doing the design myself, but i am out of time, i need a design yesterday.
I suggest you take what u need from the templates and delete everything else, that will schrink your problem, and save you time.