Alright so I have run into what I believe is an optimization issue. I have written a short app that grabs data from two fields, rips them apart character by character and matches them to each other, highlighting discrepancies. The issue seems to be that because the function loops through and not only prints each character one at a time, but changes color in a new span one at a time, there is a severe amount of bottlenecking for large data entries. One sentence of even five work just fine, but when you get up to a full page of text, things bog down and in some cases crash. I have tried to look up some fixes for repaints/reflows, but I haven't run into this issue before and don't know much about it. ANy tips welcome.
Code is here:
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Data Comparison</title>
</head>
<body>
<p><strong>Insert text into fields one and two and press 'Compare'. Matching data is green non-matching is red. </strong></p>
<div class="userField">
<h1>Input Field 1</h1>
<textarea id="textAreaOne" rows="30" cols="65"></textarea>
</div>
<div class="userField">
<h1>Input Field 2</h1>
<textarea id="textAreaTwo" rows="30" cols="65"></textarea>
</div>
<div id="submission">
<button onclick="compare(textAreaOne);">Compare</button>
</div>
<div id="divOne">
<h1 id="titleOne">Output Field 1</h1>
<p id="outputOne"></p>
</div>
<div id ="divTwo">
<h1 id="titleTwo">Output Field 2</h1>
<p id="outputTwo"></p>
</div>
</body>
</html>
CSS:
body {
width: 100%;
margin: 0;
padding: 0;
font-family: Verdana, Geneva, sans-serif;
font-size: 15px;
}
.userField {
display: inline-block;
width: 44%;
margin: 15px;
padding: 15px;
background-color: lightgrey;
border-radius: 13px;
box-shadow: 3px 3px 3px slategrey;
}
#submission {
text-align: center;
}
#divOne {
display: inline-block;
margin: 15px;
padding: 15px;
width: 44%;
word-wrap: break-word;
background-color: lightgrey;
}
#divTwo {
display: inline-block;
background-color: lightgrey;
width: 44%;
word-wrap: break-word;
margin: 15px;
padding: 15px;
}
#titleOne {
background-color: white;
width: 240px;
border-radius: 30px;
padding: 6px;
}
#titleTwo {
background-color: white;
width: 240px;
border-radius: 30px;
padding: 6px;
}
JS:
const fieldOne = document.querySelector("#textAreaOne");
const fieldTwo = document.querySelector("#textAreaTwo");
function compare(){
document.querySelector("#outputOne").innerHTML = "";
document.querySelector("#outputTwo").innerHTML = "";
document.querySelector("#divOne").style.visibility = "hidden";
document.querySelector("#divTwo").style.display = "hidden";
let dataOne = [];
let arrOne = fieldOne.value;
let temp = arrOne.split("");
dataOne.push(temp);
let dataTwo = [];
let arrTwo = fieldTwo.value;
let tempTwo = arrTwo.split("");
dataTwo.push(tempTwo);
if (fieldOne.value.length <= fieldTwo.value.length){
for (var i = 0; i<fieldOne.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
document.querySelector("#outputOne").innerHTML += "<span style='color:green'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:green'>" + dataTwo[0][i] + "</span>";
} else {
document.querySelector("#outputOne").innerHTML += "<span style='color:red'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldOne.value.length < fieldTwo.value.length){document.querySelector("#outputTwo").innerHTML += "<span>...</span>";}
}
else {
for (var i = 0; i<fieldTwo.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
document.querySelector("#outputOne").innerHTML += "<span style='color:green'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:green'>" + dataTwo[0][i] + "</span>";
} else {
document.querySelector("#outputOne").innerHTML += "<span style='color:red'>" + dataOne[0][i] + "</span>";
document.querySelector("#outputTwo").innerHTML += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldTwo.value.length < fieldOne.value.length){ document.querySelector("#outputOne").innerHTML += "<span>...</span>";}
}
document.querySelector("#divOne").style.visibility = "visible";
document.querySelector("#divTwo").style.visibility = "visible";
}
https://codepen.io/Axfinger/pen/QxvbqM?editors=0010
Thanks
The main reason your code is slow it's because you keep modify innerHtml for every letter.
This approach is way faster even with several paragraph:
[...]
let outOne = '';
let outTwo = '';
if (fieldOne.value.length <= fieldTwo.value.length){
for (var i = 0; i<fieldOne.value.length; i++){
if (dataOne[0][i] === dataTwo[0][i]){
outOne += dataOne[0][i];
outTwo += dataTwo[0][i];
} else {
outOne += "<span style='color:red'>" + dataOne[0][i] + "</span>";
outTwo += "<span style='color:red'>" + dataTwo[0][i] + "</span>";
}
}
if (fieldOne.value.length < fieldTwo.value.length){outTwo += "...";}
}
[...]
outputOne.innerHTML = outOne;
outputTwo.innerHTML = outTwo;
Note that I omitted parts of the code for clearness.
That said if you still need more speed:
Lookup for fitting as much data as possible into the red spans. That is the whole consecutive subsequence of different letters.
Execute the function in a webworker (Will take similar time but at least won't freeze the browser).
Related
I'm making a bulletin board now. Above is the template code for it, where page function has NaN. What is the reason for this error, and how should I fix it?
The code below is written in node.js.
module.exports = {
HTML:function(title, board, control, page){
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
<meta charset="utf-8">
<style type="text/css">
ul.board, ol.board {
list-style: none;
margin: 0px;
padding: 5px;
}
form {
display: inline;
}
table.type09 {
border-collapse: separate;
text-align: left;
line-height: 2;
}
table.type09 thead th {
padding: 10px;
font-weight: bold;
vertical-align: top;
color: #369;
border-bottom: 3px solid #003699;
}
table.type09 tbody th {
width: 150px;
padding: 10px;
font-weight: bold;
vertical-align: top;
border-bottom: 1px solid #ccc;
background: #f3f6f7;
}
table.type09 td {
width: 350px;
padding: 10px;
vertical-align: top;
border-bottom: 1px solid #ccc;
}
</style>
</head>
<body>
<div id="board">
<table class="type09">
<thead>
<tr>
<th>제목</th>
<th>작성자</th>
<th>날짜</th>
<th>조회수</th>
</tr>
</thead>
<tbody>
${board}
</tbody>
</table>
${control}
</div>
${page}
</body>
</html>`;
},board: function (lifeboards) {
var board = ``;
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> <b><공지>${article.title}</b> </td>`;
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
}
for (i = 0; i < lifeboards.length; i++) {
var article = lifeboards[i];
var titleBold = article.titleBold;
board += `<tr>`;
if(titleBold == "1") {
board += `<td> ${i+1}. <b>${article.title}</b> </td>`;
} else if(titleBold == "0") {
board += `<td>${i+1}. ${article.title}</td>`;
}
board += `<td>${article.writer}</td>`;
board += `<td>${article.day}</td>`;
board += `<td>${article.see}</td>`;
board += `</tr>`;
}
return board;
},page:function (lifeboards) {
var page = ``;
page =+ `<tr>`;
page =+ `<td colspan="5">`;
for(j = 0; j < lifeboards.length/5; j++) {
page =+ `[${j+1}]`;
}
page =+ `</td>`;
page =+ `</tr>`;
return page;
}
}
The picture below shows how it works.
I don't know how much more detail Stackoverflow wants, but this is all my code and there's nothing more to explain.
Please use this one , you need to add concat ( + ) operator first then =. e.g. +=
page: function (lifeboards) {
var page = ``;
page += `<tr>`;
page += `<td colspan="5">`;
for (j = 0; j < lifeboards.length / 5; j++) {
page += `[${j + 1}]`;
}
page += `</td>`;
page += `</tr>`;
return page;
}
Hope this will solve the issue.
I'm building a form that takes input including a few texareas and outputs what was input into those fields on the same page below the form. It works great, except when I paste a multi-line code snippet in any of the textareas, the output does not look like what I pasted originally.
How can I prevent code in my #results div from being styled?
Here is a screenshot showing the output of texarea elements being mis-aligned, and mis-formatted. Everything from the "FILE" to "TAGS" heading displays and is formatted correctly.
I had trouble finding the right long-tail term to Google on for this. Perhaps someone can tell me what the correct term is for this kind of
output produced from self-submitting form?
My Code:
submit.onclick = function() {
// build html output
document.querySelectorAll('input, textarea').value = "";
var out = "";
//var form = document.querySelector('form');
var outPartsArr = [];
/* GATHER FORM VALUES */
var filename = document.querySelector('#filename').value;
var dateCreated = document.querySelector('#date-created').value;
var dateModified = document.querySelector('#date-modified').value;
var postURL = document.querySelector('#post-url').value;
var postTitle = document.querySelector('#post-title').value;
var postTags = document.querySelector('#post-tags').value;
var postContent = document.querySelector('#post-content').value;
/* GET TIME */
// from: https://www.codexworld.com/how-to/get-current-date-time-using-javascript/
var today = new Date();
var yy = today.getFullYear().toString().substr(-2);
var mm = today.getMonth()+1;
var dd = today.getDate() < 10 ? "0" + today.getDate() : today.getDate() ;
var date = mm + "/" + dd + "/" + yy;
var hh = today.getHours() > 12 ? today.getHours() - 12 : today.getHours();
var mm = today.getMinutes();
var time = hh + ":" + mm;
/* BUILD OUTPUT */
var filenameOut = "<span class='line-title'>FILE: </span>" + filename + "<br>";
var dateCreatedOut = "<span class='line-title'>DATE CREATED: </span>" + dateCreated + "<br>";
var dateModifiedOut = "<span class='line-title'>DATE MODIFIED: </span>" + dateModified + "<br>";
var postURLOut = "<span class='line-title'>URL: </span>" + postURL + "<br>";
var postTitleOut = "<span class='line-title'>TITLE: </span>" + postTitle + "<br>";
var postTagsOut = "<span class='line-title'>TAGS: </span>" + postTags + "<br>";
var postContentOut = "<span class='line-title'>CONTENT: </span>" + "<pre>" + postContent + "</pre><br>";
// Add each line item html snippet to array
outPartsArr.push(filenameOut, dateCreatedOut, dateModifiedOut, postURLOut, postTitleOut, postTagsOut, postContentOut);
console.log("%c postContent ","background:orange");
console.log(postContent);
out += "<ul class='row-lines'>"
// loop through out parts array and wrap each in <li> tags
// while building the out string
outPartsArr.forEach(function(part, i) {
out += "\t<li>" + part + "</li>";
});
out += "</ul>";
console.log("%c out ","background:orange");
console.log(out);
// display in results div
document.querySelector('#results').innerHTML = out;
// #GOTCHA --> Without this return statement output appears for a milisecond
// then the form refreshes.
return false;
};
* {
box-sizing: border-box;
}
body {
width: 100%;
}
#wrapper {
max-width: 1024px;
width: 80%;
border: solid gray 1px;
margin: 2em auto;
padding: 1.2em
}
form {
border: solid red 2px;
background: aliceblue;
margin-bottom: 1.5em;
padding: .6em;
}
form label {
margin-right: 0;
padding-right: 0;
width: 200px;
float: left;
font-family: Arial, Tahoma, sans-serif;
font-weight: bold;
}
form input {
padding: .4em .6em;
margin-bottom: .4em;
width: 80%;
}
form input[type="submit"] {
background: green;
color: white;
margin-top: 1em;
width: 6em;
border-radius: .3em;
margin-left: 0;
}
textarea {
width: 80%;
height: 10em;
/*resize: both;*/
border-radius: 5px;
border: 1px solid #ccc;
box-shadow: 1px 1px 1px #999;
}
/* OUTPUT */
#results {
padding: 2em .6em;
background: #ffffb3;
border: solid brown 1px;
}
#results h3 {
font-family: Arial, Tahoma, sans-serif;
color: brown;
}
.line-title {
font-weight: bold;
float: left;
width: 10em;
color: brown;
font-family: Arial, Tahoma, sans-serif;
line-height: 1.2em;
}
.row-lines li {
line-height: 2em;
list-style: none;
}
<div id="wrapper">
<header class="content">
<h1>Eric Hepperle's Stack Overflow Post Builder (2018)</h1>
<p>Some header tag line or other introductory text.</p>
</header>
<main>
<form id="stack-post-builder" method="GET" action="#">
<label for="filename">FILE:</label>
<input type="text" id="filename" name="filename" value="" ><br>
<label for="date-created">DATE CREATED:</label>
<input type="text" id="date-created" name="date-created" value=""><br>
<label for="date-modified">DATE MODIFIED:</label>
<input type="text" id="date-modified" name="date-modified" value=""><br>
<label for="post-url">URL:</label>
<input type="text" id="post-url" name="post-url" value="" ><br>
<label for="post-title">TITLE:</label>
<input type="text" id="post-title" name="post-title" value="" ><br>
<label for="post-tags">TAGS:</label>
<textarea id="post-tags" name="post-tags" placeholder="Enter post tags"></textarea><br>
<label for="post-content">CONTENT:</label>
<textarea id="post-content" name="post-content" placeholder="Enter post tags"></textarea><br>
<!-- <input type="submit" id="stack-post-builder-submit" name="stack-post-builder-submit" value="Submit"> -->
<input type="submit" id="submit" name="submit" value="Submit">
</form>
<section id="results">Results will show up here.</section>
</main>
</div><!-- END wrapper div -->
I cannot get it to just display one at a time. It has to do a full cycle before it displays just one paragraph. Pulling my hair out.
$(function(){
setInterval(function(){$('.forumFeed > :first-child').fadeOut(3000).next('p').delay(3000).fadeIn(1000).end().appendTo('.forumFeed');}, 5000);
});
https://codepen.io/capseaslug/pen/yqyBXB
Hide all but the first paragraph tag by default. Inside the setInterval hide the one that is showing and display the next one (controlled by an index variable).
To make the items fade in/out nicely you can fade in the next element after the visible one is finished hiding.
Added some variables at the top to play with the aesthetics / number of items looped through.
SO didn't have moment.js so I hard coded some string. Codepen for a working version.
var numberOfItems = 10;
var flipSpeed = 2000;
var fadeOutSpeed = 500;
var fadeInSpeed = 200;
(function(c){
var uniquename = 'rssfeed' // id of target div
var query = 'select * from rss(0,' + numberOfItems + ') where url = "https://forums.mankindreborn.com/f/-/index.rss"'; // RSS Target, 0,5 signifies number of entries to show
var numretries = 1; // increase this number (number of retries) if you're still having problems
//////// No Need To Edit Beyond Here Unless You Want To /////////
var counter = typeof c === 'number'? c : numretries;
var thisf = arguments.callee;
var head = document.getElementsByTagName('head')[0];
var s = document.createElement('script');
window["callback_" + uniquename + (--counter)] = function(r){
head.removeChild(s);
if(r && r.query && r.query.count === 0 && counter > 0){
return thisf(counter);
}
//r now contains the result of the YQL Query as a JSON
var feedmarkup = '';
var feed = r.query.results.item // get feed as array of entries
for (var i=0; i<feed.length; i++) {
feedmarkup += '<p><span class="firstrowwrap"><a href="' + feed[i].link + '">';
feedmarkup += feed[i].title + '</a> <span class="comments"> Replies: ';
feedmarkup += feed[i].comments + ' </span></span><span class="secondRow"> <i class="fas fa-feather-alt"></i> ' ;
feedmarkup += feed[i].creator + ' <span class="posttime"> Last Post: ';
//pubishdate since
publishDate = feed[i].pubDate;
var inDate = publishDate;
var publisheddate = new Date(inDate);
feedmarkup += 'moment.js is missing ' + '</span></span></p>';
//endpublishdate since
}
document.getElementById(uniquename).innerHTML = feedmarkup;
};
var baseurl = "https://query.yahooapis.com/v1/public/yql?q=";
s.src = baseurl + encodeURIComponent(query) + "&format=json&callback=callback_" + uniquename + counter;
head.append(s);
})();
$(function(){
var index = 0;
setInterval(function() {
$('#rssfeed>p:visible').fadeOut(fadeOutSpeed, ()=> {
$('#rssfeed>p').eq(index).fadeIn(fadeInSpeed);
});
index++;
if(index === $('#rssfeed>p').length){
index = 0;
}
}, flipSpeed);
});
#main-container {
padding:4em;
background: #333;
font-family: 'exo'
}
#rssfeed p:not(:first-child) {
display: none;
}
a{
font-weight:
500;
color: #68ddda;
}
a:hover{
color: #4ca7a4;
}
.firstrowwrap{
display: flex;
justify-content: space-between;
}
.secondRow{
display: block;
padding-top: 4px;
margin-bottom: -5px;
}
#rssfeed p{
background-color: #212121;
padding: 10px;
width: 400px;
margin-bottom: 2px;
color: #464646;
}
.comments{
height: 18px;
position: relative;
z-index: 1;
padding-left: 8px;
margin-left: 4px;
font-size: 12px;
}
.comments:after{
content: "";
position: absolute;
width: 100%;
height: 100%;
left: 0px;
top: 0px;
background-color: #969696;
border-radius: 2px;
z-index: -1;
margin-left: 4px;
}
.posttime{
float: right;
font-size: 13px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid" id="main-container">
<div class="row">
<div class="col-md-12">
<div class="forumFeed" id="rssfeed"></div>
</div>
</div>
</div>
I create the checkout page of an eshop and I have a loop in which I display the products that the user has added to the cart. Inside the loop, I display the info for the products I have a text area so the user can choose the quantity of each product. The problem is that the id of each text area must be unique. How can I create many textareas in a loop with different ids?
textarea:
<form name='txtAreaForm' method='GET'>
<textarea disabled name='textArea' id='counter'></textarea>
</form>
Also, I have two buttons (+-) to change the value of the textarea, this is the .js file:
var counter = 1;
// Display total
$("#counter").text(counter);
// When button is clicked
$("#plusButton").click(function(){
counter = counter + 1;
$("#counter").text(counter);
});
//Subtract
$("#minusButton").click(function(){
if (counter>1) {
counter = counter - 1;
$("#counter").text(counter);
}
});
Though the question is not quite clear to me, you can do something like the following:
var counter = 1;
// Display total
$("#counter").text(counter);
var counter = counter + 1;
for(var i=0; i<5; i++){
$("form").append('<textarea name=textArea"+counter+" id=counter"+counter+">1</textarea><input class="plus" type="button" value="+" /><input class="minus" type="button" value="-" /><br>');
}
// When button is clicked
$(".plus").click(function(){
var txtArea = $(this).prev('textarea').text();
$(this).prev('textarea').text(parseInt(txtArea)+1);
});
//Subtract
$(".minus").click(function(){
var txtArea = $(this).prev().prev('textarea').text();
if(txtArea >=2){
$(this).prev().prev('textarea').text(parseInt(txtArea)-1);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form name='txtAreaForm' method='GET'>
</form>
You can use just JavaScript to render a form with as many textareas with its id as necessary and set the actions to each button related to each of them.
See this demo:
(function() {
// Set the plus action on every button with the class name «plus».
function setPlusAction() {
function plus(e) {
var textarea = e.target.previousSibling; // Find the textarea element related to the button clicked.
textarea.value = textarea.value * 1; // Convert the value into number.
textarea.value++; // Increment its value.
}
var elems = document.getElementsByClassName("plus"), i, len = elems.length, button;
for (i = 0; i < len; i++) {
button = elems[i]; // Find the current button.
button.onclick = plus; //Set the «plus» function on every button which has been found.
}
}
// Set the minus action on every button with the class name «minus».
function setMinusAction() {
function minus(e) {
var textarea = e.target.previousSibling.previousSibling; // Find the textarea element related to the button clicked.
textarea.value = textarea.value * 1; // Convert the value into number.
if (textarea.value > 1) {
textarea.value--; // Decrement its value.
}
}
var elems = document.getElementsByClassName("minus"), i, len = elems.length, button;
for (i = 0; i < len; i++) {
button = elems[i]; // Find the current button.
button.onclick = minus; //Set the minus function on every button which has been found.
}
}
// Render a form with the quantity of textareas required.
function buildForm(textareas) {
var html = "<form name=\"txtAreaForm\" method=\"GET\">", i;
for (i = 0; i < textareas; i++) {
html += "<div><textarea disabled name=\"textArea\" id=\"textarea";
html += i;
html += "\">1</textarea><button class=\"plus\" type=\"button\">+</button><button class=\"minus\" type=\"button\">-</button></div>";
}
html += "</form>";
return html; // Return the html content with the form.
}
/*
1. Render the form with document.getElementById("div").innerHTML = buildForm(50);
2. Once the form is renderd call setPlusAction() function;
3. And call setMinusAction() function;
*/
document.getElementById("div").innerHTML = buildForm(50); // Set 50 textareas.
setPlusAction();
setMinusAction();
})();
#div div {
border: solid 1px #ccc;
margin: 2px;
padding: 2px;
}
button.plus,
button.minus {
cursor: pointer;
}
<div id="div"></div>
Update:
jQuery version:
$(function() {
// Render a form with the quantity of textareas required.
function buildForm(textareas) {
var html = "<form name=\"txtAreaForm\" method=\"GET\">", i;
for (i = 0; i < textareas; i++) {
html += "<div><textarea disabled name=\"textArea\" id=\"textarea";
html += i;
html += "\">1</textarea><button class=\"plus\" type=\"button\">+</button><button class=\"minus\" type=\"button\">-</button></div>";
}
html += "</form>";
return html; // Return the html content with the form.
}
$("#div").html(buildForm(50)); // Render the form with 50 textareas.
$(".plus").on("click", function() {
var texarea = $(this).prev(), value = texarea.val() * 1;
value++;
texarea.val(value);
});
$(".minus").on("click", function() {
var texarea = $(this).prev().prev(), value = texarea.val() * 1;
if (value > 1) {
value--;
texarea.val(value);
}
});
});
#div div {
border: solid 1px #ccc;
margin: 2px;
padding: 2px;
}
button.plus,
button.minus {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div"></div>
Remember: IDs must be unique.
I prefer using a class, because I think it is more clear for the code.
Example: my_set_Of_Text_area.add ('<div><span> Ananas : </span>','</div>');
I prefer using data to made the link with the counting area and the + / - buttons.
$(function() {
class TxtAreaFab {
constructor(Form_ID, TextAreaPrefix, BtPlusClass, BtMinusClass) {
this._ref = 0;
this._TaP = TextAreaPrefix;
this._BtPlus = BtPlusClass;
this._BtMinus = BtMinusClass;
this._$ID = $('#' + Form_ID);
}
add(before, after) {
var elements = before;
this._ref++;
elements += "<textarea disabled id='TxtArea_" + this._ref + "'>1</textarea>";
elements += "<button class=" + this._BtPlus + " data-ref=\"TxtArea_" + this._ref + "\">+</button>";
elements += "<button class=" + this._BtMinus + " data-ref=\"TxtArea_" + this._ref + "\">-</button>";
elements += after;
$(elements).appendTo(this._$ID);
}
/* ----- not used , just here for sample
clear () {
this._$ID.html('');
this._ref = 0;
}
*/
};
var my_set_Of_Text_area = new TxtAreaFab('txtAreaForm', 'zoneTA_', 'ClassBtPlus', 'ClassBtMinus');
my_set_Of_Text_area.add('<div><span> Apples : </span>', '</div>');
my_set_Of_Text_area.add('<div><span> Oranges : </span>', '</div>');
my_set_Of_Text_area.add('<div><span> Pears : </span>', '</div>');
my_set_Of_Text_area.add('<div><span> Bananas : </span>', '</div>');
$('#txtAreaForm').on('click', "button", function(e) {
e.stopPropagation();
var $txtArea = $("#" + $(this).data("ref")),
v = parseInt($txtArea.val());
if ($(this).hasClass('ClassBtPlus')) $txtArea.val(++v);
if ((v > 1) && ($(this).hasClass('ClassBtMinus'))) $txtArea.val(--v);
return false;
});
my_set_Of_Text_area.add('<div><span> Ananas : </span>', '</div>');
});
#txtAreaForm div {
clear: both;
height: 30px;
}
#txtAreaForm div span {
display: block;
float: left;
width: 120px;
font-weight: bold;
text-align: right;
padding-right: 10px;
}
#txtAreaForm textarea {
display: block;
float: left;
width: 40px;
height: 16px;
font-weight: bold;
text-align: center;
resize: none;
}
<form name='txtAreaForm' id='txtAreaForm' method='GET'></form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
Special Fun solution! (but real).
I did it with only 9 lines of JavaScript / jQuery, and a little more in CSS.
And no need for textarea id. (Ok, my 2 "if" statements have only 1 line).
For the HTML part, each text box is placed in a "p" (paragraph), and that's it:
<p><textarea disabled > 1 </textarea></p>
<p><textarea disabled > 2 </textarea></p>
<p><textarea disabled > 3 </textarea></p>
The trick is in the CSS where I use :after and :before like the "+" or "-" buttons.
placed to the right of each box "p".
form p:after {
right: -22px;
content:'+';
...
form p:before {
right: -43px;
content:'-';
In the jQuery part.
I use the relative position of the mouse click to determine whether the operation should be a plus or minus. For the little story: -- $ (this) .outerWidth (); -- Is usefull.
Of course, it would still be better to add an ID on each textarea; but after reflection, it appeared to me that these input fields could be generated at the PHP server (?).
So, strange as it may seem, this solution is very serious. ;)
Everything is in the snippet.
$(function() {
$('form p').click(function(e) {
var
posX = (e.pageX - $(this).offset().left) - $(this).outerWidth();
Sign = (posX > 22) ? "moins" : (posX > 0) ? "plus" : "none",
Valn = parseInt($(this).children('textarea').text());
if (Sign === 'plus') $(this).children('textarea').text(++Valn);
if ((Sign === 'moins') && (Valn > 1)) $(this).children('textarea').text(--Valn);
});
});
textarea,
form,
p,
textarea {
font-family: Tahoma, sans-serif;
font-size: 16px;
}
textarea {
float: left;
width: 40px;
height: 22px;
font-weight: bold;
text-align: center;
resize: none;
line-height: 20px;
}
form p {
box-sizing: border-box;
display: block;
float: left;
clear: both;
position: relative;
border: 0;
margin: 5px 0 0 20px;
padding: 0;
}
form p:before,
form p:after {
position: absolute;
top: 2px;
width: 20px;
height: 20px;
display: block;
color: white;
background-color: darkslategray;
text-align: center;
font-size: 18px;
}
form p:after {
right: -22px;
content: '+';
line-height: 18px;
}
form p:before {
right: -43px;
content: '-';
line-height: 16px;
}
<form name="txtAreaForm" method='GET'>
<p><textarea disabled> 1 </textarea></p>
<p><textarea disabled> 2 </textarea></p>
<p><textarea disabled> 3 </textarea></p>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
I want to create a pyramid like structure on a page from the user input, and the structure should appear like this,
I tried to loop in JS to display the structure but can't change the css property in JS loop according to user input. Here is the code on this page :
var objContainer = document.getElementById("container"),
intLevels = 10,
strBlocksHTML = '';
for (var i = 0; i < intLevels; i++) {
strBlocksHTML += '<div class="buildingBlock"></div>';
strBlocksHTML += '<div></div>'; // Line break after each row
}
objContainer.innerHTML = strBlocksHTML;
.buildingBlock {
display: inline-block;
width: 20px;
height: 20px;
margin: 2px 5px;
background-color: #eee;
border: 2px solid #ccc;
}
#container {
text-align: center;
}
<div id="container"></div>
The output is displayed as a tower and also want to remove the spacing between each <div> element. How can I change this by using jquery or by some other method ? The above image is the desired output that I want.
By changing the first strBlocksHTML row to
strBlocksHTML += '<div class="buildingBlock" style="width: ' + Number(20 + 40 * i) + 'px"></div>';
it works.
you need to do some thing like this
for( var i=0; i<intLevels; i++ ){
var wd = 20 * i;
strBlocksHTML += '<div class="buildingBlock" style="width:'+wd+'px"></div>';
strBlocksHTML += '<div></div>'; // Line break after each row
}
var objContainer = document.getElementById("container"),
intLevels = 10,
strBlocksHTML = '';
for (var i = 0; i < intLevels; i++) {
var wd = 20 * i;
strBlocksHTML += '<div class="buildingBlock" style="width:' + wd + 'px;"></div>';
strBlocksHTML += '<div></div>'; // Line break after each row
}
objContainer.innerHTML = strBlocksHTML;
.buildingBlock {
display: inline-block;
width: 20px;
height: 20px;
margin: 2px 5px;
background-color: #eee;
border: 2px solid #ccc;
margin-top: -20px;
}
#container {
text-align: center;
}
<div id="container"></div>
you can allign these closer by using css
You could simple set the width via the style attribute on each created div, and calculate it dynamically – I’ve change your loop to run backwards, something like this:
for(var i=intLevels; i>0; --i) {
strBlocksHTML += '<div class="buildingBlock" style="width:'+(250-i*20)+'px"></div>';
}
Change the values (250px width from which i*20 gets subtracted) as you see fit, resp. calculate them dynamically based on the number of pyramid levels wanted.
And also you do not need the empty divs for line breaks – just keep your divs as display:block, and set the margin to auto to center them.
var objContainer = document.getElementById("container"),
intLevels = 10,
strBlocksHTML = '';
for (var i = intLevels; i > 0; --i) {
strBlocksHTML += '<div class="buildingBlock" style="width:' + (250 - i * 20) + 'px"></div>';
}
objContainer.innerHTML = strBlocksHTML;
.buildingBlock {
height: 20px;
margin: auto;
background-color: #eee;
border: 2px solid #ccc;
}
#container {
text-align: center;
}
<div id="container"></div>
var objContainer = document.getElementById("container"),
intLevels = 10,
strBlocksHTML = '';
for (var i = 0; i < intLevels; i++) {
strBlocksHTML += '<div class="buildingBlock" style="width:' + (10 * i) + 'px"></div>';
//strBlocksHTML += '<div></div>'; // Line break after each row
}
objContainer.innerHTML = strBlocksHTML;
.buildingBlock {
display: block;
width: 20px;
height: 20px;
margin: 0 auto;
background-color: #eee;
border: 2px solid #ccc;
}
#container {
text-align: center;
}
<div id="container"></div>