How to keep track if a button has been clicked already? - javascript

I am writing an app with Ionic and Firebase and my users have the choice to add something to their "Favorites".
Now, I found a way to have the user clicking the button and changing the text once clicked and saving the data in the database, but if the user moves to another page and come back, the button comes back to "Add to favorites".
How to display the text on the button regarding what the user did with it before ?
The DOM :
<div class="list card" id="topLetters-card21" ng-repeat="letter in letters">
<ion-item class="item-avatar item-icon-right" id="userId{{$index}}" alt="{{letter.uid}}" ui-sref="menu.user">
<img src="{{letter.userpic}}" alt="">
<h2>{{letter.username}} </h2>
<p>{{letter.location}}</p>
<i class="icon ion-android-arrow-dropright"></i>
</ion-item>
<h2 style="color:#000000;" class="padding-left" id="letterId{{$index}}" alt="{{letter.letter}}">{{letter.title}}</h2>
<div style="{{letter.font}}background: url(img/{{letter.background}}.jpg) no-repeat center;background-size:cover;">
<h5 style="{{letter.font}}text-align:right;"id="topLetters-heading15" style="color:#000000;" class="padding">{{letter.date}}</h5>
<h5 style="{{letter.font}}"id="topLetters-heading4" style="color:#000000;" class="padding">{{letter.opening}} {{letter.to}}, </h5>
<div id="topLetters-markdown3" style="text-align:justify;" class="show-list-numbers-and-dots padding">
<p style="color:#000000;">{{letter.message}}</p>
</div>
<h5 style="{{letter.font}}"id="topLetters-heading5" style="color:#000000;text-align:right;" class="padding">{{letter.conclusion}}, {{letter.username}}.</h5>
</div>
<button id="addletter{{$index}}" ng-click="addToFavorites($index)" class="button button-dark button-small button-block icon ion-ios-heart-outline" alt={{letter.letter}}> Add to Favorites</button>
<ion-item class="item-icon-left item-icon-right" id="topLetters-list-item29">
<i class="icon ion-ios-heart-outline"></i>{{letter.likes}}
<i class="icon ion-ios-flag"></i>
</ion-item>
<div class="spacer" style="width: 300px; height: 29px;"></div>
</div>
The Controller :
var ref = firebase.database().ref('/letters');
//retrieve the items in the cart of the user
ref.orderByChild("likes").on("value", function(snapshot1) {
$timeout(function(){
$scope.letters = snapshot1.val();
})
})
$scope.addToFavorites = function(ind){
var letterId = document.getElementById('letterId'+ind).getAttribute('alt');
var userId2 = document.getElementById('userId'+ind).getAttribute('alt');
var userId = firebase.auth().currentUser.uid;
//Add the letterUid and ID to our favorites to retrieve it later
//Add our uid to the letter to count the number of Favorites
if(document.getElementById('addletter'+ind).textContent == " Add to Favorites"){
$timeout(function(){
firebase.database().ref('accounts/' + userId + '/favorites/' + letterId).update({
letterId: letterId,
userId: userId2,
});
firebase.database().ref('letters/' + letterId + '/favorites/' + userId).update({
userId: userId,
});
document.getElementById('addletter'+ind).textContent = " Remove from Favorites";
})
} else if (document.getElementById('addletter'+ind).textContent == " Remove from Favorites")
$timeout(function(){
document.getElementById('addletter'+ind).textContent = " Add to Favorites";
firebase.database().ref('/accounts/' + userId + "/favorites/" + letterId).remove();
firebase.database().ref('/letters/' + letterId + "/favorites/" + userId).remove();
})
}

I believe you should do something like this:
JS
$scope.accountsFavorites = [];
$scope.lettersFavorites = [];
$scope.getFavorites = function(){
$scope.accountsFavorites = firebase.database().ref('/accounts/' + userId + "/favorites/")
$scope.lettersFavorites = firebase.database().ref('/letters/' + letterId + "/favorites/")
$scope.syncFavorites();
}
$scope.syncFavorites() {
$scope.letters.forEach(function(letter){
$scope.lettersFavorites.forEach(function(favoriteLetter){
if(letter.id == favoriteLetter.letter_id) { // or something
letter.isFavorite = true;
}
})
})
}
$scope.getFavorites();
HTML
<button
id="addletter{{$index}}"
ng-click="addToFavorites($index)"
class="button button-dark button-small button-block icon ion-ios-heart-outline"
alt={{letter.letter}}>
<span data-ng-if="letter.isFavorite">Remove from favorites</span>
<span data-ng-if="!letter.isFavorite">Add to favorites</span>
</button>

