how to display information texts when dialog open - javascript

I have this help dialog and some reason my information texts are not showing as soon as the dialog is open. It only start to show when I click the subsection so just wonder how I can display it as soon as the user open the dialog box. Any suggestion or help will be really appreciated.
HTML
//Clicking this will take the user each subsection
<div *ngFor="let subSection of mappedSecSub | async; let last=last">
<div *ngIf="subSection.parentId == section.id;" (click)="clicked(subSection.id, section.id)">
<a mat-list-item>{{subSection.name}}
<mat-divider *ngIf="!last" class="solid"></mat-divider>
</a>
</div>
</div>
// This display the informations text
<div class="column right">
<div *ngFor="let section of targetSectionGroup">
<h1 *ngIf="section.parentId == null" class="hint">{{section?.name}}</h1>
</div>
<div *ngFor="let section of targetSectionGroup">
<div *ngIf="section.parentId != null">
<h2 id="s{{section.id}}ss{{section.parentId}}" class="hint">{{section?.name}}</h2>
<p class="multi_lines_text" [innerHTML]="section?.text"></p>
</div>
</div>
</div>
TS
mappedSections: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);
mappedSecSub = this.mappedSections.asObservable()
targetSection: { id, name, parentId, text };
targetSectionGroup: { id, name, parentId, text }[] = [];
ngOnInit(): void {
this.fetchData();
}
fetchData = () => {
this.HelpService.getHelp().subscribe(res => {
this.mappedSections.next(res['res'])
let newMappedSection = this.mappedSections.getValue()
for (let i = 0; i < newMappedSection.length; i++) {
const element = newMappedSection[i];
if (element.parentId) {
this.targetSection = element;
break
}
}
})
}
clicked(id, parentId) {
this.targetSectionGroup = [];
let data = this.mappedSections.getValue()
for (let i = 0; i < data.length; i++) {
if (data[i].parentId == parentId || data[i].id == parentId) {
this.targetSectionGroup.push(data[i]);
}
if (data[i].id === id) {
this.targetSection = data[i]
}
}
document.querySelector(`#s${id}ss${parentId}`).scrollIntoView({ behavior: 'smooth' })
}
Right now the information text only show up when I click the subsections. I want to show it as soon as the help dialog is open.

I guess this should work
fetchData = () => {
this.HelpService.getHelp().subscribe(res => {
this.mappedSections.next(res['res']);
const response = res['res'];
this.clicked(response.id, response.parentId);
let newMappedSection = this.mappedSections.getValue()
for (let i = 0; i < newMappedSection.length; i++) {
const element = newMappedSection[i];
if (element.parentId) {
this.targetSection = element;
break
}
}
})
}

Related

Check if true or false on json parse into html

Currently have all data displaying perfectly except the boolean ones.
I have some data that if true or false they should display different html/css
So, how can I have a class or html that shows the data if returns true?
I'm a bit stuck on parsing this data on this code. As I was on the right direction until this new request.
The Json loooks like this:
{
"name": "Serena Gosling",
"supporterNumber": "0123456789",
"isStrongRelationship": true,
"ticketingPoints" :"2,500 Ticket Points",
"thumbnailUrl": "https://i.pravatar.cc/100"
},
fetch("supporters.json")
.then(response => response.json())
.then(supporters => {
localStorage.setItem("supporters", JSON.stringify(supporters));
});
let container = document.querySelector(".content");
let loadMoreButton = document.querySelector(".content button");
let initialItems = 4;
let loadItems = 2;
function loadInitialItems() {
let supporters = JSON.parse(localStorage.getItem("supporters"));
let out = "";
let counter = 0;
for (let supporter of supporters) {
if (counter < initialItems) {
out += `
<div class="supporter">
<h4 class="supporter__name">
<span class="supporter__thumbnail"></span>
${supporter.name}
${supporter.relationship}
<span class="supporter__number">(${supporter.supporterNumber})</span>
</h4>
<span class="supporter__points">${supporter.ticketingPoints}</span>
</div>
`;
}
counter++;
}
let div = document.createElement("div");
container.insertBefore(div, loadMoreButton);
div.innerHTML = out;
}
function loadData() {
let supporters = JSON.parse(localStorage.getItem("supporters"));
let currentDisplayedItems = document.querySelectorAll(".supporter").length;
let out = "";
let counter = 0;
for (let supporter of supporters) {
if (counter >= currentDisplayedItems && counter < loadItems + currentDisplayedItems) {
out += `
<div class="supporter">
<h4 class="supporter__name">
<span class="supporter__thumbnail"></span>
${supporter.name}
${supporter.relationship}
<span class="supporter__number">(${supporter.supporterNumber})</span>
</h4>
<span class="supporter__points">${supporter.ticketingPoints}</span>
</div>
`;
}
counter++;
}
let div = document.createElement("div");
container.insertBefore(div, loadMoreButton);
div.innerHTML = out;
div.style.opacity = 0;
if (document.querySelectorAll(".supporter").length == supporters.length) {
loadMoreButton.style.display = "none";
}
fadeIn(div);
}
function fadeIn(div) {
let opacity = 0;
let interval = setInterval(function() {
if (opacity <= 1) {
opacity = opacity + 0.1;
div.style.opacity = opacity;
} else {
clearInterval(interval);
}
}, 30);
}
loadInitialItems()
<div class="content">
<!-- content displaye from the javascript file -->
<button onclick="loadData()" class="load-more-button"><span>❭</span> </button>
</div>
You can use a ternary expression in the template literal.
out += `
<div class="supporter">
<h4 class="supporter__name">
<span class="supporter__thumbnail"></span>
${supporter.name}
${supporter.relationship}
<span class="supporter__number">(${supporter.supporterNumber})</span>
</h4>
<span class="supporter__points">${supporter.ticketingPoints}</span>
<span class="supporter__relationship">${supporter.isStrongRelationship ? "Strong" : "Weak"} relationship</span>
</div>
`;

