Random card/Image using buttonjavascript - javascript

I want to create a card game using java script. Being a beginner at java script, I am finding great difficulty finding a suitable tutorial for what I am trying to do. When the 'start game' button is selected, I want the computer to produce a random card. I have tried many ways of doing this and have came to no avail. Here is my code.
<html>
<head>
<title> Christmas Assignment </title>
<link rel="stylesheet" type="text/css" href="xmasass_1.css">
<script type = "text/javascript">
function randomImg(){
var myimages= [];
myimages[1] = "cards/1.gif";
myimages[2] = "cards/2.gif";
myimages[3] = "cards/3.gif";
myimages[4] = "cards/4.gif";
myimages[5] = "cards/5.gif";
myimages[6] = "cards/6.gif";
myimages[7] = "cards/7.gif";
myimages[8] = "cards/8.gif";
myimages[9] = "cards/9.gif";
myimages[10] = "cards/10.gif";
myimages[11] = "cards/11.gif";
myimages[12] = "cards/12.gif";
myimages[13] = "cards/13.gif";
function oddTrivia(){
var randomImg = Math.floor(Math.random()*(oddtrivia.length));
document.getElementById('comp').InnerHTML=myimages[randomImg];
}
ar total = 0;
function randomImg(){
var x = Math.floor(Math.random()*13)+1;
document.getElementById('img1').src = 'die'+x+'.gif';
document.getElementById('img2').src = 'die'+y+'.gif';
document.getElementById('score').innerHTML = total;
}
var card1Image;
var card2Image;
var card3Image;
var card4Image;
var card5Image;
var card6Image;
function start(){
var button = document.getElementById("startButton");
button.addEventListener("click", pickCards, false);
card1Image = document.getElementById("1");
card2Image = document.getElementById("2");
card3Image = document.getElementById("3");
card4Image = document.getElementById("4");
card5Image = document.getElementById("5");
card6Image = document.getElementById("6");
}
function pickCards(){
setImage(card1Image);
setImage(card2Image);
setImage(card3Image);
setImage(card4Image);
setImage(card5Image);
setImage(card6Image);
}
function setImage(cardImg){
var cardValue = Math.floor(1 + Math.random() * 13);
cardImg.setAttribute("src", "C:Xmas Assignment/cards/" + cardValue + ".gif");
}
window.addEventListener("load", start, false);
</script>
</head>
<body>
<div id = "settings">
<img src = "settings_img.png" width = "60" height = "60">
</div>
<div id = "bodydiv">
<h1> Card Game</h1>
<div id = "computer">
<img src = " cards/back.gif">
</div>
<div id = "comp" > Computer </div>
<div id ="arrow">
<img src ="arrow2.png" width = "100" height="100">
</div>
<div id = "player">
<img src = " cards/back.gif">
</div>
<div id = "play"> Player </div>
<div id = "kittens">
<button id = "startButton" onclick ="randomImg" > Start Game </button>
<div id = "buttons_1">
<button id ="higher"> Higher
</button>
<button id = "equal"> Equal
</button>
<button id = "lower"> Lower
</button>
</div>
<button id = "draw"> Draw your Card
</button>
<div id = "resetscore"> Reset Score
</div>
</div>
<div id = "score">
</div>
</div>
</body>
</html>
body {
background:#66ccff;
}
h1 {
text-align:center;
}
#settings {
float:right;
margin-top:10px;
}
#bodydiv {
width: 800px;
height:600px;
margin-left:200px;
margin-top:40px;
margin-bottom:60px;
background:#ffccff;
border-radius: 10px;
}
#computer {
border-radius: 10px;
position: absolute;
left:35%;
top:27%;
}
#player {
border-radius: 10px;
position: absolute;
left:55%;
top:27%;
}
#start_game {
width :120px;
height: 55px;
margin-left: 350px;
margin-top:50px;
background:white;
border:1px solid black;
}
#buttons_1 {
text-align: center;
margin-top:20px;
}
#higher {
width:140px;
height:50px;
font-size: 15px;
border-radius:10px;
font-weight:bold;
}
#equal {
width:140px;
height:50px;
font-size: 15px;
border-radius:10px;
font-weight:bold;
}
#lower {
width:140px;
height:50px;
font-size: 15px;
border-radius:10px;
font-weight:bold;
}
#draw {
width:160px;
height:30px;
margin-left:325px;
margin-top: 30px;
border:1px solid black;
background:#FFFFCC;
}
#resetscore {
text-align: center;
margin-top: 40px;
}
#arrow {
margin-left:370px;
margin-top:-130px;
}
#comp {
margin-top:240px;
margin-left:265px;
}
#play{
margin-top:10px;
margin-left:540px;
}

You code is kind of hard to read.
You forgot to close the "{" of your main function.
You are declaring "randomImg" again in the body of the "randomImg" function(use a different name).
You wrote
ar total = 0;
I think you meant to write:
var total = 0;
oddtrivia in the function "OddTrivia" is not defined.
y in the inner randomImg function is not defined.

