how get I notified when the "onload" script has finished - xul

I get a notification when a html page is loaded
-> onStateChange, stateFlags: STATE_IS_NETWORK + STATE_STOP
but I need a notification when the page ist loaded and a onload script has finished running.
Any hints ?
THX

Maybe you could add a second listener to "load" events. I was not able to find any documentation confirming that events listeners are called in order they are set, but some experiments with the code below shows that it seems to be the case. If there was a race condition I would expect to see sometimes "AB" and sometimes "BA":
<input type="text" id="field"/>
<script>
var t = document.getElementById("field");
t.value="";
function a(e) {
t.value = t.value + "A";
}
function b(e) {
t.value = t.value + "B";
}
window.addEventListener("load", a, false);
window.addEventListener("load", b, false);
</script>
One thing to be careful with this is that if you add the second event listener too late (i.e. the load event already fired) it will not be called.
Anyway, feels like a hack, but is just an idea in case you cannot find a better way to handle it.

You could use:
gBrowser.addEventListener("DOMContentLoaded", function()
{
// Page content is loaded
}, false);
but remember that gBrowser refers to the content of a tab so this will check every tab when it has been selected

Related

Vue.js - How to load data with method call via click and toggle data?

I'm loading data via my rest api when the button is clicked with a vue.js method. To hide the loaded data I'm clicking the button again. When I'm clicking the button to show the data again, the same method is called again and the data is shown twice.
<div v-if="comment.answers_count !== 0">
<button
#click="toggleAnswers"
:class="{
'btn-danger': loadAnswers,
'btn-outline-danger': !loadAnswers
}"><strong>{{ comment.answers_count }} show answers</strong></button>
</div>
How can I load the data once, hide it with button clicked and show the same loaded data when toggling the button?
Maybe theres a way to use a computed property?
Create a new property in data:function(){}
e.x
data:function(){
answers_loaded:false
}
then on your function toggleAnswers
do the following
methods:{
toggleAnswers:function(){
/** if answers are not loaded , load them **/
if(!this.answers_loaded){
/** mark answers_loaded to true, so we do not call this code
again. Should be better put on your success request handler
to make sure that they were successfully loaded**/
this.answers_loaded = true;
//code to load the answers
}
}
}
So the first time that you click the button and function toggleAnswers is called the variable answers_loaded pass the if check.
Every other time that you click the button since answers_loaded is equal to true, it will fail the if check and wont call again part of the code to load the answers
So,i can't get you real purpose?
if you want to just load data once, you can use v-once, eg
<button #click.once="loadData" #click="hideData"> loadData or hideData</button>
...
loadData() {
setTimeout(() => {
this.data = 'loaded data'
}, 500)
},
hideData() {
this.data = this.data && null
}
if you want the toggle circle then you should set a tag using %2 to judge which function to run .

.dataTable() pagination breaks class .click responsiveness