Related

Weather app with multiple locations in JavaScript / jQuery

I'm new here and I'm a beginner in programming.
I need help with my weather app. I'm using metaweather api for displaying weather, but i need to display weather for multiple location.
This is how i display weather for only one city, but i dont know how to pass more cities?!
Please help!
Here it's code (HTML)
<main>
<section>
<div class="container">
<div id="main_panel">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="app">
<img class="img-responsive img-rounded" src="images/warszawa.jpg" alt="Warszawa">
<span id="warsaw">
<span class="location">
Unknown
<i class="fa fa-map-marker"></i>
<span class="today">Today</span>
</span>
</span>
<span class="weather">
<span class="temperature">
0<sup>°</sup>
<span class="unit">c</span>
</span>
<span class="weather-icon"></span>
<h3 class="weather-state"></h3>
</span>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="app">
<img class="img-responsive img-rounded" src="images/berlin.jpg" alt="Berlin">
<span id="berlin">
<span class="location">
Unknown
<i class="fa fa-map-marker"></i>
<span class="today">Today</span>
</span>
</span>
<span class="weather">
<span class="temperature">
0<sup>°</sup>
<span class="unit">c</span>
</span>
<h3 class="weather-state"></h3>
<span class="weather-icon"></span>
</span>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-4">
<div class="app">
<img class="img-responsive img-rounded" src="images/lizbona.jpg" alt="Lizbona">
<span id="location">
Unknown
<i class="fa fa-map-marker"></i>
<span class="today">Today</span>
</span>
<span class="weather">
<span id="temperature">
0<sup>°</sup>
<span class="unit">c</span>
</span>
<h3 class="weather-state"></h3>
<span class="weather-icon"></span>
</span>
</div>
</div>
</div>
</div>
</section>
</main>
And here it is JavaScript
var temperature = [];
var cityName = 'warsaw';
var weatherSiteUrl = "http://cors-anywhere.herokuapp.com/https://www.metaweather.com/";
var weatherAPIUrl = weatherSiteUrl + "api/";
var cityLocation = weatherAPIUrl + "location/search/?query=";
var iconUrl = "https://www.metaweather.com/";
function drawWeather() {
$.getJSON(cityLocation + cityName, function(data) {
$.getJSON(weatherAPIUrl + 'location/' + data[0].woeid, function(data) {
$('.location').html(cityName + '<i class="fa fa-map-marker"></i>'); // Name of location
$('.weather-state').html(data.consolidated_weather[0].weather_state_name); //Weather state
temperature[0] = Math.floor(data.consolidated_weather[0].the_temp);
$('.temperature').html(temperature[0] + '<sup>°</sup><span class="unit">c</span>'); // Temperature
var weatherImg = iconUrl + 'static/img/weather/' + data.consolidated_weather[0].weather_state_abbr + '.svg';
$('.weather-icon').html('<img src=' + weatherImg + '>');
});
});
};
drawWeather();
Instead of hardcoding 'warsaw' pass the location to the function
var temperature = [];
var weatherSiteUrl = "http://cors-anywhere.herokuapp.com/https://www.metaweather.com/";
var weatherAPIUrl = weatherSiteUrl + "api/";
var cityLocation = weatherAPIUrl + "location/search/?query=";
var iconUrl = "https://www.metaweather.com/";
function drawWeather(cityName) {
$.getJSON(cityLocation + cityName, function(data) {
$.getJSON(weatherAPIUrl + 'location/' + data[0].woeid, function(data) {
$('.location').html(cityName + '<i class="fa fa-map-marker"></i>'); // Name of location
$('.weather-state').html(data.consolidated_weather[0].weather_state_name); //Weather state
temperature[0] = Math.floor(data.consolidated_weather[0].the_temp);
$('.temperature').html(temperature[0] + '<sup>°</sup><span class="unit">c</span>'); // Temperature
var weatherImg = iconUrl + 'static/img/weather/' + data.consolidated_weather[0].weather_state_abbr + '.svg';
$('.weather-icon').html('<img src=' + weatherImg + '>');
});
});
};
Then instead of drawWeather(); run the function using drawWeather('warsaw');, drawWeather('berlin');,...