Having poked a little bit at the code, here is a few things:
Problem no 1: randomImg()
It's hard to know your intentions, but you should likely begin with removing the start of your first function randomImg(){.
Because 1) It does not have an end and 2) If it actually spans everything then this line window.addEventListener("load", start, false); will not load on startup (since it does not get executed until randomImg() gets executed, and by then the page has already loaded.)
Problem no 2: Cannot set property 'src' of null"
Now when the first problem is out of the way, you should see "Uncaught TypeError: Cannot set property 'src' of null" if you look in your console. Yes, USE YOUR CONSOLE. Click on the error to show what causes it. Here it is:
cardImg.setAttribute("src", "C:Xmas Assignment/cards/" + cardValue + ".gif");
This means that cardImg is null. We backtrack the first call of setImage() and find that the variable card1Image is passed in. So that must mean that card1Image also is null. You can check it yourself by adding a console.log('card1Image', card1Image); in your code. Or you add a breakpoint at that point. (Use the sources-tab in chrome dev tools, click at the line-numbering to add a break point. Refresh the page and it will stop at the break point. Now you can mouse-over variables to see their values.)
Let's look at where 'card1Image' is set.
card1Image = document.getElementById("1");
So why is this returning null? Do we even have a id="1" element in the html? That could be the reason. (It is.)
There are more problems, but I'll stop there, but when you have fixed this part AND have no errors please ask again. Always check your errors and if you ask a question here you should provide errors. And when you can also be more specific with your questions.
What might someone else have done differently?
When it comes to playing cards, why not an array of objects?
var cards = [
{ src : 'cards/1.gif', value: 1 },
{ src : 'cards/2.gif', value: 2 },
{ src : 'cards/3.gif', value: 3 },
{ src : 'cards/4.gif', value: 4 }
]; // (You can of course use code to generate it.)
// Then a function to put cards in the player's hand.
var playerHand = _.sample(cards, 2);
console.log(playerHand);
Here I assume lodash, a lightweight library for when you don't want to re-invent the wheel.

Related

Span value inside a style value

this maybe a very stupid question, but is this possibe ?
well i have a sort of a slider on a html page.
this is what it shows up like now:
<p>Illustrator</p>
<div class="w3-light-grey w3-round-xlarge w3-small">
<div class="w3-container w3-center w3-round-xlarge w3-teal" style="width:75%">75%</div>
</div>
This shows up a bar,
well what want to achieve is if its possible to change that value 75% to my script data :
style="width:75%">
like i have a script, it retrieves values from my server:
var input = "10;11;15";
var arr = input.split(";");
document.getElementById("humid").innerHTML = (arr[0 ]);
this shows up my data just normal
<span id="humid">0</span>
what i want to do is something like this, but i don't know how:
I want this value from style="width:75%"> to be the humid value.
so if my humid value is 50% the width goes 50%
i did try this but no result
style="width:humid+%">
or style="width:(humid)+%">
i'm still learning,
regards
<!DOCTYPE html>
<html>
<title>TESt</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Roboto'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
html,body,h1,h2,h3,h4,h5,h6 {font-family: "Roboto", sans-serif}
</style>
<body class="w3-light-grey">
<p>Original</p>
<div class="w3-light-grey w3-round-xlarge w3-small">
<div class="w3-container w3-center w3-round-xlarge w3-teal" style="width:75%">75%</div>
</div>
<p>Media</p>
<div class="w3-light-grey w3-round-xlarge w3-small">
<div class="w3-container w3-center w3-round-xlarge w3-teal" style="#humid">0</div>
</body>
<script>
var input = "10;11;15";
var arr = input.split(";");
//alert(arr[1 ]);
document.getElementById("humid").innerHTML = (arr[0]);
document.getElementById("temp").innerHTML = (arr[1 ]);
document.getElementById("uv").innerHTML = (arr[2 ]);
</script>
</html>
Retrieve my input:
function readForestall() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("ForestAll").innerHTML =
this.responseText;
}
};
xhttp.open("GET", "readFORESTALL", false);
xhttp.send();
}
setInterval(function() {
readForestall();
}, 5000);
If I understand your question right, you want to change the width of an element based on a variable you receive. In that case you can change the inline style with JavaScript. You just need to grab the element and set the style by assigning values to the properties of the element's style property.
If you want to change the width, you can use the following:
element.style.width = '50%'
It sets the width to 50%. You can also include a variable like this:
const width = 50
element.style.width = `${width}%`
I've created a snippet below where you can set the value by using an input and it updates both the width and the content of that div. You can click on the "Run code snippet button" and see the result in live.
const barLeft = document.querySelector('#bar-left');
const barRight = document.querySelector('#bar-right');
const input = document.querySelector('[name="width"]');
const error = document.querySelector('.error');
input.addEventListener('input', (e) => {
const widthLeft = Number(e.target.value);
const widthRight = 100 - widthLeft;
if (widthLeft < 0 || widthLeft > 100) {
error.textContent =
"We don't do that here. Width must be between 0 and 100.";
return;
}
error.textContent = '';
barLeft.textContent = `${widthLeft}%`;
barLeft.style.width = `${widthLeft}%`;
barRight.textContent = `${widthRight}%`;
barRight.style.width = `${widthRight}%`;
});
body {
font-family: sans-serif;
margin: 0;
text-align: center;
}
.outer {
display: flex;
margin-bottom: 2rem;
}
.inner {
background-color: lightcoral;
box-shadow: 0 -4px 0 rgba(0, 0, 0, 0.2) inset;
height: 100%;
padding: 1rem;
}
.inner--blue {
background-color: lightblue;
}
.controls {
margin-bottom: 1rem;
}
input {
font-family: inherit;
font-size: inherit;
padding: 0.5rem 1rem;
}
.error {
color: #d32f2f;
}
<div class="outer">
<div class="inner" id="bar-left" style="width: 75%">75%</div>
<div class="inner inner--blue" id="bar-right" style="width: 25%">25%</div>
</div>
<div class="controls">
<label for="width">First bar's width:</label>
<input type="number" name="width" id="width" min="5" max="95" value="75" />
</div>
<div class="error"></div>
Update: Updated your example below. Make sure you close your tags, and check out how to add ids to elements.
<body class="w3-light-grey">
<p>Media</p>
<div class="w3-light-grey w3-round-xlarge w3-small">
<div class="w3-container w3-center w3-round-xlarge w3-teal" id="humid">
0
</div>
</div>
div>
<script>
var input = '10;11;15';
var arr = input.split(';');
// update the content of the div with ID "humid"
document.getElementById('humid').textContent = arr[0];
// change the width of the div with ID "humid"
document.getElementById('humid').style.width = `${arr[0]}%`;
</script>
</body>
Tranq,
i am not exactly sure why you would want to call the width from an array and use DOM when you can simply use CSS to accomplish this with #media instead. correct me if i am wrong, but you're just trying to adjust the width based on values of the current width of the device? this seems like a whole lot of work for what is a simple solution.
use something like to set the appropriate widths depending on the screen widths:
#media only screen and (max-width: 600px) {
#humid { width: 75%; }
}
also, it is likely you're not passing your array properly and it is returning NULL(0). you can check this via a debugger and ensure it is being passed properly. FireFox has a Great built in debugger for this. use CMD/CTRL+SHIFT+K to open the debugger in FireFox.
P.S. you are not passing the array properly. you're setting it to change the 'innerHTML' which changes everything inside of the
document.getElementById("humid").innerHTML = (arr[0 ]);
if you change "(arr[0 ]);" to something like "string" it will replace the value 0 to "string".

