Javascript MVC Controller and Click Events - javascript

I'm having a problem with the click events not working using a Javascript MVC Controller.
TEST.Assignments.AssignmentsController = function (element) {
var elements = {
activeAssignmentsPanel: $('#lpn-activeAssignments_Cont'),
assignmentViewLink: $("#lpn-activeAssignments_Cont table tr th a")
};
var _this = this;
var model = new TEST.Assignments.AssignmentModel();
this.buildAssignmentsList = function () {
var assignments = model.getActiveAssignmentsList({
assignmentMode: "active",
mock: true,
success: function (data) {
dust.render("ActiveAssignmentsPanel", data, function(err, out) {
elements.activeAssignmentsPanel.append(out);
});
}
});
};
this.getAssignmentDetails = function(assignmentId) {
console.log(assignmentId);
};
//bind all events
elements.assignmentViewLink.click(function (e) {
console.log("blah");
console.log($(this).data("assignmentKey"));
});
};//end assignments controller
$(function () {
var assignmentsController = new TEST.Assignments.AssignmentsController();
assignmentsController.buildAssignmentsList();
});
If you look at the //bind events, I have a click function there that should be working. But it is not. The constructor is being called and the elements are traced out correctly. Any idea why the click event won't work?

I assume the assignmentViewLink elements are created and appended in the success callback. If so, it looks like a sequence problem. When you bind the click event, the assignmentViewLink elements have not been created yet, and hence, the click eventhandler isn't attached.
//bind all events
// assignmentViewLink is empty []
elements.assignmentViewLink.click(function (e) {
console.log("blah");
console.log($(this).data("assignmentKey"));
});
To verify this, move the elements.assignmentViewLink(...) into the success callback.

Related

Jquery .change() event fires only once

