JavaScript: Not Calling Constructor Function - javascript

Can someone shed some light as to why this doesn't work the way I think it should (or what I'm overlooking).
function Pane(data) {
var state = {
show: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function(data) {
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
So I can console log Pane(arg).show/hide and it'll log it as a function, so why is it when I call Pane(arg).show it doesn't do anything? The functions in the object work (outside of the constructor function in their own functions).

The function is returning the state object, so it will never return the constructed object, even when used with new. Since state contains those methods, you can just call the function and immediately invoke one of the methods on the returned object.
Now, if you're expecting show and hide to automatically have access to data via closure, it's not working because you're shadowing the variable by declaring the method parameters. You can do this instead:
function Pane(data) {
var state = {
show: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
pane.classList.add('active');
},
hide: function() {
var data = data || arguments[0];
var pane = document.querySelector('.pane[data-content='+data.target+']');
var paneSibling = $(pane.parentNode.childNodes);
paneSibling.each(function(sibling) {
if(check.isElement(sibling)) {
var isActive = sibling.classList.contains('active');
if(sibling != pane && isActive) {
sibling.classList.remove('active');
};
};
});
}
}
return state;
}
Then you can use it like this:
Pane({}).show();
Or like this:
var p = Pane();
p.show();
Or force a new argument when needed:
p.show({foo:'bar'});

You are overriding the original argument in each function.
So what you are doing is to find elements with the attribute data-content='undefined'
This obviously doesn't work.
So to fix this you should just remove the data argument in the show/hide function.
Here is a plnkr showing the problem and fix.

Related

Object Passed to Callback Function Not Updating

I have a global object variable that I pass to a function, then I call another function and assign that return value to the variable which was passed to the original function. This return value does not propagate to the global object which was passed into the function for some reason.
var DEFAULT_OPTIONS = {...}
var optionsElements = new Object();
function initializeOptions(elements, optionsObject, defaultOptions) {
elements = getOptionsElements();
optionsObject = loadOptions(elements, defaultOptions);
document.getElementById("movie_categories").addEventListener("change",
function(event) {
onCategoryChange(elements, event);
});
document.getElementById("tv_categories").addEventListener("change",
function(event) {
onCategoryChange(elements, event);
});
}
initializeOptions(optionsElements, currentOptions, DEFAULT_OPTIONS);
The elements var inside initializeOptions gets set properly, why does it not update optionsElements? My understanding is that Objects are passed by reference, so it seems to me this should work.
function getOptionsElements() {
options = {
"all_movies": document.getElementById("all_movies"),
"movie_3d": document.getElementById("movie_3d"),
"movie_480p": document.getElementById("movie_480p"),
"movie_bd-r": document.getElementById("movie_bd-r"),
"movie_bd-rip": document.getElementById("movie_bd-rip"),
"movie_cam": document.getElementById("movie_cam"),
"movie_dvd-r": document.getElementById("movie_dvd-r"),
"movie_hd-bluray": document.getElementById("movie_hd-bluray"),
"movie_kids": document.getElementById("movie_kids"),
"movie_mp4": document.getElementById("movie_mp4"),
"movie_non-english": document.getElementById("movie_non-english"),
"movie_packs": document.getElementById("movie_packs"),
"movie_web-dl": document.getElementById("movie_web-dl"),
"movie_xvid": document.getElementById("movie_xvid"),
"all_tv": document.getElementById("all_tv"),
"tv_documentaries": document.getElementById("tv_documentaries"),
"tv_sports": document.getElementById("tv_sports"),
"tv_480p": document.getElementById("tv_480p"),
"tv_bd": document.getElementById("tv_bd"),
"tv_dvd-r": document.getElementById("tv_dvd-r"),
"tv_dvd-rip": document.getElementById("tv_dvd-rip"),
"tv_mp4": document.getElementById("tv_mp4"),
"tv_non-english": document.getElementById("tv_non-english"),
"tv_packs": document.getElementById("tv_packs"),
"tv_packs-non-english": document.getElementById("tv_packs-non-english"),
"tv_sd-x264": document.getElementById("tv_sd-x264"),
"tv_web-dl": document.getElementById("tv_web-dl"),
"tv_x264": document.getElementById("tv_x264"),
"tv_xvid": document.getElementById("tv_xvid"),
"sort_options": document.getElementById("sort_options")
}
return options;
}
so after I assign elements = getOptionsElements, elements no longer
points to optionsElements, but is now a reference to the object
created inside getOptionsElements?
Yes. Try passing elements to getOptionsElements , using for..in loop within getOptionsElements to set properties of elements : optionsElements , return elements from getOptionsElements
var optionsElements = new Object();
function initializeOptions(elements, optionsObject, defaultOptions) {
elements = getOptionsElements(elements);
return elements
}
function getOptionsElements(opts) {
options = {
"a":1,
"b":2,
"c":3
};
for (var prop in options) {
opts[prop] = options[prop];
}
return opts;
};
console.log(initializeOptions(optionsElements), optionsElements)

using revealling moduler pattern for complex in javascript

I have a very complex class so i decided to break into sub modules and trying to use revealing modules pattern.
I have main class and decided to divide into smaller container function. but in current scenario
But i am not able to access any internal function from outside i.e callSearchResultWithCallBack using searchFinder.Search.callSearchResultWithCallBack(). which pattern should i use to keep this code clean as well have control to call internal function in sub module.
Thanks
var searchFinder;
function SearchFinder() {
me = this;
this.searchResult = null;
this.init = function() {
declareControls();
createAccordian();
addEvents();
fillControls();
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
me.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
}
this.Search = function() {
var url = '';
var searchCriteria = {};
validateAndCreateCriteria();
callSearchResultWithCallBack();
function validateAndCreateCriteria() {
function validateAandGetCategory() {
if (SearchValidation.ValidateZipCode(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
} else if (SearchValidation.ValidateCityState(me.InputLocation.val().trim())) {
searchCriteria.location = me.InputLocation.val().trim();
}
}
}
// need to access it outsite
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
}
}
jQuery(function() {
searchFinder = new SearchFinder();
searchFinder.init();
searchFinder.Search.callSearchResultWithCallBack();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
This code has multiple issues, first I will address the fact that for example declareControls is not executing. First declare the function than execute!
this.init = function() {
var declareControls = function() {
this.SearchButtons = jQuery('.doSearch');
this.InputLocation = jQuery('#inputLocation');
this.InputDistanceWithIn = jQuery('#inputDistanceWithIn');
this.InputName = jQuery('#inputName');
}
var addEvents = function() {
this.SearchButtons.click(function() {
me.Search();
});
}
var fillControls = function() {
var getGetCategory = function() {
}
}
declareControls();
//createAccordian(); //not defined
addEvents();
fillControls();
}
Now let's look at others problems that will arise.
the me object referring to this is in the scope of searchFinder and does not refer to the same this in the instance of searchFinder.
function jQuery can be replaced by the commonly used $.
searchFinder.Search.callSearchResultWithCallBack() this is never going to work. Since the Search function is an object and callSearchResultWithCallBack isn't a property of this function.
Solution; make it part of the prototype of Search.
Steps:
Move callSearchResultWithCallBack outside the search function.
Add prototype to Search function
Call function via prototype.
function callSearchResultWithCallBack() {
me.searchResult(searchCriteria, SearchResultCallBack);
function SearchResultCallBack() {
}
}
this.Search.prototype.callSearchResultWithCallBack = callSearchResultWithCallBack;
If you want to fire this function outside of search use this:
searchFinder.Search.prototype.callSearchResultWithCallBack();
Please remember that callSearchResultWithCallBack will throw an error because searchCriteria is undefined.
This fixes your problems for now, but this code has to be revised thoroughly. But this should get you started. http://ejohn.org/blog/simple-javascript-inheritance/

How do I call a nested JavaScript function properly

I'm trying to set up function a nested function that I can call throughout my script, but I keep getting "error undefined is not a function". Perhaps someone can help me with how to do this correctly.
First I set global my variables:
var trigger = document.getElementById('trigger');
var subject = document.getElementById('subject');
Then I create a show/hide function:
var toggleVis = function() {
function showSomething() {
trigger.classList.add("active");
subject.classList.add("active");
}
function hideSomething() {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
}
Then I set my event listener:
trigger.addEventListener('click', function() {
if ( subject.classList.contains("active") ) {
toggleVis.hideSomething();
}
else {
togglePicker.showPicker();
}
});
The reason I'm trying to do it this way is that there will be other triggers for subject on the page that will need access to the show/hide functions.
You can't access the functions inside the function, they are out of scope, you could attach them as properties to the wrapping function, but it looks like you just need an object
var toggleVis = {
showSomething: function() {
trigger.classList.add("active");
subject.classList.add("active");
},
hideSomething: function() {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
}
Your togleVis variable is a function and not an object so you can't do toggleVis.hideSomething(). Try updating your code to :
var toggleVis = (function() {
return {
showSomething : function () {
trigger.classList.add("active");
subject.classList.add("active");
},
hideSomething : function () {
trigger.classList.remove("active");;
subject.classList.remove("active");
}
};
}());
With this toggleVis is now an object with two properties showSomething and hideSomething functions.

JavaScript error when creating custom object

I am finding that when I call record.create() then sometimes it succeeds, and at other times it throws an error saying that no such method exists, even though record object has its properties set appropriately.
Am I using create method incorrectly? May be I am missing something about JavaScript custom object syntax.
<script language="javascript" type="text/javascript">
var record = {
RecordID : null,
CustomerID : null,
CompanyID : null,
create : function() {
var obj = new Object();
obj.RecordID = "";
obj.CustomerID = "";
return obj;
}
};
function pageLoad(sender, eventArgs) {
{
//*******SUCCEEDS********
record = record.create()
}
function RadGrid1_RowSelected(sender, args) {
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
record= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}
</script>
UPDATE : This is what worked for me.
Instead of using the create method on 'record' global object, I ended up using a simple approach. Just call a custom method 'resetRecord' everytime I wanted to call the create( ) method on record object. That way I have no errors and my logic works perfectly.
function resetRecord() {
record.RecordID = "";
record.CustomerID = "";
record.CompanyID = "";
}
It won't work after the first call because you are overwriting the record object. This will destroy any create() method as the object returned does not have this method/property.
For you update, variables have function level scope. You are using the global record inside of RadGrid1_RowSelected.
I'm not entirely sure what you are doing but this will get you past your first problem.
function RadGrid1_RowSelected(sender, args) {
var newRecord;
currentRowIndex = args.get_gridDataItem().get_element().rowIndex;
var dataItem = args.get_gridDataItem().get_dataItem();
recordId = dataItem["Record_ID"];
if (tableView.get_selectedItems().length == 1) {
record = record.create();
record.RecordID = dataItem["Record_ID"];
record.CustomerID = dataItem["Customer_ID"];
setValues();
}
else if (tableView.get_selectedItems().length > 1) {
newRecord= record.create();//****FAILS ALWAYS even when record object has non-null properties*******
}
if ($.inArray(recordId, recordIds) == -1) {
recordIds.push(recordId);
}
}

How can I pass results from a callback via an object?

I am performing a Google local search, and wish to return the lat/long via an object.
The Google search itself works fine.
When inspected (using console.log or alert()) in the object itself, the results field appears to be populated OK.
However, when inspecting the instance of the object (instantiated before running the callback) the result is blank. I'm aware I don't need the accessor function - the end result is the same either way.
Is there something fundamental missing here? Thanks!
function GeoSearch() {
this.results = [];
this.searchComplete = function(localSearch) {
if(localSearch.results[0]) {
var resultLat = localSearch.results[0].lat;
var resultLng = localSearch.results[0].lng;
this.results = localSearch.results[0].lat;
}
}
this.getResults = function() {
return this.results;
}
}
function populateCoords(postcode) {
var localSearch = new google.search.LocalSearch();
var gs = new GeoSearch();
localSearch.setSearchCompleteCallback(gs, gs.searchComplete, [localSearch]);
localSearch.execute(postcode + ", UK");
alert(gs.getResults());
}
When you reference the function gs.searchComplete, you're detaching the method from the object it belongs to. Switch it to function () { gs.searchComplete(); }

Categories

Resources