When I construct a normal table and give each column a distinct class, the classes are responsive for all rows. However, when I call .dataTable() on my table, only page 1 of the paginated results is responsive. Page 2 and beyond are not responsive.
Example code:
var dataTableID = 'questionsTable';
var columns = {
questionID: "ID",
CategoryString: "Cat",
difficultyLevel: "Diff",
timesAsked: "Qty",
questionText: "Question Text"
};
// my own little function that builds the HTML table. <TD> classes are column names
//-- eg .questionID, .CategoryString, etc
var tableHTML = makeTable(questions, columns);
$('#' + dataTableID).html(tableHTML);
// dataTable works nicely except only page 1 .click is responsive!
$('#' + dataTableID).dataTable();
// works fine if I remove .dataTable() above. ONLY works for first page of results
// if I keep .dataTable()
$('.questionID').on("click", function() {
alert('Click called');
});
When using pagination, dataTables change the visible rows by moving <tr>'s back and forth the DOM. $('.questionID').on is processed for columns on the first page only, since those columns is the only visible (accessible) columns after initialization.
So you must assign the click handler (or whatever you want to attach) on page change rather than on initialization. Here by the use of the fnDrawCallback event :
function clickHandler() {
alert('Click called');
}
var dataTable = $('#example').dataTable({
fnDrawCallback : function() {
$('.questionID')
.off("click", clickHandler)
.on("click", clickHandler)
}
});
see demo -> http://jsfiddle.net/U9Jmg/
Notice the use of .off. dataTables actually moves the <tr>'s back and forth the DOM and a table in memory, including any attached events. If previous attached events is not released, we will end up in multiple alerts for each column.
Also note I have only used only one class .questionID for all the columns in the demo. The example is 1.10.x but this works in 1.9.x as well.
As you can see of the comments below, you could also use a delegated event instead of direct event binding. It changes the setup and perhaps it is not suitable for your needs, but anyway :
$('#example tbody').on('click', '.questionID', clickHandler);
see demo -> http://jsfiddle.net/L29Dq/
When using DataTables pagination feature (as you do), only the first page of your data is present in the dom when you attach the click event handler. That's why the handler is attached to the elements on the first page and only to those elements.
When going to another page, DataTables will redraw the table which in effect removes the attached event handler. You have to reattach the event handler after every table draw. The drawCallback option should be the right place for that:
$('#' + dataTableID).dataTable({
"drawCallback": function(settings){
$('.questionID').on("click", function(){
alert('Click called');
});
}
});
As #davidkonrad pointed out in his answer, the click handler should be removed (using off) to avoid handling the event multiple times.
The DataTables page has a section on this as well: Advanced Initialisation - DOM/jQuery events. The example there uses delegated events.

Backbone: how to test preventDefault to be called without testing directly the callback

Let's say we have a simple Backbone View, like this:
class MyView extends Backbone.View
events:
'click .save': 'onSave'
onSave: (event) ->
event.preventDefault()
# do something interesting
I want to test that event.preventDefault() gets called when I click on my element with the .save class.
I could test the implementation of my callback function, pretty much like this (Mocha + Sinon.js):
it 'prevents default submission', ->
myView.onSave()
myView.args[0][0].preventDefault.called.should.be.true
I don't think it's working but this is only to get the idea; writing the proper code, this works. My problem here is that this way I'm testing the implementation and not the functionality.
So, my question really is: how can I verify , supposing to trigger a click event on my .save element?
it 'prevents default submission', ->
myView.$('.save').click()
# assertion here ??
Thanks as always :)
Try adding a listener on the view's $el, then triggering click on .save, then verify the event hasn't bubbled up to the view's element.
var view = new MyView();
var called = false;
function callback() { called = true; }
view.render();
// Attach a listener on the view's element
view.$el.on('click', callback);
// Test
view.$('.save').trigger('click');
// Verify
expect(called).toBeFalsy();
So you want to test that preventDefault is called when a click event is generated, correct?
Couldn't you do something like (in JavaScript. I'll leave the CoffeeScript as an exercise ;)):
var preventDefaultSpy;
before(function() {
preventDefaultSpy = sinon.spy(Event.prototype, 'preventDefault');
});
after(function() {
preventDefaultSpy.restore();
});
it('should call "preventDefault"', function() {
myView.$('.save').click();
expect(preventDefaultSpy.callCount).to.equal(1);
});
You might want to call preventDefaultSpy.reset() just before creating the click event so the call count is not affected by other things going on.
I haven't tested it, but I believe it would work.
edit: in other words, since my answer is not that different from a part of your question: I think your first approach is ok. By spying on Event.prototype you don't call myView so it's acting more as a black box, which might alleviate some of your concerns.

How do I determine open/closed state of a dijit dropdownbutton?

