I'm trying to get a color name from text input using js but the code doesn't work at all. (I'm using p5.js btw)
my HTML :
<input placeholder="Type color name OR type 'Random' for a random tint!" style="width: 340px; border-radius: 5px; border: 3px rgb(0, 0, 0) solid; background-color: rgb(197, 197, 197);" id="colors"></input>
my JS :
colorss = "";
function preload() {
}
function setup() {
canvas = createCanvas(400, 400);
canvas.position(480, 300);
video = createCapture(VIDEO);
video.hide();
colorss = document.getElementById("colors").value;
console.log(colorss);
}
function draw() {
image(video, 0, 0, 400, 400);
}
function submit() {
r = random(255);
g = random(255);
b = random(255);
if(document.getElementById('colors').value == "Random") {
tint(r,g,b);
} else{
tint(colorss);
}
}
I'm using p5.js too and I tried using a different variable, so i don't understand why it isn't working... pls help
I assume your setup() function is executed ones when the page is opened and than submit() is executed once the submit button is clicked.
So what you have here is you execute setup() and load value of your input field into colorss variable. At this point the value is an empty string.
Then when you submit the form, you are using the value of colorss variable which is still an empty string.
What you need to do is use something like this:
tint(document.getElementById("colors").value);
Also, please declare variable with var, let and/or const
Related
You helped me get the draw function work properly. Here's the complete program, which works perfectly until the "draw" button is clicked. Instead of drawing a new image, the entire window vanishes. Any help greatly appreciated!
This code is formatted as instructed, 4 spaces per tab. I don't know any more details to add.
<!DOCTYPE html>
<html>
<head>
<title>Digital Holograms</title>
<style>
div {
float: left;
height: 580px;
width: 500px;;
padding: 0 10px;
}
#column1 {
background-color: #FFFFFF;
}
#column2 {
background-color: #FFFFFF;
width: 500px
}
</style>
</head>
<body>
<div id="column1">
<canvas id="my-canvas" width="500" height="500"></canvas>
<script>
let selFun = 0 // selected function to draw
// user may change this by selection box
let canvas = document.querySelector('#my-canvas')
let context = canvas.getContext('2d')
context.fillStyle = 'black'
function draw(n) {
let contourInterval = 1500
let contourWidth = 500
let fsize = 1000
let x0 = fsize / 2
let y0 = fsize / 2
for (j = 0, y = -y0; j < fsize; j++, y++) {
for (i = 0, x = -x0; i < fsize; i++, x++) {
let fun = 0
switch(n) {
case 0:
fun = (x*x + y*y)
break;
case 1:
fun = (x*x - y*y)
break;
default:
fun = (x*x + y*y)
}
if (Math.abs(fun % contourInterval) < contourWidth) {
context.fillRect(x+x0/2, y+y0/2, 1, 1)
}
}
}
document.write('<h4 style="text-align: center;">Hologram of z = x² + y²</h4>');
}
draw(selFun)
function getSelection() {
let selFun = document.getElementById("selectFunction").value
//document.write(selFun)
}
</script>
<h3>To view other holograms:</br>Select a function, then press draw</h3>
<select id="selectFunction" onchange="getSelection()">
<option value=0>z = x² + y²</option>
<option value=1>z = x² - y²</option>
</select>
<button type = "button";
onclick = draw(selFun)>Draw</button>
</div>
</body>
</html>
There a several glitches that are preventing this code working as intended.
1) The loss of content on button press
This is a result of an incorrect use of document.write() (which can only be effectively used by inline scripts to inset text as the page is loading. Running it on a loaded page causes document.open() to be executed, clearing the existing document. See: https://developer.mozilla.org/en-US/docs/Web/API/Document/write
The correct way to update information on the page is to change the innerText or innerHTML of an existing element, or insert a new element with the required text.
In my snippet I added the h4 tag, with an id of updatedTitle, to the html (initially with no content, which will be added by the script):
<h4 id="updatedTitle" style="text-align: center;"></h4>
The innerText of the tag is added by the last line of the draw() function:
document.getElementById("updatedTitle").innerText = `Hologram of ${equation}`;
Note, the template literal ${equation}, this was used to allow the equation to be updated when a new option is drawn, by fetching the markup for the equation from the element (shown later).
2) Drop Down changes not registering
After correcting point 1), there was still a problem: pressing the draw button failed to render a new graph. After some investigation with console.log()s at various parts of the execution cycle I determined that the onchange of the dropdown element was not being received by the javascript.
The reason for this turned out to be a case of very bad luck - the choice of the function name intended to handle the change: getSelection. It turns out that getSelection is a built-in method of the Window object and seemingly cannot be used as a user function name.
Changing the function name to readSelection() cured this problem;
(https://developer.mozilla.org/en-US/docs/Web/API/Window/getSelection)
3) Button onclick event argument not accessible
The button's onlick event calls the draw() function, and attempts to send selFun as an argument. As written, selFun is not accessible from the element.
Instead, the onlick was changed to simply call the draw() function without any argument.
selFun is declared, and assigned with 0, in the global scope of the script and so is accessible from function in the script. Thus the argument n used in the switch block of the draw() function can be replaced directly with selFun (and n also deleted from the function parameter):
4) modification to readSelection()
The original values of the option list items were 0 and 1, entered as (unquotted) numbers in the markup. Although this is allowed, the 0 and 1 are converted to strings when the value attribute is read regardless of whether they were quotted or not (much like the contents of a text input field). Javascript is good at coercing numbers from digit characters but I was getting a bug where selFun was not being read properly for the case statement. Formally setting selFun to an integer value cured this:
selFun = parseInt(document.getElementById("selectFunction").value);
Since readSelection is invoked each time the drop down changes, it is also the place to keep track of which equation should be used in the label on next draw. Hence the following line was included in the function:
equation = document.getElementById("selectFunction").children[selFun].innerText;
with equation being declared (and set to the dropdown initial state) in the global scope of the script, to be read and used to form a label, as discussed in 1) above.
5) Draw only working for first change of equation
Once the above changes were made, changing the dropdown and pressing the button resulted in the new equation being rendered. However, subsequent changes and attempts to draw did not appear to do much.
This was because the second equation was being drawn on top of the first and, once both equations were drawm further drawing didn's show any change.
The solution was to include a standard clear step at the start of the draw() function:
context.clearRect(0, 0, canvas.width, canvas.height);
6) Element accessibility
The entire script was moved to the foot of the html to allow all elements to load before running the script, this prevented some errors where the js was trying to access elements that did not yet exist.
The programme seems to work as intended now. I don't understand anything about the equation plots but they are most impressive and, should you add more to it in future, perhaps you will comment back here so I can have a look!
Working snippet:
let selFun = 0
let equation = document.getElementById("selectFunction").children[selFun].innerHTML; // to be used to update graph label;
let canvas = document.querySelector('#my-canvas');
let context = canvas.getContext('2d');
context.fillStyle = 'black';
function draw() {
// clear canvas'
context.clearRect(0, 0, canvas.width, canvas.height);
let contourInterval = 1500;
let contourWidth = 500;
let fsize = 1000;
let x0 = fsize / 2
let y0 = fsize / 2
for (j = 0, y = -y0; j < fsize; j++, y++) {
for (i = 0, x = -x0; i < fsize; i++, x++) {
let fun = 0
switch(selFun) {
case 0:
fun = (x*x + y*y);
break;
case 1:
fun = (x*x - y*y);
break;
default:
fun = (x*x + y*y);
} // end switch
if (Math.abs(fun % contourInterval) < contourWidth) {
context.fillRect(x+x0/2, y+y0/2, 1, 1)
} // end if;
} // next i;
} // next j;
const titleH4 = document.getElementById("updatedTitle");
document.getElementById("updatedTitle").innerText = `Hologram of ${equation}`;
} // end draw;
draw();
function readSelection() {
selFun = parseInt(document.getElementById("selectFunction").value);
equation = document.getElementById("selectFunction").children[selFun].innerText;
} // end readSelection function;
div {
float: left;
height: 580px;
width: 500px;;
padding: 0 10px;
}
#column1 {
background-color: #FFFFFF;
}
#column2 {
background-color: #FFFFFF;
width: 500px
}
select {
width: 200px;
height: 1.5em;
font-size: 2em;
border-radius: 5px;
background: cyan;
text-align: center;
}
button {
width: 100px;
height: 1.5em;
font-size: 2em;
}
<div id="column1">
<canvas id="my-canvas" width="500" height="500"></canvas>
<h3>To view other holograms:</br>Select a function, then press draw</h3>
<select id="selectFunction" onchange="readSelection()">
<option value="0">z = x² + y²</option>
<option value="1">z = x² - y²</option>
</select>
<button type = "button" onclick="draw()">Draw</button>
<h4 id="updatedTitle" style="text-align: center;"></h4>
</div>
edit
Regarding the appearance of the dropdown and button - they can be styled much like any other html element. I've added some arbitrary changes to their apperance by adding rules for select and button elements to the css. The elements can be given a class name if more specific styling is needed without affecting other elements of the same kind.
I don't know what your code is trying to do but when the button is pressed you are updating the source completely.
Here is that bad code :)
document.write('<h4 style="text-align: center;">Hologram of z = x² + y²</h4>');
Add it inside a div instead of writing it to the whole document.
document.getElementById("example").innerHTML = 'your codes';
I'm working on a homework assignment to change the color of this this div back and forth on click
<div id = "color-block">
<p id="center-text">The color is: <span id = "color-name">#F08080</span> </p>
</div>
So far I have this, which changes the color once, but then will not change it back to the original color
document.getElementById("color-block").onclick = function () {
changeColor();
};
function changeColor() {
if (
(document.getElementById("color-block").style.backgroundColor = "#f08080")
) {
document.getElementById("color-block").style.backgroundColor = "#008080";
} else {
document.getElementById("color-block").style.backgroundColor = "#f08080";
}
}
I'm unsure of what is causing the else statement to not work. Can anyone point me in the right direction?
For some reason (I'm not sure why) HEX colors (e.g. #ff0000) get converted to RGB colors (e.g. rgb(255,0,0)). It's therefore easier to just use RGB colors. There was also a fault in your if. You have to use a == for comparisons. You code ends up being like this:
document.getElementById("color-block").onclick = function () {
changeColor();
};
function changeColor() {
if (
(document.getElementById("color-block").style.backgroundColor == "rgb(240, 128, 128)")
) {
document.getElementById("color-block").style.backgroundColor = "rgb(0, 128, 128)";
} else {
document.getElementById("color-block").style.backgroundColor = "rgb(240, 128, 128)";
}
}
Demo: https://jsfiddle.net/d174aj95/
I use, (pls never mind the selector, I know it should be changed but it is found nevertheless).
let leftArrow = <HTMLElement> document
.querySelector('div[style="position: absolute; left: 6px; transform: skewX(22.6deg);' +
' transform-origin: 0px 0px 0px; height: 24px; width: 10px;' +
' box-shadow: rgba(0, 0, 0, 0.6) 0px 1px 6px; background-color: rgb(255, 255, 255);"]');
Then I use:
let myStyle = leftArrow.style; //this gets me a CSSStyleDeclaration object
console.log(myStyle); // those are equal objects
console.log(leftArrow.style); // those are equal objects
But when I do:
leftArrow.style = myStyle; //this should change nothing ?!
my element dissappears ?!
My goal is to use a class and then do sth like this:
leftArrow.style = this.getStyleFromClass(selector_to_find_class_name);
But after simple:
leftArrow.style = myStyle;
my element from upper one becomes :
<div></div>
which makes it basically not visible. Why ?
I think what you are trying to do is apply the original inline styles back. To do this, you can use cssText to get the values, and than you can set it back.
var div = document.getElementById("x");
var backUp = div.style.cssText;
div.style.backgroundColor = "yellow";
div.style.color = "blue";
window.setTimeout( function () {
div.style.cssText = backUp;
}, 4000);
<div id="x" style="background-color:red">Hello</div>
leftArrow.style = myStyle; //this should change nothing ?!
Yes but only if you have:
let myStyle = leftArrow.style; //this gets me a CSSStyleDeclaration object
letArrow.style = myStyle;
This is most likely not the code you have and you are generating the object on the fly. Do not assign to style directly. Instead assign to members of style e.g. letArrow.style.color = "red"
Background
(New to JS and 1st time using canvas)
I am trying to read a JSON file from https://analytics.usa.gov/ and display it using a canvas. I want just the first 8 records to be populated in a drop down.
I was successful in getting a dump of the file locally on my machine. Code is here (https://jsfiddle.net/uh8jamdo/)
What I was trying to do is :
1) Page Title from the data should be populated in Drop Down
2) When the User selects one and clicks submit. I want to display the Page Title, URL and active users of that particular Page Title.
Below is my attempt. Can some one please guide me. I have written code to display canvas, text and update the data.
window.onload = function() {
var button = document.getElementById("previewButton");
button.onclick = previewHandler;
}
function previewHandler() {
var canvas = document.getElementById("analytics");
var context = canvas.getContext("2d");
drawText(canvas, context);
}
// draws all the text, including the Analytics
function drawText(canvas, context) {
context.font = "50px serif";
context.fillStyle = "black";
context.font = "bold 1em sans-serif";
context.textAlign = "left";
context.fillText("No of People online on Govt Websites", 20, 40);
// draw the analytics!
selectObj = document.getElementById("site");
index = selectObj.selectedIndex;
var site = selectObj[index].value;
context.font = "italic 1.2em serif";
context.fillText(site, 30, 100);
}
function updateAnalytics(site) {
var siteSelection = document.getElementById("site");
// add all data to the site dropdown
for (var i = 0; i < site.length; i++) {
site = site[i];
// create option
var option = document.createElement("option");
option.text = site.text;
// strip any quotes out of the site so they don't mess up our option
option.value = site.text.replace("\"", "'");
// add option to select
siteSelection.options.add(option);
}
// make sure the top tweet is selected
siteSelection.selectedIndex = 0;
}
canvas {
border: 1px solid black;
}
<canvas width="600" height="200" id="analytics">
<p>You need canvas to see the Analytics Data</p>
<p>This example requires a browser that supports the HTML5 Canvas feature.</p>
</canvas>
<p>
<label for="site">Pick a Site</label>
<select id="site"></select>
</p>
<p>
<input type="button" id="previewButton" value="Preview">
</p>
</form>
</br>
<script src="https://analytics.usa.gov/data/live/top-pages-realtime.json">
</script>
You basically have it, but there are enough strange things that I figure I can modify your code and you can study what I've done. A few issues I spotted:
Instead of hardcoding a script into the html document, we can fetch the contents of URL's through XMLHttpRequest. You are going to run into some timing issues.
There is no real need to use form and submit these days. Modern web design will usually maintain a stateful object on the client, and will communicate with various back ends using things like XMLHttpRequest, above. By doing this, we don't have to redraw the page every time we get a response back from the server. When the user clicks submit, you can catch that event, but there is a protocol you need to follow (return false from the handler) to prevent the page from reloading and blowing away the user's selection. The user will not get to see your canvas, because you'll be reloading a fresh canvas every time. They also will not see their selection because you'll be resetting it after every submit.
We don't need to strip quotes when setting the javascript value. First, because these things will usually get escaped for you, but second, because it's actually easier in your case to just store the index of the selection. You really don't need value at all. It may cause issues if you use this modified value as a key.
Minimize the number of global variables. Javascript has really good support for closure, which is a powerful programming construct that allows us to limit the visibility of variables, among other things. This will make it a lot easier to test your code in the debugger because everything will be grouped in one place. (More of a style than an actual issue).
Make sure to clear out your canvas if you plan to reuse it. Successive calls to fillText will clobber the previous text.
There are plenty of other things we could explore, but hopefully this will get you started.
Also, it's great that you are doing all of this without resorting to external libraries, but you should also check them out -- javascript can do some pretty exciting things. I recommend D3.js
Finally, here is the revised javascript, which I believe does the things you've specified, and which takes into account the advice I've given:
(you can play with the jsfiddle, here:
https://jsfiddle.net/dancingplatypus/L92fq305/6/)
var site_analytics = {
run: function () {
var ANALYTICS_SITE = 'https://analytics.usa.gov/data/live/top-pages-realtime.json';
var elem_select = document.getElementById("site");
var elem_title = document.getElementById("site_title");
var elem_preview = document.getElementById("previewButton");
var site_data = null;
elem_preview.onclick = render_selection;
elem_select.onchange = render_selection;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
console.log('heya');
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
site_data = JSON.parse(xmlhttp.responseText);
sync_selector();
}
}
xmlhttp.open("GET", ANALYTICS_SITE, true);
xmlhttp.send();
function sync_selector() {
console.log('boyo');
elem_select.innerHtml = null;
if (site_data) {
for (var loop = 0; loop < Math.min(8, site_data.data.length); loop++) {
var item = site_data.data[loop];
var option = document.createElement('option');
option.text = item.page_title;
option.value = loop;
elem_select.add(option);
}
}
selected_index = (site_data.data.length > 0) ? 0 : null;
render_selection();
}
function render_selection() {
var index = elem_select.selectedIndex;
var item = site_data ? site_data.data[index] : null;
elem_title.innerText = item ? item.page_title : 'n/a';
var canvas = document.getElementById("analytics");
var context = canvas.getContext("2d");
context.clearRect(0, 0, canvas.width, canvas.height);
drawText(item, canvas, context);
};
// draws all the text, including the Analytics
function drawText(item, canvas, context) {
context.font = "50px serif";
context.fillStyle = "black";
context.font = "bold 1em sans-serif";
context.textAlign = "left";
context.fillText("No of People online on Govt Websites", 20, 40);
// draw the analytics!
context.font = "italic 1.2em serif";
context.fillText(item ? item.active_visitors : '', 30, 100);
}
}
};
window.onload = function () {
site_analytics.run();
};
Currently i'd like to read out the background color of a css through javascript to update a canvas with the desired color. So far i get it to work by creating a dummy object within html that holds that css from which i can read it:
The CSS content:
.logmessage-debug {
color: #fff;
background-color: #999999;
}
.logmessage-info {
color: #fff;
background-color: #5cb85c;
}
.logmessage-warn {
color: #fff;
background-color: #f0ad4e;
}
.logmessage-error {
color: #fff;
background-color: #d9534f;
}
.logmessage-fatal {
color: #fff;
background-color: #d955d9;
}
The HTML part:
<canvas id="myCanvas" width="200" height="200"></canvas>
<!-- The dummy objects allowing access to the css properties -->
<div id="debug" class="logmessage-debug"></div>
<div id="info" class="logmessage-info"></div>
<div id="warn" class="logmessage-warn"></div>
<div id="error" class="logmessage-error"></div>
<div id="fatal" class="logmessage-fatal"></div>
<script type="text/javascript">
updateCanvas();
</script>
The JavaScript part:
function updateCanvas() {
$.ajax({
url: "api/myWebService",
success: function (severityLevel) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = getSeverityColorFromStyle(severityLevel);
ctx.fillRect(0, 0, c.clientWidth, c.clientHeight);
},
complete: function() {
setTimeout(updateCanvas, 2000);
}
})
}
function getSeverityColorFromStyle(styleName) {
// Any other way to read the css background color
// directly instead of asking the dummy object?
return $("#" + styleName).css("background-color");
}
So far the above way works as expected and i can get out the desired colors i like. But I'm feeling uncomfortable by adding these dummy objects just to get access to the needed css values. Exists there any direct way to retrieve these values out of the css?
You could create a function that loops through all the stylesheets/rules on your page and tries to match it
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) {
return (classes[x].cssText) ? classes[x].cssText : classes[x].style.cssText;
}
}
}
See this previous post for more detail How do you read CSS rule values with JavaScript?
If you know the position of the Rule or the Sheet it is in, you can easily get it via the related CSSStyleSheet, e.g.
<style id="foo">/* etc */</style>
Then
function getSeverityColorFromStyle(kwd) {
var i, rules = document.getElementById('foo').sheet.rules;
kwd = '.logmessage-' + kwd;
for (i = rules.length; i--;) // find in sheet's rules
if (rules[i].selectorText.indexOf(kwd) !== -1) // found
return rules[i].style.backgroundColor;
return '';
}
Accessing the style of a CSSStyleRule enables you to let the browser parse the cssText.
If you don't know the sheet, you may want to do another loop over document.styleSheets
var theColor = $('.class').css('background-color');
So as it seems there exists no such simple way to access a css style like accessing an existing element within the document.
At the end i decided to take the answers from Paul and JBB and (hopefully) improved them a little bit. I iterate once over all available rules within all available style sheets and push the interesting things into my own cache object. Within the getSeverityColorFromStyle() method i then try to get the matching color out of it.
var logLevelColors;
function updateCanvas() {
if(logLevelColors == undefined)
initializeLogLevelColors();
$.ajax({
url: "api/myWebService",
success: function (severityName) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = getSeverityColorFrom(severityName);
ctx.fillRect(0, 0, c.clientWidth, c.clientHeight);
},
complete: function() {
setTimeout(updateCanvas, 2000);
}
})
}
function initializeLogLevelColors() {
logLevelColors = new Object();
var logMessageIdentifier = '.logmessage-';
$.each(document.styleSheets, function (_, styleSheet) {
$.each(styleSheet.rules, function (_, rule) {
if (rule.selectorText.indexOf(logMessageIdentifier) == 0) {
var logLevel = rule.selectorText.substring(logMessageIdentifier.length);
var color = rule.style.backgroundColor;
logLevelColors[logLevel] = color;
}
})
})
}
function getSeverityColorFrom(severityName) {
var undefinedColor = 'rgba(0, 0, 0, 0.00)';
if (logLevelColors == undefined)
return undefinedColor;
return logLevelColors[severityName]
|| undefinedColor;
}
How about setting the css class directly to canvas?
Something like: <canvas id="myCanvas" class="error"></canvas>, and then you could actually get the computed style of the canvas, and update the elements inside.
var canvas = document.getElementById("canvas"), styles = getComputedStyle(canvas);
//log the properties
console.log(styles.color, styles.backgroundColor);
<script type="text/javascript">
var myText = document.getElementById("text");
alert(myText.style.display);
alert(myText.style.color);
...etc
</script>