Cannot read property 'target' of undefined Function remove not working - javascript

I have an array that has 3 contacts. I want the same person's name to be deleted when I click on the delete button, but unfortunately I do not know where the problem is that it does not work.
I have two functions in this program, one removeContact to perform the delete operation
And I have a function called showrecords to get the content of the array and display the name and number of contacts with a dedicated delete button for each contact
In this program, I used the pattern builder pattern
Please guide me to the conclusion to solve the problem of not being deleted
Please click on the show Person button to test the program. Contacts will be displayed and click on the delete button. You will see that the delete operation is not performed.
function ElementBuilder(name) {
this.element = document.createElement(name);
this.appendSelector = function(selector) {
this.appendElement = document.querySelector(selector).appendChild(this.element);
return this
};
this.setAttribute = function(attribute, valueAttribute) {
this.element.setAttribute(attribute, valueAttribute)
return this;
};
this.addEventListener = function(event, fun) {
this.element.addEventListener(event, fun);
return this;
};
this.text = function(text) {
this.element.textContent = text;
return this;
};
this.build = function() {
return this.element;
};
}
const builder = {
create: function(name) {
return new ElementBuilder(name);
}
};
function PhoneBook() {
this.records = [{ name: "niloufar", phone: 1111 }, { name: "sara", phone: 2222 }, { name: "sara", phone: 3333 }];
// function remove
this.removeContact = function() {
const self = this
function removePerson(item) {
if (item.target.classList.contains('delbutton')) {
const remID = item.target.getAttribute('data-id');
self.records.splice(remID, 1);
}
}
return removePerson;
}
}
function Render(container) {
this.container = container;
const phoneBook = new PhoneBook();
const remove = phoneBook
.removeContact();
this.removeEntry = (item) => {
remove(item); //
this.showrecords();
}
this.init = function() {
const btn = builder
.create("button")
.text("show person")
.addEventListener("click", this.showrecords)
.appendSelector("div")
.build();
};
// Function: Read contacts from the array and display them
this.showrecords = () => {
const addBookId = document.getElementById('phone-book-container');
let index = 0;
addBookId.innerHTML = '';
const arry = phoneBook.records;
arry.forEach(elm => {
const nameContent = builder
.create('p')
.text(`${elm.name}`)
.appendSelector("div")
.build();
const phoneContent = builder
.create('p')
.text(`${elm.phone}`)
.appendSelector("div")
.build();
const anchor = builder
.create('a')
.addEventListener('click', this.removeEntry)
.setAttribute('href', '#')
.setAttribute('class', 'delbutton')
.setAttribute("id", "deleteButton")
.text("delete")
.setAttribute('date-id', `${index}`)
.appendSelector("div")
.build();
});
}
}
const phoneBookContainer = document.getElementById("phone-book-container");
const app = new Render(phoneBookContainer);
app.init();
<div id="phone-book-container"></div>