So I'm fairly novice with jquery and js, so I apologise if this is a stupid error but after researching I can't figure it out.
So I have a list of data loaded initially in a template, one part of which is a dropdown box that lets you filter the data. My issue is that the filtering only works once? As in, the .change function inside $(document).ready() only fires the once.
There are two ways to reload the data, either click the logo and reload it all, or use the search bar. Doing either of these at any time also means the .change function never fires again. Not until you refresh the page.
var list_template, article_template, modal_template;
var current_article = list.heroes[0];
function showTemplate(template, data)
{
var html = template(data);
$("#content").html(html);
}
$(document).ready(function()
{
var source = $("#list-template").html();
list_template = Handlebars.compile(source);
source = $("#article-template").html();
article_template = Handlebars.compile(source);
source = $("#modal-template").html();
modal_template = Handlebars.compile(source);
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
$("#classFilter").change(function()
{
console.log("WOW!");
var classToFilter = this.value;
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.heroClass.search(classToFilter) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
$("#searchbox").keypress(function (e)
{
if(e.which == 13)
{
var rawSearchText = $('#searchbox').val();
var search_text = rawSearchText.toLowerCase();
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.name.search(search_text) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
}
});
$("#logo").click(function()
{
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
//$("#logo").click();
});
function displayModal(event)
{
var imageNumber = $(this).data("id");
console.log(imageNumber);
var html = modal_template(current_article.article[0].vicPose[imageNumber]);
$('#modal-container').html(html);
$("#imageModal").modal('show');
}
I should note two things: first, that the search bar works perfectly, and the anonymous function inside both of them is nearly identical, and like I said, the filtering works perfectly if you try it after the initial load. The second is that the same problem occurs replacing .change(anonymous function) with .on("change",anonymous function)
Any help or advice would be greatly appreciated. Thanks.
I agree with Fernando Urban's answer, but it doesn't actually explain what's going on.
You've created a handler attached to an HTML element (id="classFilter") which causes part of the HTML to be rewritten. I suspect that the handler overwrites the HTML which contains the element with the handler on it. So after this the user is clicking on a new HTML element, which looks like the old one but doesn't have a handler.
There are two ways round this. You could add code inside the handler which adds the handler to the new element which has just been created. In this case, that would mean making the handler a named function which refers to itself. Or (the easier way) you could do what Fernando did. If you do this, the event handler is attached to the body, but it only responds to clicks on the #classFilter element inside the body. In other words, when the user clicks anywhere on the body, jQuery checks whether the click happened on a body #classFilter element. This way, it doesn't matter whether the #classFilter existed when the handler was set. See "Direct and delegated events" in jQuery docs for .on method.
Try to use some reference like 'body' in the event listeners inside your DOM like:
$('body').on('click','.articleButton', function() {
//Do your stuff...
})
$('body').on('click','#classFilter', function() {
//Do your stuff...
})
$('body').on('keypress','#searchbox', function() {
//Do your stuff...
})
$('body').on('click','#logo', function() {
//Do your stuff...
})
This will work that you can fire it more than once.

Kendo Observable Change event

I have a kendo Obervable as follows:
var ViewModel = kendo.observable({
ID: 1,
TITLE: "SomeValue",
});
and then I have bound this as follows:
kendo.bind($(".bind-view"), ViewModel );
Now there is button on the page. When clicked I need to check if there are any changes to this ViewModel.
I have tried
$(".ClearAnalysisInfo").on('click', function (event) {
ViewModel.bind("change", function (e) {
//Some code
});
});
But I'm not able to get this ViewModel property whether it changed or not.
Binding the ObservableObject's change event of inside the button's click handler is too late. You need to do that immediately after the ObservableObject is created.
Inside the change handler, you will receive information about the changed field. Use this information to raise some JavaScript flag or save the details you need, so that you can use them later in the button's click handler.
var viewModelChanged = false;
var ViewModel = kendo.observable({
ID: 1,
TITLE: "SomeValue",
});
ViewModel.bind("change", function (e) {
viewModelChanged = true;
});
$(".ClearAnalysisInfo").on('click', function (event) {
if (viewModelChanged) {
// ...
}
});

Unbinding a single event from within a prototype structure

I am trying to unbind an event handler that has been added to an object's prototype. The (cut-down) code in question is:
MyClass.prototype.bindEvents = function() {
var thisObj = this;
this.$tabs.on("click", function(e) {
return thisObj.handleTabClick($(this), e);
});
}
MyClass.prototype.unbindEvents = function() {
this.$tabs.off("click", this.handleTabClick);
}
MyClass.prototype.handleTabClick = function($tab, e) {
// do something
}
I know that I can (and did) complete clear the click event by doing
this.$tabs.off("click");
but there is another event handler on there which I wish to keep.
How do I unbind a single event within the prototype structure?
You can add a namespace to the event when you create it which you can then specifically reference when you remove the event handler. try this:
MyClass.prototype.bindEvents = function() {
var thisObj = this;
this.$tabs.on("click.foo", function(e) {
return thisObj.handleTabClick($(this), e);
});
}
MyClass.prototype.unbindEvents = function() {
this.$tabs.off("click.foo");
}
For more information see the 'Event names and namespaces' section of http://api.jquery.com/on/
Also note that your method of passing the click handler through an anonymous function to the handleTabClick function is redundant, you can simply do this:
this.$tabs.on("click.foo", thisObj.handleTabClick);
MyClass.prototype.handleTabClick = function(e) {
var $tab = $(this);
// do something
}

User-defined callback function is being fired multiple times in Javascript/jQuery

There are some similar questions, but they all seem like regarding native jQuery callback functions.
So I have this code which (live) creates a div containting some form elements.
Values of these elements should be retrieved inside a callback function when (before) the div is removed.
function popup(callback) {
// ...
// before removing the div
callback.call();
// remove div
}
Unexpectedly, the callback function is being fired multiple times (increasingly) after the first time popup is executed.
I have simplified the code, and here is the fiddle.
I hope this is what you need.
function popup(callback) {
$("body").append('<div><span id="test">test</span> close</div>');
$(document).on("click", "#close", function() {
callback.call();
//
//callback = function() {};
$(document).off("click", "#close");
$("div").remove();
});
};
$(document).on("click", "#open", function() {
popup(function() {
alert('$("#test").length = ' + $("#test").length);
});
});
Basically, you need to remove event handler by invoking off() method.
Try dynamically generating the elements instead of using a string. This will allow you to bind events easier.
function popup(callback)
{ var $elem = $("<div></div>");
$elem.append($("<span></span>").html("test"));
$elem.append(" ");
$elem.append($("<a></a>").html("close").attr("href", "#"));
$("body").append($elem);
$elem.find("a").click(function() {
callback.call();
$elem.remove();
});
};
$(document).on("click", "#open", function() {
popup(function() {
alert('$("#test").length = ' + $("#test").length);
});
});
Example: http://jsfiddle.net/4se7M/2/
I don't know the exact scenario, but why do you want to bind and unbind the event each time you show the popup?
You can bind only once, like this, can't you?
$(document).on("click", "#close", function() {
alert('$("#test").length = ' + $("#test").length);
$("div").remove();
});
function popup() {
$("body").append('<div><span id="test">test</span> close</div>');
};
$(document).on("click", "#open", function() {
popup();
});

Javascript Singleton design pattern and closure

I'm trying to create a Singleton object that deals with servicing an event listener:
var ChildParent = (function () {
var html_element = document.getElementById("quoteNum");
var row_number = 0;
return {
init: function(){
html_element["parenttype"+row_number].addEventListener("click", ChildParent.fire, false);
},
add: function(total) { //Adding a row
},
fire: function() {
alert("it fired!");
}
}
})();
However, when I call ChildParent.init(), the document-element will not get assigned to html_element, so i can't attach the listener. Oddly enough, the row_number variable is initialized to zero. Is there some sort of scoping conflict that I don't understand? When i use the step-into feature of opera's dragonfly, I can't create var assignments when in the init() function.
Make sure element with id "quoteNum" is available on the page when you are executing your script.
It may happen that you are executing the script without waiting for all the page elements to be rendered.
You may think about handling window.onload.
Update
the following change could help you fix the issue with html_element being initialized before the page is rendered.
var ChildParent = (function () {
function getElement(){
return html_element ? html_element : html_element = document.getElementById("quoteNum");
}
var html_element;
var row_number = 0;
return {
init: function(){
getElement()["parenttype"+row_number].addEventListener("click", ChildParent.fire, false);
},
add: function(total) { //Adding a row
},
fire: function() {
alert("it fired!");
}
}
})();
Is the above code executed after the element with id quoteNum exists in the DOM?
If not html_element will be null.
So make sure that all the above code is in a script tag that occurs somewhere in the document below the element (or is in a window.onload jQuery's document ready type event).

Categories

Resources