Need to enlarge image at click and then reduce it again by clicking again on external javascript file

This large image is defined in the index.html with a class="small" attribute so it shows as a thumbnail.
<img id="smart_thumbnail" class="small" src="https://image.jpg">
On a separate .js file need to create a function to bring it back to it's normal size and then back to thumbnail by clicking it again. NEED to use if/else. What I am trying to do is to switch between class="" and class="small"
So far I have this but it is not working:
document.addEventListener("DOMContentLoaded", function(event) {
var thumbnailElement = document.getElementById("smart_thumbnail");
thumbnailElement.addEventListener("click", function() {
if(thumbnailElement.className = "small";){thumbnailElement.className = "";}
else
{thumbnailElement.className = "small";}
});
});
Any suggestions? Thanks.
Here is something that I made work. It uses JS style properties to change it, not CSS classes. You could copy or reference it:
var imgEl = document.getElementById("Img");
var isBig = false;
imgEl.addEventListener("click", function() {
if (isBig) {
imgEl.style.width = "30px";
imgEl.style.height = "30px";
isBig = false;
} else {
imgEl.style.width = "100px";
imgEl.style.height = "100px";
isBig = true;
}
})
#Img {
border: 1px solid black;
background-color: red;
width: 30px;
height: 30px;
transition: 1s;
}
<div id="Img">
The CSS class switcher isn't working because '=' is not an equal operator, it is an assignment operator. use '==' or '===' for equal operators.
The code above will only run once when the website is initially loaded. To solve this problem, you will need to modify the code so that it is constantly listening for an event.
The code for it should look something similar to the following:
<!DOCTYPE html>
<html>
<head>
<title>Resizing a square with event listeners</title>
<style type="text/css">
.small {
width: 50px;
height: 50px;
}
.large {
width: 100px;
height: 100px;
}
#smart_thumbnail {
background-color: blue;
}
</style>
</head>
<body>
<div id="smart_thumbnail" class="large"></div>
<script>
var thumbnailElement = document.getElementById("smart_thumbnail");
thumbnailElement.addEventListener("click", function() {
if (this.className == "small") {this.className = "large";}
else {this.className = "small";}
});
</script>
</body>
</html>
I also modified the smart_thumbnail so that it has a large/normal size class as well as a small class.

CSSStyleSheet.insertRule - trouble with indexing and dynamic variables using Javascript