Javascript get text from child within child

I'm busy developing a wordpress plugin to look for numbers and hide them by formating the number and replacing it with 0000..., Example:
<a href="tel:0000000000">
<span>
<span>0000 000 000</span>
</span>
</a>
I have javascript that queries the <a href=""> tag. I then get the children of the a tag. However, my issue is that because I don't know what or how many children ill be working with i can't assume it will be 1 or 2 thus I have to predict and look for it.
Javascript code:
// REMOVE SPACES IN STRING
let replaceStr = function (self) {
let value = self.replace(/[- )(]/g, '')
return value
};
// REMOVE LETTERS FROM STRING
let rmLetters = function (self) {
// let value = self.replace( /^\D+/g, '')
let value = self.replace(/\D+%?/g, "");
return value
}
let a = document.querySelectorAll("a[href^='tel:'], a[href^='Tel:'], a[href^='callto:']");
for (var i = 0; i < a.length; i++) {
let hrefSlice = a[i].href.slice(4);
let countChildren = a[i].childElementCount
if (a[i].hasChildNodes()) {
let a_childNodes = a[i].children;
if (a_childNodes.length > 1) {
for (let l = 0; l < a_childNodes.length; l++) {
if (replaceStr(a_childNodes[l].textContent) === hrefSlice) {
a_childNodes[l].textContent = replaceStr(a_childNodes[l].textContent).slice(0, 4) +
"...Click Here";
} else if (replaceStr(rmLetters(a_childNodes[l].textContent)) === hrefSlice) {
a_childNodes[l].textContent = replaceStr(rmLetters(a_childNodes[l].textContent)).slice(
0, 4) + "...Click Here";
}
}
}
}
}
}
Not sure if I got you right but I'd do it like this:
document.querySelector('#hideButton').addEventListener('click', () => {
const phoneAnchors = document.querySelectorAll('a[href^="tel:"], a[href^="Tel:"], a[href^="callto:"]');
phoneAnchors.forEach((phoneAnchor) => {
const phoneNumber = phoneAnchor.href.split(':')[1] || '';
phoneAnchor.href = phoneAnchor.href.replace(/[0-9]/g, '0');
phoneAnchor.querySelectorAll('*').forEach(childNode => {
if (childNode.textContent.replace(/[ ]/g, '') === phoneNumber) {
childNode.textContent = childNode.textContent.replace(/[0-9]/g, '0');
}
});
});
});
a {
display: block;
}
<a href="tel:1234567890">
<span>
<span>1234 567 890</span>
</span>
</a>
<a href="tel:0987654321">
<span>
<span>0987 654 321</span>
</span>
</a>
<a href="tel:1122334455">
<span>
<span>1122334455</span>
</span>
</a>
<hr>
<button id="hideButton">Hide Phone Numbers</button>

Sort array of objects by key values and displaying them on a HTML element

