I want to create a class on the page by finding classes that start with "f" and end with a number and then writing that style to the head tag using the number as font-size. I'm stuck on finding class, and parsing out number into a variable to use. It can be on any element, div, p, a, span, td, body or whatever. Here is what I have so far.
/* if class starts with f and has number, add class
with font size of that in pixels and make it important */
//creates variable for the number
var number = function() {
//lost here...!
};
//prints style to head tag
$("<style>")
.prop("type", "text/css")
.html(".f" + number + "{font-size: " + number + "px !important;}")
.appendTo("head");
<div class="f30">I'm 30 pixels in text size</div>
<div class="f60">I'm 60 pixels in text size</div>
Use .each() to loop over all the elements whose class starts with f. Then loop over all the classes in the element to find the ones that are of the form f<number>. Then add all those sizes to the stylesheet.
var sizes_seen = {}; // To prevent duplicates
var styles = '';
$("[class^=f]").each(function() {
$.each(this.className.split(' '), function(i, cl) {
var result = cl.match(/^f(\d+)$/)
if (result && !(result[1] in sizes_seen)) {
var fontsize = result[1];
sizes_seen[fontsize] = true;
styles += '.f' + fontsize + '{font-size: ' + fontsize + 'px !important;}';
}
});
});
$("<style>", {
type: "text/css",
html: styles
}).appendTo("head");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="f30">I'm 30 pixels in text size</div>
<div class="f60">I'm 60 pixels in text size</div>
Faster and simpler to just create a loop and generate the style rules without worrying about searching the DOM which is the expensive part of what you are trying to do
var style ='';
for(i=1; i <= 100; i++){
style += ".f" + i+ "{font-size: " + i+ "px !important;}\n";
}
$('<style>').text(style).appendTo('head');
This would create rules for classes f1 to f100
If you use Attribute Starts With Selector you can get a list of all elements that start "f". However that seems like more work and more complicated than just defining the the styles for .f30 and .f60 in a stylesheet.
There are couple of ways you can go, however you probably need one of those two:
Generate classes for a discrete amount of different font sizes
var myFontSizes = [10, 12, 14, 16, 18]
var styles = '';
for (var i = 0; i < myFontSizes.length ; i++)
{
styles += '.f' + myFontSizes[i] + '{font-size: ' + myFontSizes[i] + 'px !important;} '
}
$("<style>")
.prop("type", "text/css")
.html(styles)
.appendTo("head");
Or the huge amount of fonts form minFont to maxFont
var styles = '';
var minFont = 1;
var maxFont = 100;
for (var i = minFont; i <= minFont ; i++)
{
styles += '.f' + i + '{font-size: ' + i + 'px !important;} '
}
$("<style>")
.prop("type", "text/css")
.html(styles)
.appendTo("head");
Related
I really want long shadows in Javascript but I dont want to code every single one line of them ,so i thought automize it so it works something like this :
for (let i = 0; i < length; i++) {
document.getElementById("text").style.textShadow = i + "px" + ' ' + i + "px" + ' ' + 0 + ' ' + color
}
The problem is it doesn't work. I also tried it with arrays with no luck, the only real working thing is to code every single one of the shadows, but I want an adaptable solution.
How can I try and implement it?
You just need to use an array here to add all shadow variables and then join them as a comma-separated string to get the desired output like:
const color = '#696767';
let shadow = []
for (let i = 0; i < 40; i++) {
shadow.push(i + "px" + ' ' + i + "px" + ' 0 ' + color)
}
document.getElementById("text").style.textShadow = shadow.join(',')
#text {
letter-spacing: 0.5rem;
font-size: 3rem;
margin-top:0
}
<h1 id="text"> HELLO WORLD </h1>
I've been trying to get a smooth scroll animation for a while now, but mainly in JS..
This hasn't been working out that well so I decided to try in CSS3.
Now I want to make this animation responsive by calling a JS function which adds the CSS rules for the animation responsive to the object the animation is for. Here is the JS code I've got so far. I'll also leave a Fiddle, but I'm new to that so things might not work right away.
function getTexts() {
var element = document.getElementsByClassName('toplink');
for (x = 0, len = element.length; x < len; x++){
var ID = element[x].textContent.toLowerCase();
var object = document.getElementById(ID);
console.log(object);
addCSSAnimator(ID);
}
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = document.getElementById(el);
var Class = DOM.getAttribute("class");
var Parent = DOM.parentElement.getAttribute("id");
var rect = DOM.getBoundingClientRect();
var rule = ".toplink[ id= '"+el+"' ]:target - #"+Parent+" div."+Class+" {\n" +
"-webkit-transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"}";
console.log("Stylesheet: ",sheet," object: ",DOM," Class: ",Class," offset X&Y:",rect.x," ",rect.y);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
https://jsfiddle.net/dtj46c64/
You may try moving to jquery for this solution. Use document.ready and window.resize functions to handle the animation and also instead of for loop. use the jquery .each() function to get the elements. Try working around the following code i changed for you to go along with. Hope this puts you in the right direction to achieve your goal:
<script>
function getTexts() {
$(".toplink").each(function () {
let ID = $(this)
console.log(ID);
addCSSAnimator(ID);
});
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = el;
var Class = DOM.attr("class");
var Parent = DOM.parent().attr("id");
var rect = DOM[0].getBoundingClientRect();
var rule = ".toplink[ id= '" + el + "' ]:target - #" + Parent + " div." + Class + " {\n" +
"-webkit-transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"}";
console.log("Stylesheet: ", sheet, " object: ", DOM, " Class: ", Class, " offset X&Y:", rect.left, " ", rect.top);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
$(window).on('resize', function () {
getTexts();
});
$(document).ready(function () {
getTexts();
});
</script>
Notice i changed the rect.y to rect.top as on some browsers the getBoundingClientRect fucntion does not return x and y values but left and top are always filled.
Also dont know why you are getting id of the parent of the object as there is no id set to the parent of the anchor class="toplink" so it will always return as null or empty.
Sorry for not a 100% answer as got busy but i hope the solution so far i suggested will help you tweak and find what your looking for.
I have created 64 color buttons in dom by js. they have class name like this:
c1
c2
c3
c4
and so on..
I have created this by this codes:
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
var Cselector = ".c" + linum;
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>");
}
I have already set all color in css style sheet.
like this:
.c1 {
background-color: #F44336;
}
.c2 {
background-color: #E91E63;
}
.c3 {
background-color: #9C27B0;
}
.c4 {
background-color: #673AB7;
}
Now i dont get the color in dom.
it show color-code="undefined"
How can I fix it?
I am sorry for the title. I can't understand what should be the title. So I put this.
Edit:
Due to a answer from #Abdul I have corrected my js. But still it shows color-code="undefined". When I console log this it shows
rgb(244, 67, 54) main.js:10
63 undefined main.js:10
this line is wrong:
var colorMenu = $(Cselector).css( "background-color" );
should be:
var colorMenu = $('.' + Cselector).css( "background-color" );
OR keep your line but change this:
var Cselector = ".c" + linum;
^ notice the period
see this fiddle
I would also refactor your code:
https://jsfiddle.net/6551a0ku/2/
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 5; linum++) {
var className = 'c' + linum;
var Cselector = '.' + className;
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append(getATag(className, colorMenu)),
eg_color_ul_2.append(getATag(className, colorMenu));
}
function getATag(className, colorMenu) {
var aTag = "<a class='"
+ className
+ "' color-code='"
+ colorMenu
+ "'>a</a>";
return aTag;
}
I think there is a misunderstanding of where jQuery will pull the background-color property from. The DOM/jQuery doesn't have a direct understanding of the CSS properties you set down until you associate them with a DOM element either in the actual DOM, or in a Document Fragment.
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
var Cselector = ".c" + linum;
// the problem is here, at this point, there are no dom elements that match .cN so there is no value to return
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>");
}
You can fix this by appending the anchor tags to the DOM first and then assigning the color code attribute.
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
eg_color_ul_1.append("<a class=\"c" + linum + "\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\"></a>");
}
for (var linum = 1; linum < 65; linum++) {
var domElement = $(".c" + linum)
var colorMenu = domElement.css("background-color")
domElement.attr('color-code', colorMenu)
}
I am unfamiliar with JQuery but if element.css("property") is the equivalent of element.style.property then that's your problem, the style there is referring to the inline style attribute and, as you are using a stylesheet, this is returning nothing.
The solution is to instead use getComputedStyle(), like so:
var eg_color_ul_1=$(".eg-ul-1");
var eg_color_ul_2=$(".eg-ul-2");
for(var linum=1;linum<65;linum++){
var colorMenu=window.getComputedStyle($(".c"+linum),null).getPropertyValue("background-color");
eg_color_ul_1.append("<a class=\"c"+linum+"\" data-color-code=\""+colorMenu+"\"></a>");
eg_color_ul_2.append("<a class=\"c"+linum+"\" data-color-code=\""+colorMenu+"\"></a>");
}
I'd also suggest using data attributes rather than custom attributes to avoid any potential issues.
I have a few JavaScript functions designed to add and remove HTML divs to a larger div. The function init is the body's onload. New lines are added when an outside button calls NewLine(). Divs are removed when buttons inside said divs call DeleteLine(). There are a few problems with the code though: when I add a new line, the color values of all the other lines are cleared, and when deleting lines, the ids of the buttons, titles, and line boxes go out of sync. I've gone through it with the Chrome debugger a few times, but each time I fix something it seems to cause a new problem. I would greatly appreciate some input on what I'm doing wrong.
function init()
{
numOfLines = 0; //Keeps track of the number of lines the Artulator is displaying
}
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
LineBoxCode += "<div class = 'Line Box' id = 'LineBox" + numOfLines + "'>" //The code is only split onto multiple lines to look better
+ " <h6 id = 'Title " + numOfLines + "' class = 'Line Box Title'>Line " + numOfLines + "</h6>";
+ " <p>Color: <input type = 'color' value = '#000000'></p>"
+ " <input type = 'button' value = 'Delete Line' id = 'DeleteLine" + numOfLines + "' onclick = 'DeleteLine(" + numOfLines + ")'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
function DeleteLine(num)
{
deletedLineName = "LineBox" + num;
deletedLine = document.getElementById(deletedLineName);
deletedLine.parentNode.removeChild(deletedLine);
num++;
for ( ; num < numOfLines + 1 ; )
{
num++;
var newNum = num - 1;
var changedLineName = "LineBox" + num;
var changedHeaderName = "Title" + num;
var changedButtonName = "DeleteLine" + num;
var changedButtonOC = "DeleteLine(" + newNum + ")";
var changedLine = document.getElementById(changedLineName);
var changedHeader = document.getElementById(changedHeaderName);
var changedButton = document.getElementById(changedButtonName);
var changedLine.id = "LineBox" + newNum;
var changedHeader.innerHTML = "Line" + newNum;
var changedHeader.id = "Title" + newNum;
var changedButton.setAttribute("onclick",changedButtonOC);
var changedButton.id = "DeleteLine" + newNum;
}
num--;
numOfLines = num;
}
You are having a hard time debugging your code because of your approach. You are "marking" various elements with the IDs you construct, and using the IDs to find and address elements. That means that when things change, such as line being deleted, you have to go back and fix up the markings. Almost by definition, the complicated code you wrote to do something like that is going to have bugs. Even if you had great debugging skills, you'd spend some time working through those bugs.
Do not over-use IDs as a poor-man's way to identify DOM elements. Doing it that way requires constructing the ID when you create the element and constructing more IDs for the sub-elements. Then to find the element again, you have to construct another ID string and do getElementById. Instead, use JavaScript to manage the DOM. Instead of passing around IDs and parts of IDs like numbers, pass around the DOM elements themselves. In your case, you don't need IDs at all.
Let's start off with DeleteLine. Instead of passing it a number, pass it the element itself, which you can do my fixing the code inside your big DOM string to be as follows:
<input type='button' value='Delete Line' onclick="DeleteLine(this.parentNode)"/>
So we have no ID for the line element, no ID for the element, and no ID within the onclick handler. DeleteLine itself can now simply be
function DeleteLine(line) {
{
line.parentNode.removeChild(line);
renumberLines();
}
We'll show renumberLines later. There is no need to adjust IDs, rewrite existing elements, or anything else.
Since we no longer need the ID on each line or its sub-elements, the code to create each element becomes much simpler:
function NewLine()
{
var LineBoxHolder = document.getElementById("LineBoxHolder");
numOfLines += 1;
var LineBoxCode = "<div class='LineBox'>" +
+ " <h6 class='LineBoxTitle'>Line " + "numOfLines + "</h6>"
+ " <p>Color: <input type='color' value='#000000'></p>"
+ " <input type='button' value='Delete Line' onclick= 'DeleteLine(this.parentNode)'/>"
+ "</div>";
LineBoxHolder.innerHTML += LineBoxCode;
}
The only remaining work is to fix up the titles to show the correct numbers. You can do this by just looping through the lines, as in
function renumberLines() {
var LineBoxHolder = document.getElementById("LineBoxHolder");
var lines = LineBoxHolder.childElements;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var h6 = line.querySelector('h6');
h6.textContent= "Line " + (i+1);
}
}
I voted to close because the question is too broad, but will answer anyway on a few points to... well, point in the right direction.
var changedButton.setAttribute("onclick",changedButtonOC); This is not a variable declaration. Omit the var.
for ( ; num < numOfLines + 1 ; ) { num++; ... The correct form here would be simply for (; num < numOfLines + 1; num++) { ....
Instead of incrementing (num++) then decrementing (num--) around the loop, why not just use the right math?
See:
for (; num < numOfLines; num++) {
...
}
function createList(arrunique, arrayout) {
for (i = 0; i < arrayout[0].length; i++) {
var divIdC = i;
var divIdT = i + 10;
$('#tb').append('<select name="combo" style="float:left; width:100px;" id="' + divIdC + '" onchange="getComboVal(this,' + divIdC + ')"></select>');
$('#tb').append('<input type="text" name = "textBox" style= "width:100px;" id="' + divIdT + '" onkeyup="validate(this,"' + divIdT + '") value="0">');
var select = document.getElementById(divIdC);
select.options[select.options.length] = new Option("Select " + arrunique[i][0]);
for (j = 1; j < arrunique[i].length; j++) {
select.options[select.options.length] = new Option(arrunique[i][j]);
};
};
}
In this code I want to generate a combo box and a textbox and I want to apply some style sheet attribute or any class. How can I do this. Its not working.
There are many, many ways of styling a javascript created element. Here are a few.
Click here for live demo.
var myElem = document.createElement('div');
myElem.style.color = '#FFF';
with jQuery:
var $myElem = $('<div></div>');
$myElem.css('color', '#FFF');
or jQuery css object syntax (for passing multiple styles)
$myElem.css({display: 'block', background: '#000'});
Rather than adding the style after creating the element, you may also consider just adding a class to the element after creating it and styling this class in your css file.
CSS file:
.myElem {
color: #FFF;
}
myElem.className = 'myElem';
or
$myElem.addClass('myElem');
$('#tb').append('<input type="text" class="YOURCLASS" name = "textBox" style= "width:100px;" id="'+divIdT+'" onkeyup="validate(this,"'+divIdT+'") value="0">');
See this simplified jsFiddle. Ensure that the console is not generating an errors, and that you're calling the createList() function.