I've tried this js code with no result.
Explanation: my page loads a div named row with a min-height not in px but in vh.
I need to set that value to another div's height, named row2.
window.onload = function() {
var number = document.getElementById('row').style.minHeight;
document.getElementById('row2').style.height = number+'vh';
}
Where am I doing wrong?
Thanks
Your first line inside the function:
var number = document.getElementById('row').style.minHeight;
will return you the value with units.
So, you don't to pass units to the second assignation.
In short, change your code to be unit agnostic, something like this:
window.onload = function() {
const minHeight = document.getElementById('row').style.minHeight;
document.getElementById('row2').style.height = minHeight;
}
Use getComputedStyle and it will return the units, so you need to chop it off.
window.onload = function() {
var row = document.getElementById('row')
var number = parseInt(window.getComputedStyle(row).minHeight)
document.getElementById('row2').style.height = number + 'vh';
}
div {
border: 1px solid black;
}
#row {
min-height: 100px;
background-color: yellow;
}
<div id="row"> boom
</div>
<div id="row2"> room
</div>
window.onload = function() {
var number = document.getElementById('row').offsetHeight;
var numberVh = number * 0.10718113612004287;
document.getElementById('row2').style.height = numberVh+'vh';
}
<div id='row' style="height:150px;background-color:blue;">row1</div>
<input type="button" value="row2 height"/>
<div id='row2' style="background-color:black;">row2</div>
Related
In this program, I'm able to add inputs with a button but I need to show the length of each input as it changes. I'm able to get the length using an EventListener, but I'm not sure how to change the text value for any newly created buttons.
On line 12, you can see that I'm able to change the value successfully on the first input but I'm using an html variable. If you look at my addCell() function, you'll see that I have an element as a child of each node to keep track of the length of each input. I need to access that element in my change() function so I can set the event.target.value.length to the corresponding nodes child element.
I've tried using this, setting var x = this and I've tried using the event.target properties to find the corresponding node and even innerHTML.
var i = 0;
var count = 1;
var length = 2;
var chars = 0;
document.addEventListener('input', function (evt) {
change(evt);
});
function change(elem) {
var check = document.getElementById("first");
if (event.target == check) {
document.getElementById("len").innerHTML = event.target.value.length;
return;
}
// Here's where I'm stuck
}
function removeCell() {
if (count <= 1) {
alert("Illegal operation, the police have been notified.")
return;
}
var elem = document.getElementById('main');
elem.removeChild(elem.lastChild);
count = count - 1;
length = length - 1;
}
function addCell() {
var node = document.createElement('div');
node.innerHTML += length;
var inp = document.createElement('INPUT');
var size = document.createElement('size');
inp.setAttribute("type", "text");
node.appendChild(inp);
node.appendChild(size);
document.getElementById('main').appendChild(node);
count += 1;
length += 1;
i += 1;
}
#area {
width: 585px;
background-color: lightgrey;
color: black;
border-style: solid;
margin-left: auto;
margin-right: auto;
min-height: 100px;
height: auto
}
#texts {
width: 220px;
height: 50px;
border-style: solid;
}
body {
background-color: grey;
}
<div id="area">
<form id="main">
<pre><b> input </b> length</pre>
<span id="list">
1<input type="text" id="first"> <var id="len"></var>
</span>
</form>
<br />
<button onclick="addCell()">Add Cell</button>
<button onclick="removeCell()">Remove Cell</button>
<button onclick="sort()">Sort</button>
</div>
Since I'm able to use alert() to show me the correct length of each newly created input each time it changes, I know there's a way to access the "size" element I created to update it using event.target.value.length
Your problem is that you use a "global" input event listener and your change() function is not programmed to handle multiple input fields because in it you are querying known element ids first and len.
If you want to go with a global listener you have to tell your change() function how to access the new input and corresponding target fields.
An easier way is that you modify your addCell() function and attach an event listener to the input field that you are creating instead of using a global one. Thereby each input field holds its own event listener. Since both the input field and your size element, which displays the length of the input value, are created in the same scope you can use easily write the length to the corresponding size element.
inp.addEventListener('input', function(){
size.innerText = inp.value.length;
});
If you want this to work with your provided HTML you need to remove your first input field and call addCell() manually so that your initial input gets rendered.
Your code should then look like this (note: I set var count = 0; and var length = 1;):
var i = 0;
var count = 0;
var length = 1;
var chars = 0;
function removeCell() {
if (count <= 1) {
alert("Illegal operation, the police have been notified.")
return;
}
var elem = document.getElementById('main');
elem.removeChild(elem.lastChild);
count = count - 1;
length = length - 1;
}
function addCell() {
var node = document.createElement('div');
node.innerHTML += length;
var inp = document.createElement('INPUT');
var size = document.createElement('size');
inp.setAttribute("type", "text");
inp.addEventListener('input', function(){
size.innerText = inp.value.length;
});
node.appendChild(inp);
node.appendChild(size);
document.getElementById('main').appendChild(node);
count += 1;
length += 1;
i += 1;
}
addCell();
#area {
width: 585px;
background-color: lightgrey;
color: black;
border-style: solid;
margin-left: auto;
margin-right: auto;
min-height: 100px;
height: auto
}
#texts {
width: 220px;
height: 50px;
border-style: solid;
}
body {
background-color: grey;
}
<div id="area">
<form id="main">
<pre><b> input </b> length</pre>
<span id="list"></span>
</form>
<br />
<button onclick="addCell()">Add Cell</button>
<button onclick="removeCell()">Remove Cell</button>
<button onclick="sort()">Sort</button>
</div>
If HTML layout is planned out and is consistent you can use [name] attribute for form controls and .class or even just the tagName. Use of #id when dealing with multiple tags is difficult and unnecessary. Just in case if you weren't aware of this critical rule: #ids must be unique there cannot be any duplicate #ids on the same page. Having duplicate #ids will break JavaScript/jQuery 90% of the time.
To accessing tags by .class, #id, [name], tagName, etc. use document.querySelector() and document.querySelectorAll() for multiple tags.
To access forms and form controls (input, output, select, etc) by [name] or #id use the HTMLFormElement and HTMLFormControlsCollection APIs.
.innerHTML is destructive as it overwrites everything within a tag. .insertAdjacentHTML() is non-destructive and can place an htmlString in 4 different positions in or around a tag.
Event handlers and event listeners work only on tags that were initially on the page as it was loaded. Any tags dynamically added afterwards cannot be registered to listen/handle events. You must delegate events by registering an ancestor tag that's been on the page since it was loaded. This was done with delRow() since the buttons are dynamically created on each row (changed it because one delete button that removes the last row isn't that useful. ex. 7 rows and you need to delete 4 rows just to get to the third row).
Here's a breakdown of: [...ui.len] ui references all form controls .len is all tags with the [name=len]. The brackets and spread operator converts the collection of len tags to an array.
There's no such thing as <size></size>. So document.createElement('size') is very wrong.
const main = document.forms.main;
main.oninput = count;
main.elements.add.onclick = addRow;
document.querySelector('tbody').onclick = delRow;
function count(e) {
const active = e.target;
const ui = e.currentTarget.elements;
const row = active.closest('tr');
const idx = [...row.parentElement.children].indexOf(row);
const length = [...ui.len][idx];
length.value = active.value.length;
return false;
}
function addRow(e) {
const tbody = document.querySelector('tbody');
let last = tbody.childElementCount+1;
tbody.insertAdjacentHTML('beforeend', `<tr><td data-idx='${last}'><input name='txt' type="text"></td><td><output name='len'>0</output></td><td><button class='del' type='button'>Delete</button></td>`);
return false;
}
function delRow(e) {
if (e.target.matches('.del')) {
const row = e.target.closest('tr');
let rows = [...row.parentElement.children];
let qty = rows.length;
let idx = rows.indexOf(row);
for (let i = idx; i < qty; i++) {
rows[i].querySelector('td').dataset.idx = i;
}
row.remove();
}
return false;
}
body {
background-color: grey;
}
#main {
width: 585px;
background-color: lightgrey;
color: black;
border-style: solid;
margin-left: auto;
margin-right: auto;
min-height: 100px;
height: auto
}
tbody tr td:first-of-type::before {
content: attr(data-idx)' ';
}
<form id="main">
<table>
<thead>
<tr>
<th class='txt'>input</th>
<th class='len'>length</th>
<th><button id='add' type='button'>Add</button></th>
</tr>
</thead>
<tbody>
<tr>
<td data-idx='1'><input name='txt' type="text"></td>
<td><output name='len'>0</output></td>
<td><button class='del' type='button'>Delete</button></td>
</tr>
</tbody>
</table>
<!--These are dummy nodes because of the
HTMLFormControlsCollection API ability to use id or name, there
must be at least 2 tags with the same name in order for it to
be considered iterable-->
<input name='txt' type='hidden'>
<input name='len' type='hidden'>
</form>
Currently the width() method and all of it's variations in jQuery return pixel values. The same happens when calling the css('width') method.
I have elements, which are styled in .css files, and I have no way of knowing if they're styled in percentages or pixels, but in case it's in percentage or no width is explicitly set on the element, I need to get a percent value.
For example if I have the following:
.seventy { width: 70%; }
.pixels { width: 350px; }
<div class="seventy"></div>
<div class="pixels"></div>
<div class="regular"></div>
I would need these results.
$('.seventy').method() //=> '70%'
$('.pixels').method() //=> '350px'
$('.regular').method() //=> '100%' since that's how block elements behave
Is there anything in jQuery I can use to achieve this effect? Or a custom approach to it?
You can parse the document.stylesheets to find a match. Note, this will only return the actual style after the browser has parsed it so is of no use for getting raw unadulterated CSS as written in file. For that you'd need to parse the file itself rather than the document.stylesheets.
This code is old and untested so your mileage may vary. I have no idea how well it performs with inherited values or more complicated selectors.
//TEST PARSE CSS
var CSS = function () {
var _sheet;
var _rules;
function CSS() {
_sheet = document.styleSheets[0];
if (_sheet.rules) {
_rules = _sheet.rules; // IE
} else {
_rules = _sheet.cssRules; // Standards
}
this.find = function (selector) {
var i = _rules.length;
while(i--){
if (_rules[i].selectorText == selector) {
break;
}
if(i==0){break;}
}
//return _rules[i].cssText;
return _rules[i].style;
}
this.set = function (foo) {
//to do
}
};
return new CSS();
};
//init
var css = new CSS();
//view the console.
console.log(css.find(".regular"));//Note how the width property is blank
//update elements with the results
document.querySelector(".seventy").innerHTML = css.find(".seventy").width;
document.querySelector(".pixels").innerHTML = css.find(".pixels").width;
document.querySelector(".regular").innerHTML = css.find(".regular").width;
//other tests
document.getElementById("a").innerHTML = css.find("body").color;
document.getElementById("b").innerHTML = css.find("h1").color;
document.getElementById("c").innerHTML = css.find("h1").width;
document.getElementById("d").innerHTML = css.find(".notInDom").color;
body {
font-family:sans-serif;
color:black;
background-color:#cccccc;
}
h1 {
color:blue;
font-size:1.5em;
font-weight:400;
width:70%;
}
.seventy, .pixels, .regular {display:block; border:1px solid red;}
.seventy {display:block; border:1px solid red; width: 70%; }
.pixels { width: 350px; }
.regular {}
.notInDom {
color:red;
}
<h1>Find and Read Style Attributes Directly from the Stylesheet.</h1>
<div class="seventy"></div>
<div class="pixels"></div>
<div class="regular"></div>
<ul>
<li>css.find("body").color = <span id='a'></span></li>
<li>css.find("h1").color = <span id='b'></span></li>
<li>css.find("h1").width = <span id='c'></span></li>
<li>css.find(".notInDom").color = <span id='d'></span></li>
</ul>
<p>This is a work in progress and hasn't been tested in any meaningful way. Its messy and very limited.</p>
function getStyle(className) {
var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
for (var x = 0; x < classes.length; x++) {
if (classes[x].selectorText == className) {
(classes[x].cssText) ? alert(classes[x].cssText) : alert(classes[x].style.cssText);
}
}
}
getStyle('.test');
In my CSS I have a particular class for a div
div.videl
{
width: 80%;
margin: 0 auto;
background-color: #39275b;
color: white;
padding: 5px;
}
and then a function to add divs of that class:
this.addVideo = function()
{
var newVidElement = document.createElement("div");
newVidElement.class = "videl";
newVidElement.innerHTML = "<p>(" + ++this.numVids + ") <textarea class='vidtxt'></textarea></p>"
document.getElementById("vidplaydiv").appendChild(newVidElement);
}
However, for some reason, that function is not correctly applying the CSS properties when I test it out. See this page http://jaminweb.com/YoutubePlaylist.html and click the Add Another Video button. Any idea what I'm doing wrong?
className is the name of the attribute you're trying to set.
newVidElement.className = "videl";
When you don't know the property name of the HTML attribute, You can always use setAttribute, for example:
newVidElement.setAttribute('class','videl')
Change the JavaScript code as below -
this.addVideo = function()
{
var newVidElement = document.createElement("div");
newVidElement.className = "videl";
newVidElement.innerHTML = "<p>(" + ++this.numVids + ") <textarea class='vidtxt'></textarea></p>"
document.getElementById("vidplaydiv").appendChild(newVidElement);
}
I am trying to create a dynamic js table and I want to give id to each cell dynamically. I want to use those ids to use in different js event handlers. How it can be done? I have tried in different ways but none of them works!
<html>
<head>
<style>
#colors {
float: right;
width: 400px;
height: 400px;
}
</style>
</head>
<body>
<script>
var d;
var k = 0;
function makeit() {
var tbl = document.createElement("table");
var atts = document.createAttribute("style");
atts.value = "border:1px solid black;text-align:center;padding:2px;margin:3px 3px 3px 3px;";
tbl.setAttributeNode(atts);
for (i = 0; i < 5; i++) {
var rows = tbl.insertRow(i);
for (j = 0; j < 7; j++) {
d = rows.insertCell(j);
d.height = "50px";
d.width = "50px";
d.style.backgroundColor = "yellow";
d.addEventListener("click", function myfunc() { d.style.backgroundColor = "red"; });
}
}
document.body.appendChild(tbl);
}
window.onload = makeit;
</script>
</body>
</html>
Just add
d.id = "r" + i + "c" + j;
under
d=rows.insertCell(j);
to set unique ids on each td.
Obviously, you can change the syntax r2c4 (which would be 3. row and the 5. cell) to your own liking.
If you want to call a function when clicking on a specific td you could even pass the row index (i) and column index (j) to that function.
Side note
You should consider using a JavaScript library or framework like jQuery for manipulations like this. It would facilitate your work a lot in the long term.
The problem is a scope issue. When adding the event listener, d's reference gets updated to be the last table cell you have created.
You can simply change the event listener's function to:
function myfunc() {
this.style.backgroundColor="red";
}
So that this references the object it is attached to. Depending on your intention, you may not need unique ids if you have access to the cell itself.
Using an approach that includes wongcode's solution, you may wish to consider the following code:
<html>
<head>
<style>
#myTbl{ border:1px solid black;text-align:center;padding:2px;margin:3px 3px 3px 3px; }
#myTbl td{ width: 50px; height: 50px; background-color: yellow;}
</style>
</head>
<body>
<script>
function onCellClicked(e)
{
this.style.backgroundColor = 'red';
}
function makeit()
{
var tbl=document.createElement("table");
tbl.id = 'myTbl';
var curCellIndex = 0;
for(i=0;i<5;i++)
{
var rows=tbl.insertRow(i);
for(j=0;j<7;j++)
{
d=rows.insertCell(j);
d.id = 'cell_' + curCellIndex;
curCellIndex++;
d.addEventListener("click",onCellClicked, false);
}
}
document.body.appendChild(tbl);
}
window.onload=makeit;
</script>
</body>
</html>
Some of the advantages include:
Smaller html file created in your editor
Smaller html code created in the browser
Use of context and the this keyword
Smaller memory consumption, since each TD doesn't contain the full
body of the event handler (it only include a 'pointer' to the
function to be executed)
EDIT: forgot to add code to give the cells an id. Now fixed.
I have following page in which there is a div menu. Inside menu we can have <table>, <p>, <h>. Different elements for example:
<div id="menu">
<p>abc def</p>
<table>
<tr><td>helloo </td><tr>
<tr><td>hiii </td><tr>
</table>
<div id="sub"><p>123 this is test</p></div>
</div>
Is there a way to change size of all text in between elements inside menu. For example: abc def, hellooo, hiii, 123 this is test. Can i change all that text using jquery or javascript some how.
Yes you can use JavaScript and or jQuery to do what you want, but why wouldn't you just use CSS like suggested?
or you can try this:
<Style>
/*Assumed everything is inheriting font-size*/
#menu{
font:12px;
}
/* Force all children to have a specified font-size */
#menu *{
font:14px;
}
</style>
<script>
//JavaScript
document.getElementById('menu').style.fontSize = "14px";
//jQuery
$("#menu").css({'font-size':'14px'});
</script>
You can do this with css:
#menu {
font-size: XXX;
}
jQuery Example
$('#menu').nextAll().css('font', '14px');
Take a look at this:
http://jsfiddle.net/oscarj24/jdw6K/
Hope this helps :)
var VINCI = {};
VINCI.Page = {
init : function() {
this.initFontResize();
},
initFontResize : function() {
var container = $('#menu, #sub');
var originalFontSize = parseFloat(container.css('font-size'), 10);
var size_level = 0;
var maximum_size_level = 5;
var size_change_step = 1.4;
function calculateFontSize()
{
return originalFontSize + (size_level * size_change_step);
}
// Increase Font Size
$('.increaseFont').click(function(){
if (size_level < maximum_size_level) {
size_level++;
container.stop().animate({'font-size' : calculateFontSize()});
}
return false;
});
// Decrease Font Size
$('.decreaseFont').click(function(){
if (size_level > 0) {
size_level--;
container.stop().animate({'font-size' : calculateFontSize()});
}
return false;
});
};
VINCI.Page.init();