Angularjs order by not working properly

I'm facing a little problem with order by that i could not underdstand.
When i reoder the array i can see that every thing is working perfectly, but the problem is in the ng-click function of the list.
For example if i have this array:
$scope.ticketsEncour = [
{_id: 1, vendeur: 'John Doe', date_ticket: '18:52', total: 50},
{_id: 2, vendeur: 'Foo Bar', date_ticket: '12:12', total: 20},
{_id: 3, vendeur: 'John Smith', date_ticket: '11:02', total: 10},
{_id: 4, vendeur: 'Test Test', date_ticket: '05:10', total: 6000}
]
And this is ther reoder and click functions:
$scope.reverse = false;
$scope.orderItems = function (item) {
$scope.reverse = !$scope.reverse;
if (item != undefined) {
if (item == $scope.orderItem) {
$scope.orderType = $scope.orderType == '+' ? '-' : '+';
}
else {
$scope.orderItem = item;
$scope.orderType = '+';
}
}
$('.iconOrder').removeClass('up').removeClass('down');
if ($scope.orderType == '+') {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('down')
}
else {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('up')
}
return $scope.orderType + $scope.orderItem;
}
$scope.goToCaissePage = function (id) {
id = id.replace("app/caisse/", "");
console.log(id);
};
And my Html Code
<ion-list class="list articlesList swipedList" show-delete="showDelete">
<ion-item class="item item-button-right stable-bg">
<span class="row">
<span class="col col-20" ng-click="orderItems('vendeur')">
<strong>Vendeur</strong>
<div class="iconOrder" name="vendeur">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
<span class="col col-20" ng-click="orderItems('date_ticket')">
<strong>Heure</strong>
<div class="iconOrder" name="date_ticket">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
<span class="col col-10" ng-click="orderItems('total')">
<strong>Total</strong>
<div class="iconOrder" name="total">
<i class="icon ion-android-arrow-dropup"></i>
<i class="icon ion-android-arrow-dropdown"></i>
</div>
</span>
</span>
</ion-item>
<ion-item class="item item-button-right pad-item" ng-repeat="ticket in ticketsEncour | orderBy : orderBy : orderItem:reverse track by $index">
<span class="row">
<span class="col col-20 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.vendeur }}
</div>
</span>
<span class="col col-20 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.date_ticket | date:'HH:mm' }}
</div>
</span>
<span class="col col-10 col-pad" ng-click="goToCaissePage('app/caisse/{{ticket._id}}')">
<div>
{{ ticket.total.toFixed(2) }}€
</div>
</span>
</span>
</ion-item>
</ion-list>
When i click on any item of the ng-repeat it shows the right id in the console. But when i use the reorder i can is that the HTML has changed but the ng-click function render always the old one:
click on index 0 => console 1 (perfect)
After reoder with any type:
click on index 0 => console 1 (expected 3 for example)
Thanks
Update: changed the array name (copy cut error)
Updated with #Weijian suggestion
I suggest using the orderBy that uses the scope variables directly. This is also the method suggested by the angular docs.
js
$scope.reverse = false;
$scope.orderItems = function (item) {
if( item == $scope.orderItem ){
$scope.reverse = !$scope.reverse;
}
$scope.orderItem = item;
$('.iconOrder').removeClass('up').removeClass('down');
if( $scope.reverse ){
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('down');
}
else {
$('.iconOrder[name="' + $scope.orderItem + '"]').addClass('up');
}
}
html
orderBy:orderItem:reverse
https://docs.angularjs.org/api/ng/filter/orderBy
this way is cleaner since you avoid the mixed use of the orderItems function.
I fixed the issue, i was from the track by $index in the ng-repeat loop

How to show ionic popup using ng-click inside ng-repeat

