I'm trying to get offline.js working together with toastr alerts.
My limited JS knowledge is holding me back but hoping some can shed some light on this.
What I want to happen
When the connection goes from down to up, I want to display a "re-connected successfully" message in a toast alert.
The Problem
I don't understand how to check for that status in offline.js. The docs mention that it's possible using this:
Offline.on(event, handler, context) : Bind an event. Events:
up: The connection has gone from down to up
down: The connection has gone from up to down
the up event does what i want but i can't figure out how to put it in to practice...
Below is really just some psuedocode explaining what i'd like to happen:
function checkifbackonline(){
var backonlinemessage = "re-connected successfully";
var checkstate = Offline.on(event, handler, context);
if (checkstate = true) {
toastr.info(backonlinemessage);
}
}
window.setInterval(checkifbackonline, 3000);
Can anyone put me on the right path?
you have not attached up event as per the documentation.
function checkifbackonline(evt){
var backonlinemessage = "re-connected successfully";
toastr.info(backonlinemessage);
}
Offline.on("up", checkifbackonline);
when up is triggerd it will call checkifbackonline function. If you want to remove the event binding then call Offline.off("up");
Related
I am flabbergasted trying to figure out a way to prevent the button click from rendering multiple times based on the number of clicks. If you I click "submitButton" once, everything runs once. If I click it a second time, everything runs twice. If I click it a third time, everything runs three times... And so on...
Here is the code I am running to initiate the running of several functions. The subsequent functions grab data from a database, creates batches of 100, then inserts that data into an HTTP POST request.
submitButton.addEventListener("click", () => {
if (document.getElementById("subject").value == "") {
alert(
"Please add a Subject for your Push Notification before sending."
);
} else if (document.getElementById("body").value == "") {
alert(
"Please add a Message Body for your Push Notification before sending."
);
} else if (
document.querySelectorAll("input[type=radio]:checked").length < 1
) {
alert("Please select a Jump-To page before sending.");
} else {
btn.classList.add("button--loading");
submitButton.disabled = true;
SelectData();
}
});
Following SelectData(); are the functions that batch, create and send the HTTP POST request. At the end of all of this, I've attempted to add the following to prevent some type of storage of EACH click event, operating under the assumption that is my problem. That is, that each click is being stored locally in the browser, and thus if number of clicks = 2 then SelectData(); will run twice along with all other functions related to the click event.
submitButton.removeEventListener("click", null);
submitButton.disabled = false;
I was hopeful the above would be my answer, but it has not done anything differently. I'd love some help and am happy to provide more specifics if necessary, but i am stumped. I appreciate your help in pointing me in the right direction!
The second argument for removeEventListener must be exactly the function provided to addEventListener
function myOnClickFunc() {
console.log("oh jolly, a click!")
}
myElement.addEventListener("click", myOnClickFunc)
myElement.removeEventListener("click", myOnClickFunc) // note the exact same object is passed
This would probably fix it. Though it is preferable for you to rewrite your code in a way where you use the same event listener repeatedly instead of removing and readding it.
I have the following code in a javascript file:
if(dojo.byId('WC_selectedColorNumber') == null && this.defaultColor != null)
{
dijit.byId('WC_color_selection').domNode.style.display = 'block';
dojo.html.set(dojo.query(".message__button .add"), "Add product with only base color " + this.defaultColor + "?");
var userResponse = true;
dojo.connect(WC_add_color_yes, "onclick", function(evt){
userResponse = true;
});
dojo.connect(WC_add_color_no, "onclick", function(evt){
userResponse = false;
});
//var userResponse = confirm("Add product with only base color " + this.defaultColor + "?");
//I WANT TO WAIT HERE FOR THE RESPONSE
if(userResponse == false) //if user clicks Cancel or 'no', display a message and leave the function.
{
alert("Remember to select a color before adding to cart."); //should be a tooltip/popup (not javascript alert) with the same message
return; //return so item doesn't get added to cart
}
}
Firstly, the logic behind this code is correct and it works perfectly well when using javascript confirm's.
As of now, everything comes up and displays correctly, and clicking the buttons perform the correct actions (if I put a console.log in the onclick dojo events, they do indeed print to the console when I click the buttons). However, the program doesn't wait for the responses and continues beyond the dojo.connect methods before it sees the user's input.
I need it to wait until either the yes or no button have been pressed, but I cannot figure out how to do it. I've tried using a
while(userResponse == null);
but a) it's generally a terrible idea and b) it didn't work anyways.
How can I make my code wait until the user has clicked one of the two buttons?
If you can make a jsfiddle I'd be able to help you more, I think, but your dojo.connect calls shouldn't be inside a logic flow like this. Instead, set up your connects on widget startup, and have them act generically.
In your example code, it looks to me like saying "Yes" means "Use default color", and "No" means "User must specify color". So...
startup: function () {
this.inherited(arguments);
dojo.connect(WC_add_color_yes, "onclick", dojo.hitch(this, function(evt){
this.useDefaultColor();
}));
dojo.connect(WC_add_color_no, "onclick", dojo.hitch(this, function(evt){
this.displayColorPicker();
}));
}
And then... only display those two buttons (or the dialog they're hopefully in) when applicable.
There is no "wait" or "sleep" function in javascript and each invocation of javascript code executes to completion (it does not get interrupted in mid execution by a response to some other event). You have correcly identified the historical execeptions that overcome this - global alert and confirm functions execute in browser native code and wait on user input.
Because of this your code will have to be restructured in some way, e.g. an event handler for "add to cart" validates the color choice and calls a function to really add it to the cart if valid. If it is not valid it modifies the DOM to present user with some buttons. The handler for the "yes" option would likewise call the same function to really add it to the cart.
Specific code is outside the scope of this answer - there must be many methods in page and code design to achieve the desired result. For example only: breaking up the sequential code and putting it in separate event handlers, coding using Promise objects defined in EC6 but not supported in MSIE, or perhaps even providing an option of "none - base color only" in the color selection logic.
FYI the dojo 1.10 toolkit documentation reports support for Dojo Promises but I leave research to determine its suitability with you.
I have a very simple backbone dialog which simply shows a bootstap modal with a message. Im using it throughout the app and have built it so that you pass the title and message to be displayed, and the callback to be executed on click of the button. I have an errorListener and in there the view is created, attached to DOM and rendered:
var messageDialog;
var callback = function() {
....
messageDialog.remove();
messageDialog.unbind();
};
....
var errorListener = function() {
if (!messageDialog) {
messageDialog = new MessageDialog({
title: 'Error',
message: 'We have encountered an error. Please try again.',
buttonText: 'Try Again'
});
$('body').append(messageDialog.$el);
messageDialog.render();
}
messageDialog.setCallback(tryAgain);
messageDialog.show();
}
The problem is after the first time the messageDialog is created, attached to the DOM and shown, it wont be shown again. This is because if i do a console.log() on messageDialog, I stil see it's a varaible containing a Backbone view. I thought after calling remove() and unbind() in the callback, the messageDialog variable would be garbage collected. Do I need to do:
messageDialog = null;
after the unbind()? Is this the correct way of doing things?
I think that .remove() is enough, it removes it from the DOM and also removes binded events to avoid phantom views.
http://backbonejs.org/#View-remove
Is there any reason that myview.remove(); doesn't feet your needs ?
Hope it helps.
I'm currently working on an app which has brand_field_id as one of it's parameters. It will hold the Custom Ticket Field ID for "Brand". The thing is: it is not required as the user might want or not to use the functionality it provides. Expected behaviour:
If this field is filled with an ID, an event listener for it's .change will be added on the custom field (and stuff will get done);
If it is left blank, nothing should happen. It means user opted to not use it.
Zendesk already provides the perfect listener for Custom Ticket Field change event, which works like this (dynamically using brand_field_id):
events: {
"ticket.custom_field_ticket.custom_field_{{brand_field_id}}.changed": "myCustomFieldChangedFunction"
}
... aaand it would be really awesome if the app didn't crash when brand_field_id is empty.
Since I don't want the app crashing if brand_field_id is left blank, I figured to validate it before adding the event listener, but didn't manage to get it done. I've tried a few variations of the following code within app.created event, but all unsuccessful.
if(!_.isEmpty(this.setting('brand_field_id'))){
console.log('Brand change event added');
this.events['ticket.custom_field_ticket.custom_field_{{brand_field_id}}.changed'] = 'brandChangedHandler';
}
console.log gets fired, so the validation is ok. Unfortunately the event never fires for the custom field.
So my question is: how can I add an event listener on the go? Or is there another way to achieve what I need?
I've even posted about this in Zendesk's community on a similar thread but no answers so far. The workaround I've found there actually works, but I'm not very fond of it:
events: {
// [...]
'*.changed': 'anyFieldChangedHandler'
},
// [...]
anyFieldChangedHandler: function(e){
// If the changed field was {brand_field_id}
if(!_.isEmpty(this.setting('brand_field_id')) && e.propertyName === 'ticket.custom_field_'+ this.setting('brand_field_id')){
this.brandChangedHandler(e);
}
},
It's much too broad and will fire whenever any field is changed on the ticket. I would like to find a better, cleaner and more elegant solution.
I'm in the same boat as I am aware of how difficult it is to find answers related to the Zendesk Apps framework.
I would do something like this
events: {
"ticket.custom_field_ticket.custom_field_{{brand_field_id}}.changed":"itChanged"
},
itChanged: function(){
if(ticket.custom_field_ticket.custom_field_{{brand_field_id}} !== null && ticket.custom_field_ticket.custom_field_{{brand_field_id}} !== undefined){
//Your custom field exists and has a value. Do something with it.
}
else{
//Your custom field does not exist and/or does not have a value. do nothing
}
}
Would something like this work for your app? I'm not sure if this would have the same functionality as !_.isEmpty() but you might give it a try. I use this a lot in my app sometimes just as a safe guard incase my app loads faster than the actual ticket, which causes some values to be "undefined" at the time the app loads.
Hope this helps
I have isolated the issue, see and try the full source here.
Steps to reproduce:
Press Ctrl+Enter to run the snippet
Click on 'Say Hello' custom command button, and check if the event
handler runs
Click on top left 'Save State' button
Click on 'Load State' button, and restore the previous state.
Now click again on 'Say Hello' button and demonstrate the event handle will not run, instead something weird is happening.
Notes: Please do not search for the solution around the localStorage. The issue can be reproduced by using different server side state persisting solution. (as my original app does)
Any idea where to patch? ... or workaround?
Hopefully this will help you out.
http://dojo.telerik.com/EDUCO/4
I have added the following piece of code for you:
dataBound: function (e) {
$(".k-grid-SayHello").on('click', function (a) {
console.log(e);
a.preventDefault();
alert('Hello');
});
},
When the rebind occurs I suspect that it is losing the connection to the event handler so all I have done if looked for the button based on it's class name and reattached it.
Obviously you can adapt the solution to meet your needs but this is something I do for my projects when I need to "invoke" custom actions on buttons/ dynamically create things on the fly.
Any issues let me know.
To keep function references after calling grid.setOptions()
I added the function references back to the deserialized configuration object before passing it to the setOptions method.
( http://docs.telerik.com/kendo-ui/api/javascript/ui/grid#methods-setOptions )
$(document).ready(function () {
var grid = $("#myGrid").data("kendoGrid");
var originalOptions = grid.getOptions();
var savedOptions = JSON.parse(localStorage["myGrid-options"]);
if (savedOptions) {
var detaylarFunc = originalOptions.columns[3].command[0].click;
savedOptions.columns[3].command[0].click = detaylarFunc;
grid.setOptions(savedOptions);
} else {
grid.dataSource.read();
}
});
//Custom command
function Detaylar(e) {
e.preventDefault();
var grid = $("#myGrid").data("kendoGrid");
options = grid.getOptions();
localStorage["myGrid-options"] = kendo.stringify(grid.getOptions());
}