How do I create a message queue? - javascript

I want to display little messages to provide feedback to the user while he
is providing input or just interacting with the UI.
I need it for my firefox addon, so I have to develop it in plain javascript
and not jQuery.
I want the message to appear, but only one message can be visible at the same
time, so I need some kind of queue to manage incomming messages. After a certain time
e.g. 3 sec the message should fade away or just disappear.
For now I am able to add messages to the DOM. Any suggestions how to implement the queue
and how to push the messages forward according to the time?
Thanks!

Perheps you need the concept of FIFO (First In First Out)
Take a look at this simple example in plan java script language:
function Queue() {
var data = [];
this.isEmpty = function() {
return (data.length == 0);
};
this.enqueue = function(obj) {
data.push(obj);
};
this.dequeue = function() {
return data.shift();
};
this.peek = function() {
return data[0];
};
this.clear = function() {
data = [];
};
}

You can use jQuery in a firefox plugin:
Include a script tag in the xul file that points to the jQuery file, e.g.:
<script type="text/javascript" src="chrome://extensionname/content/jquery.js" />
In each js function that uses jQuery, insert this line:
$jQuizzle = jQuery.noConflict();
In each jQuery call, if you are trying to manipulate the document in the current browser window, you must supply the context as "window.content.document", like this:
$jQuizzle(".myClass", window.content.document).show();
Then you can use this jQuery plugin:
http://benalman.com/projects/jquery-message-queuing-plugin/

It's not clear what sort of message you want to display. The nsIAlertsService can display messages but I'm not sure how well it queues them. If you want something simpler then perhaps you could just show a custom <tooltip> element.

Related

How to run a long script and send constant feedback to an html dialog