You have to pass the item (which is actually the event object) to your function:
function ElementBuilder(name) {
this.element = document.createElement(name);
this.appendSelector = function(selector) {
this.appendElement = document.querySelector(selector).appendChild(this.element);
return this
};
this.setAttribute = function(attribute, valueAttribute) {
this.element.setAttribute(attribute, valueAttribute)
return this;
};
this.addEventListener = function(event, fun) {
this.element.addEventListener(event, fun);
return this;
};
this.text = function(text) {
this.element.textContent = text;
return this;
};
this.build = function() {
return this.element;
};
}
const builder = {
create: function(name) {
return new ElementBuilder(name);
}
};
function PhoneBook() {
this.records = [{ name: "niloufar", phone: 1111 }, { name: "sara", phone: 2222 }, { name: "sara", phone: 3333 }];
// function remove
this.removeContact = function() {
const self = this
function removePerson(item) {
if (item.target.classList.contains('delbutton')) {
const remID = item.target.getAttribute('date-id');
self.records.splice(remID, 1);
}
}
return removePerson;
}
}
function Render(container) {
this.container = container;
const phoneBook = new PhoneBook();
const remove = phoneBook
.removeContact();
this.removeEntry = (item) => {
remove(item);
this.showrecords();
}
this.init = function() {
const btn = builder
.create("button")
.text("show person")
.addEventListener("click", this.showrecords)
.appendSelector("div")
.build();
};
// Function: Read contacts from the array and display them
this.showrecords = () => {
const addBookId = document.getElementById('phone-book-container');
addBookId.innerHTML = '';
const arry = phoneBook.records;
arry.forEach((elm, index) => {
const nameContent = builder
.create('p')
.text(`${elm.name}`)
.appendSelector("div")
.build();
const phoneContent = builder
.create('p')
.text(`${elm.phone}`)
.appendSelector("div")
.build();
const anchor = builder
.create('a')
.addEventListener('click', this.removeEntry)
.setAttribute('href', '#')
.setAttribute('class', 'delbutton')
.setAttribute("id", "deleteButton")
.text("delete")
.setAttribute('date-id', `${index}`)
.appendSelector("div")
.build();
});
}
}
const phoneBookContainer = document.getElementById("phone-book-container");
const app = new Render(phoneBookContainer);
app.init();
<div id="phone-book-container"></div>

Related

Get uk address from javascript using woosmap

