How to make a 10x10 rectangle of "#" characters? - javascript

I am working with jquery and upon the HTML document completing loading, I need to display a 10x10 rectangle of "#" characters in my div tag whose ID is "artArea". I cannot seem to figure it out. Any help would be wonderful!
Here is my current progress: I am not sure if my function (retangle) is completely wrong or if I am calling the function incorrectly. https://jsfiddle.net/7u1ao2d9/

You can try to find the width of the given # character. Here is the code used to find the dimensions of the # character and calculate the dimensions for the container. Be sure that the target div and the character calculating divs both have the same line height and font size. Be sure to put the #charWidth div out of sight.
$(document).ready(function() {
$('#charWidth').html('#');
var charWidth = $('#charWidth').width();
var charHeight = $('#charWidth').height();
var target = document.getElementById('target');
target.style.width = 10 * charWidth + 'px';
target.style.height = 10 * charHeight + 'px';
console.log(10 * charWidth);
console.log(10 * charHeight);
for (var i = 0; i != 100; i++) {
if ((i % 10) == 0) target.innerHTML += '<br>';
target.innerText += '#';
}
});
#charWidth {
position: absolute;
top: 5000000000000vh;
opacity: 0;
display: table;
/*be sure that it has the same line height and font size as your target div*/
font-size: 16px;
line-height: 16px;
}
#target {
font-size: 16px;
line-height: 16px;
white-space: pre-wrap;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="charWidth"></div>
<div id="target"></div>

Count up to 100 while inserting a line break every 10 counts. Use the function to generate the output and use it on any element you want.
function rectangle(){
var r = "";
//Go about 10x10=100 counts
for (var i = 1; i <= 100; i++){
if (i % 10 === 0) //Insert line break every 10 counts
r += "\n"
else
r += "#";
}
return r;
}
$('#artArea').val() = rectangle();
Also consider this typical script pattern
<html>
<head>
<script>
$(document).ready(...)
</script>
</head>
<body>
...
</body>
</html>
You can use Developer Tools to debug your script.

There are quite a few issues with your code. For one, it's not a great idea to stick the script tag that draws your "#" rectangle in the div where you want the rectangle to go. It is a much better practice to put the script tags with the rest of your script tags at the bottom of the document. In this case, since you're using jQuery, make sure you put the rectangle drawing script tag BELOW the script tag that loads the jQuery library.
Now if your script tag is in the right place, the following should work for you:
<script>
function drawRect(){
var rect = "";
for (var i = 0; i < 10; i +=1){
for (var j = 0; j < 10; j += 1){
rect += "#"
}
rect += "\n"
}
return rect;
}
document.getElementById("artArea").innerHTML = drawRect();
</script>
All the above function is doing is using nested for-loops to build up a string of text. For every one time the outer loop runs, the inner loop will run ten times, so the function uses the inner loop to add 10 "#"s to the string, then the outer loop adds one "\n" to the end of the the 10 "#"s. The "\n" is called a newline character and causes a line-break in the text. To make sure this line-break renders in your html, add the following code to your css file:
#artArea {
white-space: pre;
}
Once the nested loops finish running, we have a string that contains a 10x10 grid of "#"s. Now all that remains is to select the HTML element we want to display the grid and insert that string into it. That's what the document.querySelector("#artArea").innerHTML = drawRect(); line does.
It's not super-obvious from your question, but looking at your code, it appears that you want this rectangle function to be able to draw different grids composed of different characters, depending on user input. If that's the case, then you would want to grab the input and pass it in as an argument to your function, like so:
var rows= parseInt($("#numRows").val(), 10);
var cols= parseInt($("#numCols").val(), 10);
var char= ("#drawChar").val();
function drawRect(rows,cols,char){
var rect = "";
for (var i = 0; i < rows; i +=1){
for (var j = 0; j < cols; j += 1){
rect += char;
}
rect += "\n"
}
return rect;
}
drawRect(rows,cols,char);
Just be aware that writing the function this way opens the door to possible errors and even security lapses depending upon user input. For example, if the user doesn't put a number into the row or col fields, that will break the code. So if you go this route you need to do more error-checking, character escaping, etc.

