Trying to make <textarea> mimic a <div> - html

curently I have this for HTML and CSS respectively:.....How would I contruct CSS and html that looks the same using a <div>. The one I created had horizontal scrolling and looked crazy.
<textarea class="textarea_readonly" readonly="readonly" name="mcRemarkOld" rows="7" cols="100" scrolling="auto"></textarea>
.textarea_readonly
{
background-color: #DDDDD0;
margin: 0px;
width: 100%;
}

Instead of trying to mimic a div, replace the textarea using JavaScript. Usage (run on load):
var textarea = document.getElementsByName("mcRemarkOld")[0];
turnTextAreaIntoDiv(textarea);
function turnTextAreaIntoDiv(elem){
var div = document.createElement("div");
// Copy significant attributes, customize.
div.className = elem.className;
div.style.cssText = elem.style.cssText;
div.id = elem.id;
div.name = elem.name;
div.innerHTML = elem.innerHTML; //`<a>` turns in <a>
elem.parentNode.replaceChild(div, elem);
}
Fiddle: http://jsfiddle.net/7bTNH/

Related

Get value from html to style element

I'm trying to define the width of my outer span (.bar-1) element by using the value of my inner span element.
<span class="bar bar-1">
<span name="PERCENTAGE" id="PERCENTAGE" disabled="" title="Total Percentage" maxlength="255" value="66" tabindex="-1" sectionid="MODE_TOOL">
<span class="Text">66</span>
</span>
I have no possibility of changing the content, I'm just trying to figure out a way how I can make my outer span width = 66%.
I believe you would need Javascript for something like that.
Using jQuery:
var tmp = $(".Text").text();
And than use that value to set a style on .bar1 like:
$(".bar1").width(tmp);
If I understand your question, you can do that in JavaScript. Spans don't have width though, unless you use display: inline-block;.
With basic JavaScript:
<script>
var elem = document.getElementsByClassName('bar-1');
for(i = 0; i <elem.length; i++) {
elem[i].style.width = document.getElementById('PERCENTAGE').innerText + "%";
elem[i].style.display = "inline-block";
}
</script>
Thank you both. Unfortunately the admins didn't allow me of adding JavaScript code.
In the end, I used the following css solution:
span[value="66"] {width:66%};
Obviously, I needed to add this for each number between 0 and 100.

Html and css to pdf. Using transform:translate in TCPDF or some other library

I've been researching for a past few days and could not find specific solution for my problem.
I've created a program where I can set position of text with drag and drop on specific image by using Interact.js library, it is remembering positions by css transform:translate property. I've seen that there are many php and javascript libraries for converting html to pdf, but non of them is not able to use transform:translate property to set text position based on parent position inside pdf.
If anyone know how to solve positioning text with transform:translate or to give some other suggestions,I would be thankful. For now I am using TCPDF to import image backgrounds to pdf but not able to position text as I want to. I also tried FPDF, domPDF but with no luck. Thanks in advance.
let divs = Array.prototype.slice.call(document.getElementsByTagName('div'));
let bodyRect = document.body.getBoundingClientRect();
divs.forEach((div) => {
var style = div.getAttribute('style'),
divRect = div.getBoundingClientRect(),
offsetY = divRect.top, // - bodyRect.top,
offsetX = divRect.left; // - bodyRect.left;
if (style && style.indexOf('translate') != -1) {
div.style.position = 'absolute';
div.style.top = offsetY + 'px';
div.style.left = offsetX + 'px';
div.style.transform = '';
}
});
<div style="height: 50mm ;width: 90mm;"> <img src="" style="margin:auto ;max-height: 50mm;max-width: 90mm; min-height: 50mm; min-width: 90mm; width: 90mm; height: 50mm">
<div>
<div style="position: absolute; overflow: hidden;font-family: ; color: ; font-style: ; font-weight: ; font-size: ; transform: translate( 100px, -100px);">TEXT</div>
</div>
</div>
I would write a js sequence to transform all css translate in inline style position absolute, which are understood by html2pdf utilities.

Go to last div added inside div [duplicate]

