Im building a random DogAPI image generator, where you put a number from 1-50 into a form text box, hit send, and it displays random dog photos of that amount.
Im almost there. If you put '1' into the text field, it will return 1 random image! But the issue is when you put 2 or more. It prints to the console just fine, showing you the number you chose in the form of links to those images, but on the main page, it shows a broken image link. They are all inside of an array, inside of an object... im just confused on how to show all images in object and not just 1 alone.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>How Many?</title>
<link rel="shortcut icon" href="#">
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="container">
<h1>How Many Dog Pics Do You Want?</h1>
<p>Pick a number between 1-50</p>
<form>
<input class="number" value="3" type="text" placeholder="1-50?" required>
<input type ="submit" value="Show me the doggies!">
</form>
<section class="results hidden">
<h2>Here you go!</h2>
<img class="results-img" alt="placeholder">
</section>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
<script src="index.js"></script>
</body>
</html>
CSS:
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
}
.container {
max-width: 600px;
margin: 0 auto;
}
.hidden {
display: none;
}
JS:
'use strict';
function getDogImage(text) {
fetch(`https://dog.ceo/api/breeds/image/random/${text}`)
.then(response => response.json())
.then(responseJson => displayResults(responseJson));
}
function watchForm() {
$('form').submit(event => {
event.preventDefault();
var text = $('.number').val();
if(text < 50){
getDogImage(text);
}else{
alert('Number must be between 1-50')
};
});
}
function displayResults(responseJson) {
console.log(responseJson);
//replace the existing image with the new one
$('.results-img').replaceWith(
`<img src="${responseJson.message}" class="results-img">`
)
//display the results section
$('.results').removeClass('hidden');
}
$(function() {
console.log('App loaded! Waiting for submit!');
watchForm();
});
Here is a sample of what you're going to have to do. You can probably do this in an ES6 way but here is my working example below. This will print out the array in your object and allow you to iterate so you can print the image urls out. You can see the working example here on my Codepen -
https://codepen.io/CodeHero1/pen/JjoEYMv
var messageObject = { message: [
'https://images.dog.ceo/breeds/rottweiler/n02106550_12828.jpg',
'https://images.dog.ceo/breeds/sheepdog-english/n02105641_6875.jpg',
'https://images.dog.ceo/breeds/terrier-lakeland/n02095570_4656.jpg' ], status:
'success' };
for(var i=0; i < messageObject.message.length; i++){
console.log(messageObject.message[i]);
}
I took this a step further in my CodePen example and have a live working example of returning the images with Jquery append. I'll also post the most important piece of this code here. I have refactored your function a little to give you a better example. Please see below.
function displayResults(responseJson) {
console.log(responseJson);
for(var i=0; i < responseJson.message.length; i++){
console.log(responseJson.message[i]);
$('.results').append(
`<img src="${responseJson.message[i]}" class="results-img">`
);
}
//display the results section
$('.results').removeClass('hidden');
}
Related
I want to incrementally reveal a code block with the following conditions:
Code not shown yet is hidden instead of greyed out
When new lines are revealed, they are highlighted with different background color
When transitioning between auto animated slides, new lines of code that are not hidden should also be highlighted
I've managed to do 1 by changing the opacity of .reveal .hljs.has-highlights tr:not(.highlight-line). For 2, I've tried to keep track of newly added lines with a script but it doesn't work since revealjs autogenerates a fragment for each transition. I guess the solution to 3, which I have not tried yet, would be similar to 2.
I'm new to JavaScript, so I'm not sure how to proceed, what's the best way to do this? Here's a MWE for my use case
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>reveal.js</title>
<link rel="stylesheet" href="dist/reset.css">
<link rel="stylesheet" href="dist/reveal.css">
<link rel="stylesheet" href="dist/theme/black.css">
<link rel="stylesheet" href="dist/custom.css">
<!-- Theme used for syntax highlighted code -->
<link rel="stylesheet" href="plugin/highlight/monokai.css">
</head>
<body>
<div class="reveal">
<div class="slides">
<section data-state="stats" data-auto-animate>
<pre data-id="code-animation" ><code data-line-numbers="1,2|1-6">
function $initHighlight(block, cls) {
try {
if (cls.search(/\bno\-highlight\b/) != -1)
return process(block, true, 0x0F) +
` class="${cls}"`;
</code></pre>
</section>
<section data-state="stats" data-auto-animate>
<pre data-id="code-animation" ><code data-line-numbers="1-8|1-11|1-14">
function $initHighlight(block, cls) {
try {
if (cls.search(/\bno\-highlight\b/) != -1)
return process(block, true, 0x0F) +
` class="${cls}"`;
} catch (e) {
/* handle exception */
}
for (var i = 0 / 2; i < classes.length; i++) {
if (checkCondition(classes[i]) === undefined)
console.log('undefined');
}
</code></pre>
</section>
</div>
</div>
<script src="dist/reveal.js"></script>
<script src="plugin/highlight/highlight.js"></script>
<script>
Reveal.initialize({
hash: true,
plugins: [ RevealHighlight ]
});
</script>
</body>
</html>
I am making an offline application of a music website using JS and I am handling song queues using arrays. I added song blocks with skip buttons so users can choose which song to skip without spamming another skip button that only allows them to skip the first song of the queue. The problem is, splicing the array with the index of the selected song the users wanted to skip removes the rest of the songs after it.
Example array: ["songA","songB","songC","songD","songE"]
If the user choose to skip songC, the song queue will become ["songA","songB"] and the songC to songE will be removed, but in reality the expected outcome should be ["songA","songB","songD","songE"].
I have no idea what is wrong with the code and I have searched similar topics regarding this problem but still no results. I am still new to JS and my code's a bit rough but I'm pretty sure that's not the cause of the issue.
JS:
//function of skip buttons on song blocks
songPlaylist.addEventListener("DOMNodeInserted", function() {
iconList = document.querySelectorAll(".deleteIcon");
iconList.forEach(function(element) {
element.addEventListener('click', function() {
var nameOfSong = this.parentNode.childNodes[0].dataset.name;
var indexByName = songQueue.indexOf(nameOfSong);
var selectedBlock = this.parentNode;
if (songQueue.length == 1) {
songQueue.shift();
songPlaylist.removeChild(songPlaylist.firstChild);
var emptyMsgSpan = document.createElement("div");
emptyMsgSpan.className += "emptyMsgSpan";
var emptyMsg = document.createTextNode("Playlist is empty! How 'bout adding some music?");
emptyMsgSpan.appendChild(emptyMsg);
document.getElementById("playlistContainer").appendChild(emptyMsgSpan);
setTimeout(function() {
audioPlayer.src = "";
}, 1000);
} else {
songQueue.splice(indexByName,1); // <--- press first block output delete everything
// press any block after first deletes everything beneath it
songPlaylist.removeChild(selectedBlock);
for (var blockIndex = indexByName; blockIndex <= songQueue.length; blockIndex++) {
document.getElementById("playlistContainer").children[blockIndex].childNodes[1].dataset.index -= 1;
}
};
});
});
});
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="index.css">
<link href="https://fonts.googleapis.com/css?family=Bai+Jamjuree" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Jost&display=swap" rel="stylesheet">
<!--<div>Icons made by Roundicons from www.flaticon.com</div>-->
<title>Mue - Custom Playlist</title>
</head>
<body>
<div id="bg">
<div class="titleBar">
<button style="background: none; border: none; cursor: pointer;" onclick="location.reload(); return false;">
<span>MUE</span>
</button>
</div>
<div class="songNameDisplay">
<span id="nowPlaying"></span>
</div>
<div class="trackContainer">
<div class="btn play"></div>
<div class="audioTrack">
<div class="trackBtn"></div>
</div>
<div id="skipBtn">
<div class="triangle1"></div>
<div class="triangle2"></div>
<div class="rect"></div>
</div>
</div>
<button id="fileBtn" class="fileBtn"><span>Upload</span></button>
</div>
<audio id="audioPlayer" controls autoplay></audio>
<input type="file" id="file" />
<div id="playlistContainer"></div>
</body>
<script src="index.js"></script>
<script>
const bg = document.getElementById("bg");
window.addEventListener('scroll' , function() {
let offset= window.pageYOffset;
bg.style.backgroundPositionY = offset * 0.5 + "px";
});
</script>
</html>
Thanks in advance.
Problem
When I click the buttons for playoff season or regular, the divs that holds the content players-list and players-regular appear to jump out of place when they fade in and out. How do I prevent this from happening?
I've tried using position fixed on some of elements, but things would get way out of place. I've included a JSFiddle here: http://jsfiddle.net/onlyandrewn/gcthaffs/
Click listener
// Click listener, toggles between sheets
$('button').click(function() {
$('button').removeClass("active");
$(this).toggleClass("active");
if ($('button.regular').hasClass('active')) {
$('#players-list').fadeOut(500);
$('.note').fadeOut(500);
$('#players-regular').fadeIn(2000);
} else {
$('#players-regular').fadeOut(500);
$('#players-list').fadeIn(2000);
$('.note').fadeIn(2000);
}
});
index.html
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8">
<title>Wheat Kings' leading point scorers</title>
<meta name="description" content="Wheat Kings' leading point scorers">
<meta name="author" content="Andrew Nguyen">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/css/style.css">
<link href='http://fonts.googleapis.com/css?family=Lato:300,400,700,900' rel='stylesheet' type='text/css'>
</head>
<body>
<h1>Wheat Kings leading goal scorers</h1>
<p class="year"></p>
<button class="playoffs active">Playoffs</button>
<button class="regular">Regular Season</button>
<div class="top">
<div id="players-list"></div>
<div id="players-regular"></div>
<p class="note">Note: Since there was a five-way tie for 6th place, players who scored two goals were then ranked by their total points in the playoffs. The other two players not listed here are Nolan Patrick and Macoy Erkamps.</p>
</div><!-- /.top -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tabletop.js/1.3.5/tabletop.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.0/handlebars.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"></script>
<!-- This is where the template for facts goes -->
<script id="players" type="text/x-handlebars-template">
<div class="container">
<div class="group">
<div class="{{row}}">
<p class="goals">{{goals}}</p>
<img src="{{image}}" alt="" class="head">
<p class="name">{{name}}</p>
<p class="position">{{position}}</p>
</div><!-- /.group -->
</div><!-- /.row -->
</div><!-- /.container -->
</script>
<script type="text/javascript">
// Click listener, toggles between sheets
$('button').click(function() {
$('button').removeClass("active");
$(this).toggleClass("active");
if ($('button.regular').hasClass('active')) {
$('#players-list').fadeOut(500);
$('.note').fadeOut(500);
$('#players-regular').fadeIn(2000);
} else {
$('#players-regular').fadeOut(500);
$('#players-list').fadeIn(2000);
$('.note').fadeIn(2000);
}
});
// Original
var public_spreadsheet_url = "https://docs.google.com/spreadsheets/d/1RMN49oyRlTxW5kv8MnYJwQRttis2csgVFH46kyORCaQ/pubhtml";
$(document).ready( function() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
parseNumbers: true } );
});
function showInfo(data, tabletop) {
var source = $("#players").html();
var template = Handlebars.compile(source);
// The actual name of the sheet, not entire .csv
$.each(tabletop.sheets("Playoffs").all(), function(i, fact) {
var html = template(fact);
// You need an element with this id or class in your HTML
$("#players-list").append(html);
$('.container').eq(i).addClass(data.Playoffs.elements[i]);
// This logs all the objects in the sheet
// console.log(data);
// This logs just validity
// console.log(data.Playoffs.elements[i]);
})
// If you need to get data from a second sheet in single Google Doc
$.each(tabletop.sheets("Regular").all(), function(i, fact) {
var html = template(fact);
// You need an element with this id or class in your HTML
$("#players-regular").append(html);
$('.container').eq(i).addClass(data.Regular.elements[i]);
// This logs all the objects in the sheet
// console.log(data);
// This logs just validity
// console.log(data.Regular.elements[i]);
});
}
</script>
</body>
</html>
base.scss
/*----------------------------------
MAIN STYLES
----------------------------------*/
html {
font-size: 62.5%; /* 10px browser default */
}
body {
max-width: 600px;
padding: 10px;
}
.top {
max-width: 600px;
}
#players-list,
#players-regular {
}
h1 {
font-family: 'Lato', sans-serif;
font-weight: 900;
border-bottom: 1px solid #ccc;
padding-bottom: 8px;
}
.note {
position: relative;
width: 95%;
left: 3%;
}
This is happening because the fadeOut is not done when the fadeIn starts. You end up with both divs visible for a short period of time, and when the fadeOut is done the first div is hidden and you see the jump.
How about something like this:
$('#players-list').fadeOut(500, function() {
$('#players-regular').fadeIn(500);
});
This way the second div is displayed only when the first one is completely hidden.
Also, decrease the animation duration a bit, it makes for better user experience ;).
I seem to make a mistake in the following:
html: index.html, main.html, etc
js: jQuery, jQuery UI, own.js, own_main.js
The end result should be an index page that based on a menu choice loads a html in a div.
The HTML that loads has a button element that I want to use with jQuery UI.
Index.html
<html lang="us">
<head>
<meta charset="utf-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Dev</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="css/kendo.dataviz.default.min.css" rel="stylesheet" />
<link href="css/kendo.dataviz.min.css" rel="stylesheet" />
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
<link rel="stylesheet" href="css/main.css">
<link href="css/jquery-ui-1.10.3.custom.css" rel="stylesheet">
<link href="css/typ.css" rel="stylesheet" />
<script src="js/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<script src="Scripts/jquery-2.0.3.js"></script>
<script src="js/jquery-ui-1.10.3.custom.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/typ.js"></script>
<script src="js/typ-persons.js"></script>
</head>
<body>
<div id="content"></div>
</body>
</html>
typ.js file
function currentLoc(goToLoc) {
if (CheckLogin() == 0) {
//Not logged in, go to main
$("#content").load("/main.html");
window.localStorage.globalLocation = "/main.html";
} else {
if (goToLoc == '') {
console.log("No GoToLoc: " + goToLoc);
if (window.localStorage.globalLocation == '') {
console.log("No Global location");
$("#content").load("/main.html");
window.localStorage.globalLocation = "/main.html";
} else {
console.log("Global Location " + window.localStorage.globalLocation);
$("#content").load(window.localStorage.globalLocation);
}
} else {
console.log("GoToLoc " + goToLoc);
$("#content").load(goToLoc);
window.localStorage.globalLocation = goToLoc;
}
}
}
persons.html
<script src="js/typ-persons.js"></script>
<div class="container">
<style>
#toolbar {
padding: 4px;
display: inline-block;
}
/* support: IE7 */
* + html #toolbar {
display: inline;
}
</style>
<div id="toolbar" style="width:100%;" class="ui-widget-header ui-corner-all">
<button id="btnNew" ></button>
<button id="btnSave"></button>
<label for="persons">Find Person by Name or ID: </label>
<input type="text" class="input-sm" id="persons">
<input type="hidden" id="person-id">
</div>
</div>
typ-persons.js
$(function () {
$("#btnNew").button({
text: false,
label: "New Person",
icons: {
primary: "ui-icon-document"
}
})
.click(function () {
});
$("#btnSave").button({
text: false,
label: "Save",
disabled: true,
icons: {
primary: "ui-icon-disk"
}
})
.click(function () {
});
});
On the persons page there is also an autocomplete element with json data.
This works like a charm.
The problem is that the toolbar does not get the buttons applied from the typ-persons.js.
When I add the jQuery UI to the persons.html the buttons do work and get styled as they are supposed to.
The problem then is that jQuery UI loads twice and the autocomplete drowdown disappears on mouse over.
Kind of a paradox here and I would like both to work.
Thanks for your help,
Joris
I have the hunch that your persons.html file is the main.html addressed in the code. Otherwise I can't see where do you load persons.html or what are you loading when you load main.html.
Why are you adding typ-persons.js to persons.html, if you already have it in your main html file? In the way it's added, there's going to be double binding on button clicks. More than once, I believe. It would work on first load and then screw button behavior for good.
EDIT: After OP clarifications, these are my suggestions.
First: instead of putting new JS into persons html, make it just plain html. Make sure you don't use id attributes when that content is prone to be loaded several times. In that case, it's best to use classes.
<div class="container">
<style>
#toolbar {
padding: 4px;
display: inline-block;
}
/* support: IE7 */
* + html #toolbar {
display: inline;
}
</style>
<div id="toolbar" style="width:100%;" class="ui-widget-header ui-corner-all">
<button class="btnNew" ></button>
<button class="btnSave"></button>
<label for="persons">Find Person by Name or ID: </label>
<input type="text" class="input-sm" id="persons">
<input type="hidden" id="person-id">
</div>
</div>
Second: since you won't load new JS in that ajax call, you need to give the new buttons their behavior somewhere, right? Try to do that after they're appended, using jQuery's callback. I'd reccomend you use get method instead of load to have a bit more control on new content. Instead of
$("#content").load("/persons.html");
Try
$.get("/persons.html",function(responseText) {
var newElement=jQuery(responseText);
$("#content").append(newElement);
$(".btnNew", newElement).button({
text: false,
label: "New Person",
icons: {
primary: "ui-icon-document"
}
}).click(function () {
});
$(".btnSave",newElement).button({
text: false,
label: "Save",
disabled: true,
icons: {
primary: "ui-icon-disk"
}
}).click(function () {
});
});
Third: whatever listener you need to be set on dynamic elements, delegate them to the document to avoid needing to redeclare it (with the risk of double binding). I see no examples of this in your original post, but if you have any case of click, focus, or blur listeners (to name a few) I'll include a practical example.
I am using the following code to access the camera but aim is to read QR codes using camera.
Using the following code I can only take the picture and save it then using my backend read the QR code from the saved file.
How can I modify the code to process the picture while the camera is reading.
Or something like sending the streams to the back-end and once the QR code is detected it notifies the user.
I need to work with a tablet.
I can use the following to record videos as well but how to send the streams to back-end
<input type="file" capture="camera" accept="video/*">
My code to take pictures
<!DOCTYPE HTML>
<html>
<head>
<meta name="viewport" content="width=320; user-scalable=no" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>ColorThief Demo</title>
<script type="text/javascript" charset="utf-8" src="jquery-2.0.0.min.js"></script>
<script type="text/javascript" charset="utf-8" src="quantize.js"></script>
<script type="text/javascript" charset="utf-8" src="color-thief.js"></script>
<style>
#yourimage {
width:100%;
}
#swatches {
width: 100%;
height: 50px;
}
.swatch {
width:18%;
height: 50px;
border-style:solid;
border-width:thin;
float: left;
margin-right: 3px;
}
</style>
</head>
<body>
<input type="file" capture="camera" accept="image/*" id="takePictureField">
<img id="yourimage">
<div id="swatches">
<div id="swatch0" class="swatch"></div>
<div id="swatch1" class="swatch"></div>
<div id="swatch2" class="swatch"></div>
<div id="swatch3" class="swatch"></div>
<div id="swatch4" class="swatch"></div>
</div>
<script>
var desiredWidth;
$(document).ready(function() {
console.log('onReady');
$("#takePictureField").on("change",gotPic);
$("#yourimage").load(getSwatches);
desiredWidth = window.innerWidth;
if(!("url" in window) && ("webkitURL" in window)) {
window.URL = window.webkitURL;
}
});
function getSwatches(){
var colorArr = createPalette($("#yourimage"), 5);
for (var i = 0; i < Math.min(5, colorArr.length); i++) {
$("#swatch"+i).css("background-color","rgb("+colorArr[i][0]+","+colorArr[i][1]+","+colorArr[i][2]+")");
console.log($("#swatch"+i).css("background-color"));
}
}
//Credit: https://www.youtube.com/watch?v=EPYnGFEcis4&feature=youtube_gdata_player
function gotPic(event) {
if(event.target.files.length == 1 &&
event.target.files[0].type.indexOf("image/") == 0) {
$("#yourimage").attr("src",URL.createObjectURL(event.target.files[0]));
}
}
</script>
</body>
</html>
Capturing the video and sending it to the server will be prohibitively bandwidth-intensive on a mobile device. I would give jsqrcode a try and do it all client-side in JavaScript. Also, see this answer.
You need to have a look at the Stream API. There are some demos at the bottom of Eric Bidelman's blog post.