I have this problem is that when the second suggestion is selected the dropdown does not disappear, so i want it to disappear as soon as it clicked
I have a script for uk address which is working fine, so here is how it works so if someone enter a postal code after that the first suggestion shows up and then when selected the second suggestion shows up to complete the address. Am using woosmap for the api.
Please note for this particular project i cant use google api, its specifically for the uk addresses
here is the code.
<div id="app">
<div hidden id="map"></div>
<div class="autocomplete-input-container">
<div class="autocomplete-input">
<input id="input-value" type="text" autocomplete="off" placeholder="Type in a UK postal code..">
</div>
<div class="autocomplete-results-container">
<div class="autocomplete-results">
</div>
</div>
</div>
</div>
<script
src="https://sdk.woosmap.com/map/map.js?key=API-KEY&language=en"></script>
<script>
javascript am using
let myMap;
let markerAddress;
const woosmap_key = "API-KEY";
function buildQueryString(params) {
const queryStringParts = [];
for (let key in params) {
if (params.hasOwnProperty(key)) {
let value = params[key];
queryStringParts.push(
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`
);
}
}
return queryStringParts.join("&");
}
function debounce(func, wait, immediate) {
let timeout;
return function () {
const context = this;
const args = arguments;
const later = () => {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
function autocompleteLocalities(input) {
const args = {
key: woosmap_key,
input,
types: "postal_code",
components: "country:gb|country:je|country:im|country:gg"
};
return fetch(
`https://api.woosmap.com/localities/autocomplete/?${buildQueryString(args)}`
).then((response) => response.json());
}
function getDetails(public_id) {
let args = {
key: woosmap_key,
public_id,
addresses_per_page: 1000,
language: "en"
};
return fetch(
`https://api.woosmap.com/localities/details/?${buildQueryString(args)}`
).then((response) => response.json());
}
function displayDetails(res) {
markerAddress.setMap(null);
const result = res.result;
document.getElementById("input-value").value = result.formatted_address;
const results = document.querySelector(".autocomplete-results");
const position = {
lat: result.geometry.location.lat,
lng: result.geometry.location.lng
};
if (myMap.getZoom() < 16) {
myMap.setZoom(19);
myMap.panTo(position);
}
myMap.panTo(position);
markerAddress.setMap(myMap);
if (result.addresses) {
results.innerHTML = "";
let html = "";
for (let addressIndex in result.addresses.list) {
const address = result.addresses.list[addressIndex];
let predictionClass = "no-viewpoint";
let formatted_name = address["description"];
const publidId = address["public_id"];
html += `<div class="prediction ${predictionClass}" detail="true" public-id="${publidId}">
${formatted_name}
</div>`;
}
results.innerHTML = html;
results.style.display = "block";
const data = results.querySelectorAll(".prediction");
for (let result of data) {
result.addEventListener("click", () => {
const detail = result.getAttribute("detail");
const publicId = result.getAttribute("public-id");
if (detail === "true") {
getDetails(publicId).then((res) => displayDetails(res));
}
});
}
}
}
function displayResults(
value,
environment = "develop-api.woosmap.com",
postal_code
) {
let results = document.querySelector(".autocomplete-results");
// Get Woosmap results
autocompleteLocalities(value, myMap.getCenter()).then(
({ localities, addresses }) => {
results.innerHTML = "";
results.parentElement.style.display = "none";
markerAddress.setMap(null);
let html = "";
const responses = localities || addresses || [];
for (let prediction_id in responses || []) {
const prediction = responses[prediction_id];
const predictionClass = prediction["has_addresses"]
? `prediction-expandable`
: "";
const formatted_name = prediction["description"];
const addresses = prediction["has_addresses"]
? `<span class='light'>- see addresses</span>`
: "";
const publidId = prediction["public_id"];
html += `<div class="prediction ${predictionClass}" prediction-id=${prediction_id} detail="${prediction["has_addresses"]}" public-id="${publidId}">
${formatted_name} ${addresses}
</div>`;
}
results.innerHTML = html;
results.style.display = "block";
results.parentElement.style.display = "flex";
const data = results.querySelectorAll(".prediction");
for (let result of data) {
result.addEventListener("click", () => {
results.style.display = "none";
const detail = result.getAttribute("detail");
const predictionId = parseInt(
result.getAttribute("prediction-id"),
10
);
const publicId = result.getAttribute("public-id");
const prediction = localities[predictionId];
const position = {
lat: prediction.location.lat,
lng: prediction.location.lng
};
if (prediction.viewpoint) {
myMap.fitBounds(prediction.viewpoint.bounds);
myMap.panTo(position);
} else {
myMap.panTo(position);
myMap.setZoom(4);
}
if (detail === "true") {
getDetails(publicId).then((res) => displayDetails(res));
result.setAttribute("detail", "false");
}
markerAddress.setPosition(position);
markerAddress.setMap(myMap);
if (detail === "true") {
getDetails(publicId).then((res) => displayDetails(res));
}
});
}
}
);
}
function init() {
const mapElement = document.getElementById("map");
myMap = new woosmap.map.Map(mapElement, {
center: {
lat: 52.2928,
lng: -1.717
},
disableDefaultUI: true,
gestureHandling: "greedy",
zoom: 6,
styles: {
featureType: "poi",
stylers: [{ visibility: "off" }]
}
});
markerAddress = new woosmap.map.Marker({
icon: {
url: "https://images.woosmap.com/icons/pin-red.png",
scaledSize: {
height: 64,
width: 46
}
}
});
registerEvents();
}
function registerEvents() {
const results = document.querySelector(".autocomplete-results");
const input = document.querySelector(".autocomplete-input > input");
input.addEventListener(
"input",
debounce(function () {
let value = this.value;
value.replace('"', '\\"').replace(/^\s+|\s+$/g, "");
if (value !== "") {
displayResults(value);
} else {
results.innerHTML = "";
}
}, 150)
);
}
init();
here the example for the above and also with the problem https://codesandbox.io/s/localities-autocomplete-uk-postalcode-woosmap-map-v0y6so?from-embed
thank u

module.exports with function

I have several JavaScript files that I create enums. for example:
source.enum.js
const enumUtils = require('../enum.utils');
const EmailAddressesSourceType = enumUtils.createEnum([
['DIRECTORY', 'directory'],
['FILE', 'file'],
['ARRAY', 'array']
]);
module.exports = { EmailAddressesSourceType };
The enum.utils.js is just a file that do the simple function of creating an enum from array:
class EnumUtils {
constructor() { }
// This method takes a map of elements and converts them to freeze objects (an enum-like object).
createEnum(mapItems) {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
}
}
const enumUtils = new EnumUtils();
module.exports = enumUtils;
Now since I have 5-6 js files with enums, I want to avoid 'const enumUtils = require('../enum.utils');' in each of them, and do it all together in index.js file, something like this:
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
But, there are compilation error in:
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
My question is, there is a workaround so enable me to reduce the 'const enumUtils = require('../enum.utils');' in each file of the enums js file?
Thanks!
UPDATE 1
The error I'm getting is this:
The current status of the file (before I was trying to refactor) - It works OK:
index.js
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
module.exports = {
Color, ColorCode, EmailAddressStatus, EmailAddressType, EmailAddressesSourceType,
Method, Mode, Placeholder, SendEmailStepName, Status, StatusIcon
};
This guy, guy-incognito, solved for me the issue. Now it works like a charm. Thanks man!
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
Color: createEnum(Color),
ColorCode: createEnum(ColorCode),
EmailAddressStatus: createEnum(EmailAddressStatus),
EmailAddressType: createEnum(EmailAddressType),
EmailAddressesSourceType: createEnum(EmailAddressesSourceType),
Method: createEnum(Method),
Mode: createEnum(Mode),
Placeholder: createEnum(Placeholder),
SendEmailStepName: createEnum(SendEmailStepName),
Status: createEnum(Status),
StatusIcon: createEnum(StatusIcon)
};

How do i use nativescript load on demand funtion

EDIT
i was able to get it to work, but one problem now is, before it creates and additional empty item before showing other items.
NB the load on demand function works fine, but i don't know why an additional empty item is created. i guess there's an issue with my code
const viewModel = observableModule.fromObject({
_sourceDataItems: [],
dataItems: new ObservableArray(),
initDataItems: function () {
var url="https://adekunletestprojects.000webhostapp.com/skog/searchResults.php?search=" + encodeURIComponent("Adeyeye") + "&location=" + encodeURIComponent("Lagos");
fetch(url).then((response) => response.json()).then((res) => {
this._sourceDataItems = new ObservableArray(res.items);
this.dataItems.push(this._sourceDataItems);
}).catch((err) => {
var toast = Toast.makeText("Unable to load users");
toast.show();
});
},
addMoreItemsFromSource: function (chunkSize) {
console.log(this._sourceDataItems);
let newItems = this._sourceDataItems.splice(0, chunkSize);
this.dataItems.push(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load more item---");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(10);
listView.notifyLoadOnDemandFinished();
}, 1500);
args.returnValue = true;
} else {
args.returnValue = false;
listView.notifyLoadOnDemandFinished(true);
}
},
});
Search-view-model.js
_sourceDataItems: new ObservableArray(),
dataItems: new ObservableArray(),
initDataItems: function () {
var url = "https://adekunletestprojects.000webhostapp.com/skog/searchResults.php?search=" + encodeURIComponent("Adeyeye") + "&location=" + encodeURIComponent("Lagos");
fetch(url).then((response) => response.json()).then((res) => {
this._sourceDataItems = res.items;
this.addMoreItemsFromSource(6);
}).catch((err) => {
alert(err.message);
});
},
addMoreItemsFromSource: function (chunkSize) {
console.log(this._sourceDataItems);
let newItems = this._sourceDataItems.splice(0, chunkSize);
this.dataItems.push(newItems);
},
onLoadMoreItemsRequested: function (args) {
console.log("---load more item---");
const that = new WeakRef(this);
const listView = args.object;
if (this._sourceDataItems.length > 0) {
setTimeout(function () {
that.get().addMoreItemsFromSource(10);
listView.notifyLoadOnDemandFinished();
}, 1500);
args.returnValue = true;
} else {
args.returnValue = false;
listView.notifyLoadOnDemandFinished(true);
}
},
Search.js
exports.pageLoaded = function (args) {
const page = args.object;
var searchViewModel = new SearchViewModel();
page.bindingContext = searchViewModel;
searchViewModel.initDataItems();
searchViewModel.addMoreItemsFromSource(5);
}

