How to test (unit test) arrow functions in JS via Jasmine? - javascript

I've done a small project "Notes" and now trying to test it using Jasmine. But since it's my first script using module style and imitation of the private functions, I can't understand how can I test the business logic of my script, since Jasmine doesn't see my arrow functions at all. Please help me to start my tests.
// eslint-disable-next-line func-names
const NotesList = ((function () {
const NOTE_TITLE = 'notesList';
const initNotesList = () => {
if (localStorage.getItem(NOTE_TITLE)) {
return JSON.parse(localStorage.getItem(NOTE_TITLE));
}
return [];
};
let notesList = initNotesList();
const saveData = (data) => {
notesList = [...data];
localStorage.setItem(NOTE_TITLE, JSON.stringify(notesList));
};
const addNote = (note) => {
if (notesList.includes(note)) {
return {
done: false,
error: 'The note is in the notes list already',
};
}
saveData([...notesList, note]);
return {
done: true,
};
};
const removeNote = (note) => {
const filteredNotesList = notesList.filter((item) => item !== note);
if (filteredNotesList.length === notesList.length) {
return {
done: false,
error: 'Note doesn\'t exist',
};
}
saveData(filteredNotesList);
return { done: true };
};
return {
getNotesList() {
return notesList;
},
addItem(item) {
return addNote(item);
},
removeItem(item) {
return removeNote(item);
},
};
})());
const STYLES = {
show: 'd-block',
};
const UI = {
noteValue: document.querySelector('#note-value'),
addNote: document.querySelector('#add-note'),
removeNote: document.querySelector('#remove-note'),
errorMessage: document.querySelector('#error-message'),
list: document.querySelector('#list'),
renderNotesList() {
this.clearNotesList();
NotesList.getNotesList().forEach((item) => {
const li = document.createElement('li');
li.innerText = item;
this.list.append(li);
});
},
clearNotesList() {
this.list.innerText = '';
},
handleNotesListResponse(result) {
if (result.done) {
this.noteValue.value = '';
this.errorMessage.classList.remove(STYLES.show);
this.renderNotesList();
} else {
this.errorMessage.innerText = result.error;
this.errorMessage.classList.add(STYLES.show);
}
},
};
UI.addNote.addEventListener('click', (event) => {
event.preventDefault();
const result = NotesList.addItem(UI.noteValue.value);
UI.handleNotesListResponse(result);
});
UI.removeNote.addEventListener('click', (event) => {
event.preventDefault();
const result = NotesList.removeItem(UI.noteValue.value);
UI.handleNotesListResponse(result);
});
UI.renderNotesList();
body{font-family:"Roboto Condensed",sans-serif;font-size:16px}header{background:none}.nav-link{font-size:20px}.container{max-width:1200px;background-image:url(../images/blue-snow.png)}.container-header{max-width:1200px}.container-footer{max-width:1200px}footer li{display:inline;padding-right:5px;padding-bottom:5px}ul li a :hover{transform:rotate(1turn);transition:0.5s ease-in}html{scroll-behavior:smooth}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
crossorigin="anonymous">
<link
href="https://fonts.googleapis.com/css?family=Roboto+Condensed&display=swap"
rel="stylesheet">
<link rel="stylesheet" type="text/css" href="../dist/style.css"/>
<title>Homework 1</title>
</head>
<body>
<div class="container-header mx-auto">
<header>
<nav class="navbar navbar-expand-lg navbar navbar-light bg-light">
<a class="navbar-brand pr-4"
href="https://github.com/TrekFuel/home_tasks_FE-2" target="_blank"><img
src="../images/github-logo-header-image.png"
alt="GitHub" title="GitHub"
width="40" height="40"/></a>
<button class="navbar-toggler" type="button" data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active pr-5">
<a class="nav-link" href="homework-3.html">Home Tasks (to the
previous page)<span
class="sr-only"></span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="#2">Contacts<span
class="sr-only"></span></a>
</li>
</ul>
</div>
</nav>
</header>
</div>
<div class="container mx-auto d-flex">
<main>
<div class="row mt-5 mb-5 ml-3 mr-3">
<div class="col">
<h1 class="text-center mb-4">Notes</h1>
<div class="input-group input-group-lg mx-auto mt-5 mb-5">
<input type="text" class="form-control"
id="note-value"
name="note-value"
value=""
placeholder="Note"
aria-label="Note"
aria-describedby="button-addon4 inputGroup-sizing-lg">
<div class="input-group-append" id="button-addon4">
<button class="btn btn-outline-secondary" id="add-note"
type="button">Add note
</button>
<button class="btn btn-outline-secondary" id="remove-note"
type="button">Remove
note
</button>
</div>
</div>
<div class="alert alert-danger d-none" id="error-message"
role="alert"></div>
</div>
</div>
<div class="row mt-3 mb-3">
<div class="col">
<ul id="list"></ul>
</div>
</div>
</main>
</div>
<div class="container-footer mx-auto">
<footer>
<a name="2"></a>
<div class="card text-center">
<div class="card-header">
<a name="7"></a>
<h3>Contacts</h3>
</div>
<div class="card-footer text-center">
<ul class="list-unstyled p-2">
<li>
<a href="https://vk.com/bolotinnikita" target="_blank">
<img src="../images/vk-logo.png"
width="30"
height="30"
alt="ВК"
title="ВК"/></a>
</li>
<li>
<a href="https://twitter.com/bolotinnick" target="_blank">
<img src="../images/twitter-logo.png"
width="30"
height="30"
alt="Twitter"
title="Twitter"/></a>
</li>
<li>
<a href="https://www.linkedin.com/in/bolotinnick/" target="_blank">
<img src="../images/linkedin-logo.png"
width="30"
height="30"
alt="LinkedIn"
title="LinkedIn"/></a>
</li>
<li>
<a href="https://github.com/TrekFuel" target="_blank">
<img src="../images/github-logo.png"
width="30"
height="30"
alt="GitHub"
title="GitHub"/></a>
</li>
<li>
<a href="https://www.instagram.com/bolotinnick/" target="_blank">
<img src="../images/instagram-logo.png"
width="30"
height="30"
alt="Instagram"
title="Instagram"/></a>
</li>
<li>
<a href="mailto:ridge96#yandex.ru?subject=website">
<img src="../images/email-logo.png"
width="30"
height="30"
alt="Email"
title="Email"/></a>
</li>
<li>
<a href="https://t.me/bolotinnick" target="_blank">
<img src="../images/telegram-logo.png"
width="30"
height="30"
alt="Telegram"
title="Telegram"/></a>
</li>
<li>
<a href="skype:nick-spinner96?add">
<img src="../images/skype-logo.png"
width="30"
height="30"
alt="Skype"
title="Skype"/></a>
</li>
<li>
<a href="viber://chat?number=+375291328633">
<img src="../images/viber-logo.png"
width="30"
height="30"
alt="Viber"
title="Viber"/></a>
</li>
<li>
<a href="https://wa.me/375291328633" target="_blank">
<img src="../images/whatsapp-logo.png"
width="30"
height="30"
alt="WhatsApp"
title="WhatsApp"/></a>
</li>
</ul>
<div class="btn btn-info mb-2">Bolotin Nikita ©, 2019-2020 <br>
FE-2
Courses
</div>
</div>
<div class="text-left m-2">
<a href="#top" class="btn btn-primary" id="btn">To the top
↑</a>
</div>
</div>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
<script src="../js/notes(hw-3).js"></script>
</body>
</html>
// eslint-disable-next-line no-undef
describe('notes(hw-3).js -> initNotesList', () => {
// eslint-disable-next-line no-undef
it('should return Object from the LocalStorage in case there are items'
+ ' there, otherwise should return an empty array', () => {
});
});