I've read up on inserting css rules using Javascript and have managed to get it working (after some trial & error). So I have 2 questions:
Q.1 Why is an index < 1 not working - see Mozilla example (and many others) below:
// push a new rule onto the top of my stylesheet - doesn't work...
myStyle.insertRule("#blanc { color: white }", 0); // returns Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to insert the rule.
// change the index and it works!
myStyle.insertRule("#blanc { color: white }", 1);
This article by David Walsh (very helpful), explains that the default for index is -1. He uses 1 in his example, which is what worked for me. Anything less than 1, ie 0 or -1 (as per the default) threw the following errors:
Index -1 error:
Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet': The index provided (4294967295) is larger than the maximum index (2071).
Index 0 error:
Uncaught DOMException: Failed to execute 'insertRule' on 'CSSStyleSheet': Failed to insert the rule.
It's not a huge problem, but it does mean I can't control specificity. I can use !important or rework the css/inserted rule so that it overrides any existing styles, but as I'm just learning JavaScript, I'd really like to know why it's not working as expected. Does anyone have any ideas?
Q.2 Having got it to work using index 1, I now want to pull in values dynamically. I have the item names in an array, which is used to create multiple objects, inside which are the property values I want to use for the individual style rules for that object.
Basically what I'm trying to output is this (which works):
styleSheet.insertRule("#item { border-top-color: #000000; border-right-color: #ffffff; }", 1);
But using variables, something like this:
styleSheet.insertRule("[itemName] { border-top-color: [itemName.value1]; border-right-color: [itemName.value2]; }", 1); // itemName.valueX being the object's array item
I've tried heaps of things, but I can't get the array item bit to work, ie colour and colour4 should actually be itemName.value1/2 or a var that equals the same. This is the closest I've got so far...
styleSheet.insertRule("#" + name + " { border-top-color: " + colour + "; border-right-color: " + colour4 + " !important; }", 1); // 1st rule works, 2nd doesn't show anything
It all works lovely if I write it manually (as per the 1st example), but how to do it dynamically? I've found info on insertRule, but not using dynamic values - can anyone help/point me in the right direction?
Many thanks in advance!
Expanded WIP for more clarity:
function itemColours() {
for (i = 3; i < itemsArray.length; i++) {
let name = itemsArray[i];
let colour = #000000;
console.log(item1.value); // returns the hex value I want to use in the rule
styleSheet.insertRule("#" + name + " { border-top-color: " + colour + "; border-right-color: " + name + ".value !important; }", 1);
// rule 1 works, rule 2 doesn't...
}
Update 2
This demo:
can accept user data to use insertRule() and deleteRule().
has an Add Set button which will create and append a clone of the <form> part of the document
has 3 styleSheets Bootstrap [0], CSSOM, and the <style> tag.
Demo 4
// Just for demo
.as-console-wrapper {
width: 170px;
max-height: 40px;
transform: translateX(340px)
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' title='Bootstrap-3.3.7'>
<link href='https://glpjt.s3-us-west-1.amazonaws.com/ir/cssom.css' rel="stylesheet" title='CSSOM'>
<style title='Tag'>
body {
max-width: 96%;
visibility: hidden;
font: 400 16px/1.2 Verdana
}
ul.x-list.x-list {
margin-left: 0;
padding-left: 1em;
text-indent: -1em;
list-style-type: none;
}
li.x-item.x-item {
list-style: none;
line-height: 1.5;
}
.x-flex.x-flex {
display: flex;
justify-content: center;
align-items: center;
}
.x-col {
display: flex;
flex-direction: column
}
option::before {
content: attr(name)
}
#idx {
max-width: 6ch;
}
label {
margin: 10px auto 10px -15px
}
#add {
position: fixed;
z-index: 1;
top: 50px;
left: 20px
}
</style>
</head>
<body>
<main class='container' style='padding:50px 0 20px 20px'>
<form id='cssom' class='row x-col'>
<div class='btn-group col-sm-12'>
<input id='add' class='btn-lg btn-success' type='button' value='Add Set'>
</div>
<section class='row'>
<!--=================================[0]-->
<fieldset class='set0 col-sm-12'>
<hr>
<div class='row x-flex'>
<!--=================================[1]-->
<label class='form-control-label col-sm-2'>CSS Rule</label>
<textarea id='rul0' class='form-control col-sm-10' rows='2'>li.x-item.x-item::before {content: '\1f539\00a0';list-style:none;font-size:small;position:relative;bottom:2px}</textarea>
</div>
<div class='form-inline row'>
<label class='form-control-label col-sm-2'>Stylesheet</label>
<select id='sht0' class='form-control col-sm-4'>
<optgroup label="LINK">
<!--================================[3]-->
<option value='0' selected name='Bootstrap-3.3.7'> [0]</option>
<option value='1' name='CSSOM'> [1]</option>
</optgroup>
<optgroup label="STYLE">
<option value='2' name='Tag'> [2]</option>
</optgroup>
</select>
<label class='form-control-label col-sm-1'>Rule Index</label>
<input id='idx0' class='form-control col-sm-1' type='number' min='-1' value='0'>
<!--==========[4]-->
<div class="btn-group col-sm-4">
<!--=====[5]-->
<input id='ins0' class='btn btn-primary' type='button' value='Insert Rule' onclick='modRule(this)'>
<!--======[6]-->
<input id='del0' class='btn btn-danger' type='button' value='Delete Rule' onclick='modRule(this)'>
</div>
</div>
</fieldset>
</section>
<hr><br>
</form>
<hgroup class='x-inline'>
<!--====================================[hgroup.x-inline]-->
<h1 class='h1'>CSSStyleSheet</h1>
<h2 class='h2'>.insertRule()</h2>
</hgroup>
<article class='text-primary'>
<blockquote class='blockquote'>
<h3 id="Restrictions" class='h3'>Restrictions</h3>
<p>CSS stylesheet rule-lists have a number of intuitive and not-so-intuitive <a class="external" href="https://drafts.csswg.org/cssom/#insert-a-css-rule">restrictions</a> affecting how and where rules can be inserted. Violating these will likely
cause an error raised as a <a title="The DOMException interface represents an abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API." href="https://developer.mozilla.org/en-US/docs/Web/API/DOMException"><code>DOMException</code></a> </p>
<!--==========================[ul.x-list | li.x-fade]-->
<ul id='list' class='list-group-flush x-list'>
<li class='list-group-item-text fade x-fade x-item'>If index > number of rules in the stylesheet (the <a title="A CSSRuleList is an (indirect-modify only) array-like object containing an ordered collection of CSSRule objects." href="https://developer.mozilla.org/en-US/docs/Web/API/CSSRuleList"><code>CSSRuleList</code></a>.length),
then aborts with IndexSizeError.</li>
<li class='list-group-item-warning x-item'>If rule cannot be inserted at index 0 due to some CSS constraint, then aborts with HierarchyRequestError.</li>
<li class='list-group-item-danger x-item'>If more than one rule is given in the rule parameter, then aborts with SyntaxError</li>
<li class='list-group-item-text x-fade x-item'>If trying to insert an #import at-rule after a style rule, then aborts with HierarchyRequestError.</li>
<li class='list-group-item-text x-fade x-item'>If rule is #namespace at-rule and list has more than just #import at-rules and/or #namespace at-rules, then aborts with InvalidStateError.</li>
</ul>
</blockquote>
<footer class='blockquote-footer'>
<!--===============================[[cite.x-cite]-->
<cite class='x-cite'><a href='https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule#Restrictions'>CSSStyleSheet.insertRule() - Wed APIs #Restrictions | MDN</a></cite> </footer>
</article>
</main>
<script>
var cnt = 0;
var form = document.forms[0];
var add = document.getElementById('add');
function modRule(ID) {
var e = window.event;
var i = ID.id.split('').pop();
console.log('ruleIndex: ' + i);
var sheets = document.styleSheets;
var sheet = document.getElementById('sht' + i);
var rulez = document.getElementById('rul' + i);
var index = document.getElementById('idx' + i);
var vSht = parseInt(sheet.value, 10);
var vIdx = parseInt(index.value, 10);
var vRul = rulez.value;
if (e.target.value === 'Delete Rule') {
switch (vSht) {
case 0:
sheets[0].deleteRule(vIdx);
break;
case 1:
sheets[1].deleteRule(vIdx);
break;
case 2:
sheets[2].deleteRule(vIdx);
break;
default:
sheets[0].deleteRule(vIdx);
break;
}
} else if (e.target.value === 'Insert Rule') {
switch (vSht) {
case 0:
sheets[0].insertRule(vRul, vIdx);
break;
case 1:
sheets[1].insertRule(vRul, vIdx);
break;
case 2:
sheets[2].insertRule(vRul, vIdx);
break;
default:
sheets[0].insertRule(vRul, vIdx);
break;
}
} else {
return;
}
}
add.addEventListener('click', addSet, false);
function addSet(e) {
cnt++;
var set = document.querySelector('.set0');
var opt = document.options
var dupe = set.cloneNode(true);
dupe.className = 'set' + cnt;
var fields = Array.from(dupe.querySelectorAll('[id]'));
var ids = fields.map(function(ID, idx) {
var zero = ID.id.lastIndexOf("0");
ID.id = ID.id.slice(0, zero);
ID.id = ID.id + cnt;
if (ID.id === 'rul' + cnt) {
ID.textContent = 'p {color:red}';
}
console.log('id: ' + ID.id + ' val: ' + ID.value);
return ID.value;
});
form.appendChild(dupe);
}
</script>
</body>
</html>
Update
If the stylesheet is big, wouldn't it be more efficient to dynamically create a new stylesheet for them?
Yes, but not an external <link> it's far more efficient and a ton more easier to dynamically manipulate a <style> block at the bottom of the </head>.
Not only is it simple, it's powerful since it's at the bottom of the cascade it'll override anything from an external <link>.
Also another thing to consider is that a HTTP request isn't needed unlike an external file which requires it and that' adds to your website's latency.
Demo 3 features 3 functions:
injectCSS() will be called mere microseconds before it's counterpart injectJS() at window.onload. It will create a <style> block within the </head> along with whatever styles we want initially.
injectJS() loads after injectCSS() because as a general rule style should always load before script. It will create a <script> tag and append it as the last child of the <body> tag specifically right before the closing </body> tag. Just like injectCSS() it may have anything within its tags that's script.
inject() calls both injectCSS() and injectJS() asynchronously to ensure that the former will always load before the latter.
As far as this demo relates to the OP, injectCSS() is the function that we should concern ourselves with as was already explained previously.
Details are commented in the demo
For faster loading time, please review the PLUNKER instead.
Demo 3
<!DOCTYPE html>
<html>
<head>
<style>
html {
font: 400 100%/1 Consolas;
}
html,
body {
height: 100%;
width: 100%;
}
main {
height: auto;
width: 100%;
padding: 10px;
}
section {
height: auto;
width: 100%;
padding: 10px
}
fieldset {
min-width: 70%;
margin: 20px 0;
padding: 10px;
}
var {
background: rgba(0, 0, 0, .7);
color: lime;
}
</style>
</head>
<body>
<h1></h1>
<main>
<p><var>injectCSS =</var> All paragraphs will be red</p>
<section>
<form id='test0'>
<fieldset>
<legend>Test Log</legend>
<label for='msg0'>injectCSS()...:
<output id='msg0'></output></label>
<br>
<label for='msg1'>injectJS()....:
<output id='msg1'></output></label>
</fieldset>
</form>
</section>
<section>
</section>
</main>
<footer>
<p>Review this page with Firebug/DevTools and we'll see an extra <style> tag in the <head> and we'll see an extra <script> tag right before the closing <\body> tag.</p>
</footer>
<script>
// HTMLFormControlsCollection★
var x0 = document.forms[0].elements;
var m0 = x0.msg0;
var m1 = x0.msg1;
// Input strings of styles and scripts that are to be injected
var css = "p {color:red}";
var js = "document.querySelector('h1').innerHTML = '<var>injectJS =</var> H1 HTML'";
/* This function manages injectCSS() and injectJS() functions by using
|| the async/await★ keywords. Times are provided by
|| performance.now()★ method.
*/ //* ✎ Delete/add the first * to disable/enable this version of inject().
// The proceeding edit ✎ must be done as well.
var inject = async function() {
var wait0 = injectCSS.call(this, css);
var wait1 = injectJS.call(this, js);
m0.value = performance.now();
var init1 = await wait1;
m1.value = performance.now()
return false;
};
/*/// ✎ Delete/add the first / to enable/disable this version of inject().
// The previous edit ✎ must be done as well.
var inject = function() {
injectCSS.call(this, css);
m0.value = performance.now();
injectJS.call(this, js);
m1.value = performance.now()
return false;
};
/* These 2 functions do the same thing but with different content.
|| They could be refactored into one function but I made them
|| separately to show injectCSS() sepatately for QA SO46985099.
|| Both creates a tag, then writes the code in it, and then appends
|| it to DOM.
*/
function injectCSS(style) {
var sty = document.createElement("style");
sty.innerHTML = style;
document.querySelector('head').appendChild(sty);
}
function injectJS(script) {
var scr = document.createElement("script");
scr.innerHTML = script;
document.body.appendChild(scr);
}
/* The main function inject() is called at window.load. This is the last
|| loading event possible in which we are able call our function. This
|| ensures that specific CSS is loaded before specific JS is called.
|| This is the last step in the loading process, therefore there should be
|| no more styles to render or script that blocks.
*/
window.onload = inject;
</script>
</body>
</html>
Demo Outline
Collects all <link> and <style> into a styleSheetList using document.stylesheets
Converts it into an array called sheetArray with Array.from()
The target is the 3rd <link> which is sheetArray[2]
Then there are 2 rules inserted at index 0 and index 1 successfully.
This is done through a for loop and arrays as the dynamic parameters and interpolation of Template Literals.
This demo does not function on SO, go to PLUNKER for a functioning demo.
Note: In the demo content is an excerpt from MDN that defines the restrictions of insertRule(). The highlighted items may apply to your specific errors.
Demo 1 - index.html [Review PLUNKER for a working demo]
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css' rel='stylesheet'>
<link href="style.css" rel="stylesheet">
<link href='cssom.css' rel="stylesheet">
</head>
<body>
<main class='container'>
<hgroup class='x-inline'>
<!--====================================[hgroup.x-inline]-->
<h1 class='h1'>CSSStyleSheet</h1>
<h2 class='h2'>.insertRule()</h2>
</hgroup>
<article class='text-primary'>
<blockquote class='blockquote'>
<h3 id="Restrictions" class='h3'>Restrictions</h3>
<p>CSS stylesheet rule-lists have a number of intuitive and not-so-intuitive <a class="external" href="https://drafts.csswg.org/cssom/#insert-a-css-rule">restrictions</a> affecting how and where rules can be inserted. Violating these will likely
cause an error raised as a <a title="The DOMException interface represents an abnormal event (called an exception) which occurs as a result of calling a method or accessing a property of a web API." href="https://developer.mozilla.org/en-US/docs/Web/API/DOMException"><code>DOMException</code></a> </p>
<!--==========================[ul.x-list | li.x-fade]-->
<ul class='list-group-flush x-list'>
<li class='list-group-item-text x-fade'>If index > number of rules in the stylesheet (the <a title="A CSSRuleList is an (indirect-modify only) array-like object containing an ordered collection of CSSRule objects." href="https://developer.mozilla.org/en-US/docs/Web/API/CSSRuleList"><code>CSSRuleList</code></a>.length),
then aborts with IndexSizeError.</li>
<li class='list-group-item-warning'>If rule cannot be inserted at index 0 due to some CSS constraint, then aborts with HierarchyRequestError.</li>
<li class='list-group-item-danger'>If more than one rule is given in the rule parameter, then aborts with SyntaxError</li>
<li class='list-group-item-text x-fade'>If trying to insert an #import at-rule after a style rule, then aborts with HierarchyRequestError.</li>
<li class='list-group-item-text x-fade'>If rule is #namespace at-rule and list has more than just #import at-rules and/or #namespace at-rules, then aborts with InvalidStateError.</li>
</ul>
</blockquote>
<footer class='blockquote-footer'>
<!--===============================[[cite.x-cite]-->
<cite class='x-cite'><a href='https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule#Restrictions'>CSSStyleSheet.insertRule() - Wed APIs #Restrictions | MDN</a></cite> </footer>
</article>
</main>
<script>
var sheets = document.styleSheets;
var sheetArray = Array.from(sheets);
var sel = ['ul.x-list', 'li::before'];
var dec = [`margin-left: 0; padding-left: 1em; text-indent: -1em;`, `content: '🔹';`];
var idx = [0, 1];
var qty = idx.length;
for (let r = 0; r < qty; r++) {
sheetArray[2].insertRule(`${sel[r]} {${dec[r]}}`, idx[r]);
}
</script>
</body>
</html>
Deno 2 - cssom.css
/*0*/
hgroup.x-inline {display:flex; justify-content:center; align-items: center;}
/*1*/
ul.x-list.x-list {list-style: none;}
/*2*/
li.x-fade.x-fade {color:rgba(0,0,0,.3);}
/*3*/
cite.x-cite.x-cite {position:relative; left:60%}
/*4*/
cite.x-cite.x-cite::before {content:"\2014 \00A0"}
/*5*/
.blockquote-footer::before {content: '';}
/*6*/
li.list-group-item {line-height:1.5}
/*7*/
a {text-shadow: 2px 5px 3px rgba(192,192,192,.8)}

How can I change the x position of a div via javascript when I click on another div this way?

<body>
<div id = "SiteContainer">
<div id = "NavigationButtons"></div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition();">x</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition();">y</div>
<div id = "VideoWrapper">
<div id = "SlideShowItem">
<img src="Images/A.png" alt="A"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/B.png" alt="B"></img>
</div>
<div id = "SlideShowItem">
<img src="Images/C.png" alt="C" ></img>
</div>
</div>
</div>
</div>
<script>
var wrapper = document.querySelector("#VideoWrapper");
function setPosition(e)
{
if(e.target.name = "forward")
{
if!(wrapper.style.left = "-200%")
{
wrapper.style.left = wrapper.style.left - 100%;
}
}
else
{
if(e.target.name = "back")
{
if!(wrapper.style.left = "0%")
{
wrapper.style.left = wrapper.style.left + 100%;
}
}
}
}
</script>
</body>
Hi, I am very new to javascript. What I am trying to do, is change the x-position of a div when another div (NavigationForward or NavigationBackward) is clicked. However it does not appear to do anything at all. Basically if the div with name forward is clicked, I want to translate the VideoWrapper -100% from it's current position and +100% when "back". The css div itself VideoWrapper has a width of 300%. Inside this div as you can see is a SlideShowItem which is what will change. Perhaps I am adding and subtracting 100% the wrong way?
EDIT:
Thanks everyone for helping me out with this...I had just one more query, I am trying to hide the arrows based on whether the wrapper is at the first slide or the last slide. If its on the first slide, then I'd hide the left arrow div and if it's on the last, I'd hide the right arrow, otherwise display both of em. Ive tried several ways to achieve this, but none of em work, so Ive resorted to using copies of variables from the function that works. Even then it does not work. It appears that my if and else if statements always evaluate to false, so perhaps I am not retrieving the position properly?
function HideArrows()
{
var wrapper2 = document.getElementById("VideoWrapper");
var offset_x2 = wrapper2.style.left;
if(parseInt(offset_x2,10) == max_x)
{
document.getElementById("NavigationForward").display = 'none';
}
else if(parseInt(offset_x2,10) == min_x)
{
document.getElementById("NavigationBackward").display = 'none';
}
else
{
document.getElementById("NavigationForward").display = 'inline-block';
document.getElementById("NavigationBackward").display = 'inline-block';
}
}
//html is the same except that I added a mouseover = "HideArrows();"
<div id = "ShowReelContainer" onmouseover="HideArrows();">
To achieve this type o slider functionality your div VideoWrapper must have overflow:hidden style, and your SlideShowItemdivs must have a position:relative style.
Then to move the slides forward or backward you can use the style left which allows you to move the divs SlideShowItem relative to it's parent VideoWrapper.
I've tested this here on JSFiddle.
It seems to work as you described in your question, although you may need to do some adjustments, like defining the width of your slides, how many they are and so on.
For the sake of simplicity, I defined them as "constants" on the top of the code, but I think you can work from that point on.
CSS
#VideoWrapper{
position:relative; height:100px; white-space:nowrap;width:500px;
margin-left:0px; border:1px solid #000; overflow:hidden; }
.SlideShowItem{
width:500px; height:100px;display:inline-block;position:relative; }
#NavigationForward, #NavigationBackward{
cursor:pointer;float:left; background-color:silver;margin-right:5px;
margin-bottom:10px; text-align:center; padding:10px; }
HTML
<div id = "SiteContainer">
<div id = "NavigationButtons">
</div>
<div id = "ShowReelContainer">
<div id= "NavigationBackward" name = "back" onclick="setPosition('back');">prev</div>
<div id= "NavigationForward" name = "forward" onclick="setPosition('forward');">next</div>
<div style="clear:both;"></div>
<div id = "VideoWrapper">
<div class= "SlideShowItem" style="background-color:blue;">
Slide 1
</div>
<div class = "SlideShowItem" style="background-color:yellow;">
Slide 2
</div>
<div class = "SlideShowItem" style="background-color:pink;">
Slide 3
</div>
</div>
</div>
</div>
JavaScript
var unit = 'px'; var margin = 4; var itemSize = 500 + margin; var itemCount = 3; var min_x = 0; var max_x = -(itemCount-1) * itemSize;
function setPosition(e) {
var wrapper = document.getElementById("VideoWrapper");
var slides = wrapper.getElementsByTagName('div');
var offset_x = slides[0].style.left.replace(unit, '');
var curr_x = parseInt(offset_x.length == 0 ? 0 : offset_x);
if(e == "forward")
{
if(curr_x <= max_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + -itemSize) + unit;
}
else if(e == "back")
{
if(curr_x >= min_x)
return;
for(var i=0; i<slides.length; i++)
slides[i].style.left= (curr_x + itemSize) + unit;
} }
After you analyze and test the code, I don't really know what's your purpose with this, I mean, you maybe just playing around or trying to develop something for a personal project, but if you are looking for something more professional avoid to create things like sliders on your own, as there are tons of plugins like this available and well tested out there on the web.
Consider using jQuery with NivoSlider, it works like a charm and is cross browser.
I would recommend using jQuery, this will reduce your coding by quite a bit. Can read more here: http://api.jquery.com/animate/
I've created a simple fiddle for you to take a look at. This example uses the .animate() method to reposition two div elements based on the CSS 'left' property.
CSS:
#container {
position: absolute;
left: 1em;
top: 1em;
right: 1em;
bottom: 1em;
overflow: hidden;
}
#one, #two {
position: absolute;
color: white;
}
#one {
background: pink;
width: 100%;
top:0;
bottom:0;
}
#two {
background: blue;
width: 100%;
left: 100%;
top:0;
bottom:0;
}
HTML:
<div id="container">
<div id="one">Div One</div>
<div id="two">Div Two</div>
</div>
JavaScript/jQuery:
var one, two, container;
function animateSlides(){
one.animate({
left : '-100%'
}, 1000, function(){
one.animate({
left : 0
}, 1000);
});
two.animate({
left : 0
}, 1000, function(){
two.animate({
left:'100%'
}, 1000);
});
};
$(function(){
one = $('#one');
two = $('#two');
container = $('#container');
setInterval(animateSlides, 2000);
});
JSFiddle Example: http://jsfiddle.net/adamfullen/vSSK8/3/