I am creating a chat using Ajax requests and I'm trying to get messages div to scroll to the bottom without much luck.
I am wrapping everything in this div:
#scroll {
height:400px;
overflow:scroll;
}
Is there a way to keep it scrolled to the bottom by default using JS?
Is there a way to keep it scrolled to the bottom after an ajax request?
Here's what I use on my site:
var objDiv = document.getElementById("your_div");
objDiv.scrollTop = objDiv.scrollHeight;
This is much easier if you're using jQuery scrollTop:
$("#mydiv").scrollTop($("#mydiv")[0].scrollHeight);
Try the code below:
const scrollToBottom = (id) => {
const element = document.getElementById(id);
element.scrollTop = element.scrollHeight;
}
You can also use Jquery to make the scroll smooth:
const scrollSmoothlyToBottom = (id) => {
const element = $(`#${id}`);
element.animate({
scrollTop: element.prop("scrollHeight")
}, 500);
}
Here is the demo
Here's how it works:
Ref: scrollTop, scrollHeight, clientHeight
using jQuery animate:
$('#DebugContainer').stop().animate({
scrollTop: $('#DebugContainer')[0].scrollHeight
}, 800);
Newer method that works on all current browsers:
this.scrollIntoView(false);
var mydiv = $("#scroll");
mydiv.scrollTop(mydiv.prop("scrollHeight"));
Works from jQuery 1.6
https://api.jquery.com/scrollTop/
http://api.jquery.com/prop/
alternative solution
function scrollToBottom(element) {
element.scroll({ top: element.scrollHeight, behavior: 'smooth' });
}
smooth scroll with Javascript:
document.getElementById('messages').scrollIntoView({ behavior: 'smooth', block: 'end' });
If you don't want to rely on scrollHeight, the following code helps:
$('#scroll').scrollTop(1000000);
Java Script:
document.getElementById('messages').scrollIntoView(false);
Scrolls to the last line of the content present.
My Scenario: I had an list of string, in which I had to append a string given by a user and scroll to the end of the list automatically. I had fixed height of the display of the list, after which it should overflow.
I tried #Jeremy Ruten's answer, it worked, but it was scrolling to the (n-1)th element. If anybody is facing this type of issue, you can use setTimeOut() method workaround. You need to modify the code to below:
setTimeout(() => {
var objDiv = document.getElementById('div_id');
objDiv.scrollTop = objDiv.scrollHeight
}, 0)
Here is the StcakBlitz link I have created which shows the problem and its solution : https://stackblitz.com/edit/angular-ivy-x9esw8
If your project targets modern browsers, you can now use CSS Scroll Snap to control the scrolling behavior, such as keeping any dynamically generated element at the bottom.
.wrapper > div {
background-color: white;
border-radius: 5px;
padding: 5px 10px;
text-align: center;
font-family: system-ui, sans-serif;
}
.wrapper {
display: flex;
padding: 5px;
background-color: #ccc;
border-radius: 5px;
flex-direction: column;
gap: 5px;
margin: 10px;
max-height: 150px;
/* Control snap from here */
overflow-y: auto;
overscroll-behavior-y: contain;
scroll-snap-type: y mandatory;
}
.wrapper > div:last-child {
scroll-snap-align: start;
}
<div class="wrapper">
<div>01</div>
<div>02</div>
<div>03</div>
<div>04</div>
<div>05</div>
<div>06</div>
<div>07</div>
<div>08</div>
<div>09</div>
<div>10</div>
</div>
You can use the HTML DOM scrollIntoView Method like this:
var element = document.getElementById("scroll");
element.scrollIntoView();
Javascript or jquery:
var scroll = document.getElementById('messages');
scroll.scrollTop = scroll.scrollHeight;
scroll.animate({scrollTop: scroll.scrollHeight});
Css:
.messages
{
height: 100%;
overflow: auto;
}
Using jQuery, scrollTop is used to set the vertical position of scollbar for any given element. there is also a nice jquery scrollTo plugin used to scroll with animation and different options (demos)
var myDiv = $("#div_id").get(0);
myDiv.scrollTop = myDiv.scrollHeight;
if you want to use jQuery's animate method to add animation while scrolling down, check the following snippet:
var myDiv = $("#div_id").get(0);
myDiv.animate({
scrollTop: myDiv.scrollHeight
}, 500);
I have encountered the same problem, but with an additional constraint: I had no control over the code that appended new elements to the scroll container. None of the examples I found here allowed me to do just that. Here is the solution I ended up with .
It uses Mutation Observers (https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) which makes it usable only on modern browsers (though polyfills exist)
So basically the code does just that :
var scrollContainer = document.getElementById("myId");
// Define the Mutation Observer
var observer = new MutationObserver(function(mutations) {
// Compute sum of the heights of added Nodes
var newNodesHeight = mutations.reduce(function(sum, mutation) {
return sum + [].slice.call(mutation.addedNodes)
.map(function (node) { return node.scrollHeight || 0; })
.reduce(function(sum, height) {return sum + height});
}, 0);
// Scroll to bottom if it was already scrolled to bottom
if (scrollContainer.clientHeight + scrollContainer.scrollTop + newNodesHeight + 10 >= scrollContainer.scrollHeight) {
scrollContainer.scrollTop = scrollContainer.scrollHeight;
}
});
// Observe the DOM Element
observer.observe(scrollContainer, {childList: true});
I made a fiddle to demonstrate the concept :
https://jsfiddle.net/j17r4bnk/
Found this really helpful, thank you.
For the Angular 1.X folks out there:
angular.module('myApp').controller('myController', ['$scope', '$document',
function($scope, $document) {
var overflowScrollElement = $document[0].getElementById('your_overflow_scroll_div');
overflowScrollElement[0].scrollTop = overflowScrollElement[0].scrollHeight;
}
]);
Just because the wrapping in jQuery elements versus HTML DOM elements gets a little confusing with angular.
Also for a chat application, I found making this assignment after your chats were loaded to be useful, you also might need to slap on short timeout as well.
Like you, I'm building a chat app and want the most recent message to scroll into view. This ultimately worked well for me:
//get the div that contains all the messages
let div = document.getElementById('message-container');
//make the last element (a message) to scroll into view, smoothly!
div.lastElementChild.scrollIntoView({ behavior: 'smooth' });
small addendum: scrolls only, if last line is already visible. if scrolled a tiny bit, leaves the content where it is (attention: not tested with different font sizes. this may need some adjustments inside ">= comparison"):
var objDiv = document.getElementById(id);
var doScroll=objDiv.scrollTop>=(objDiv.scrollHeight-objDiv.clientHeight);
// add new content to div
$('#' + id ).append("new line at end<br>"); // this is jquery!
// doScroll is true, if we the bottom line is already visible
if( doScroll) objDiv.scrollTop = objDiv.scrollHeight;
Just as a bonus snippet. I'm using angular and was trying to scroll a message thread to the bottom when a user selected different conversations with users. In order to make sure that the scroll works after the new data had been loaded into the div with the ng-repeat for messages, just wrap the scroll snippet in a timeout.
$timeout(function(){
var messageThread = document.getElementById('message-thread-div-id');
messageThread.scrollTop = messageThread.scrollHeight;
},0)
That will make sure that the scroll event is fired after the data has been inserted into the DOM.
This will let you scroll all the way down regards the document height
$('html, body').animate({scrollTop:$(document).height()}, 1000);
You can also, using jQuery, attach an animation to html,body of the document via:
$("html,body").animate({scrollTop:$("#div-id")[0].offsetTop}, 1000);
which will result in a smooth scroll to the top of the div with id "div-id".
Scroll to the last element inside the div:
myDiv.scrollTop = myDiv.lastChild.offsetTop
You can use the Element.scrollTo() method.
It can be animated using the built-in browser/OS animation, so it's super smooth.
function scrollToBottom() {
const scrollContainer = document.getElementById('container');
scrollContainer.scrollTo({
top: scrollContainer.scrollHeight,
left: 0,
behavior: 'smooth'
});
}
// initialize dummy content
const scrollContainer = document.getElementById('container');
const numCards = 100;
let contentInnerHtml = '';
for (let i=0; i<numCards; i++) {
contentInnerHtml += `<div class="card mb-2"><div class="card-body">Card ${i + 1}</div></div>`;
}
scrollContainer.innerHTML = contentInnerHtml;
.overflow-y-scroll {
overflow-y: scroll;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="d-flex flex-column vh-100">
<div id="container" class="overflow-y-scroll flex-grow-1"></div>
<div>
<button class="btn btn-primary" onclick="scrollToBottom()">Scroll to bottom</button>
</div>
</div>
Css only:
.scroll-container {
overflow-anchor: none;
}
Makes it so the scroll bar doesn't stay anchored to the top when a child element is added. For example, when new message is added at the bottom of chat, scroll chat to new message.
Why not use simple CSS to do this?
The trick is to use display: flex; and flex-direction: column-reverse;
Here is a working example. https://codepen.io/jimbol/pen/YVJzBg
A very simple method to this is to set the scroll to to the height of the div.
var myDiv = document.getElementById("myDiv");
window.scrollTo(0, myDiv.innerHeight);
On my Angular 6 application I just did this:
postMessage() {
// post functions here
let history = document.getElementById('history')
let interval
interval = setInterval(function() {
history.scrollTop = history.scrollHeight
clearInterval(interval)
}, 1)
}
The clearInterval(interval) function will stop the timer to allow manual scroll top / bottom.
I know this is an old question, but none of these solutions worked out for me. I ended up using offset().top to get the desired results. Here's what I used to gently scroll the screen down to the last message in my chat application:
$("#html, body").stop().animate({
scrollTop: $("#last-message").offset().top
}, 2000);
I hope this helps someone else.
I use the difference between the Y coordinate of the first item div and the Y coordinate of the selected item div. Here is the JavaScript/JQuery code and the html:
function scrollTo(event){
// In my proof of concept, I had a few <button>s with value
// attributes containing strings with id selector expressions
// like "#item1".
let selectItem = $($(event.target).attr('value'));
let selectedDivTop = selectItem.offset().top;
let scrollingDiv = selectItem.parent();
let firstItem = scrollingDiv.children('div').first();
let firstItemTop = firstItem.offset().top;
let newScrollValue = selectedDivTop - firstItemTop;
scrollingDiv.scrollTop(newScrollValue);
}
<div id="scrolling" style="height: 2rem; overflow-y: scroll">
<div id="item1">One</div>
<div id="item2">Two</div>
<div id="item3">Three</div>
<div id="item4">Four</div>
<div id="item5">Five</div>
</div>

Textarea with maximum one row

Is it possible to have a textarea in HTML with a single line that never wraps to a 2nd line?
I'd like to behave pretty much like an input.
I've tried :
<textarea class="compact" rows="1" wrap="soft"> </textarea>
.compact{
resize: none;
line-height: 20px;
height: 20px;
overflow: hidden;
white-space: nowrap;
}
Why am I not using an input actually?
Mostly because of the IE 10 compatibility and requirement to copy-paste text in the control. If the pasted text contains \r\n, IE 10 will simply trim any other characters after \r\n and paste that result in the input.
For example, the text
1
2
3
will be pasted as 1 without the rest of the text.
I think I got it. I wired up an jQuery listener.
Using this, no word wrapping is allowed, even when pasting a multi-line string into it. And spaces are still preserved.
$(document).ready(function () {
$('#formatTextArea').on("keyup", function () {
var string1 = $('#formatTextArea').val()
string1 = string1.replace(/(\r\n|\n|\r)/gm, "");
$('#formatTextArea').val(string1)
});
});
<textarea class="compact" id="formatTextArea" rows="1" cols="30" wrap="off"></textarea>
It looks like you can use wrap="soft" and possibly max-length
<textarea rows="1" wrap="soft" maxlength="20" ></textarea>
You can use a little javascript:
var textarea = $("#your_textarea");
textarea[0].onpaste = function() {
window.setTimeout(function() {
var output = textarea.val().replace(/\r?\n|\r/g, ' ') ;
textarea.val(output )
}, 1);
}
See this demo
You can use contenteditable attribute on a div. Its widely supported in old browsers http://caniuse.com/#search=contenteditable
I created a small fiddle here:
http://jsfiddle.net/wr14yLh5/
Html
<div contenteditable></div>
Css
div{
background: green;
color: #fff;
}
div br{
display: none;
}
JS
$("div").keypress(function(e){ return e.which != 13; });

How to position a liquid/elastic textbox next to a button?

I want to position a textbox and a button next to each other in an 'elastic' or 'liquid' way (what's the correct term?) like so:
(source: ocactus.org)
When placed in a container of arbitrary width (incl. browser window resizing), the button should right align and take up as much width as it requires while the textbox should use the remaining width. Unfortunately the button's width cannot be fixed in CSS as it depends on the caption (different actions, languages etc.).
What is a good solution for the above that works cross browser?
I was able to get this to work within a table (I know, but it works) where it would correctly handle page resizing as well as the value of the button changing:
<table class="elastic">
<tr>
<td><input class="textbox" type="text"></td>
<td class="button"><input type="button" value="Test Button"></td>
</tr>
</table>
There may be a <div> alternative out there for styling.
EDIT: I revamped my example to use the following style sheet:
.elastic { width:100%; }
.elastic .textbox { width: 100%; }
.elastic .button { width: 1%; }
It's hard to give a definitive answer without seeing some code but the following will size the input 50% of the browser width with the button next to it.
input {width:50%}
<input>
<button>save</button>
HTML:
<div class="widebox">
<input type="text" value="" />
<button>Button</button>
</div>
jQuery:
<script type="text/javascript">
$(document).ready(function(){
var w = $(".widebox");
$(".widebox input:text").css({ width: (w.width - (w.children("button:first").width + 20)) });
});
</script>
Note: Be sure to include the jQuery library in your document's <head>. For speed I recommend using the one hosted by Google: http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
Here's a jQuery extension I wrote based on NGJ Graphics' answer. It takes into account multiple buttons such as Ok/Cancel options.
(function($) {
$.fn.extend({
widebox: function() {
var el = $(this);
var width = 0;
el.children("button").each(function() {
width += $(this).outerWidth( true );
});
el.children("input:text").css({ width: (el.width() - (width + 40)) });
}
});
})(jQuery);