encapsulating and instantiating objects

I'm trying to assign an object to the property of another object.
That is model of the real project. Here, I have a race, with an array of cars, which have an driver property. The driver property is an object. At the console output, I want to have a car with the name of the driver.
<script>
let carsNames = ["Ferrari", "Mercedes", "Maserati", "Renault"];
let drivers = ["Ayrton", "Alain", "Michael", "Nikki"];
let Car = (function (_team, _driver) {
let team = _team;
let driver = _driver;
return {
getTeam: function () {
return team;
},
getDriver: function () {
return driver;
}
}
});
let Driver = (function (_name) {
let name = _name;
return {
getName: function () {
}
}
});
let Race = (function () {
cars = [];
for (let i = 0; i < carsNames.length; i++) {
driver = new Driver(drivers[i]);
car = new Car(carsNames[i], driver);
cars.push(car);
}
return {
getCars: function () {
return cars;
}
}
});
let GPSyldavie = new Race();
let myrace = GPSyldavie.getCars();
myrace.forEach(function (mr) {
console.log(mr.getTeam(), mr.getDriver().getName());
})
// Console output :
// Ferrari undefined
// Mercedes undefined
// Maserati undefined
// Renault undefined
</script>
The point is to bind a driver with a car, but somewhere I fail to tell to the car that it is driven by a driver.
You're getName function does not return anything...
let Driver = (function (_name) {
let name = _name;
return {
getName: function () {
}
}
});
Should look more like...
let Driver = (function (_name) {
let name = _name;
return {
getName: function () {
return name;
}
}
});

