How to update nativescript radlistview with new items at intervals - javascript

i'm creating a nativescript core app with radlistview and i would like the listview to add new items automatically at intervals.
if you have any knowledge of how i can achieve this, please help, i would appreciate.
this is my view-model.js
_sourceDataItems: new ObservableArray(),
dataItems: new ObservableArray(),
initDataItems: function () {
var url="example.com";
fetch(url).then((response) => response.json()).then((res) => {
var count = res.items.length;
this._sourceDataItems = res.items;
this.addMoreItemsFromSource(5);
}).catch((err) => {
});
},
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(25);
listView.notifyLoadOnDemandFinished();
}, 1500);
args.returnValue = true;
} else {
args.returnValue = false;
listView.notifyLoadOnDemandFinished(true);
}
},
});
if you need anymore info, let me know

Related

Run Script as new content loaded , how can i listen to DOM change?

Hi im working on a Chrome extension that adds badges to users, now the problem is i have to refresh the page everytime so the badges can load because there are client-side changes . How can i watch events change so i run the function on first time page load ?
I read something about input event listener or MutationObserver but im not sure how can i implement that , Any help would be much appreciated .
CODE:
function Foreground() {
let users = null;
let queries = [];
let userIds = [];
document.addEventListener("DOMContentLoaded", function(event) {});
window.addEventListener('load', () => {
fetchUsersAndQueries();
chrome.runtime.onMessage.addListener(async(message, sender, res) => {
if (message.users) {
fetchUsersAndQueries();
if (users) {
return res(users);
} else {
return res([]);
}
}
if (message.refresh) {
try {
assignBadges();
} catch (error) {
console.log(error.message);
}
}
return true;
});
let done = false;
setInterval(() => {
if (done) {
return;
}
if (users) {
done = true;
try {
assignBadges();
} catch (error) {
console.log(error.message);
}
}
}, 500);
});
async function fetchUsersAndQueries() {
userIds = await getAPIUserIds();
let isStop = false;
setInterval(() => {
if (isStop) {
return;
}
const parasiteContainer = document.querySelector('#parasite-container');
if (parasiteContainer) {
if (parasiteContainer.shadowRoot) {
try {
const roster1 = parasiteContainer.shadowRoot.querySelector(`[name="roster1"]`);
const roster2 = parasiteContainer.shadowRoot.querySelector(`[name="roster2"]`);
if (!roster1) {
return
};
if ([...roster1.children].length === 1) {
if (roster1.firstElementChild.children.length === 1) {
if (roster1.firstElementChild.firstElementChild.length === 1) {
const fTeam = [...roster1.firstElementChild.firstElementChild.firstElementChild.children].map(item => getUsername(item));
const sTeam = [...roster2.firstElementChild.firstElementChild.firstElementChild.children].map(item => getUsername(item));
users = fTeam.concat(sTeam).flat();
queries.push([...roster1.firstElementChild.firstElementChild.firstElementChild.children]);
queries.push([...roster2.firstElementChild.firstElementChild.firstElementChild.children]);
isStop = true;
} else {
const fTeam = [...roster1.firstElementChild.firstElementChild.children].map(item => getUsername(item));
const sTeam = [...roster2.firstElementChild.firstElementChild.children].map(item => getUsername(item));
users = fTeam.concat(sTeam).flat();
queries.push([...roster1.firstElementChild.firstElementChild.children]);
queries.push([...roster2.firstElementChild.firstElementChild.children]);
isStop = true;
}
} else {
const fTeam = [...roster1.firstElementChild.children].map(item => getUsername(item));
const sTeam = [...roster2.firstElementChild.children].map(item => getUsername(item));
users = fTeam.concat(sTeam).flat();
queries.push([...roster1.firstElementChild.children]);
queries.push([...roster2.firstElementChild.children]);
isStop = true;
}
}
queries.forEach(query => {
query.map(item => {
if (item.children.length > 1) {
[...item.children].map(child => {
// const container = child.querySelector('.sc-hCQDas'); // Classname might change in the future.
const container = child.firstElementChild ? .firstElementChild ? .firstElementChild ? .firstElementChild ? .children[2];
if (container) {
container.insertAdjacentHTML(
'beforeend',
createBadge(badgesResponse.data.exists, child.dataset.userId)
);
}
});
} else {
// const container = item.querySelector('.sc-hCQDas'); // Classname might change in the future.
const container = item.firstElementChild ? .firstElementChild ? .firstElementChild ? .children[0];
if (container) {
container.insertAdjacentHTML(
'beforeend',
createBadge(badgesResponse.data.exists, item.dataset.userId)
);
}
}
});
});
}

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

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>

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);
}

How to deal with multiple files?

I have two .js-files:
main.js
require("./randomEvent.js").start("hey");
require("./randomEvent.js").start("hi");
require("./randomEvent.js").start("hello");
randomEvent.js
var repeat = true;
exports.start = (randomString) => {
while (repeat) {
console.log(randomString);
}
}
exports.stop = (randomString) => {
repeat = false;
}
I want to start randomEvent.js 3 times, each with different randomStrings.
And if I do
require("./randomEvent.js").stop("hi");
it should stop the start("hi") function / it should set repeat to false.
How?
Thanks in advance!
You can implement your randomEvents.js as a class. So every instance has its own repeat flag.
function RandomEvent(str) {
this.repeat = true;
this.randomString = str;
this.start = () => {
setInterval(() => {
if (this.repeat) {
console.log('-->', this.randomString);
}
}, 1000);
}
this.stop = () => {
this.repeat = false;
}
}
module.exports = RandomEvent;
and main.js
let RandomEvent = require('./randomEvent');
let sayHi = new RandomEvent('hi');
let sayHello = new RandomEvent('hello');
let sayHey = new RandomEvent('hey');
sayHi.start();
sayHello.start();
sayHey.start();
setTimeout(() => {
console.log('stop saying hi')
sayHi.stop();
}, 5000);
Or you can store for every string, its own flag:
randomEvents.js
var repeat = {};
exports.start = (randomString) => {
repeat[randomString] = true;
setInterval(() => {
if (repeat[randomString]) {
console.log('-->', randomString);
}
}, 1000);
}
exports.stop = (randomString) => {
repeat[randomString] = false;
}
and in main.js
require("./randomEvent.js").start("hey");
require("./randomEvent.js").start("hi");
require("./randomEvent.js").start("hello");
setTimeout(() => {
console.log('stop saying hi')
require("./randomEvent.js").stop("hi");
}, 5000);
randomEvent.js
var repeatFlags = {};
function repeatLog(str) {
if (repeatFlags[str]) {
console.log(str);
setTimeout(() => {
repeatLog(str);
});
}
}
exports.start = (randomString) => {
repeatFlags[randomString] = true;
repeatLog(randomString);
}
exports.stop = (randomString) => {
repeatFlags[randomString] = false;
}

How to wrap FileSystemFileEntry.file into a function that returns Observable?

I'm trying to read files recursively from the dropped folder.
onDrop(event) {
event.preventDefault();
this.folderData = [];
this.filesData = [];
const items = event.dataTransfer.items;
for (let i = 0; i < items.length; i++) {
const item = items[i].webkitGetAsEntry();
if (item) {
this.scanFiles(item, this.folderData);
}
}
// send out data
// this.dropped.emit({ folderData: this.folderData, filesData: this.filesData });
}
private scanFiles(item, container: Array<any>) {
const nodeData = {
name: item.name,
isDirectory: item.isDirectory,
item: item,
children: []
};
container.push(nodeData);
if (item.isDirectory) {
const directoryReader = item.createReader();
directoryReader.readEntries(entries => {
if (entries) {
entries.forEach(entry => this.scanFiles(entry, nodeData.children));
}
});
} else if (item.isFile) {
// How to return an Observable array here?
item.file(file => {
file.fullPath = item.fullPath;
this.filesData.push(file);
});
}
}
According to MDN, FileSystemFileEntry.file returns the result in its callback.
https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry/file
So before onDrop sends out the result, it has to wait, until all the FileSystemFileEntry.file callbacks complete.
I want to use Observable.forkJoin to achieve this. But before that, how to wrap FileSystemFileEntry.file into a function that returns Observable?
It turns out that a single forkJoin can't resolve the problem. I finally complete this by recursive forkJoin.
onDrop(event) {
event.preventDefault();
this.folderData = [];
this.filesData = [];
const items = event.dataTransfer.items;
const obs = [];
for (let i = 0; i < items.length; i++) {
const item = items[i].webkitGetAsEntry();
if (item) {
obs.push(new Observable<any>(observer => this.scanFiles(item, this.folderData, observer)));
}
}
forkJoin(obs).subscribe(e => {
this.dropped.emit({ folderData: this.folderData, filesData: this.filesData });
});
}
private scanFiles(item, container: Array<any>, observer: Subscriber<any>) {
const nodeData = {
name: item.name,
isDirectory: item.isDirectory,
item: item,
children: []
};
container.push(nodeData);
if (item.isDirectory) {
const directoryReader = item.createReader();
directoryReader.readEntries(entries => {
if (entries) {
if (entries.length === 0) {
observer.next();
observer.complete();
} else {
const subObs = entries.map(entry => new Observable<any>(innerObserver =>
this.scanFiles(entry, nodeData.children, innerObserver)));
forkJoin(subObs).subscribe(e => {
observer.next();
observer.complete();
});
}
} else {
observer.next();
observer.complete();
}
});
} else if (item.isFile) {
item.file(file => {
file.fullPath = item.fullPath;
this.filesData.push(file);
observer.next();
observer.complete();
});
}
}
For more detial check https://github.com/ft115637850/ngx-folder-uploader.

Categories