As the title says, I wanted the font to be reduced based on the number of lines in the div and from a start size. (Each line reduces the font).
The function below is all I have and works based on the height of the div.
$.fn.resizeText = function (options) {
var settings = $.extend({ maxfont: 40, minfont: 17 }, options);
var style = $('<style>').html('.nodelays ' +
'{ ' +
'-moz-transition: none !important; ' +
'-webkit-transition: none !important;' +
'-o-transition: none !important; ' +
'transition: none !important;' +
'}');
function shrink(el, fontsize, minfontsize)
{
if (fontsize < minfontsize) return;
el.style.fontSize = fontsize + 'px';
if (el.scrollHeight > el.closest(".container").offsetHeight) shrink(el, fontsize - 1, minfontsize);
}
$('head').append(style);
$(this).each(function(index, el)
{
var element = $(el);
element.addClass('nodelays');
shrink(el, settings.maxfont, settings.minfont);
element.removeClass('nodelays');
});
style.remove();
}
The size you are looking for is relative to the font family, because it is not always the same number of lines if they are tested with different fonts in the same text. using the following solution:
How can I count text lines inside an DOM element? Can I?
This is an approximate solution, taking into account a maximum number of lines
<body>
<div id="content" style="width: 80px; font-size: 20px; line-height: 20px; visibility: hidden;">
hello how are you? hello how are you? hello how are you? hello how are you? how are you? how are you? how are you?
</div>
<script>
function countLines(elm) {
var el = document.getElementById(elm);
var divHeight = el.offsetHeight;
var lineHeight = parseInt(el.style.lineHeight);
var lines = divHeight / lineHeight;
return lines;
}
var max_lines = 10;
function auto_size_text(elm) {
var el = document.getElementById(elm);
var lines = countLines(elm);
var size = parseInt(el.style.fontSize.replace("px", ""));
if(lines > max_lines) {
size--;
el.style.fontSize = size + "px";
el.style.lineHeight = size + "px";
auto_size_text(elm);
}
}
function show_div (elm) {
var el = document.getElementById(elm);
el.style.visibility = "";
}
auto_size_text("content");
show_div("content");
</script>
</body>
Related
I have created random stars using a js unction which manipulates CSS based on window height & width. My goal was to fit them at all-time in the viewport as I resize the height and width of the window.
The problem is every time that I resize the window, the js function adds CSS to previous ones without removing them first which causes a horizontal scroll and other unappealing visual issues.
Is there any way to prevent that? perhaps disabling and re-enabling the function or something else that fits the stars exactly in the viewport and make them behave dynamically as the width and height change without keeping the previous applied css properties and values?
<style>
body, html {margin: 0;}
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
</style>
<body>
<div id="header"></div>
<script>
window.onresize = function() {
skyCity();
};
function skyCity() {
for( var i=0; i < 400; i++) {
var header = document.getElementById("header"),
cityLight = document.createElement("i"),
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
</script>
</body>
Simply said, every time you resize, you call skyCity() which runs header.appendChild(cityLight); 400 times. It is just programmed to add new lights...
You can, a) remove every <i> from #header in skyCity() before the loop,
and b), b for better, init the 400 <i> once on load, on then on resize just update their properties.
it seems that the issue is it appends more i tags or stars when resizing, not really css issue.
I suggest to clear the wrapper #header before adding more <i>s.
You can do something like this:
window.onresize = function() {
skyCity();
};
function skyCity() {
var header = document.getElementById("header")
header.innerHTML=''
for( var i=0; i < 400; i++) {
var cityLight = document.createElement("i"),
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
<div id="header"></div>
You can check the full page link so you can try to resize the window
I would suggest you keep the "stars" as an array (cityLights in the code below) and apply the new style every time the browser size changes.
<style>
body, html {margin: 0;}
#header {display: grid;background-color: #2e2e2e;width: 100vw;height: 100vh;overflow: hidden;}
#header i {position: absolute;border-radius: 100%;background: grey; }
</style>
<body>
<div id="header"></div>
<script>
window.onresize = function() {
skyCity();
};
var header = document.getElementById("header");
var cityLights = []
for( var i=0; i < 400; i++) {
cityLights.push(document.createElement("i"));
}
function skyCity() {
for( var i=0; i < 400; i++) {
var cityLight = cityLights[i],
x = Math.floor(Math.random() * window.innerWidth * .98),
y = Math.floor(Math.random() * window.innerHeight),
size = Math.random() * 1.5;
animate = Math.random() * 50;
cityLight.style.left = x + 'px';
cityLight.style.top = y + 'px';
cityLight.style.width = size + 1.5 + 'px';
cityLight.style.height = size + 1.5 + 'px';
cityLight.style.opacity = Math.random();
cityLight.style.animationDuration = 10 + animate + 's';
header.appendChild(cityLight);
}
};
skyCity();
</script>
</body>
I'm trying to make an element that shrinks as you click it more and more. Once it reaches a threshold of 1%, it should reappear in full length and not be clickable. the style.pointerEvents is not working. (This is code added in, in order to solve an issue.) This is all of the code, there must be conflicting variables or something. But the main premise is to shake the element and shrink and then regrow and disable itself and after a waiting period enable itself.
`var rotated = false;
var height = 24.6;
var width = 15
function clickedhub() {
clicked();
timeout();
}
function clicked() {
document.getElementById('box').onclick = function() {
var div = document.getElementById('box'),
deg = rotated ? 0 : 10;
div.style.webkitTransform = 'rotate('+deg+'deg)';
div.style.msTransform = 'rotate('+deg+'deg)';
div.style.oTransform = 'rotate('+deg+'deg)';
div.style.transform = 'rotate('+deg+'deg)';
}
setInterval(res, 140);
function res() {
document.getElementById('box').style = function() {
var div = document.getElementById('box'),
deg = rotated ? 0 : 0;
div.style.webkitTransform = 'rotate('+deg+'deg)';
div.style.mozTransform = 'rotate('+deg+'deg)';
div.style.msTransform = 'rotate('+deg+'deg)';
div.style.oTransform = 'rotate('+deg+'deg)';
div.style.transform = 'rotate('+deg+'deg)';
}
}
}
function timeout() {
document.getElementById('box').onclick = function() {
var div = document.getElementById('box');
width = width / 1.5;
height = height / 1.5;
}
}
setInterval(gamerule, 10);
function gamerule() {
var div = document.getElementById('box');
if (width <= 1) {
div.removeEventListener("click", gamerule);
width = 100;
height = 100;
} else {
width--;
height--;
}
div.style.width = width + '%';
div.style.height = height + '%';
div.addEventListener("click", gamerule);
}
`
This should work for you
//setInterval(gamerule, 10);
let width = 100;
let height = 100;
var div = document.getElementById('box');
function gamerule() {
if (width <= 1) {
div.removeEventListener("click", gamerule);
width = 100;
height = 100;
} else {
width--;
height--;
}
div.style.width = width + '%';
div.style.height = height + '%';
}
div.addEventListener("click", gamerule);
#box{
background-color:red;
width:100%;
height:100%;
}
#container{
width:500px;
height:500px;
}
Click on the red box
<div id="container" >
<div id="box">
</div>
</div>
I need to modify a pasted image inside a contenteditable div: resize it proportionately, add borders, etc... Perhaps this can be achieved by adding a className that will alter the necessary CSS properties.
The problem is that I don't know how to reference the focused, i.e. the active, the clicked-upon image or any element for that matter.
This is the HTML that I am trying to use
<!DOCTYPE html>
<html>
<body>
<div contenteditable="true">This is a div. It is editable. Try to change this text.</div>
</body>
</html>
Using css, html and javascript
Your editable content should be inside a parent div with an id or class name, you can even have different divs for images and such.
Then it is as simple as having css like so:
#editableContentDiv img {
imgProperty: value;
}
Then you can have javascript like so:
function insertImage(){
var $img = document.querySelector("#editableContentDiv img");
$img.setAttribute('class','resize-drag');
}
Eventually if you have more than one img inside the same div you can use querySelectorAll instead of querySelector and then iterate through the img tags inside same div.
I beleive that should at least give you an idea of where to start with what you want.
Similar example
I found this gist that seems to have similar things to want you want but a bit more complicated.
function resizeMoveListener(event) {
var target = event.target,
x = (parseFloat(target.dataset.x) || 0),
y = (parseFloat(target.dataset.y) || 0);
// update the element's style
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
// translate when resizing from top or left edges
x += event.deltaRect.left;
y += event.deltaRect.top;
updateTranslate(target, x, y);
}
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.dataset.x) || 0) + event.dx,
y = (parseFloat(target.dataset.y) || 0) + event.dy;
updateTranslate(target, x, y);
}
function updateTranslate(target, x, y) {
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the position attributes
target.dataset.x = x;
target.dataset.y = y;
}
function insertImage() {
var $img = document.createElement('img');
$img.setAttribute('src', 'https://vignette.wikia.nocookie.net/googology/images/f/f3/Test.jpeg/revision/latest?cb=20180121032443');
$img.setAttribute('class', 'resize-drag');
document.querySelector(".container-wrap").appendChild($img);
var rect = document.querySelector(".container-wrap").getBoundingClientRect();
$img.style.left = rect.left;
$img.style.top = rect.top;
}
function dataTransfer() {
//cleanup
var $out = document.querySelector(".out-container-wrap");
while ($out.hasChildNodes()) {
$out.removeChild($out.lastChild);
}
//get source
var source = document.querySelector('.container-wrap')
//get data
var data = getSource(source);
//add data to target
setSource($out, data);
}
/**
* Get data from source div
*/
function getSource(source) {
var images = source.querySelectorAll('img');
var text = source.querySelector('div').textContent;
//build the js object and return it.
var data = {};
data.text = text;
data.image = [];
for (var i = 0; i < images.length; i++) {
var img = {}
img.url = images[i].src
img.x = images[i].dataset.x;
img.y = images[i].dataset.y;
img.h = images[i].height;
img.w = images[i].width;
data.image.push(img)
}
return data;
}
function setSource(target, data) {
//set the images.
for (var i = 0; i < data.image.length; i++) {
var d = data.image[i];
//build a new image
var $img = document.createElement('img');
$img.src = d.url;
$img.setAttribute('class', 'resize-drag');
$img.width = d.w;
$img.height = d.h;
$img.dataset.x = d.x;
$img.dataset.y = d.y;
var rect = target.getBoundingClientRect();
$img.style.left = parseInt(rect.left);
$img.style.top = parseInt(rect.top);
//transform: translate(82px, 52px)
$img.style.webkitTransform = $img.style.transform = 'translate(' + $img.dataset.x + 'px,' + $img.dataset.y + 'px)';
//$img.style.setProperty('-webkit-transform', 'translate('+$img.dataset.x+'px,'+$img.dataset.y+'px)');
target.appendChild($img);
}
//make a fresh div with text content
var $outContent = document.createElement('div')
$outContent.setAttribute('class', 'out-container-content');
$outContent.setAttribute('contenteditable', 'true');
$outContent.textContent = data.text;
target.appendChild($outContent);
}
interact('.resize-drag')
.draggable({
onmove: dragMoveListener,
inertia: true,
restrict: {
restriction: "parent",
endOnly: true,
elementRect: {
top: 0,
left: 0,
bottom: 1,
right: 1
}
}
})
.resizable({
edges: {
left: true,
right: true,
bottom: true,
top: true
},
onmove: resizeMoveListener
})
.resize-drag {
z-index: 200;
position: absolute;
border: 2px dashed #ccc;
}
.out-container-content,
.container-content {
background-color: #fafcaa;
height: 340px;
}
#btnInsertImage {
margin-bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="http://code.interactjs.io/interact-1.2.4.min.js"></script>
</head>
<body>
<button id="btnInsertImage" onclick="insertImage()">Insert Image</button>
<div class="container-wrap">
<div class="container-content" contenteditable="true">This is the content of the container. The content is provided along with the image. The image will be moved around and resized as required. The image can move within the boundary of the container.</div>
</div>
<button id="btnSubmit" onclick="dataTransfer()">Submit</button>
<div class="out-container-wrap">
</div>
</body>
</html>
Source
This is what I tried and it seems to be working - at least on my system, the snippet I made does not work unfortunately.
function getSelImg(){
var curObj;
window.document.execCommand('CreateLink',false, 'http://imageselectionhack/');
allLinks = window.document.getElementsByTagName('A');
for(i = 0; i < allLinks.length; i++)
{
if (allLinks[i].href == 'http://imageselectionhack/')
{
curObj = allLinks[i].firstChild;
window.document.execCommand('Undo'); // undo link
break;
}
}
if ((curObj) && (curObj.tagName=='IMG'))
{
//do what you want to...
curObj.style.border = "thick solid #0000FF";
}
}
<!DOCTYPE html>
<html>
<body>
<input type="button" onclick="getSelImg()" value="set img border">
<div contenteditable="true">This is a div.<br>
It is editable.<br>
Try to paste an image here:<br>
###########################<br>
<br>
<br>
<br>
###########################
</div>
</body>
</html>
I'm having this code:
<div id="curvy">
This is the curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(1100);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
/* var css = $(this).css('transform');
css = css + ' rotateY(-50deg)'; */
if(counter > 5) {
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
$(this).css('vertical-align','top');
console.log(text);
//$(this).html('');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
/* newElem.css('position','relative');
newElem.css('z-index',counter); */
newElem.css('vertical-align','top');
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
//console.log(value);
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
}
</style>
This is working fine but after I start rotating each letter using rotateY in its own span, the parent span seems to add a white space in between that I want to get rid of.
Check jsfiddle
Well I was approaching it totally incorrectly.
The issue wasnt the spans, the padding or any margins but the translateX or rotate value.
Since CircleType was using the initial size of the letter when rendering the effect, the manipulations that I did through jQuery later weren't taken into account by it.
I had to save the matrix and then decide if I would go for an increment on the rotate value or on the translateX value. I chose the latter because it felt less complicated to play with. Since I need that the rotation will begin after a specific amount of character, I use the appropriate checks.
<div id="curvy">
Curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(900);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
var padding = 0;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
var css = $(this).css('transform').replace(/[^0-9\-.,]/g, '').split(',');
var x = css[12] || css[4];
var y = css[13] || css[5];
var a = css[0];
var b = css[1];
var angle = Math.atan2(b, a) * (180/Math.PI);
if(counter > 5) {
if(counter >= 12) {
padding = padding + 6 ;
} else
padding = padding + 4 ;
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
x = parseFloat(x) + padding;
$(this).css('transform', 'translateX('+x+'px) rotate('+angle+'deg)');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
top: 50%;
left: 50%;
position: absolute;
}
</style>
Updated jsFiddle
I want to get the exact positions of the div using its class name. Here is the screenshot.. My script which is finding a div position is highlighted in yellow and the div i am looking for is at the bottom highlighted red. Since my script is placed above the div so i am finding the parent div of the document and then comparing the div class with the div class i am looking for and thats how i am getting the positions. The positions are not exact. For example if the Top and Left position of the div is 50,150 then i am getting like 55,155.
function getPosition(element) {
var xPosition = 0;
var yPosition = 0;
var left = 0;
var top = 0;
var i = 0;
while (element) {
xPosition = (element.offsetLeft);
yPosition = (element.offsetTop);
console.log("TOP Pos: "+yPosition+"Left Pos: "+xPosition);
if (i == 1) {
left = xPosition;
top = yPosition;
}
element = element.offsetParent;
i++;
}
return {
x: left,
y: top
};
}
And this is how i am using this method.
function ReadDivPos(selector) {
var _divPos = "";
var parentDoc = window;
while (parentDoc !== parentDoc.parent) {
parentDoc = parentDoc.parent;
}
parentDoc = parentDoc.document;
var parentDiv = parentDoc.getElementsByTagName('div');
var divs = [];
for (var i = 0; i < parentDiv.length; i++) {
if (parentDiv[i].className == "content") {
var pos = getPosition(parentDiv[i]);
var x = pos["x"];
var y = pos["y"];
console.log("Values+ Top: " + y + " Left: " + x);
var w = parentDiv[i].offsetWidth;
_divPos += x + "," + w + "," + y + "," + (x + w) + ","+window.screen.availWidth+"\\n";
}
}
console.log("Values+ x: " + _divPos);
return _divPos;
}
This is working fine but i am just wondering is there any other better way to make it done using jquery or any other method. Thanks in advance!.
See :
$(function() {
var x = $(".target").offset().left,
y = $(".target").offset().top;
$(".target").html("x: " + x + " y: " + y);
});
body
{
padding: 0;
}
.target
{
background-color: lightgreen;
width: 7em;
height: 7em;
line-height: 7em;
text-align: center;
left: 100px;
top: 20px;
font-family: Calibri;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="target"></div>