Show / Hide javascript function - html

I'm trying to show a div if the URL contains a parameter.
I've run my JS on Chrome Console and it works just fine, but when I publish it doesn't work.
What am I doing wrong?
HTML
<div class="alert alert-success" id="vendaPremium" style="display: none;">
<div class="container">
<div class="alert-icon">
<i class="material-icons">check</i>
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="material-icons">clear</i></span>
</button>
<b>Uhulll! Você acaba de se tornar cliente Meu Marketing Premium. Em breve entraremos em contato. \o/</b>
</div>
</div>
JavaScript
function sucessoCompra() {
var alertaPagSeguro = window.location.href.split("?")[1];
if (alertaPagSeguro === 'sucessoPagSeguro') {
$('#vendaPremium').show();
} else {
$('#vendaPremium').hide();
}
}
window.onload = sucessoCompra();

This is how I would do it:
$(document).ready(function() {
sucessoCompra();
});
function sucessoCompra() {
const urlParams = new URLSearchParams(window.location.search);
var alertaPagSeguro = urlParams.get("query"); // Replace with name of your parameter
if (alertaPagSeguro == "sucessoPagSeguro") {
// Parameter equals string
$("#vendaPremium").show();
} else {
// Parameter does not equal string, or doesn't exist
$("#vendaPremium").hide();
}
}
Problem could be because the script is executed before the JQuery library has been processed. If that's the issue, simply insert the <script> element (of your main code) below the JQuery Library.
Otherwise, what's the URL to the published webpage? Using my example above would probably be more efficient, as URLSearchParams() is widely supported - not on Internet Explorer however, so you may need a fallback.

Related

Ajax, the old value appears first and then the new one

I have Session::flash notifications(bootstrap toasts), which is used to notify about adding a product to the cart:
#if(Session::has('add-product'))
<div aria-live="polite" aria-atomic="true" class="d-flex justify-content-center align-items-center">
<div class="toast fixed-top" role="alert" aria-live="assertive" aria-atomic="true" data-delay="3000">
<div class="toast-header bg-success">
<span class="mr-auto notif_text"></span>
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
</div>
#endif
CartController with Session:flash:
public function addCart(Request $request, $id){
$product = Product::find($id);
$oldCart = Session::has('cart') ? Session::get('cart') : NULL;
$cart = new Cart($oldCart);
$cart->add($product, $product->id);
$request = Session::put('cart', $cart);
Session::flash('add-product', $product->name);
return response()->json([
'total_quantity' => Session::has('cart') ? Session::get('cart')->totalQty : '0',
'notif_text' => 'Product' . Session::get('add-product', $product->name) . 'added to cart'
]);
}
And Ajax request:
$(document).ready(function() {
$('.product-icon-container').find('.ajaxcartadd').click(function(event) {
event.preventDefault();
$('.toast').toast('show');
$.ajax({
url: $(this).attr('href'),
dataType: 'JSON',
success: function(response) {
$('.prodcount').html(response.total_quantity);
$('.notif_text').html(response.notif_text); //!!!Here I load the notification text!!
}
});
return false;
});
});
My question is how to make sure that the old value does not appear, but a new one appears immediately.
Now it works like this:
img_1
Then after about 1 second a new notification appears:
img_2
How can this be fixed?
first remove already assigned value like this then assign value to that class element.
document.getElementsByClassName("prodcount").innerHTML = ""; // or $('.prodcount').innerHTML = "";
document.getElementsByClassName("notif_text").innerHTML = ""; // or $('.notif_text').innerHTML = "";
$('.prodcount').html(response.total_quantity);
$('.notif_text').html(response.notif_text);
Solution for my case, maybe someone will find it useful:
The reason is that the product is added when the ajax status is success (this is where the handler for clicking on the "Add to cart" button is).
I am using bootstrap toasts, they are included with:
$('.toast').toast('show');
And since the inclusion of notifications was not inside the ajax request, it turned out that first an empty or old value was loaded, and then only a new one.
The solution was to move the inclusion "bootstrap toasts" inside ajax:
$(document).ready(function() {
$('.product-icon-container').find('.ajaxcartadd').click(function(event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
dataType: 'JSON',
success: function(response) {
$('.prodcount').html(response.total_quantity);
$('.notif_text').html(response.notif_text); //!!!Here I load the notification text!!
$('.toast').toast('show');//!!!I moved it here!!!
}
});
return false;
});
});
But there is one nuance that I understood just now. Flash messages are not always loaded asynchronously, since they depend on the session (if I understood correctly), and if your user visits the site for the first time, flash will not work. Therefore, it is worth displaying messages without flash:
Bootstrap toasts:
<div aria-live="polite" aria-atomic="true" class="d-flex justify-content-center align-items-center">
<div class="toast fixed-top" role="alert" aria-live="assertive" aria-atomic="true" data-delay="3000">
<div class="toast-header bg-success">
<span class="mr-auto notif_text"></span>
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
</div>
CartController:
public function addCart(Request $request, $id){
$product = Product::find($id);
$oldCart = Session::has('cart') ? Session::get('cart') : NULL;
$cart = new Cart($oldCart);
$cart->add($product, $product->id);
$request = Session::put('cart', $cart);
return response()->json([
'total_quantity' => Session::has('cart') ? Session::get('cart')->totalQty : '0',
'notif_text' => 'Product' . $product->name . 'added to cart'
]);
}
P.S. If you want bootstrap toasts with the same styles as mine, add this to your css:
.toast{
max-width: none;
}
.toast.fixed-top{
margin-top: 30px;
left: auto;
right: auto;
}
.toast-header{
border: 0;
padding: 0.75rem 1.25rem;
color: #fff;
border-radius: 0.25rem;
}
.close{
opacity: 1;
color: #fff;
text-shadow: 0 1px 0 #000;
}
.close:hover{
color: #fff;
opacity: 0.5;
}
You can try the easiest way in your ajax call as. You can use this instead of toast also just as:
$('.prodcount').empty().show().html(response.total_quantity).delay(3000).fadeOut(300);
$('.notif_text').empty().show().html(response.notif_text).delay(3000).fadeOut(300);

