Hide Snackbar when another one is clicked - javascript

here is my code for three Snackbars using the Material Design Lite component library :
(function() {
'use strict';
window['counter'] = 0;
var snackbarContainer = document.querySelector('#sb-message-box');
var showToastButton = document.querySelector('.button1');
showToastButton.addEventListener('click', function() {
'use strict';
var data = {
message: 'Example Message #1',
timeout: 6000
};
snackbarContainer.MaterialSnackbar.showSnackbar(data);
});
}());
(function() {
'use strict';
window['counter'] = 0;
var snackbarContainer = document.querySelector('#sb-message-box');
var showToastButton = document.querySelector('.button2');
showToastButton.addEventListener('click', function() {
'use strict';
var data = {
message: 'Example Message #2',
timeout: 6000
};
snackbarContainer.MaterialSnackbar.showSnackbar(data);
});
}());
(function() {
'use strict';
window['counter'] = 0;
var snackbarContainer = document.querySelector('#sb-message-box');
var showToastButton = document.querySelector('.button3');
showToastButton.addEventListener('click', function() {
'use strict';
var data = {
message: 'Example Message #3',
timeout: 6000
};
snackbarContainer.MaterialSnackbar.showSnackbar(data);
});
}());
Now I would like to hide one Snackbar as soon as another one is clicked. Currently, the divs are shown one after the other as soon as the 6000ms are up. Can you please help me on this one? Thanks so much!

I too ran into this issue. After some digging, I came up with a little hack.
Use the following code to update the current notification for a new one.
Replace where you'd normally use snackbarContainer.MaterialSnackbar.showSnackbar(data); with:
snackbarContainer.MaterialSnackbar.cleanup_();
setTimeout(function(){
snackbarContainer.MaterialSnackbar.showSnackbar(data);
}, snackbarContainer.MaterialSnackbar.Constant_.ANIMATION_LENGTH)
I'm new to javascript, but it seems to work for me.
Edit: It seems like this is not a foolproof method, when the time-out expires on the previous notification, it closes the new one. I don't have an answer for this yet.
Edit 2: Not foolproof, but gets you going, you need to make some changes to material.js for this to work:
Change 1: Somewhere in MaterialSnackbar = function MaterialSnackbar(element)
Change 2: At the start of MaterialSnackbar.prototype.cleanup_
Change 3: Replace your post code with this.
snackbarContainer.MaterialSnackbar.cleanup_();
snackbarContainer.MaterialSnackbar.skipClearing++;
setTimeout(function(){
snackbarContainer.MaterialSnackbar.showSnackbar(data);
}, snackbarContainer.MaterialSnackbar.Constant_.ANIMATION_LENGTH)
I hope this helps.

Given the API provided by this SnackBar component, it is only plossible to show the alert and not possible to hide it. I would suggest either switching to a better component (this one is excessively simplistic) or hacking your way around it by creating a function that directly destroys all the existing alerts before displaying the new one.

There is a slightly hacky approach to accomplish this.
var snackbarContainer = document.querySelector('#toast');
Let us define a handler which will handle the callback to hide the snackbar,
var handler = function(event) {
snackbarContainer.classList.remove('mdl-snackbar--active');
snackbarContainer.setAttribute("aria-hidden", "true");
};
Now, let's show the snackbar as follows,
var data = {
message: 'Snack time!',
timeout: 2000,
actionHandler: handler,
actionText: 'Dismiss'
};
snackbarContainer.MaterialSnackbar.showSnackbar(data);
That's all!

In the current version of Material Design lite you can just call
mySnackbar.MaterialSnackbar.cleanup_();
and it will hide smoothly.

Related

Using a click event to have a menu appear - but not working with new code with Knockout and Jquery

Previously I had this code that was working to spoof a click event in a knockout method.
self.addProductToCart = function(data) {
var $productNotification = $(".product-notification");
ax.Cart.addCartItem({product_id:data.id, name:data.name, description:data.description});
$productNotification.slideDown(1000).fadeOut(200, function() { $('#cart-nav a.first').click();});};
Now they want to use css3 to animate so I took that the slideDown method out and replaced it with this and it's not working. I am probably missing something stupid here. Thank you
self.addProductToCart = function(data) {
var $productNotification = $(".product-notification");
ax.Cart.addCartItem({product_id:data.id, name:data.name, description:data.description});
$('body').addClass("test");
(function() { $('#cart-nav a.first').click();});};
As Roy J stated in the comments, you have an anonymous function that is not executing. It doesn't even appear that the anonymous function is necessary. Try changing this line:
(function() { $('#cart-nav a.first').click();});};
To this:
$('#cart-nav a.first').click();

AngularJS - Shared service object being deleted incorrectly