how can I dynamically resize an html textbox to avoid overflowing?

I would like to know how to resize a textbox to prevent text nearby it from overflowing.
I have 3 elements in a row, a label, a text box, and a button. the label however, can have words of varying lengths. if the word is too long it will move the text input too far to the side and the button will overflow onto the next line. to preserve the style of the page, I would prefer that the button stays on the same line as the other 2 elements.
I am trying to get the text box to shrink only as much as necessary to allow room for the other elements.
can I do this with JQuery?
Edit: here's the JFiddle thing:
http://jsfiddle.net/425ve/2/
and here's the main code:
<html>
<head>
<style>
body{
background-color:#000000;
color:#cccccc;
}
#chatbox{
width:100%;
height:85%;
border-style:solid;
border-color:#000000;
overflow:auto;
}
#mainchat{
width:82%;
float:left;
margin:0;
}
#sidebar{
float:left;
height:97%;
width:17%;
border-style:dashed;
border-width:1px;
border-color:#AAAAAA;
border-right:0;
border-top:0;
border-bottom:0;
overflow:auto;
}
#topbar{
border-style:dashed;
border-width:1px;
border-color:#AAAAAA;
border-left: 0;
border-top: 0;
float:left;
width:82%;
}
a{
color:#cccccc;
text-decoration:none;
}
a:hover{
color:#CCCCEE;
background-color:111122;
}
#topbarname{
float:right;
}
#message{
width: 90%;
background-color:#000000;
border-color:#CCCCCC;
border-style:solid;
border-width: 1px;
color:CCCCCC;
}
#submitbutton{
background-color:#000000;
border-color:#CCCCCC;
border-style:solid;
border-width: 1px;
color:#CCCCCC;
}
</style>
<script>
function getCookie(name) {
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0) return null;
}
else
{
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1) {
end = dc.length;
}
}
return unescape(dc.substring(begin + prefix.length, end));
}
function doSomething() {
var myCookie = getCookie("IceID");
if (myCookie == null) {
window.location="login.php"
}
else {
// do cookie exists stuff
}
}
doSomething();
</script>
</head>
<body>
<div id="topbar">
| Information | Logs | characters | Profile | Private logs | Messages | Logout |
</div>
<div id="mainchat">
<div id="chatbox">
<?php
include("getpost.php");
//improve this with AJAX!
?>
</div>
<div id="input">
<form id="inputchat">
<b id="name">
<?php
echo $_COOKIE['IceID'];
?>
</b>
<input type="text" name="message" id="message"></input>
<input type="submit" id="submitbutton" value="say"></input>
</form>
</div>
<div id="utools">
</div>
</div>
<div id="sidebar">
<div id="title">
A
</div>
<div id="list">
</div>
</div>
</body>
</html>
Edit:to clarify, the name doesn't actively change while the page is being used(only right before being displayed), but it will be different depending on who loads the page. their username fits into that label.
You don't need jQuery. jQuery could make it much simpler though. I prefer vanilla.
var left = document.getElementById('name')
var resizable = document.getElementById('message')
var right = document.getElementById('submitbutton')
realign()
window.addEventListener('resize', realign)
function realign() {
resizable.style.width = '0'
var extraWidth = getWidth(resizable) // Measure the border and padding on it's own.
resizable.style.width = getWidth(resizable.parentNode) - getWidth(left) - getWidth(right)
function getWidth(element) { // Superior to offsetWidth because it measures fractions of a pixel which is even more relevant when using the browser zoom feature.
var rect = element.getBoundingClientRect() // A accurate way to measure location on the screen.
return rect.right - rec.left // The accurate width.
}
}
The only adjustment you need would be to fix my typo(s) if I made any and then if you want to support older versions of IE, you need to use the alternative to addEventListener, Google it.

Categories

Resources