Initializing variable in HTML5 for Input tag

Here is the html source code of page that loads array of products:
<div class="container" *ngFor="let product of products">
<div class="product">
<div class="img-container">
<img
//image url
</div>
<div class="product-info">
<div class="product-content">
<h1>{{product.name}}</h1>
<p>{{product.description}}</p>
<p>Price: {{product.price}} $</p>
<p>Quantity:
<button type="button" class="btn btn-danger" (click)="minusQuantity(product)">-</button>
<input type="number" class="input-quantity" [(ngModel)]="product.count"/>
<button type="button" class="btn btn-success" (click)="plusQuantity(product)">+</button>
<div class="buttons">
<a class="button add" (click)="addToCart(product)">Add to Cart</a>
</div>
</div>
</div>
</div>
</div>
When page is loaded, numeric input is empty (there is no value visible inside). Hence clicking on - and + buttons to invoke minusQuantity() and plusQuantity() have no effect on the product.count and displaying it on the page.
I've tried to set default value, but it is overridden by ngModel. If i use only value without ngModel, then input does not react to any changes caused by -/+ buttons (since it's just hardcoded "1").
But if I input e.g. "1" manually on the input, then + and - buttons do work, since there is a value provided, and it works OK.
Question is:
How avoid this issue? Is there any way to initialize input type with some value and then pass it to the product.count correctly? Or the approach should be totally different?
Fragments of components that handle +/- methods:
product.component.ts
plusQuantity(product: ProductModel) {
if (product.count < 99) {
this.cartService.increaseQuantity(product);
}
}
minusQuantity(product: ProductModel) {
if (product.count > 1) {
this.cartService.decreaseQuantity(product);
}
}
cartService.ts
increaseQuantity(product: ProductModel) {
product.count = product.count + 1;
this.orderElement.quantity = product.count + 1;
return product.count;
}
decreaseQuantity(product: ProductModel) {
product.count = product.count - 1;
this.orderElement.quantity = product.count - 1;
return product.count;
}
Use a javascript file with the code:
var cartService = {}
cartService.plusQuantity = function(product) {
product = ProductModel;
if (product.count < 99) {
this.cartService.increaseQuantity(product);
}
};
cartService.minusQuantity = function(product) {
product = ProductModel;
if (product.count > 1) {
this.cartService.decreaseQuantity(product);
}
};
Then it might work!

ng-click according to element ID