here's my html code.
<div class='list' ng-repeat='worker in categories' >
<br><a class="item item-thumbnail-left" ng-click="showConfirm(worker.$id)">
<img src="img/tech_support.png">
<p>{{worker.$id}}</p>
<p>Address: {{worker.Address}}</p>
<p><u>more..</u></p>
</a>
</div>
and here's my controller.js
man.controller('categoryCtrl',function($scope,$firebaseArray,
$firebaseObject,$state,$stateParams,$ionicPopup,$window,$timeout){
var category = $stateParams.categoryId;
var categoryRef = Refroot.child('Workers').child(category);
$scope.categories=$firebaseArray(categoryRef);
$scope.showConfirm= function(id){
var workerId = id;
var workRef = Refroot.child('Workers');
var lastRef = workRef.child(category).child(workerId);
$scope.workerlist = $firebaseArray(lastRef);
var confirmPopup = $ionicPopup.confirm({
title: 'Worker Profile',
});
confirmPopup.then(function(res) {
if(res) {
console.log('Sure!');
} else {
console.log('Not sure!');
}
});
console.log(workerId + '' + category + '' + lastRef);
}
});
Hope you guys could help me, it will be a great help for my thesis :)
You should be using $index as below
<div class='list' ng-repeat='worker in categories track by $index' >
<br><a class="item item-thumbnail-left" ng-click="showConfirm($index)">
<img src="img/tech_support.png">
<p>{{$index}}</p>
<p>Address: {{worker.Address}}</p>
<p><u>more..</u></p>
</a>
</div>

hover over one element and addClass to other elem in Angular JS

Attempting with the below jQuery method: But this does not work in my Angular environment, assuming because I'm attempting to do this outside of angular JS scope methods, but I don't know how to implement this using Angular scope methods (new to angular) any advice?
$('.song-thumb .hover-play').on('mouseenter', function(e) {
var elem = $('section.suggestedAlbums img');
elem.trigger(e.type);
elem.addClass('hoverclass');
});
$('.song-thumb .hover-play').on('mouseleave', function(e) {
var elem = $('section.suggestedAlbums img');
elem.trigger(e.type);
elem.removeClass('hoverclass');
});
var count = 0;
$('section.suggestedAlbums img').hover(function() {
count++;
$('[remove]').html('<label remove><br>It triggers the hover event(' + count + ') too.<br></label>');
});
Full page code:
<script>
$('.song-thumb .hover-play').on('mouseenter', function(e) {
var elem = $('section.suggestedAlbums img');
elem.trigger(e.type);
elem.addClass('hoverclass');
});
$('.song-thumb .hover-play').on('mouseleave', function(e) {
var elem = $('section.suggestedAlbums img');
elem.trigger(e.type);
elem.removeClass('hoverclass');
});
var count = 0;
$('section.suggestedAlbums img').hover(function() {
count++;
$('[remove]').html('<label remove><br>It triggers the hover event(' + count + ') too.<br></label>');
});
</script>
<!-- <h2>{{trackListData.listTitle}}</h2>
--><div ng-repeat="track in trackListData.tracks track by $index " class="feature-item-homepage fade-animate-nostagger">
<div class="song-thumb" ng-class="{active: $root.currentPlaying.song_id == track.id}">
<!--3 Cases-->
<!--Not the song being played-->
<div class="hover-play" ng-if="$root.currentPlaying.song_id != track.id" ng-click="$root.playSong(track);">
<i class="fa fa-plus add-to-playlist" ng-init="playlistOption = false" ng-click="$root.initPlaylistOption($event, track.id); $event.stopPropagation();"></i>
<i class="fa fa-play play-song"></i>
<img src="img/producer_icon_white.png" class="prod_logo">
<div class="song-title" style="width: 80%;padding-top:25px;">
<a class="song-linking" href="#/song/{{track.id}}">
<h4>{{track.title}}</h4>
<h5>{{track.artist.user_name}}</h5>
</a>
</div>
</div>
<!--The current song but paused-->
<div class="hover-play" ng-if="$root.currentPlaying.song_id == track.id && !$root.isPlaying" play-music>
<i class="fa fa-plus add-to-playlist" ng-init="playlistOption = false" ng-click="$root.initPlaylistOption($event, track.id); $event.stopPropagation();"></i>
<i class="fa fa-play play-song"></i>
</div>
<!--The current song but playing-->
<div class="hover-play" ng-if="$root.currentPlaying.song_id == track.id && $root.isPlaying" pause-music>
<i class="fa fa-plus add-to-playlist" ng-init="playlistOption = false" ng-click="$root.initPlaylistOption($event, track.id); $event.stopPropagation();"></i>
<i class="fa fa-pause pause-song"></i>
</div>
<img ng-src="{{(track.albums[0].album_picture? $root.fileServer +'uploads/' + track.albums[0].album_picture:(track.artist.profile_picture? $root.fileServer +'uploads/' + track.artist.profile_picture:'img/defaultalbum.png'))}}" />
</div>
<!-- <div class="song-title-wrap">
<div class="song-title">
<a class="song-linking" href="#/song/{{track.id}}">
<h4>{{track.title}}</h4>
<h5>{{track.artist.user_name}}</h5>
</a>
</div>
</div> -->
</div>
Add a controller to a containing div:
<div ng-controller='MyController'>
Add ngMouseleave and ngMouseenter to the .song-thumb .hover-play element
<div class="hover-play" ng-if="$root.currentPlaying.song_id != track.id" ng-click="$root.playSong(track);" ng-mouseenter='state.hoverPlay=true;' ng-mouseleave='state.hoverPlay=false'>
Add the controller
angular.controller('MyController', [ '$scope', function ($scope) {
$scope.state = {
hoverPlay: false
};
}]);
Use ngClass to add/remove the class
<img ng-class="{ 'hoverclass': state.hoverPlay }" . . . >