I'm making a movie sorter list, you enter the title and then the rating and it will show you the movies in order by rating. I have an array of objects and I managed to sort the array by rating, but I can't find a way to actually display the array in order on the HTML DOM.
I've tried for loops and forEach's but they don't work the way I want.
const movieTitle = document.querySelector(".movie-title");
const movieRating = document.querySelector(".movie-rating");
const movieList = document.querySelector(".movie-list");
const sortBtn = document.querySelector(".btn");
let movieStorage = [];
function sendMovie() {
if(event.keyCode == 13) {
if(movieTitle.value != "" && movieRating.value != "") {
title = movieTitle.value;
rating = parseInt(movieRating.value);
movieStorage.push({
title: title,
rating: rating
});
// If rating of a is bigger than rating of b return 1, if not return -1
movieStorage.sort((a, b) => (a.rating > b.rating) ? -1 : 1);
console.log(movieStorage);
addMovieToList(title, rating);
movieTitle.value = "";
movieRating.value = "";
} else {
console.log("Fields missing");
}
}
}
function addMovieToList(title, rating) {
const div = document.createElement("div");
div.className = "list-items";
div.innerHTML = `
<div class="item-title">
<p>${title}</p>
</div>
<div class="item-rating">
<p>${rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
movieList.appendChild(div);
}
function sortByRating(element) {
for(let i = 0; i < movieStorage.length; i++) {
element.innerHTML = `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
}
document.addEventListener("click", (e) => {
const deleteIcon = e.target;
const item = document.querySelector(".list-items");
if(deleteIcon.classList.contains("delete")) {
deleteIcon.parentElement.parentElement.remove(item);
}
})
tldr demo
After sorting the array, you need a way to reference movie divs to sort them. There are many ways to do it, what I chose is using id. When you create movie <div>, give it an ID unique for each movie name:
// Simple function to generate hash number for each string
function hashStr(stringValue) {
var hash = 0, i, chr;
if (stringValue.length === 0) return hash;
for (i = 0; i < stringValue.length; i++) {
chr = stringValue.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
const MOVIES = [
{name: "a", rating: 3},
{name: "b", rating: 6},
{name: "c", rating: 3},
{name: "d", rating: 2},
{name: "e", rating: 1},
];
function showMovies() {
const moviesDiv = document.querySelector("#movies");
for(const movie of MOVIES)
{
const id = "movie-"+hashStr(movie.name);
// If there's no element with the ID, we need to create the DIV for the movie
if(!document.querySelector("#"+id)) {
const elm = document.createElement("div");
elm.appendChild(new Text(movie.name + " ("+movie.rating+"/10)"));
elm.id = id;
elm.classList.add("movie");
moviesDiv.appendChild(elm);
}
}
}
Then, when sorting, you can reference each movie by ID:
// Sort movies using given property (eg. "name")
// The second param determines sort direction
function sortBy(property, ascending=true) {
MOVIES.sort((a,b) =>{
return cmp(a[property], b[property], ascending);
});
// Now after sorting the array, we can sort the HTML elements
const moviesDiv = document.querySelector("#movies");
let lastMovie = null;
for(const movie of MOVIES)
{
const id = "#movie-"+hashStr(movie.name);
const movieDiv = document.querySelector(id);
console.log(id, movieDiv);
// If created
if(movieDiv) {
// remove and append after last processed movie (for the first movie, this will append to top)
moviesDiv.insertBefore(movieDiv, lastMovie);
}
}
}
// Compare string and number, makes no sense for other types
function cmp(a,b, ascending=true) {
if(typeof a=='number' && typeof b == "number") {
return ascending ? a-b : b-a;
}
else if(typeof a=='string' && typeof b == "string"){
return (ascending ? 1 : -1) * a.localeCompare(b);
}
else {
return 0;
}
}
When you add a movie, you just call sort again. You will need to remember the last sorting parameters for that.
Your sort will work fine. The problem is that after you've sorted you can't just display that movie, you have to redisplay the entire list. You're almost there with your sortByRating method, but it doesn't recreate the entire list correctly. Try something like:
function showMoviesList(element) {
let innerHTML = "";
for (let i = 0; i < movieStorage.length; i++) {
innerHTML += `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
element.innerHTML = innerHTML;
}
This resets the inner HTML of the element to the complete movie list in order every time it's called.
Now call showMoviesList(movieList) instead of calling addMovieToList in sendMovie.

Unable to add the item in array on scan in Angular 2

I am developing an application using Angular 2.. In my application I am using barcode scanner to scan in the text field and storing those items in the array.
When I scan the item get added to array, but when I scan another item the old item it replace the old value in array.
Below is the piece of code which I am using. Please help me if you see any fix for the weird issue.
import { Component,ViewChild,Input, Output,OnInit,ChangeDetectorRef } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HeaderComponent } from '../common/header.component';
//import { SaleCart } from '../model/SaleCart';
//import * as $ from "jquery";
declare var jQuery: any
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./posapp.component.css']
})
export class TestComponent implements OnInit{
title = 'Treewalker POS';
public cartItems = [];
public query;
public filteredList = [];
public products = [{"id":"3","name":"Pears Soap Original 75gm","sku":"89675432189","price":"32.00","special_price":"32.00","qty":null,"barcode":"89675432189","tax":"5","discount":"0"},{"id":"1","name":"Rin","sku":"1111111111111","price":"11.00","special_price":"11.00","qty":"10.000","barcode":"1111111111111","tax":"5","discount":"0"},{"id":"2","name":"Test 1","sku":"23456","price":"10.00","special_price":"10.00","qty":"10.000","barcode":"23456","tax":"5","discount":"0"}];
constructor() {
}
ngOnInit() {
}
add(item) {
/* check the items in the json data */
let flag = false;
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}
let localCart = [];
if(sessionStorage.getItem("cart")){
localCart = JSON.parse(sessionStorage.getItem("cart"));
//console.log(JSON.stringify(localCart));
}
//console.log("food "+JSON.stringify(this.cart));
if(flag && localCart.length) {
let exist = 0;
for(let i=0; i < localCart.length; i++) {
if(localCart[i].item.barcode == item) {
localCart[i].ctr = parseInt(localCart[i].ctr) + 1;
//console.log("#### "+this.cart[i].ctr+" --- "+item);
exist = 1;
}
}
if(!exist){
localCart.push(foodItem);
}
sessionStorage.setItem("cart",JSON.stringify(localCart));
//this.barcode = "";
}else if(flag){
localCart.push(foodItem);
sessionStorage.setItem("cart",JSON.stringify(localCart));
}
//this.cart = JSON.parse(sessionStorage.getItem("cart"));
//this.itemsCnt = localCart.length;
//console.log("--- "+this.itemsCnt);
console.log(JSON.parse(sessionStorage.getItem('cart')));
//this.onScanProduct.emit(localCart);
}
filter(e) {
//e.preventDefault();
if (this.query !== ""){
this.filteredList = this.products.filter(function(el){
if(el.barcode.toLowerCase() == this.query.toLowerCase()) {
return el.barcode.toLowerCase() == this.query.toLowerCase();
}else{
return el.barcode.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
}
}.bind(this));
/* scanned item will be added to the cart */
console.log(this.filteredList.length);
if(this.filteredList.length > 0 && e.which == 13){
//console.log(JSON.stringify(this.filteredList));
for (let product of this.filteredList) {
//console.log(filter.barcode+"=="+this.query);
if(product.barcode == this.query) {
this.add(product.barcode);
jQuery('#barcode').val("");jQuery('#barcode').focus();
this.filteredList = [];
}
}
}
}else{
this.filteredList = [];
}
}
}
Below is the html template
<div class="content-wrapper">
<section class="content">
<form>
<div class="row">
<!-- sales item add window -->
<!-- end -->
<div class="col-sm-4">
<div class="box box-primary">
<div class="box-body">
<div class="form-group">
<div class="row">
<div class="col-md-9">
<!--<input type="text" class="form-control" id="barcode" name="barcode" [(ngModel)]="barcode" (ngModelChange)="add($event)"
placeholder="Enter item code or scan the barcode" autocomplete="off" />-->
<input id="barcode" type="text" class="form-control validate filter-input" name="query" [(ngModel)]="query" (keyup)="filter($event)" placeholder="Enter item code or scan the barcode" autocomplete="off" [ngModelOptions]="{standalone: true}">
</div>
<div class="suggestions" *ngIf="filteredList.length > 0">
<ul>
<li *ngFor="let item of filteredList" >
<a (click)="select(item)" href="javascript:;">{{item.barcode}} {{item.name}}</a>
</li>
</ul>
</div>
<div class="col-md-3">
<button type="button" class="btn btn-primary" (click)="createnewproduct(newproduct)">New Product</button>
</div>
</div>
</div>
</div> <!-- end of box body -->
</div>
</div>
</div><!-- end of row -->
</form>
</section>
</div>
Below is the input field which is being used to scan the barcode
<input id="barcode" type="text" class="form-control validate filter-input" [(ngModel)]="query" (keyup)="filter()" placeholder="Enter item code or scan the barcode" autocomplete="off">
I am assuming you are using only the function add. I tried to implement in a javascript like in the following code but I am pretty sure you are referencing that object somewhere else and you are changing it. That's my conclusion but I might be wrong.
var factoryP = (function(){
function P() {
this.cart = [];
this.products = [{'barcode': 1, 'name': 'a'}, {'barcode': 1, 'name': 'b'}]
}
function add(item) {
/* check the items in the json data */
//console.log("cart length "+JSON.stringify(this.cart));
let flag = false;
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
//console.log("check "+item);
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}
if(flag && this.cart.length) {
let exist = 0;
for(let i=0; i < this.cart.length; i++) {
if(this.cart[i].item.barcode == item) {
//console.log("Same product");
this.cart[i].ctr = parseInt(this.cart[i].ctr) + 1;
exist = 1;
}
}
if(!exist){
console.log(foodItem);
this.cart.push(foodItem);
}
}else if(flag){
console.log("step 4 "+item);
this.cart.push(foodItem);
}
}
P.prototype.add = add;
return new P();
});
instanceP = factoryP();
instanceP.add(1);
instanceP.add(1);
instanceP.add(1);
instanceP.add(2);
console.log(instanceP.cart[0].ctr)
//output 3
instanceP.cart[1].ctr
//output 1
Check your code here. Every time you are initializing the foodItem array with empty array. So whenever code will call add method, it will first empty your foodItem array.
Please check my comment in your code below:
add(item) {
let flag = false;
//Akshay: You need to make your changes here. Initialize your foodItem array out of this scope
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
//console.log("check "+item);
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}

Difficulty with error "Uncaught TypeError: Cannot read property 'name' of undefined"

I've been working on a JavaScript code in order to make a checkout cart of a pizza, but have been having an issue with the showCart function.
let pizzas=[
{ name:"Pepperoni", img:"pizza.png", price:8.99},
{ name:"Alfredo", img:"pizza.png", price:9.99},
{ name:"Cheese", img:"cheese.png", price:7.99}
];
function registerButtonEvents()
{
let buttons=document.getElementsByTagName("button");
for(let i = 0; i < buttons.length-1; i++)
{
buttons[i].addEventListener("click", function() {
addToCart(i);
});
}
let number = localStorage.getItem("number");
if(number == null)
number = 0;
document.getElementById("num").innerHTML = number;
}
function addToCart(pId)
{
let cartJ = localStorage.getItem("cart");
let cart;
if(cartJ===null) //Cart is empty
{
cart=[];
}
else
{
cart=cartJ.split(",");
}
cart.push(pId);
let number= localStorage.getItem("number");
if(number===null)
number = 0;
document.getElementById("num").innerHTML = `${++number}`;
localStorage.setItem("cart", cart.toString());
localStorage.setItem("number", number);
}
function clearCart()
{
localStorage.removeItem("cart");
localStorage.removeItem("num");
}
function showCart()
{
let cartJ = localStorage.getItem("cart");
let cart = [];
let info = "";
if(cartJ === null)
{
document.getElementById("myCart").innerHTML=`<h2>No items in cart!</h2>`;
}
else
{
cart = cartJ.split(",");
for (let i in cart)
{
let item = pizzas[cart[i]];
info+=
`<div class="row">
<div class="col-md-2 text-center">
<h3>${item.name}</h3>
</div>
<div class="col-md-2 text-center">
<img class="pizza" src="./images/${item.img}" alt="pepperoni">
</div>
<div class="col-md-2 text-center">
<h3>${item.price}</h3>
</div>
<div class="col-md-2 text-center">
<button type="button" class="btn btn-primary" onclick="removePizza(${i})">Remove</button>
</div>
</div>
`;
}
document.getElementById("myCart").innerHTML=info;
}
}
function removePizza(piz)
{
var cart = localStorage.getItem("cart");
cart = cart.split(",");
cart.splice(piz, 1);
if (cart.length == 0)
clearCart();
else
{
localStorage.setItem("cart", cart);
localStorage.setItem("number",cart.length);
}
showCart();
}
Developer tools tell me that the error is in the line in:
let item = pizzas[cart[i]];
but I don't necessarily understand why. If anyone could send some feedback it would be greatly appreciated.
The problem is when you access <h3>${item.name}</h3>. Your item is undefined there because your cart (cart = cartJ.split(",");) probably stores some strings like "Pepperoni" (as you split them using a comma) and after that you want to access the pizzas array using one of those strings instead of an index.

Categories