This version creates a table made up of Rows x Cols cells, places a # (or whatever you set Char to) inside each cell, and leaves you with something you can modify by using id = r(row number)c(col number).
I placed this block inside the head of the document.
As others have suggested, there should be some kind of input validation to ensure people do not place an array of javascript code pieces or similar.
Style the table and cells to make your output do what you want.
<script type="text/javascript">
function rectangle()
{
/**
*
*/
var Rows = parseInt($("input#numRows").val(), 10);
var Cols = parseInt($("input#numCols").val(), 10);
var Char = $("input#drawChar").val());
var artArea = document.getElementById("artArea")
if (document.getElementById("artTable"))
{
// assuming we made it
artArea.removeChild(document.getElementById("artTable"))
}
var my_table = document.createElement("TABLE");
my_table.id = "artTable"
artArea.appendChild(my_table);
for (var i=0; i < Rows; i++)
{
var this_row = document.createElement("TR")
this_row.id = "r" + i;
for ( var j=0; j < Cols; j++)
{
var this_cell = document.createElement("TD");
this_cell.id = this_row.id + "c" + j;
var my_text = document.createTextNode(Char);
this_cell.appendChild(my_text);
this_row.appendChild(this_cell);
}
my_table.appendChild(this_row);
}
}
$( document ).ready(function() { rectangle(); });
</script>
Tried it on jsfiddle, but have not made a document.

Here's a one-liner, excluding the docready:
$(document).ready(
$('#artArea').html("#".repeat(10).concat("\n").repeat(10))
);
You'll want to, like #btwebste mentioned, use a white-space declaration to ensure that the newlines are rendered.
#artArea {
text-align: center;
white-space: pre;
}
https://jsfiddle.net/rgjy50e5/

Related

Using DOM to append newlines in a paragraph

This may be a more basic question as I am learning/practicing using the DOM. But I have the following:
var demo_div = document.createElement("div")
demo_div.classList.add("demo")
var p_div = document.createElement("p")
var br = document.createElement("br")
for(let i = 0; i < 100; i++){
if (i % 5 == 0){
var text = document.createTextNode("meow")
}
else{
var text = document.createTextNode("woof")
}
p_div.appendChild(text)
p_div.appendChild(br)
}
demo_div.appendChild(p_div)
document.body.appendChild(demo_div)
I'm trying to create a div with the class = "demo" and then append a child node which is a paragraph to it. The paragraph will have 100 lines but every 5th line will have a different value.
That part wasn't hard at all the part I'm confused about is when I append the break to the paragraph, after each line is appended, the break doesn't actually work. Instead the break shows up at the end of the loop (As seen in the inspector). Any insight would be appreciated. Thanks.
You need to create a unique <br> element for each line break that you
want applied. Currently you're reusing the same <br> element which causes that same element to shift from it's last position to the next point in the text that you place it (via appendChild()).
Consider adding var br = document.createElement("br") inside your loop construct as shown:
var demo_div = document.createElement("div")
demo_div.classList.add("demo")
var p_div = document.createElement("p")
for(let i = 0; i < 100; i++){
if (i % 5 == 0){
var text = document.createTextNode("meow")
}
else{
var text = document.createTextNode("woof")
}
// Create a new br element for each loop iteration, and append it
// to your div like so:
var br = document.createElement("br")
p_div.appendChild(text)
p_div.appendChild(br)
}
demo_div.appendChild(p_div)
document.body.appendChild(demo_div)
You're only every creating one br - see how its creation is outside of the loop, rather than inside of the loop. When you call appendChild with an element that already exists in the DOM, the element is removed from its previous location and appended to the new parent.
Create the <br> inside the loop instead, just like you're doing with text:
var demo_div = document.createElement("div")
demo_div.classList.add("demo")
var p_div = document.createElement("p")
for(let i = 0; i < 100; i++){
var br = document.createElement("br")
if (i % 5 == 0){
var text = document.createTextNode("meow")
}
else{
var text = document.createTextNode("woof")
}
p_div.appendChild(text)
p_div.appendChild(br)
}
demo_div.appendChild(p_div)
document.body.appendChild(demo_div)

How to print a javascript array values in a jQuery .html() function?