I'm using a dijit DropDownButton with an application I'm developing. As you know, if you click on the button once, a menu appears. Click again and it disappears. I can't seem to find this in the API documentation but is there a property I can read to tell me whether or not my DropDownButton is currently open or closed?
I'm trying to use a dojo.connect listener on the DropDownButton's OnClick event in order to perform another task, but only if the DropDownButton is clicked "closed."
THANK YOU!
Steve
I had a similar problem. I couldn't find such a property either, so I ended up adding a custom property dropDownIsOpen and overriding openDropDown() and closeDropDown() to update its value, like this:
myButton.dropDownIsOpen = false;
myButton.openDropDown = function () {
this.dropDownIsOpen = true;
this.inherited("openDropDown", arguments);
};
myButton.closeDropDown = function () {
this.dropDownIsOpen = false;
this.inherited("closeDropDown", arguments);
};
You may track it through its CSS classes. When the DropDown is open, the underlying DOM node that gets the focus (property focusNode) receives an additional class, dijitHasDropDownOpen. So, for your situation:
// assuming "d" is a dijit.DropDownButton
dojo.connect(d, 'onClick', function() {
if (dojo.hasClass(d.focusNode, 'dijitHasDropDownOpen') === false) {
performAnotherTask(); // this fires only if the menu is closed.
}
});
This example is for dojo 1.6.2, since you didn't specify your version. It can, of course, be converted easily for other versions.

jQuery - Page with a ton of checkboxes, how to bind?

I have a page of checkboxes, in some cases more than 100. I'm currently doing this:
$('form[name=myForm] input[name=myCheckbox]').change(function(){
var numChkd = $('input[name=myCheckbox]:checked').size();
console.log(numChkd);
};
But as you could imagine this can get wicked slow. Is there a better way to bind an event to multiple elements? This works, but I want to know if there is a better way?
You can bind an event to the parent container that will wrap all of the checkboxes and then check if the object that caused an event is a checkbox. This way you only bind one event handler. In jQuery you can use $.live event for this.
Don't recount every time a checkbox changes. Just use a global variable, like this:
var CheckboxesTicked = 0;
$(document).ready(function() {
CheckboxesTicked = $(":checkbox:checked").length;
$(":checkbox").change(function() {
if ($(this).is(":checked")) {
CheckboxesTicked += 1
} else {
CheckboxesTicked -= 1
}
});
});
Btw, the documentation states that you'd better use .length instead of .size() performance wise.
You could create a container element (like a Div with no styling) and attach the event handler to the container. That way, when the change() event happens on one of the checkboxes and percolates up the DOM, you'll catch it at the container level. That's one way to make this faster.
You should use .delegate(). One binding on a parent element can replace all the individual bindings on the child elements. It's perfect for this situation (and also solves the problem of attaching behavior to dynamically-added elements, should the need arise).
$('form[name=myForm]').delegate('input[name=myCheckbox]','change', function(){
var numChkd = $(this).siblings(':checked').length; // assuming siblings
console.log(numChkd);
});
This is how I would approach it:
$('form[name=myForm]').each(function() {
var $form = $(this),
$boxes = $form.find('input[name=myCheckbox]');
$form.delegate('input[name=myCheckbox]', 'change', function() {
var numChkd = $boxes.filter(':checked').length;
console.log(numChkd);
});
});
This takes advantage of caching the $boxes selection. It will look for all the boxes when it sets up the event. It uses .delegate() to attach an event to the form which will get fired anytime an child input[name=myCheckbox] creates a change event. In this event handler, you can easily filter the already obtained list of checkboxes by which ones are :checked and get the length of the matched elements. (The documentation for .size() basically states there is no reason to ever use it... It just returns this.length anyway...)
See this fiddle for a working demo
demo: http://jsfiddle.net/kKUdm/
$(':checkbox').change(function(){
if($(this).is(':checked')){
var name = $(this).attr('name');
var value = $(this).val();
console.log(name + ':' + value);
}
});
Var $chks = $(":checkbox");
Var ChkCount =0;
Var chktimer =0;
Function updateChkCount(){
ChkCount = $chks.filter(":checked").length;
$chks.end();
// do something witb ChkCount
}
$chks.bind("check change", function(){
clearInterval(chktimer);
chktimer = setInterval("updateChkCount()",250);
});