In a Google Spreadsheet, I have a long script that permorms many actions in steps, like:
function MyLongScript()
{
var Results1 = Action1();
//send feedback 1
var Results2 = Action2(Results1);
//send feedback 2
var Results3 = Action3(Results2);
//send feedback 3
//end code
}
And I want to show the users a dialog box that tells them that script is running and updates each step of the scritp, like "Action1 complete", ..., "Action2 complete" and so on.
So, I have the HTML interface which contains some table rows with these steps. The question is: how do I make the dialog see that the code performed a certain step?
Right now I'm trying to start the code from the dialog after it loads:
$(function() {
google.script.run
.withSuccessHandler(MainCodeSuccess)
.withFailureHandler(MainCodeFailure)
.MyLongScript();
}
And the dialog is called with the UI and HtmlService:
function CallDialog()
{
var ui = HtmlService.createTemplateFromFile('FeedbackWindow')
.evaluate()
.setWidth(300)
.setHeight(500);
SpreadsheetApp.getUi().showModalDialog(ui, "Dialog Title");
}
What I need is either a getStatus() in the dialog scritp or a sendStatus() in the server script.
What is the best way of achieving this?
You can run multiple google.script.run calls to the server simultaneously. You can't have one server call send multiple success calls back. You could have your MyLongScript() run, save progress status somewhere, and just keep that running, then have a second google.script.run executing on a loop every certain time period. You can use a JavaScript setInterval(): window.setInterval("javascript function", milliseconds); I don't think that there is a jQuery equivalent.
So it might (roughly) look like this:
$(function() {
google.script.run
.withSuccessHandler(MainCodeSuccess)
.withFailureHandler(MainCodeFailure)
.MyLongScript();
window.setInterval("statusChecker()", milliseconds);
}
window.statusChecker = function() {
google.script.run
.withSuccessHandler(statusCheckSuccess)
.withFailureHandler(onFailure)
.StatuChecker();
};
window.statusCheckSuccess = function(returnStatus) {
if (returnStatus !== false) {
//To Do - show msg to user
document.getElementById('idMsgToUser').textContent = returnStatus;
};
};
Your MyLongScript() might need to be saving the state of the current status to a file. I'm not sure if the subsequent, and simultaneous google.script.run calls wipes out the data in a global variable. If a global variable would hold the data even with all the simultaneous server scripts running, you could save the current status to a global variable. You'd need to experiment with that, or maybe someone knows the answer to that question.

Use jQuery to determine when Django's filter_horizontal changes and then get the new data

I have a filter_horizontal selector in my Django admin that has a list of categories for products (this is on a product page in the admin). I want to change how the product change form looks based on the category or categories that are chosen in the filter_horizontal box.
I want to call a function every time a category is moved from the from or to section of the filter_horizontal.
What I have now is:
(function($){
$(document).ready(function(){
function toggleAttributeSection(choices) {
$.getJSON('/ajax/category-type/', { id: choices}, function (data, jqXHR) {
// check the data and make changes according to the choices
});
}
// The id in the assignment below is correct, but maybe I need to add option[]??
var $category = $('#id_category_to');
$category.change(function(){
toggleAttributeSection($(this).val());
});
});
})(django.jQuery);
The function never gets called when I move categories from the left side to the right side, or vice versa, of the filter_horizontal.
I assume that $category.change() is not correct, but I don't know what other events might be triggered when the filter_horizontal is changed. Also, I know there are multiple options inside of the select box. I haven't gotten that far yet, but how do I ensure all of them are passed to the function?
If anyone can point me in the right direction I would be very grateful. Thank!
You need to extend the SelectBox.redisplay function in a scope like so:
(function() {
var oldRedisplay = SelectBox.redisplay;
SelectBox.redisplay = function(id) {
oldRedisplay.call(this, id);
// do something
};
})();
Make sure to apply this after SelectBox has been initialized on the page and every time a select box refreshes (option moves, filter is added, etc.) your new function will be called.
(Code courtesy of Cork on #jquery)
I finally figured this out. Here is how it is done if anyone stumbles on this question. You need to listen for change events on both the _from and _to fields in the Django filter_horizontal and use a timeout to allow the Django javascript to finish running before you pull the contents of the _from or _to fields. Here is the code that worked for me:
var $category = $('#id_category_to');
$category.change(function(){
setTimeout(function () { toggleAttributeSection(getFilterCategoryIds()) }, 500);
});
var $avail_category = $('#id_category_from');
$avail_category.change(function(){
setTimeout(function () { toggleAttributeSection(getFilterCategoryIds()) }, 500);
});
And this is how I get the contents of the _to field:
function getFilterCategoryIds() {
var x = document.getElementById("id_category_to");
var counti;
var ids = [];
for (counti = 0; counti < x.length; counti++) {
ids.push(x.options[counti].value);
}
return ids;
}
I know it was a convoluted question and answer and people won't come across this often but hopefully it helps someone out.

Javascript How to check if a call is being made, and kill it if it is

Using jQuery I'm writing a website api call in Javascript, which so far works pretty well. When a person updates a number in a text input it does a call to the API and updates a field with the response. It gets problematic however, when I user quickly makes a lot of changes. The javascript then seems to pile up all queries, and somehow does them side by side, which gives the field to be updated kind of a stressy look.
I think one way of giving the user a more relaxed interface, is to only start the API call after the user finished editing the input field for more than half a second ago. I can of course set a timeout, but after the timeout I need to check if there is not already a call under way. If there is, it would need to be stopped/killed/disregarded, and then simply start the new call.
First of all, does this seem like a logical way of doing it? Next, how do I check if a call is underway? And lastly, how do I stop/kill/disregard the call that is busy?
All tips are welcome!
[EDIT]
As requested, here some of the code I already have:
function updateSellAmount() {
$("#sellAmount").addClass('loadgif');
fieldToBeUpdated = 'sellAmount';
var buyAmount = $("#buyAmount").val();
var sellCurrency = $("#sellCurrency").val();
var buyCurrency = $("#buyCurrency").val();
var quoteURL = "/api/getQuote/?sellCurrency="+sellCurrency
+"&buyAmount="+buyAmount
+"&buyCurrency="+buyCurrency;
$.get(quoteURL, function(data, textStatus, jqXHR){
if (textStatus == "success") {
$("#sellAmount").val(data);
$("#sellAmount").removeClass('loadgif');
}
});
if (fieldToBeUpdated == 'sellAmount') {
setTimeout(updatesellAmount, 10000);
}
}
$("#buyAmount").on("change keyup paste", function(){
updateSellAmount();
});
If you make your AJAX call like this:
var myAjaxDeferred = $.ajax("....");
You can check it later with:
if (myAjaxDeferred.state() === "pending") {
// this call is still working...
}

Is there a way to reinitialize/refresh/reload an actual JavaScript/jQuery method?

So, for a little backstory, I'm using the jRecorder plugin for jQuery on a page that is dynamically fed some HTML via ajax. The user can record a .wav narration for an image in a slideshow, then (via ajax) flip over to another image, record another narration, rinse and repeat. End backstory!
The question itself is geared more towards jQ/JS in general, I believe. When I run the 'record' function again, I get this error in the console:
Uncaught TypeError: Object # has no method 'jStartRecording'
This only appears when I switch to the second image and click "record". The first narration records just fine, and can be played back and whatnot with no issue. I'm thinking I'm receiving the error because I need to re-initialize or reload the jRecorder plugin/method/function since I am trying to call jRecorder again using a different set of options (after switching to another image in the slideshow). Since I'm calling it again, it would appear that something hasn't completely loaded, or there is some sort of conflict between each instance of the plugin's operation.
Bottom line: is there a way to reinitialize a jQuery plugin so it can be run again after dynamically switching parameters?
Perhaps I'm barking up the wrong tree entirely -- I don't know. Any insight from a different set of eyes would be greatly appreciated. Thanks so much!
EDIT: As requested, here's a little bit of code. And here is the plugin source. Hope it helps!
renderPanes() is called each time the widget containing the narration recorder is refreshed with a new image's data. Obviously some things have been edited out for brevity and security.
function renderPanes(type, bucket_id) {
var isRecording = false;
$.getJSON( [endpoint] )
.done(function(json){
[....]
$.jRecorder({
host : [endpoint],
callback_started_recording: function(){callback_started(); },
callback_stopped_recording: function(){callback_stopped(); },
callback_activityLevel: function(level){callback_activityLevel(level); },
callback_activityTime: function(time){callback_activityTime(time); },
callback_finished_sending: function(time){ callback_finished_sending() },
swf_path : '/assets/js/jrecorder/jRecorder.swf',
});
$("#narration_play").click(function(){
var audio = new Audio("[folder path]/"+bucket_id+".wav");
audio.play();
});
$("#narration_record").click(function(){
if (!isRecording) {
$.jRecorder.record(30);
$("#narration_record").html("<i class='icon-stop'></i> Stop");
isRecording = true;
} else {
isRecording = false;
$("#narration_record").html("<i class='icon-comment'></i> Record");
$("#narration_play").removeClass('disabled');
$.jRecorder.stop();
$.jRecorder.sendData();
}
});
});
}

callback function for google.ads.search.Ads()

Following the docs on https://developers.google.com/custom-search-ads/docs/implementation-guide I created some code to retrieve ads on a search result page.
This code assumes that you place a container on your webpage where the function
new google.ads.search.Ads(pageOptions, adblock1, adblock2);
appends an iFrame to that may contain ads. I say MAY contain, because sometimes the iFrames stay empty.
Question:
Now I need to know weather there are any ads displayed in the containers or not. How do I do this?
The call is a-synchronous, so when do I initialise the check? (the google reference does not note a callback function)
How do I check if there's an ad shown. Because with Javascript I can't look inside the iFrame..
Any suggestions welcome! :)
Regards,
Jorn
the callback function, that maybe helps you is:
'noAdLoadedCallback':
function(containerName, adsLoaded) {
if (!adsLoaded) {
try {
---- do something here ---
}
catch (e) {}
}
}
You can put this on each adblock.
Cheers
Nik
Today I faced the same problem, and based on the response from #Niko Nik the solution that worked for me is the following one:
AppComponent.prototype.prepareAds = function (containerId, nOfAds, query) {
var csa = window._googCsa || function () {};
var self_1 = this;
var pageOptions = {
'pubId': this.gootleAdClient,
'adtest': this.googleAdTest,
'adLoadedCallback': function adLoadedCallback(containerName, adsLoaded) {
self_1.adsLoaded[containerName] = adsLoaded;
}
};
var adBlock = {
'container': containerId,
'width': '100%',
'number': nOfAds
};
if (query) {
pageOptions['query'] = query;
}
this.adsLoaded[containerId] = true;
csa('ads', pageOptions, adBlock);
}
I found that adLoadedCallback has the advantadge that it's called when there are ads and when there are not (adsLoaded parameter is true when there are an false when there are not).
You could always add a MutationObserver and wait for the iframe to be inserted, then check its height. If it's less than 30 pixels tall, it's probably empty.
I haven't seen any callbacks in the CSA code, but I have seen two undocumented options for ad blocks, clicktrackUrl and linkTarget. One is a url for a tracking pixel that's loaded when ads are clicked, the other acts like the target attribute on an a tag.

Categories