What exactly are you looking to test that you can't already test? The getNotesList, addItem, removeItem methods are already exposed. Just simply test the exposed, public functions directly. This will indirectly test all of the implementation details.
Now, it might be that there is some bit of the code that is not testable through this manner, or it is extremely awkward to test. In this case, you should refactor your code to make it more testable.
For example, the initNotesList function is not directly testable. You may want to expose this as a public function (ie- add it to the return statement) and write some unit tests against it. I would also create and expose a clearNotesList function to aid in the set up and tear down of tests.
But other than that, there's not much to do. There's no magic to unit testing. You just need to create clear, simple code and expose the proper pieces to make testing easy.

Related

Why does my delete button does not delete the card

I want to delete the card when we click on the delete button after adding a TODO note
I have created a website which uses localstorage to store notes and display when clicking the create TODO button and it all works but when I click the delete button after the note is created (You have to create a TODO first) it does not delete the div itself
I want to delete the card when we click on the delete button
CODE:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO List</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<style>
.main-title {
text-align: center;
}
.input {
border: 2px solid grey;
}
.all-todo {
display: flex;
margin: 30px;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">TODO List</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<h1 class="main-title">TODO List</h1>
<div class="container">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Task Name</label>
<input type="text" class="form-control input" id="exampleFormControlInput1">
</div>
<div class="mb-3">
<label for="exampleFormControlTextarea1" class="form-label">Task Details</label>
<textarea class="form-control input" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary" id="main-btn">Create TODO</button>
<button type="button" class="btn btn-warning" id="clr">Clear LocalStorage</button>
</div>
<div class="all-todo"></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
</body>
<script>
let button = document.getElementById("main-btn")
button.onclick = () => {
let key = document.getElementById("exampleFormControlInput1").value
let value = document.getElementById("exampleFormControlTextarea1").value
if (key != "" && value != "") {
iHTML = ""
localStorage.setItem(key, value)
iHTML += `
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title">${key}</h5>
<p class="card-text">${localStorage.getItem(key)}</p>
<button type="button" id="note" onclick='${key}.innerHTML=""' class="btn btn-danger '${key}'">Delete</button>
</div>
</div>
`
document.getElementsByClassName("all-todo")[0].innerHTML += iHTML
}
else {
alert("Task Name or Details cannot be empty!")
}
}
let clr_btn = document.getElementById("clr")
clr_btn.onclick = () => {
localStorage.clear()
}
</script>
</html>
The error is thrown on this line onclick='${key}.innerHTML=""'. You will want to first remove the item from local storage e.g: localStorage.removeItem('${key}') and then remove the html. Theres many way of achieveing this but this.parentElement.parentElement.remove() should be sufficient
The complete button should look something like <button type="button" id="note" onclick="localStorage.removeItem('${key}'); this.parentElement.parentElement.remove()" class="btn btn-danger '${key}'">Delete</button>
Heres a working example:
https://jsfiddle.net/qt83bshd/
Well, i post you a simple solution for your problem.
Instead of use innerhtml to introuce your todos, yo can create the elements.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO List</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
<style>
.main-title {
text-align: center;
}
.input {
border: 2px solid grey;
}
.all-todo {
display: flex;
margin: 30px;
}
/* add css in this poiint to optimize code*/
.card {
width: 18rem;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">TODO List</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<h1 class="main-title">TODO List</h1>
<div class="container">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Task Name</label>
<input type="text" class="form-control input" id="exampleFormControlInput1">
</div>
<div class="mb-3">
<label for="exampleFormControlTextarea1" class="form-label">Task Details</label>
<textarea class="form-control input" id="exampleFormControlTextarea1" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary" id="main-btn">Create TODO</button>
<button type="button" class="btn btn-warning" id="clr">Clear LocalStorage</button>
</div>
<div class="all-todo"></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
</body>
<script>
let button = document.getElementById("main-btn")
button.onclick = () => {
// collect the div that contains all the todos
let alltodo = document.querySelector(".all-todo");
let key = document.getElementById("exampleFormControlInput1").value
let value = document.getElementById("exampleFormControlTextarea1").value
// and if it any todo create the card
if (key != "" && value != "") {
localStorage.setItem(key, value)
// with create element we can create the card more easy
var todo = document.createElement("div");
todo.setAttribute("class", "card");
var button = document.createElement("button");
button.textContent = "eliminar";
var titulo = document.createElement("h5");
titulo.textContent = key;
button.onclick = () => {
console.log(button.parentElement.remove())
// in this point we can also remove the todo from the local storage wih localstorage.removeItem()
}
// introduce all items in dom
todo.appendChild(titulo)
todo.appendChild(button);
alltodo.appendChild(todo);
// iHTML = ""
// localStorage.setItem(key, value)
// iHTML += `
// <div class="card" style="width: 18rem;">
// <div class="card-body">
// <h5 class="card-title">${key}</h5>
// <p class="card-text">${localStorage.getItem(key)}</p>
// <button type="button" id="note" onclick='${key}.innerHTML=""' class="btn btn-danger '${key}'">Delete</button>
// </div>
// </div>
// `
// document.getElementsByClassName("all-todo")[0].innerHTML += iHTML
}
else {
alert("Task Name or Details cannot be empty!")
}
}
let clr_btn = document.getElementById("clr")
clr_btn.onclick = () => {
localStorage.clear()
}
</script>
</html>

Why isn't my search icon fetching the API?

I added a search Icon to my code, but now I need it to fetch the results in the API. I assigned it an id so I can access it but it's not working. What newbie mistake am I making?
const searchForm = document.querySelector('form');
const searchResultDiv = document.querySelector('.search-result');
const container = document.querySelector('.container');
let searchQuery='';
const searchIcon = document.getElementById('search-icon');
searchForm.addEventListener('submit', (e) => {
e.preventDefault();
searchQuery = e.target.querySelector('input').value;
fetchAPI();
})
searchIcon.addEventListener('click', (search) => {
searchQuery = search.target.querySelector('input').value;
fetchAPI();
})
<head>
<link href='https://unpkg.com/boxicons#2.1.2/css/boxicons.min.css' rel='stylesheet'>
</head>
<div class="container">
<div class="logo" style="cursor: pointer">
<img src="/Images/logo img.png">
<h1 class="brand">Recipe App</h1>
</div>
<form>
<input type="text" placeholder="Find Yummy Recipes...">
<i class='bx bx-search' id="search-icon" style="cursor: pointer;"></i>
</form>
<div class="search-result">
<!-- <div class="item">
<img src="/Images/Food-1.jpg" alt="">
<div class="food-details">
<h1 class="title">This is a Recipe</h1>
<a class="view-button" href="#">View Recipe</a>
</div>
<p class="item-data">Calories: 120</p>
</div> -->
</div>
</div>
The snippet below demonstrates how you can assign two event listeners ('click' and 'submit') to the body of the document. The if condition in the callback function turns it into a "delegated" event handling: the action will unfold only if the sIcon element was click-ed or the submit event was triggered (e. g. by hitting the return key after entering text into the input field).
As #DaveNewton remarked in a comment already, you should evaluate the inp.value as late as possible and not communicate it through a global variable but rather as an argument to the fetchAPI() function.
const sIcon = document.getElementById('search-icon'),
inp=document.querySelector("input");
['click','submit'].forEach(ty=>document.body.addEventListener(ty,ev=> {
ev.preventDefault();
if(ev.type=='click'&&ev.target==sIcon||ev.type=='submit')
fetchAPI(inp.value);
}));
function fetchAPI(pat){
console.log(`fetching data with pattern: ${pat}`);
}
<head>
<link href='https://unpkg.com/boxicons#2.1.2/css/boxicons.min.css' rel='stylesheet'>
</head>
<div class="container">
<div class="logo" style="cursor: pointer">
<img src="/Images/logo img.png">
<h1 class="brand">Recipe App</h1>
</div>
<form>
<input type="text" placeholder="Find Yummy Recipes...">
<i class='bx bx-search' id="search-icon" style="cursor: pointer;"></i>
</form>
<div class="search-result">
<!-- <div class="item">
<img src="/Images/Food-1.jpg" alt="">
<div class="food-details">
<h1 class="title">This is a Recipe</h1>
<a class="view-button" href="#">View Recipe</a>
</div>
<p class="item-data">Calories: 120</p>
</div> -->
</div>
</div>

I want to display the result that I fetched from this weather API(https://openweathermap.org/current) but when i type the city name i get no response

I want to display the result that I fetched from this API (https://openweathermap.org/current) but when i type the city name i get no response. I could not figure out where the error is happening.
This api takes the name of the city and gets you weather details, here i am only interested in displaying the weather (weather[0].main) and the temperature (main.temp).
The result will be displayed in the tag with id "result".
Here's my code,
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="style.css">
<title>Weather</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="index.html">
<img src="image_prev_ui.png" width="85" alt="image not available"/>
myProject
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="index.html">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="quote.html">Motivationl Quotes</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="weather.html">Weather</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container-fluid mt-5">
<div class="jumbotron jumbotron-fluid mt-5">
<div class="text-center text-white mt-5">
<h1 class="display-4">Find Weather</h1>
<p class="lead"><em>Enter the name of any city for weather information</em></p>
<form id="forminput">
<input type="text" class="form-control text-center mt-5" id="city" placeholder="Example: Kolkata">
<button class="btn btn-outline-light btn-lg mt-5" type="submit">Submit</button>
</form>
<p id="result" class="text-white text-center fst-italic mt-5"></p>
</div>
</div>
</div>
<footer class="bg-dark text-center text-lg-start">
<div class="text-center text-white p-3" style="background-color: rgba(0, 0, 0, 0.2);">
© 2021 Copyright:
<a class="text-muted" href="index.html">myProject.com</a>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="script.js"></script>
</body>
</html>
And here's the js jquery
$(document).ready(funtion(){
$("#forminput").submit(function(event){
performSearch(event);
});
});
function performSearch(event){
var request;
event.preventDefault();
request = $.ajax({
url :'https://api.openweathermap.org/data/2.5/weather',
type : "GET",
data : {
q : $("#city").val(),
appid : '2c476e538ecec946a44e8cc19a3effde',
units : 'metric'
}
});
request.done(function(response){
formatSearch(response);
});
}
function formatSearch(jsonObject){
var city_name = jsonObject.name;
var city_weather = jsonObject.weather[0].main;
var city_temp = jsonObject.main.temp;
$("#result").text("Weather now in "+city_name+" is "+city_weather+" and the temperature is "+city_temp+" Celcius.");
}
Hi #Abhishek Can you try to send your request like this
let url = `https://api.openweathermap.org/data/2.5/weather?q=${$("#city").val()}&appid=2c476e538ecec946a44e8cc19a3effde&units=metric`;
let request = $.ajax({
url :url,
type : "GET"
});

Safari javascript null is not an object

Having some issues with my sliding nav in safari. Basically it just doesn't work. In the inspector panel it is returning the error:
"TypeError: null is not an object (evaluating 'document.getElementById("contracted-menu").style')
Here is the code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cuttsy+Cuttsy | How we work</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/bootstrap.css" rel="stylesheet" type="text/css">
<link href="css/fonts/fonts.css" rel="stylesheet" type="text/css">
<link href="css/main.css" rel="stylesheet" type="text/css">
<link href="css/media.css" rel="stylesheet" type="text/css">
<script src="js/menu.js"></script>
<script src="http://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
if (window.matchMedia("(min-width: 769px)").matches) {
function openNav() {
document.getElementById("expanded-menu").style.marginLeft = "0";
document.getElementById("contracted-menu").style.marginLeft = "-75px";
}
function closeNav() {
document.getElementById("expanded-menu").style.marginLeft = "-230px";
document.getElementById("contracted-menu").style.marginLeft = "0";
}
} else if (window.matchMedia("(max-width: 768px)").matches){
function openNav() {
document.getElementById("expanded-menu").style.marginTop = "0";
document.getElementById("contracted-menu").style.marginTop = "-75px";
}
function closeNav() {
document.getElementById("expanded-menu").style.marginTop = "-100vh";
document.getElementById("contracted-menu").style.marginTop = "0";
}
}
</script>
</head>
<body>
<!-- ======================
========== MENU ===========
======================= -->
<div class="expanded-menu" id="expanded-menu">
<!-- MENU -->
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">
<img src="images/Backarrow.png" alt="back arrow">
</a>
<a href="index.html">
<img src="images/Cuttsy+Cuttsy_Logo_Square_RGB.png" class="logo" alt="cuttsy and cuttsy logo">
</a>
who we are
<img src="images/Line.png" class="menu-line" alt="line">
how we work
<img src="images/Line.png" class="menu-line" alt="line">
what we do
<img src="images/Line.png" class="menu-line" alt="line">
who we do it for
<img src="images/Line.png" class="menu-line" alt="line">
cuttings
<img src="images/Line.png" class="menu-line" alt="line">
join us
<img src="images/Line.png" class="menu-line" alt="line">
contact
<div class="socialmedia">
<a href="https://www.facebook.com/cuttsyandcuttsy/" target="_blank">
<img src="images/social-media-icons/Facebook.png" alt="facebook logo">
</a>
<a href="https://www.instagram.com/cuttsyandcuttsy/?hl=en" target="_blank">
<img src="images/social-media-icons/Instagram.png" alt="instagram logo">
</a>
<a href="https://www.linkedin.com/company/2128917/" target="_blank">
<img src="images/social-media-icons/Linkedin.png" alt="linkedin logo">
</a>
<a href="https://twitter.com/cuttsyandcuttsy" target="_blank">
<img src="images/social-media-icons/Twitter.png" alt="twitter logo">
</a>
</div>
<div class="privacy">
<p>Privacy policy</p>
<p>© Cuttsy+Cuttsy 2018</p>
</div>
</div>
<!-- ======================
======= SMALL MENU ========
======================= -->
<div class="contracted-menu" id="contracted-menu">
<a href="javascript:void(0)" onclick="openNav()">
<img src="images/nav-icons/menu.png" class="burger" alt="open menu">
</a>
<div class="menu-icons">
<a href="who-we-are.html">
<img src="images/nav-icons/Who-we-are.png" alt="who we are">
</a>
<a href="how-we-work.html">
<img src="images/nav-icons/How-we-work.png" alt="how we work">
</a>
<a href="what-we-do.html">
<img src="images/nav-icons/What-we-do.png" alt="what we do">
</a>
<a href="who-we-do-it-for.html">
<img src="images/nav-icons/who-we-do-it-for.png" alt="who we do it for">
</a>
<a href="cuttings.html">
<img src="images/nav-icons/cuttings.png" alt="cuttings">
</a>
<a href="join-us.html">
<img src="images/nav-icons/join.png" alt="join us">
</a>
<a href="contact.html">
<img src="images/nav-icons/contact.png" alt="contact us">
</a>
<div class="socialmedia-sm">
<a href="https://www.facebook.com/cuttsyandcuttsy/" target="_blank">
<img src="images/social-media-icons/Facebook.png" class="sm-small" alt="facebook logo">
</a>
<a href="https://www.instagram.com/cuttsyandcuttsy/?hl=en" target="_blank">
<img src="images/social-media-icons/Instagram.png" class="sm-small" alt="instagram logo">
</a>
<a href="https://www.linkedin.com/company/2128917/" target="_blank">
<img src="images/social-media-icons/Linkedin.png" class="sm-small" alt="linkedin logo">
</a>
<a href="https://twitter.com/cuttsyandcuttsy" target="_blank">
<img src="images/social-media-icons/Twitter.png" class="sm-small" alt="twitter logo">
</a>
</div>
</div>
</div>
<!-- ======================
========= CONTENT =========
======================= -->
<div class="webcontent">
<div id="main">
<div>
<div class="row" class="col-sm-12">
<h1>How we work.</h1>
<p class="intro">At Cuttsy and Cuttsy, we never lose sight of what really matters – people. That’s why we pride ourselves on developing close and mutually respectful relationships with our clients. It’s why we constantly keep in mind what the patient or end-user really needs to know. And it’s why we work hard to maintain an award-winning culture of professional development to attract the very best people we can to join our team.</p>
</div>
<div class="secNav">
<ul>
<li class="subButton">Emotional Intelligence</li>
<li class="subButton">Co+Create</li>
<li class="subButton">Health Literacy</li>
</ul>
<ul class="secNav-level2">
<li class="subButton">Compliance</li>
<li class="subButton">CSR</li>
</ul>
</div>
<div class="row">
<hr class="dividingline">
<h2>Emotional Intelligence</h2>
<div class="col-sm-10">
<p id="intro-body">Emotional Intelligence (EI) is the capability of individuals to recognise their own and other people’s emotions and use emotional information to guide thinking and behaviour.</p>
<p class="body-copy">
One of our guiding principles is the power of EI. By guiding our thinking and behaviour, EI helps us to build meaningful and impactful connections in our communications.</p>
<h3>EI guides what we do</h3>
<img src="images/emotional-intelligence.png" class="bodyimg">
<hr class="dividingline">
<img src="images/reason-emotion.png" class="bodyimg">
<p class="body-copy" style="padding-top:30px;">
If you would like to find out more about how we use EI to guide our processes, let’s talk.</p>
</div>
</div>
</div>
</div>
</div>
</body>
<footer class="global-footer">
<div class="footer-nav col-sm-10">
<div class="col-sm-3">
<ul>
<li>Home</li>
<li>Who we are</li>
<li>Meet the Team</li>
<li>CPD</li>
<li>How we work</li>
<li>Co+Create</li>
</ul>
</div>
<div class="col-sm-3">
<ul>
<li>Health Literacy</li>
<li>Compliance</li>
<li>CSR</li>
<li>What we do</li>
<li>Books</li>
<li>Who we do it for</li>
</ul>
</div>
<div class="col-sm-3">
<ul>
<li>Cuttings</li>
<li>Join us</li>
<li>Contact</li>
<li>Privacy policy</li>
</ul>
</div>
</div>
</footer>
</html>
Anyone have any ideas? It's the code between the script tags that doesn't want to work.
assign your functions to variables like this:
<script>
if (window.matchMedia("(min-width: 769px)").matches) {
var openNav = function() {
document.getElementById("expanded-menu").style.marginLeft = "0";
document.getElementById("contracted-menu").style.marginLeft = "-75px";
}
var closeNav = function() {
document.getElementById("expanded-menu").style.marginLeft = "-230px";
document.getElementById("contracted-menu").style.marginLeft = "0";
}
} else if (window.matchMedia("(max-width: 768px)").matches){
var openNav = function() {
document.getElementById("expanded-menu").style.marginTop = "0";
document.getElementById("contracted-menu").style.marginTop = "-75px";
}
var closeNav = function() {
document.getElementById("expanded-menu").style.marginTop = "-100vh";
document.getElementById("contracted-menu").style.marginTop = "0";
}
}
</script>

Vue2 Transition Mode not working

The following is the code of my .vue. swapping between div worked just fine and the transition fade works well too. but mode out-in not working at all. both elements were shown at the same time while transitioning.
EDIT##
Sorry that I am not familiar with fiddle. Please find the full code of my .vue below for your best reference.
<template>
<div>
<div class="col-md-3">
<namecard :shop="shop" :owner="user"></namecard>
</div>
<div class="col-md-9">
<div>
<ul class="nav nav-tabs shop-manage-tabs">
<li class="nav-item">
<a class="nav-link" :class="isActive == 'items' ? 'active' :''" #click.prevent="activateTab('items')">Items</a>
</li>
<li class="nav-item">
<a class="nav-link" :class="isActive == 'operaters' ? 'active' : ''" #click.prevent="activateTab('operaters')">Operaters</a>
</li>
<li class="nav-item">
<a class="nav-link" :class="isActive == 'info' ? 'active' : ''" #click.prevent="activateTab('info')">Info</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" :class="isActive == 'statistics' ? 'active' : ''">Statistics</a>
<div class="dropdown-menu">
<a class="dropdown-item" #click.prevent="activateTab('statistics')">Action</a>
<a class="dropdown-item" #click.prevent="activateTab('statistics')">Another action</a>
<a class="dropdown-item" #click.prevent="activateTab('statistics')">Something else here</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" #click.prevent="activateTab('statistics')">Separated link</a>
</div>
</li>
</ul>
</div>
<transition-group name="fade" mode="out-in">
<div v-if="isActive == 'items'" key="items">
<div class="card" style="padding: 1rem">
<h1>Control Panel</h1>
<button type="button" class="btn btn-success" #click="addNewProduct = true">Add New Product</button>
<button type="button" class="btn btn-danger" #click="addNewProduct = true">Delete Product</button>
</div>
<add-new-product v-show="addNewProduct"></add-new-product>
<div class="card" style="padding: 1rem">
<item-card :productId="product.id" v-for="product in shop.products" :key="product"></item-card>
</div>
</div>
<div v-else-if="isActive == 'operaters'" key="operaters">
<div class="card" style="padding: 1rem">
<h1>Control Panel</h1>
<button type="button" class="btn btn-success" #click="addNewProductModal = true">Add Operator</button>
<button type="button" class="btn btn-danger" #click="addNewProductModal = true">Delete Operator</button>
</div>
<div class="card">operaters</div>
</div>
<div v-else-if="isActive == 'info'" class="card" key="info">
<div class="card">info</div>
</div>
<div v-else-if="isActive == 'statistics'" class="card" key="statistics">
<div class="card">statistics</div>
</div>
</transition-group>
</div>
</div>
</template>
<script>
import itemCard from './Item-card.vue'
import nameCard from '../Namecard.vue'
import addNewProduct from './Add-new-product.vue'
export default {
components:{
'item-card':itemCard,
'namecard':nameCard,
'add-new-product':addNewProduct,
},
data(){
return{
user:{},
shop:{},
isActive:'items',
addNewProduct:false,
}
},
props:[
],
created(){
this.getUserInfo()
},
mounted(){
},
methods:{
getUserInfo(){
var vm = this
vm.$http.get('/getAuthUser').then((response)=>{
vm.user = response.data
vm.$http.get('/getShop/'+vm.user.id).then((response)=>{
vm.shop = response.data.data.shop
})
})
},
activateTab(tab){
var vm = this
vm.isActive = tab
}
}
}
</script>
You need to give key attribute to each of the div to make the transition work smoothly. In your case I see an extra ', which might be an issue, try removing that.
Change
<div v-if="isActive == 'items'" key="'items'">
to
<div v-if="isActive == 'items'" key="items">
and similarly at other places as well.

Categories

Resources