Let ReactJS mixins require an external module

I know we should avoid using mixins , but let's use it for this case.
I defined a few logging in/out functions as a mixins module and I require it in a number of components.
var loginStore = require('../../stores/LoginStore'); // this is the problem ?
var AuthMixins = {
statics: {
willTransitionTo(transition) {
console.log(loginStore.id);
if (!loginStore.isLoggedIn()) {
transition.redirect('login');
}
}
},
_getLoginState() {
return {
userLoggedIn: loginStore.isLoggedIn()
};
},
componentDidMount() {
this.changeListener = this._onChange;
loginStore.addChangeListener(this.changeListener);
},
_onChange() {
this.setState(this._getLoginState());
},
getInitialState() {
return {
userLoggedIn: this._getLoginState()
};
},
componentWillUnmount: function() {
loginStore.removeChangeListener(this.changeListener);
}
};
module.exports = AuthMixins;
LoginStore.js :
var AppDispatcher = require('../dispatchers/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var LoginStore = (function() {
var _cred = null,
_user = null,
id = Date.now();
var eventEmitter = new EventEmitter();
var _listenToLogin = function(action) {
if (action.actionType === 'LOGIN_USER') {
_cred = action.cred;
_user = action.user;
eventEmitter.emit('CHANGE');
} else if (action.actionType === 'LOGOUT_USER') {
_cred = null;
_user = null;
eventEmitter.emit('CHANGE');
}
};
AppDispatcher.register(_listenToLogin.bind(this));
var user = function() {
return _user;
};
var cred = function() {
return _cred;
};
var addChangeListener = function(cb) {
eventEmitter.on('CHANGE', cb);
};
var removeChangeListener = function(cb) {
eventEmitter.removeListener('CHANGE', cb);
};
var isLoggedIn = function() {
return (!!_user);
};
return ({
id: id,
user: user,
cred: cred,
isLoggedIn: isLoggedIn,
addChangeListener: addChangeListener,
removeChangeListener: removeChangeListener
});
})();
module.exports = LoginStore;
As you can see I want LoginStore to be Singleton , so when I access it from different parts of the code , it has the same state.
The following is how I use mixins :
About.js :
'use strict';
var React = require('react');
var AuthMixins = require('./mixins/LoginMixins');
var About = React.createClass({
displayName: 'About',
mixins: [AuthMixins],
getDefaultProps: function() {
return {
message: 'Default Prop for About page'
};
},
render: function() {
return (<div>
{this.props.message}
</div>);
}
});
module.exports = About;
Now, the problem is that every time About is loaded , a new instance of LoginStore is loaded. (not respecting this fact that we want it to be singleton) in return it shows that the user is not logged in.

Categories