How to correct this redundancy in an array?

I'm building an app in ionic, and I need to pass items into another array, but when I pass the same item again it's considered the same item - really - but I need that to not happen. I need them to be considered different or or at least be considered different. Each item(is an object) of array have a var "qntt"(quantity) and when this bug happen, instead put the same item in array, plus one in this var. OBS: I'm using ng-repeat="item in items track by $index" in html.
<ion-view title="Order">
<ion-content overflow-scroll="true" padding="true" style="background: url(img/background1.jpg) no-repeat center;" class="has-header" ng-controller="pedidoCtrl">
<button class="button button-dark button-small button-block" ng-click="showDelete = !showDelete">Remover</button>
<ion-list show-delete="showDelete">
<ion-item class="item-thumbnail-left item-remove-animate" ng-repeat="item in items track by $index">
<ion-delete-button class="ion-minus-circled" ng-click="deleteItem(item)"></ion-delete-button>
<img src="{{item.img}}">
<h2>{{item.nome}}</h2>
<div class="row">
<div class="col col-60">
<h2>R{{item.subtotal | currency}}</h2>
</div>
<div class="col col-15">
<button class="button button-clear button-assertive button-small icon ion-minus" ng-click="subQtt(item)"></button>
</div>
<div class="col col-10">
<h2>{{item.qtt}}</h2>
</div>
<div class="col col-15">
<button class="button button-icon-right button-clear button-assertive button-small icon ion-plus" ng-click="addQtt(item)"></button>
</div>
</div>
</ion-item>
</ion-list>
<button style="text-align:right;" class="button button-assertive button-block icon-left ion-cash">R{{total | currency}}</button>
<div style="margin-right:-20px;">
<button style="left:-10px;" class="button button-dark button-large button-full icon ion-android-cart">Order</button>
</div>
</ion-content>
.controller('orderCtrl', function($scope, productService) {
$scope.items = null;
$scope.items = productService.getProducts();
$scope.deleteItem = function(item){
$scope.items.splice($scope.items.indexOf(item), 1);
};
$scope.$watchCollection('items', function(array) {
if (array) {
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
}
$scope.addQtt = function(item){
item.qtt = item.qtt + 1;
item.subtotal = item.price * item.qtt;
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
};
$scope.subQtt = function(item){
if(item.qtt > 1)
{
item.qtt--;
item.subtotal = item.price * item.qtt;
}
else
{
$scope.items.splice($scope.items.indexOf(item), 1);
}
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
};
});
})
.service('productService', [function(){
var productList = [];
var addProduct = function(product) {
productList.push(product);
};
var getProducts = function(){
return productsList;
};
return {
addProduct: addProduct,
getProducts: getProducts,
};
}]);
That's because you are not calling the service method addProduto() within your controller. Try calling produtoService.addProduto() within the $scope.addQnt() method as below and it should work:
$scope.addQnt = function(item){
item.qntd = item.qntd + 1;
item.subtotal = item.preco * item.qntd;
$scope.total = array.reduce(function(total,item) {
return total + item.subtotal;
},0);
// Add this line to retain your addition in service
produtoService.addProduto(item);
// Get updated list of products
$scope.items = productoService.getProdutos();
// Alternatively use '$scope.items.push(item)'
};
Also, you need to refresh your $scope.items by triggering a call to productoService.getProdutos(), though you can do it directly by pushing in $scope.items.push(item)

Categories