So I have a ng-repeat iterating through an array that contains the elements form an API. Through the ng-repeat , I print out the same number of div(s) containing the names of some properties as the number of property present in the API in different objects. Now the next step that I want is that when I click on any property Name div, another screen is opened up which has the details of the property ( details are then fetched from the API which I can do). What I am not able to do is how to use the ng-click that it goes to the details screen but according the property that is clicked. I know that somehow I need to pass the property ID in ng-click and lead it to a different screen. Can't figure out how. Kinda am new to Angularjs so can someone help?
<div ng-repeat="prop in propertyDetails" class="propertyCard"
ng-click="Something here which I cant figure out ">
<p class="propSummaryName">{{ prop.name }}</p>
<div>
Now when the divs are created for the different properties when I click on one of them a new screen comes and then I show there what I want to show for the property.
PS- for property ID : prop.id
Use can directly write function call.
<div ng-repeat="prop in propertyDetails" class="propertyCard"
ng-click="propDetails(prop.id)">
<p class="propSummaryName">{{ prop.name }}</p>
$scope.showDetails(propId) {
// do want ever you want to };
If you want to show property details on another screen then you can use
modal or routing.
hey it's Simple You can call the #scope function in the ng Click and inside the function call the reset service and then open the popup
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body ng-app="myApp" ng-controller="test">
<div ng-init="loadData()">
<div ng-repeat="prop in propertyDetails" class="propertyCard"
ng-click="openMyPopUp(prop)">
<p class="propSummaryName">{{ prop.name }}</p>
<div>
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Modal Heading</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
Name : {{popupData.name}}
Id : {{popupData.id}}
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</body>
</html>
<script type="text/javascript">
var app = angular.module('myApp', []);
app.controller('test', function($scope, $http) {
var popup = angular.element("#myModal");
//for hide model
popup.modal('hide');
var url = 'your-url.com/rest/api'
$scope.loadData = function(){
$http.get(url).then(function(res){
$scope.propertyDetails = res.data;
});
}
$scope.openMyPopUp= function(data) {
$http.get(url + '?id=' + data.id).then(function(res){
$scope.popupData = res.data;
});
//for show model
popup.modal('show');
}
});
</script>
If you need to rederct to another page mean you can do like this
var url = "http://" + $window.location.host + "/Account/Login";
$log.log(url);
$window.location.href = url;
inside this function

How to change ng-include inside firebase firestore function

When I click on continue button it checks clients ID in firestore database and if ID does'nt exist then $scope.filePath = "createClient.htm" is called. everything is working fine but when I call this piece of code inside firebase function nothing happens
Inside HTML
<div ng-include="filePath" class="ng-scope">
<div class="offset-1 offset-sm-2 col-11 col-sm-7">
<h2>Enter Client ID</h2>
<br>
<div class="form-group">
<label for="exampleInputEmail1">ID</label>
<input id="client_id" type="text" class="form-control" placeholder="Client ID">
</div>
<div class="float-right">
<button type="button" class="btn btn-danger">Cancel</button>
<button type="button" ng-click="searchClient()" class="btn btn-success">Continue</button>
</div>
</div>
</div>
Internal Script
<script>
$scope.searchClient = function()
{
//$scope.filePath = "createClient.htm"; it works here
var id= document.getElementById('client_id').value;
db.collection("clients") // db is firestore reference
.where("c_id","==",id)
.get()
.then(function(querySnapshot)
{
querySnapshot.forEach(function(doc)
{
if(!doc.exists)
{
console.log("Client Does'nt Exist");
$scope.filePath = "createClient.htm"; // but doesnt works here inside this firebase function
}
}
);
}
);
}
};
</script>
when console.log is shown and firebase function are fully executed then if I click on "Continue" Button again it works fine and content of createClient.htm is shown inside ng-include="filePath". why i need to click twice ?

get an arraylist from a service using HTTP in ANGULAR

