Referencing Ajax-Loaded Element in JS Object Instance - javascript

How do you reference an element that doesn't exist yet from within a JavaScript object instance?
var Dynamic = function(el) {
this.$instance = $(el);
}
var dynamicInstance = new Dynamic('#dynamic');
Since the #dynamic element is loaded via Ajax, the script doesn't see it when dynamicInstance is created and can't reference it.
If it helps solve the issue, I could also reference the element from inside the object without passing it in when it's created -- but am still unclear on how to make the object aware of the element.

If you want to keep things decoupled you can accept a callback function as a parameter and call it once the new element is loaded and appended to the dom
function doAjaxCall(callback) {
$.ajax({
success : function(response) {
//Logic to create the new element based on response
callback();
}
});
}
doAjaxCall(function() {
var dynamic = new Dynamic('#dynamic');
});
In that way you keep everything decoupled while avoiding the race condition created by ajax calls.

Related

Detect when a function is getting called in JavaScript

There are several elements on HTML page which triggers a js function HardCoded().
I cannot modify HardCoded() function.
I want to run some custom js code after the HardCoded() function is getting called. How can I do that? Is there any handlers for js functions?
I'm building a chrome extension that's why I cannot modify page source code.
I have access to JQuery.
One way is to find all elements who are calling HardCoded() and attach events to those elements but I would like to avoid this method.
You could do something like this:
var oldFn = HardCoded;
window.HardCoded = function(){
var res = oldFn.apply(this, arguments);
// New Code ....
return res;
}
What this does is to create a reference to the HardCoded function, redefine this function and then call the old implementation using the previously created reference.

Jquery Multiple Click Events

I am dynamically creating objects which construct a view and bind events to the constructed view when clicked. However, the click event is always attaching itself to the last created object. I do want to have the same click event for each object, but the data that I am passing to a new class is unique per instance.
Object creation:
$.each(data,function(i,json)
{
var channelWrapper = new ChannelDisplayView(that.channelContainer, json);
that.channelContainer.append(channelWrapper.createView());
});
ChannelDisplayView.js
function ChannelDisplayView(parent, data){
this.parent = parent;
this.data = data;
}
ChannelDisplayView.prototype.createView = function(){
this.channelWrapper = $("<div/>").addClass("channelDisplay").attr("id", this.data.fullName);
this.channelTitle = $("<div/>").addClass("channelTitle").html(this.data.fullName);
this.channelSource = $("<div/>").addClass("sourceType").html(this.data.sourceType);
this.channelWrapper.append(this.channelTitle);
this.channelWrapper.append(this.channelSource);
that = this;
this.channelWrapper.unbind().on("click",function(event){
ControllersSingleton.getInstance().getProgramController().setupPage(that.data);
});
return this.channelWrapper;
}
As you can see each class will hold its own JSON data and this should be used to pass to an instance of another controller if the "div" is clicked. The data being sent no matter what div I click is always from the last created object.
Am I missing something obvious here?
It looks like you have created a global that which on each loop iteration is being overwrote with that = this.
Instead of calling append on that.channelContainer try using the instance you have created like channelWrapper.channelContainer.append.... channelWrapper is scoped to the loop iteration.
You can bind an event handler to your whole document and listen for all events of a certain type, responding with a callback if the event target matches a certain selector. For instance:
$(document).on('click', '.some-class', function(e){
console.log('.some-class element clicked.');
});
That code will listen for any clicks on the document, and if the target matches the selector in the second parameter, it will execute the callback function in the third parameter.
I often find it best to use a method like this when I am dynamically adding elements to the DOM.

Maintaining the jquery object in ajax post

I want to maintain the datatable object in ajax call. Please refer below code
$(function(){
function applyDataTables(options) {
//datatable object
var $datatable = $("#table1").dataTable(options);
if (some condition) {
this.dataTableObj = [];
this.dataTableObj.push($datatable);
} else {
$datatable = dataTableObj[0];
}
...............................................
}
})();
first time page load, it will call this function and find some datatable object after that am making some ajax post that time also it will trigger the same function and finding the datatable object.
so, i want to maintain the $datatable object when the page loaded first time, during some ajax posts i want to use this same object for other purpose how can i maintain the $datatable object in ajax post.
if i add that object to "this.dataTableObj" i can able to get the value of old object in ajax post.whether it is correct way of maintaining existing object in javascript.
Thanks,
Well "this" always refers to calling object.
but if you call
applyDataTables(options) //this will be window object;
and it can be overridden using call, apply or bind method
applyDataTables.call(someObj,options) //this will point to someObj
In your function this can be confusing.
Plus if you are passing it to some callback this can be overriden by call or apply method.
So instead of storing datatableObj in this you can store it on some global namespacing whose scope will be on all ajax call.
You may define
var globV={
dataTableObj:[]
};
//you can use different namespacing too instead of globV
$(function(){
function applyDataTables(options) {
//datatable object
var $datatable = $("#table1").dataTable(options);
if (some condition) {
globV.dataTableObj = [];
globV.dataTableObj.push($datatable);
} else {
$datatable = globV.dataTableObj[0];
}
...............................................
}
})();