I have a JavaScript array that contains a set of strings. I want to display them in a HTML div element by line by line using j Query or JavaScript.
My code is up to now:
var data = data;
for (i = 1; i <= data.length; i++) {
data[i] = data[i] + '<br />';
$(target).html('<a>'+data[i]+'</a>');
}
My data is displayed in this moment right now.
Labelling MachinesLabels - Plastic, Metal, Foil etcLabels FabricLaboratories - MedicalLaboratories - TestingLaboratory Equipment & SuppliesLaboratory Equipment Services & Calibration
I want them displayed like this as links (inside tags):
Labelling Machines
Labels - Plastic, Metal, Foil etc
Labels Fabric
Laboratories - MedicalLaboratories - Testing
Laboratory Equipment & Supplies
Laboratory Equipment Services & Calibration
Thanks in advance
You should add the breaks outside of the link tags and use .html() only once, as it completely replaces the innerHTML of the given element, i.e.
str = "";
for (i = 1; i <= data.length; i++) {
str += "<a>" + data[i] + "</a><br />";
}
$(target).html(str);
I would suggest another approach, to use innerHTML (javascript) or append (jquery) as another answer has already mentioned
for (i = 1; i <= data.length; i++) {
target.innerHTML += "<a>" + data[i] + "</a><br />";
}
Your code is incomplete here.Not sure if you have declare variable i anywhere in code.Also you are starting to loop from 1st index
Instead of appending to DOM on every iteration,create a string and concat the value to it. Append it on completion of the iteration.
var data = data,
htmlString="";
for (var i = 0; i <= data.length; i++) {
htmlString+= data[i] + '<br />';
}
$(target).append(htmlString);
The cleanest way will be wrapped in a div. And you need to use .append() method to not override the initial data that is already added to the target.
var data = ["Hello", "World", "Lorem", "Ipsum", "More length"];
for (var i = 0; i < data.length; i++) {
$("#result").append('<div>' + data[i] + '</div>');
}
.link {
color: #5ca5cc;
margin-bottom: 10px;
text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>
Clean and more simple code along with working demo.
Instead of a for/loop you could use ES6 in one line with map and a template literal.
$(target).html(arr.map(el => `<a>${el}</a><br/>`));
DEMO
var data = data;
var str = '';
for (var i = 1; i <= data.length; i++) {
str += `<a>${data[i]}<br /></a>`;
}
$(target).html(str);
Try this.

Making individual letters in a string different colours

I'm trying to make the colour different for certain letters (if found) in a string eg. the letter i. The search count is working I just can't figure out the changing html colour of the individual letter.
I know if it was a whole word then I could just use split strings, but can't figure out how to do it for a single letter. I've found some examples, one that I have tried is at the bottom that is not working either.
//getMsg is another function, which passes in a user inputted string
function searchMsg(getMsg) {
alert (getMsg);
var msgBoxObject = document.getElementById('msgBox');
var pos = getMsg.indexOf('i')
var txtToFind = (document.getElementById('txtToFind').value);
var count = 0;
while (pos !== -1){
count++;
pos = getMsg.indexOf('i', pos + 1);
document.writeln (+count);
msgBoxObject.innerHTML = (count);
}
getMsg = getMsg.replace('/i/g<span class="red">i</span>');
document.writeln (getMsg);
}
Edit; I've added in this, but can't get the loop to work correctly so it displays all instances of the letter found instead of just one: /*while (pos !== -1){
count++;
pos = getMsg.indexOf('i', pos + 1);
document.writeln (+count);
msgBoxObject.innerHTML = (count);
}
*/
var count = 0; // Count of target value
var i = 0; // Iterative counter
// Examine each element.
for(i=0; i<arr.length; i++)
{ if(arr[i] == targetValue)
count++;
}
return count;
}
searchIndex = txtMsg.indexOf(txtToFind);
if (searchIndex >=0 ) {
// Copy text from phrase up till the match.
matchPhrase = txtMsg.slice(0, searchIndex);
matchPhrase += '<font color="red">' + txtToFind + '</font>';
matchPhrase += txtMsg.slice(searchIndex + txtToFind.length);
} else {
matchPhrase = "No matches"
}
displayProcessedMsg(matchPhrase);
document.writeln(matchPhrase);
You either need to add the corresponding css for that class or change the tag like #john_Smith specified
Adding the CSS
span.red {
color: red;
}
Changing the tag
On your code replace this
getMsg = getMsg.replace('/i/g<span class="red">i</span>');
for
getMsg = getMsg.replace('/i/g<span style:"color:red">i</span>');
Some example of inline css
Some advice on color palettes
Try looking into d3 color scales(https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors) or apply a principle similar to incrementing an RGB value instead of using names of colors.
Hope this helps.

Table created in JavaScript doesn't display; No errors in console?