When I trigger deleteQuestion() a second time 2 questions get deleted. Any idea? Let me know if you need to see more of my code.
controller.js
crtPromoCtrl.controller('surveyCtrl', ['$scope', 'surveySrv', function($scope, surveySrv)
{
$scope.questions = surveySrv.getQuestions();
$scope.editQuestion = function(index)
{
surveySrv.setEditQuestion(index);
};
$scope.deleteQuestion = function(index)
{
$(document).off('click', '#confirmationModal #confirm');
$('#confirmationModal').modal('show');
$(document).on('click', '#confirmationModal #confirm', function()
{
surveySrv.deleteQuestion(index);
$scope.$apply();
});
};
}]);
service.js
crtPromoSrv.service('surveySrv', function()
{
var questions = [];
var editQuestion;
this.getQuestions = function()
{
return questions;
};
this.addQuestion = function(question)
{
questions.push(question);
};
this.setEditQuestion = function(index)
{
editQuestion = questions[index];
};
this.getEditQuestion = function()
{
return editQuestion;
};
this.clearEditQuestion = function()
{
editQuestion = undefined;
};
this.deleteQuestion = function(index)
{
questions.splice(index, 1);
console.log(questions);
};
});
EDIT: I'm thinking it's an event propagation thing, since when I have 5 q's it deletes #2 and #3 when I delete #2.
EDIT: Fixed, see controller.js code.
It appears you are adding the 'click' function to your #confirmationModal #confirm button multiple times. The first time $scope.deleteQuestion is called, it adds the function. The second time you call it, it adds it again so when it is clicked, the function is called twice.
A simple fix would be to unbind the 'click' event before adding it again. Something like this: $('#confirmationModal #confirm').off('click');
The better solution here is to not use jQuery at all for these event bindings. Using a simple Angular modal directive (like the one provided in the Angular-UI library, for instance) would be the correct way to do this. Then you can just have an ng-click on the button and never have this problem.

Scroll to bottom of page after get request AngularJs

I'm familiar with using something like:
$scope.gotoBottom = function(){
$location.hash('bottom');
$anchorScroll();
}
and this works.. yet what I'm seeing is an issue when retrieving data that's being used in an ng-repeat and attempting to resize when that data comes in.
Example (in controller):
users.get({userList:$routeParams.conversationId}, function(data){
$scope.userList = data;
$scope.gotoBottom();
})
The gotoBottom method is firing to fast, while the ng-repeat is looking on $scope.userList and buidling it's table based off that.
I want to be able to toggle gotoBottom after that list has been remade (or whenever it's modified). Is there a better way to achieve this?
Thank you!
You can use $watch listener to fire gotoBotton when an AngularJs variable change.
$scope.ActivityList = new Array();
$scope.$watch("ActivityList", function () {
$scope.$evalAsync(function () {
$scope.DoSomething();
});
}, true);
$scope.DoSomething = function () {
$(function () {
//$scope.gotoBottom();
});
};
Also you can run scrolling bottom after page is loaded
angular.element($window).bind('load',
function() {
var element = document.getElementById("messages-list").lastElementChild;
element.id = "bottom";
/*-------------*/
$location.hash('bottom');
$anchorScroll();
}

mootools fx.reveal

I'm trying to do a simple show/hide transition for a message div using fx.reveal in mootools 1.4. The effect works the first time, but not on subsequent clicks.
Any hints as to where I'm going wrong?
http://jsfiddle.net/MYgH6/1/
var mytween = new Fx.Reveal(document.getElementById('mydiv'), {duration: 2500});
$('myclick').addEvent('click', function(){
mymessage();
});
function mymessage(){
var mymessage = document.getElementById('mydiv');
mymessage.set('html','YO!');
mytween.reveal();
mytween.dissolve();
}
var mytween = new Fx.Reveal(document.getElementById('mydiv'), {
duration: 1000,
onComplete:function(){
this.element.dissolve();
}
});
$('myclick').addEvent('click', function(){
mymessage();
});
function mymessage(){
var mymessage = document.getElementById('mydiv');
mymessage.set('html','YO!');
mytween.reveal();
}
I know it's not best answer, as you specified using Fx.Reveal, but I'd use wink command
http://mootools.net/docs/more/Fx/Fx.Reveal#Element:wink
Like here: http://jsfiddle.net/zalun/MYgH6/5/
var msg = document.getElementById('mydiv').hide();
$('myclick').addEvent('click', function() {
msg.wink();
});
You can certainly specify the message within the function as you did before.

About Sencha/Ext JS Events fire & on

We're working on a web apps. To keep components pre-configured, I did a lot Ext.extend work.
Here is the pre-definitions.
In the entrance, in index.js
Ext.setup({
onReady: function() {
var app = new App();
}
});
The main class, in App.js, App will new some card components, such as:
App = Ext.extend(Ext.Panel,{
initComponent: function(){
this.sub1 = new Sub_Class_1();
this.sub2 = new Sub_Class_2();
this.sub3 = new Sub_Class_3();
this.items = [this.sub1, this.sub2, this.sub3];
App.superclass.initComponent.call(this);
this.sub1.on('Event1', this.Event1_fn, this)
},
Event1_fn: function() {
//some codes
}
});
The problem comes, in the definition of Sub_Class_1, in Sub_Class_1.js:
var firefun = function() {
this.fireEvent('Event1');
};
Sub_Class_1 = Ext.extend(Ext.Panel,{
//some similar init configure jobs.
//add *firefun* into this class
})
The problem is, if I fire the event in firefun, there is no reaction from the program. Is there something wrong with the scope? Can the community help me with suggestions that I can use to fix it?
I solved it. This is indeed due to the scope problem.
To solve it, I pass the eventName, eventListener, scope to the function. Let it can fire within the correct scope. Boom, it works!
Any better solution?

Categories