Customising a JQuery Element

Is it inadvisable to add methods to a JQuery element?
eg:
var b = $("#uniqueID");
b.someMethod = function(){};
Update
Just to clarify, I am working on a JS-driven app that is binding JSON data to local JS objects that encapsulate the business logic for manipulating the actual underlying DOM elements. The objects currently store a reference to their associated HTML element/s. I was thinking that I could, in effect, merge a specific instance of a jquery element with it's logic by taking that reference add adding the methods required.
Well, there's nothing inherently wrong with it. It is, however, pretty pointless. For example:
$('body').someMethod = function(){};
console.log($('body').someMethod); // undefined
You are attaching the new function only to that selection, not to all selections of that element.
What you should do instead is to add a new function to jQuery.fn, which is a shortcut for jQuery.prototype:
jQuery.fn.someMethod = function() {
if (this[0].nodeName == 'body') {
// do your function
}
return this; // preserve chaining
};
The problem is that your function would be quite transient. A further requery and it will be gone. You can extend the jQuery object itself by $.fn.someMethod = function() {} and this method will be available for all queries.
$.fn.someMethod = function() {}
var b = $("body");
b.someMethod();
Or you can create a jQuery plugin. You can define a plugin this way:
$.fn.someMethod = function(options) {
# ...
});
Call it using $('body').someMethod();

Javascript scope help

I am relatively new to javascript so please be patient if what i am asking is completely stupid!
I am trying to make a simple module. Inside the module i want to have a config object that holds settings for the module. I am also using jquery. The jquery selectors work only when in a function directly in the main object/module.
I understand that javascript has functional scope so I am suprised that I cannot use the jquery selectors anywhere inside the module.
EDIT:
I want to be able to directly set all of my configs inside the configs object using jquery selectors. This way i keep all the messy stuff inside one place and can then access configs.whatever throughout the rest of the module. At the moment jquery selectors do not work inside the configs module.
var OB = function() {
var configs = {
'mode' : 'test',
'numOfSelects' : $('.mySelect').find('select').length, // This doesnt work
}
var getMode = function() {
return configs.mode;
}
function init() {
alert(configs.numOfSelects); // This alerts 0 until the following line
alert($('.mySelect').find('select').length); // This correctly alerts 2
};
var handlers = {
successHandler : function() {
alert("Success");
},
errorHandler : function() {
alert("error");
}
}
return {
init : init,
getMode : getMode
}
}( );
$(document).ready(function(){
OB.init();
});
It isn't that jQuery isn't in scope — that's that the code isn't executing when you think it is. The variable config is defined when that anonymous function (var OB = function() {}()) is executed. The DOM isn't ready yet, so that DOM traversal doesn't find anything. When you do the DOM traversal in init(), that isn't executed until it's explicitly called inside the $(document).ready() handler, at which point that DOM is set up. That's the difference you're seeing.
OB() needs to be called after the DOM has completely loaded. Hence the answer by Marcelo, which calls OB() in the ready() method.
EDIT: It's funny that my original answer below was incorrect because I didn't notice two little parentheses at the end of the definition of OB, and it turns out that these are the culprit. You define and then immediately invoke OB, which is before the DOM has been fully loaded. Remove those parentheses and make the change I suggest below.
Calling OB() returns an object with init and getMode, but you haven't called OB(), you've only referred to OB. Try this instead:
$(document).ready(function(){
OB().init();
});
Also, I assume you want to later refer to getMode. In particular, you will to get the copy of getMode that has access to the same local scope that your init() call had access to. To achieve this, you will need to store the result of calling OB() for later use:
var ob;
$(document).ready(function(){
ob = OB();
ob.init();
});
function some_other_function() {
... ob.getMode() ...;
}

Categories

Resources