I'm learning JavaScript and got to the section in my book that described creating new DOM elements like tables, rows, and columns, so I wanted to create a table similar to the periodic table of elements that I could later go back to and fiddle with as I learned new things. My problem is that, from everything that I understand so far, this code should work. Except that it doesn't display anything, and there is nothing showing up in the console in FireFox v29.0.
Ideally, I wanted to create 7 rows (periods) and 18 columns (groups), and then display the elements that were associated at those locations in the table, and then try formatting it (for example, there are empty cells inserted between elements 1 and 18, since the only elements in that period are Hydrogen (1) and Helium (2). An example of this can be seen here: http://www.webelements.com/
However, my first task (creating a basic table) just doesn't seem to work, and either I'm using the wrong terminology or no one has posted about this before (and "javascript periodic table" links mostly to just things like http://www.webelements.com/). Any ideas on what I'm missing here?
<html>
<head>
<title>Periodic Table</title>
</head>
<body>
<script>
var periodicTable = createTable( 7, 18);
var period = 7;
var group = 18;
document.body.appendChild(periodicTable);
function createTable( period, group ) {
var elementId = 0;
var table = document.createElement('table');
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {
var element = tr.appendChild(document.createElement('td'));
element.innerHTML = ++elementId;
}
}
return table;
}
</script>
</html>
Edit
Based on the helpful comments below, I've changed the code to look like this:
<script>
var periodicTable = createTable( 7, 18);
document.body.appendChild(periodicTable);
function createTable( period, group ) {
var elementId = 0;
var table = document.createElement('table');
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {
var element = tr.appendChild(document.createElement('td'));
element.innerHTML = ++elementId;
}
}
return table;
}
</script>
In your original code you had this:
var periodicTable = createTable( 7, 18);
var period = 7;
var group = 18;
document.body.appendChild(periodicTable);
function createTable( rows, cols ) {
:
for (var p = 1; p < period; ++p) {
var tr = table.appendChild(document.createElement('tr'));
for (var g = 1; g < group; ++g) {...}
}
return table;
}
Thought vars are hoisted, i.e. variables are declared at the beginning of the scope, they are not initialized, values are assigned where ever an assignment is met. In your code period and group have value undefined until they are given values, after createTable has been executed.
You pass two arguments to createTable(), where their names are rows and cols. However, when you're needing those values, you use global variables period and group, which are undefined at the time the function is executed (they get their values after function has been finished).
To fix this, just rename the arguments rows and cols to period and group, and consider to remove the global variables (if they are not needed somewhere else ofcourse).

How can I use greasemonkey and javascript to change the colour of every letter on a page to a randomly selected one?

So I've read a few similar questions, and I've managed to do things like change the background colour, but I have not yet been able to get this to work;
What I want, is for each subsequent letter on a page to be randomly coloured. The colour space used isn't really important, as that's easy to fix once it actually works (am using this one at the moment), but I can't even get the text to change colour yet. I'm hoping I'm just making a silly mistake somewhere...
This is what i'm trying at the moment; and it kind of works, but it's very dependant on what tagName i use, and because of the nature of most webpages, it can break a lot of things if i'm not careful...
jsFiddle
var elements = document.getElementsByTagName('p');
for(var i=0,l=elements.length;i<l;++i) {
var str = elements[i].textContent;
elements[i].innerHTML = '';
for(var j=0,ll=str.length;j<ll;++j) {
var n = document.createElement('span');
elements[i].appendChild(n);
n.textContent = str[j];
n.style.color = get_random_colour();
}
}
function get_random_colour() {
var letters = '0123456789ABCDEF'.split('');
var colour = '#';
for (var i = 0; i < 6; i++ ) {
colour += letters[Math.round(Math.random() * 15)];
}
return colour;
}​
In this example, p works fine, and doesn't seem to break anything, but if I do * or html or body then it breaks the page. Is there a way to get all the text on the page, and not break it?
And another thing; I later changed the colour function to hopefully only pick colours that are in HSV(random,1,1) so that i only get nice bright colours, but it's not working. I'm presuming I just have some JS error in there, but I'm not that familiar with JS, so I'm finding it hard to find...
Here are the changes
To do this, you will want to recurse through just the text nodes, careful not to trash child HTML elements.
See the demo at jsFiddle.
var x = document.querySelector ("body"); // Etc.
buggerTextNodesIn (x);
function buggerTextNodesIn (node) {
var wrapClass = 'gmColorBarf';
function turnerizeTextNodes (node) {
if (node.nodeType === Node.TEXT_NODE) {
//--- Skip this node if it's already been wrapped.
if ( ! node.parentNode.classList.contains (wrapClass) ) {
var oldText = node.nodeValue;
var parent = node.parentNode;
for (var J = 0, len = oldText.length; J < len; ++J) {
var wrapSpan = document.createElement ("span");
wrapSpan.classList.add (wrapClass);
wrapSpan.textContent = oldText[J];
wrapSpan.style.color = getRandomColor ();
parent.insertBefore (wrapSpan, node);
}
parent.removeChild (node);
}
}
else if (node.nodeType === Node.ELEMENT_NODE) {
/*--- IMPORTANT! Start "bottom up" since we will be adding
gazillions of nodes and "top down" would skew our length measurement.
*/
for (var K = node.childNodes.length - 1; K >= 0; --K) {
turnerizeTextNodes (node.childNodes[K] );
}
}
}
turnerizeTextNodes (node);
}
function getRandomColor () {
var letters = '0123456789ABCDEF'.split ('');
var color = '#';
for (var J = 0; J < 6; ++J) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
Note that to get iframed content, the easiest way is to tune the #include, #exclude, and/or #match directives to trigger on the iframe URL(s) -- if they don't already.

Categories

Resources