Looping Through Multiple JSON Requests (YouTube Data API) - javascript

Part of a website I am working on is a video page. I am pulling the videos from a YouTube account by accessing the YouTube Data API. Grabbing the videos in no particular order and not sorted works fine, but when I try to sort them into categories, I start running into trouble. Let's say there are three categories, Fruit, Vegetable, Pets. Instead of grabbing all the videos at once, I want to grab all the videos tagged with Fruit, append them to a <ul id="Fruit">. Then request all videos tagged with Vegetable, etc.
When starting out, I had the browser alert when it had finished getting the request and then appending the appropriate list. After I took out the alert, it still worked, but not the way I expected. Either the loop is advancing too quickly, or not advancing at all, but I can't seem to spot the mistake. What ends up happening is that all the videos get put into one list, <ul id="Vegetable">.
Please note: I am using a plugin called jGFeed which wraps the jQuery getJSON function, so I believe you can treat it as such.
var videoCategories = ['Fruit', 'Vegetable', 'Pets'];
for (var i = 0; i < videoCategories.length; i++) {
var thisCategory = videoCategories[i];
$.jGFeed('http://gdata.youtube.com/feeds/api/users/username/uploads?category='+thisCategory,
//Do something with the returned data
function(feeds) {
// Check for errors
if(!feeds) {
return false;
} else {
for(var j=0; j < feeds.entries.length(); j++) {
var entry = feeds.entries[i];
var videoUrl = entry.link;
$('ul#'+thisCategory).append('<li>'+entry.title+'</li>');
}
});
}

The problem is, you're using the 'thisCategory'-variable to set the category-name. The problem is, the value if this variable changes, while you're waiting for a response from the server.
You could try to put the whole script inside a function:
var videoCategories = ['Fruit', 'Vegetable', 'Pets'];
for (var i = 0; i < videoCategories.length; i++) {
getCategory(videoCategories[i]);
}
function getCategory(thisCategory)
{
$.jGFeed('http://gdata.youtube.com/feeds/api/users/username/uploads?category='+thisCategory,
//Do something with the returned data
function(feeds) {
// Check for errors
if(!feeds) {
return false;
} else {
for(var j=0; j < feeds.entries.length(); j++) {
var entry = feeds.entries[i];
var videoUrl = entry.link;
$('ul#'+thisCategory).append('<li>'+entry.title+'</li>');
}
});
}
I haven't tested this, so I'm not sure if it works..

Related

How to do I remove users from my list when someone leaves the page?

On my website, I have an active user tab but when you leave the page it doesn't remove you from the list. I have tried window.onbeforeunload(); and $(window).on('beforeunload', removeActiveUser()); to remove the client from the list. I tried making the code call an alert, and the alert showed up right after the page loaded, not when you were closing the page. Is there a way to do it without server side code? If I do need server side what would it be?
function removeActiveUser() {
var i = 0;
delay(1000);
var keys = currentActiveUsers;
var table = currentActiveUsers2;
for (i; i < keys.length; i++) {
var l = keys.length;
var k = keys[i];
console.log(k);
var name = table[k].Name;
var link = new Firebase("https://firebaseio.com/ActiveUsers/" + table[k]);
//var link2 = new Firebase("https://firebaseio.com/error/);
if (name == Name && table[k].Id == cId) {
link.remove();
}
}
}
$(window).on('beforeunload', removeActiveUser());
So your main problem is triggering an action when the user leaves the page (correct me if I misunderstood you there)
If that's the case then one of the solutions I'd use is to send out an http request every n seconds.
Since you're using firebase you can have your client JS update an entry against that user (let's call it alive_timestamp) and every n seconds update it, so your table would look like:
[
{
user: 'nick',
alive: '1521677841583'
},
{
user: 'alex',
alive: '1521677621325'
}
]
On your JS you'd have a function that reads this particular field and has a rule: if Date.now() - user.alive < y then removeActiveUser(user)

Delete Selected Checkboxes from database using Javascript in Laravel 5.4?

I'm here again to ask for a help. I have a pagination page result in my page view. When I selected 2 or more rows in the list of results using checkbox I want to remove them from the list as well as from my database using a button placed outside the pagination. I found a JS script that could remove them from the list but it cannot remove it the database. I can visualize what I want to happen but I am not so familiar with JS scripting, I do enter code herenot know how to include a script inside that could remove the array of selected (ids) of data rows and remove it from the DB. Please can someone evaluate my code and teach me where and how to do this. I am really stacked here. Cannot proceed unless I get the solution to my BIG problem.
Here's the JS script... It's working perfectly
<script>
function delBoxes(){
var e = document.getElementsByName("chkrow");
var message = 'Are you sure you want to delete?';
var row_list = {length: 0};
for (var i = 0; i < e.length; i++) {
var c_box = e[i];
if (c_box.checked == true) {
row_list.length++;
row_list[i] = {};
row_list[i].row = c_box.parentNode.parentNode;
row_list[i].tb = row_list[i].row.parentNode;
}
}
if (row_list.length > 0 && window.confirm(message)) {
for (i in row_list) {
if (i == 'length') {
continue;
}
var r = row_list[i];
r.tb.removeChild(r.row);
}
} else if (row_list.length == 0) {
alert('Please select row to delete.');
}
}
</script>
Here's the Href (button like)
<span>
Delete Selected</span>
Here's my Route: Route:: get('/postDelete_inv_selected','InvController#postDelete_inv_selected');
And my Controller (Unfixed until I can get the array of selected rows)
public function postDelete_inv_selected(Request $request)
{
///delete code here/ redirect back to pagination result
}
UPDATED THE CODE BELOW:
I'm not sure if I understand your code correctly since you did not include the HTML of your code, but the way it looks, that should be deleting the rows already on your HTML as you have mentioned.
For the DB part, I suggest you collect the id of the items you'll delete somewhere in loop part on your code, making it look like this:
// array declaration
var id_to_delete = [];
for (var i = 0; i < e.length; i++) {
var c_box = e[i];
if (c_box.checked == true) {
row_list.length++;
row_list[i] = {};
row_list[i].row = c_box.parentNode.parentNode;
row_list[i].tb = row_list[i].row.parentNode;
// collect the id of the rows to delete
id_to_delete.push(c_box.value);
}
}
// send a request to server
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/postDelete_inv_selected", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send( "id_to_delete=" + JSON.stringify(id_to_delete) );
probably with an html id or data- attribute (ie. <td data-id='1'>).
Then pass it as a stringified json or an array on the route via AJAX request, then process the deletion on your controller.
Also, it would be best to replace the route with post rather than get.
NOTE: I haven't tested these lines, but I'm pretty sure you get the idea on where to start.

How to pass variable reference to Observable subscription

I'm trying to get tweets from Twitter, and then get the hashtags from those tweets and get images from Flickr.
I want the tweets and images to be united together. However, see the console logs at the end. I expect the first one will output the current tweet and the second will output the images retrieved for this tweet.
However, what happens is that console.log(tweets[i]) always prints out the last tweet in the list, while console.log(results) prints the current results (i.e. every flickr result is printed).
By the way, the tweets and flicks are being retrieved from a json file for now.
tweets$.subscribe((tweets) => {
for (var i in tweets) {
var hashtags = tweets[i].entities.hashtags;
for (var j in hashtags) {
var flicks$ = this.flickrService.getImagesMock(hashtag[j]);
flicks$.subscribe((results) => {
console.log(tweets[i]);
console.log(results);
});
}
}
});
So my question is, how do I get the tweets[i] in the $flicks.subscribe to refer to the i that was in use when the subscription was created?
I guess it's a clasical problem with scope in async js.
for (var i in tweets) {
(function(index) {
var hashtags = tweets[index].entities.hashtags;
for (var j in hashtags) {
var flicks$ = this.flickrService.getImagesMock(hashtag[j]);
flicks$.subscribe((results) => {
console.log(tweets[index]);
console.log(results);
});
}
})(i);
}
Basically, in your example nested subscribe is executed after first loop is already finished.

Spotify API Temporary Playlist not working correctly

I am trying to create a temporary playlist from a set of songs and display the playlist. For some reason, the playlist will randomly leave out a song or two on the screen and sometimes it works perfectly. No idea why.
var SortSongsMakeList = function(data)
{
SortSongs(data);
document.querySelector('h1').innerHTML = "";
models.Playlist.createTemporary('Server Songs').done(function(playlist)
{
playlist.load('tracks').done(function(loadedPlaylist)
{
for(var i = 0; i < data.length; i++)
{
loadedPlaylist.tracks.add(models.Track.fromURI(data[i].song_uri));
}
});
var newList = List.forPlaylist(playlist);
document.querySelector('h1').appendChild(newList.node);
newList.init();
playlist.tracks.clear();
// Remove the temporary ones not in use to reduce resource load
models.Playlist.removeTemporary( models.Playlist.fromURI(playlist.uri) );
});
}
You're better off setting all the tracks at once with an array, like in this answer: https://stackoverflow.com/a/21053309/9970

Looping alternative in Javascript/jQuery with AJAX

I have the following piece of code of which I'm worried for performance wise. I'm not sure if it's a good idea to loop through $.ajax just like that. Is there a more efficient way to loop through an array in jQuery ajax?
What this code is supposed to do:
This code is supposed to take a bunch of URLs through a text area and if the URLs are broken into new lines, then each URL will be part of the urls_ary array. Otherwise, if there is not line break and the entered text area value is an URL, the value will be stored in single_url.
Now, I need to send these URLs (or URL) to my server-side script (PHP) and process those links. However, if the array urls_ary is the one to be sending data through AJAX, I'd need to send each URL individually, causing me to run the $.ajax call inside a for loop, which I think is inefficient.
var char_start = 10;
var index = 0;
var urls = $('textarea.remote-area');
var val_ary = [];
var urls_ary = [];
var single_url = '';
urls.keyup(function(){
if (urls.val().length >= char_start)
{
var has_lbrs = /\r|\n/i.test(urls.val());
if (has_lbrs) {
val_ary = urls.val().split('\n');
for (var i = 0; i < val_ary.length; i++)
{
if (!validate_url(val_ary[i]))
{
continue;
}
urls_ary[i] = val_ary[i];
}
}
else
{
if (validate_url(urls.val()))
{
single_url = urls.val();
}
}
if (urls_ary.length > 0)
{
for (var i = 0; i < urls_ary.length; i++)
{
$.ajax({
// do AJAX here.
});
}
}
else
{
$.ajax({
// do AJAX here.
});
}
}
});
function validate_url(url)
{
if(/^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*#)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|#)|\/|\?)*)?$/i.test(url)){
return true;
}
return false;
}
Doing the $.ajax calls in a loop isn't the inefficient part. The AJAX requests will queue up, waiting for an available connection (only a certain number of requests per connection are allowed at a time). What's inefficient is the fact that you're doing multiple AJAX calls. Ideally, you could add the ability on the server to process multiple URLs at a time, then post an array of URLs in your client code instead of doing multiple requests.
So basically, the only way to be more efficient is to change the server-side code, then rewriting the client code should be straightforward.

Categories

Resources