i have a component named zoomdetails which contains the specific details of a product
when i click on the product image the zoomdetails component displays and contains the details of the clicked product
so i m using route and adding the id of the product to the URL
the problem is :
when i load the products arraylist from the service and try to get the product by its id and looping the arraylist an error appears and indicates Cannot read property 'length' of undefined
here is the zoomdetails.component.ts code :
(i ve added some log.console comments to see the results)
export class ZoomdetailsComponent implements OnInit {
x: string="";
produitzoom:IProduct;
produits:IProduct[];
errormessage1 :string ;
currentId : number;
constructor(private _route:ActivatedRoute,private _router:Router,private _productServic:ProductdataService)
{
console.log("Logging the route : " + JSON.stringify(_route.snapshot.params));
this.currentId = +_route.snapshot.params['id'];
console.log("Logging the current ID : " + this.currentId)
this._productServic.getProducts()
.subscribe(productss => this.produits=productss ,error=>this.errormessage1= <any>error);
console.log("************************************************************************************")
}
Myspan(){
this._router.navigate(['/']);
}
find (id:number,P:IProduct[]) :IProduct{
console.log("+++++++DANS FIND ERROR +++++++++++++++++++++++++")
for (let product of P )
{
if (product.idpr==id )
{
return product;
}
}
}
ngOnInit() {
console.log("-------------DANS NGONINITTT-------------------------------------------------------------")
this.produitzoom=this.find(this.currentId,this.produits)
console.log(this.produitzoom.productName)
console.log("--------------------------------------------------------------------------")
}
and this is my zoomdetails component .html
<router-outlet></router-outlet>
<div id="zoom" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close" (click)="Myspan()">×</span>
<div class="container">
<div class="row">
<div class="col-md-4 item-photo">
<img src={{produitzoom.imgUrl}} style="width:360px;height:650px;">
</div>
<div class="col-md-6" style="border:0px solid rgba(163, 152, 152, 0.856)">
<span class="pull-right">
<!-- Datos del vendedor y titulo del producto -->
<h1>{{produitzoom.productName}}</h1>
<h4 style="color:#337ab7"> {{produitzoom.author}} <small style="color:#337ab7">(50 ventes)</small></h4>
<!-- Precios -->
<h2 class="title-price"><small>Price</small></h2>
<h3 style="margin-top0px">{{produitzoom.price}} $</h3>
<br> <br>
<!-- Detalles especificos del producto -->
<div class="section" style="background:rgb(222, 228, 222);">
<h5 class="title-attr" >
<div>
<br>
{{produitzoom.description}}
<br> <br>
</div>
</h5>
</div>
<br><br>
<!-- Botones de compra -->
<script>
console.log("Test of value : " + JSON.stringify(produitzoom))
</script>
<button class="btn btn-success right" [routerLink]="['/Authentification',produitzoom]">
<span class="glyphicon glyphicon-shopping-cart"></span> Add to Cart
</button>
</span>
<br> <br> <br> <br>
<ul class="menu-items">
<li class="active">Customers Reviews</li>
</ul>
<div style="width:100%;border-top:1px solid silver">
<p style="padding:15px;">
<small>
Stay connected either on the phone or the Web with the Galaxy S4 I337 from Samsung. With 16 GB of memory and a 4G connection, this phone stores precious photos and video and lets you upload them to a cloud or social network at blinding-fast speed. With a 17-hour operating life from one charge, this phone allows you keep in touch even on the go.
With its built-in photo editor, the Galaxy S4 allows you to edit photos with the touch of a finger, eliminating extraneous background items. Usable with most carriers, this smartphone is the perfect companion for work or entertainment.
</small>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
and these are the errors :
Logging the route : {"id":"1"} zoomdetails.component.ts:22 Logging the current ID : 1 zoomdetails.component.ts:25 ************************************************************************************ zoomdetails.component.ts:50 -------------DANS NGONINITTT------------------------------------------------------------- zoomdetails.component.ts:38 +++++++DANS FIND ERROR +++++++++++++++++++++++++ ZoomdetailsComponent_Host.html:1 ERROR TypeError: Cannot read property 'length' of undefined (from the find method )
ERROR TypeError: Cannot read property 'imgUrl' of undefined (from the html file produitzoom.imgurl)
what should i do !
first, about the imgUrl error, because of the fact that initially produitzoom is undefined, and it gets it's value after an async call, you can change the value of binding to this: [src]="produitzoom? produitzoom.imgUrl : null".
also about the other error, you are calling this.produitzoom=this.find(this.currentId,this.produits) inside your ngOnInit function, but again, bacuase of the fact that the produits is also undefined at the beginning of the component's lifecycle, and gets it's value after an async call. you should move that this.find() call over to the subscribtion's success. something like this:
productss => {
this.produits=productss;
this.produitzoom = this.find(this.currentId,this.produits)
}
Note!!
it's also very important and recommended that if you are subscribing to an observable, you unsubscribe it at the end of that component's Lifecycle (inside ngOnDestroy function). otherwise, this would cause memory leeks and untracable errors... you can do that by defining a property for subscription like:
productsSubscription: Subscription;
dont forget to import Subscription from rxjs/subscription. and then assign the subscription to this property like:
this.productsSubscription = this._productServic.getProducts()
.subscribe(.....);
and inside ngOnDestroy:
ngOnDestroy(){
if(this.productsSubscription){
this.productsSubscription.unsubscribe();
}
}
have that if there to prevent any undefined-related errors.
The problem is that you are loading the products in your constructor, which is asynchronous. Then in your ngOnInit function that is called later on you're using the result of those loaded products, but unfortunately they seem to be not loaded yet. Therefore your P array is not existing yet and so you are using an undefined object in a for loop, which is not working.
ngOnInit() {
console.log("-------------DANS NGONINITTT-------------------------------------------------------------")
// --> here you use the products from the constructor
// but they are not loaded yet, because the loading process takes time and is asynchronous
this.produitzoom=this.find(this.currentId,this.produits)
console.log(this.produitzoom.productName)
console.log("--------------------------------------------------------------------------")
}
What you should do is place the loading of your products in the ngOnInit function as well. There you can wait for the result and then call the find function.
nOnInit(){
// don't subscribe in the constructor, do it in the ngOnInit
this._productServic.getProducts().subscribe(productss => {
// now the results are here and you can use them
this.produits = productss;
// only then you can call the find function safely
this.produitzoom = this.find(this.currentId, this.produits)
}, error => this.errormessage1 = <any>error);
}