Javascript calling other function without reason - javascript

I want to attach an event to a button and if user clicks, an alert should appear. But here, even if the user doesnt click, the alert appears.
Js File :
var init = function (m) {
_m = m;
var actionButton = document.getElementById("action");
if (actionButton) {
var buttonId = "action";
if (actionButton.attachEvent) {
actionButton.attachEvent("onclick", _onActionClick(buttonId));
}
}
var _onActionClick = function (buttonId) {
alert("3");
}
Here, I get alert 3.
But, with this code, I do not get alert 3.
var init = function (m) {
_m = m;
var actionButton = document.getElementById("action");
if (actionButton) {
var buttonId = "action";
if (actionButton.attachEvent) {
actionButton.attachEvent("onclick", _onActionClick);
}
}
var _onActionClick = function (){
alert("3");
}
Can someone, let me know where am I going wrong ?

onclick needs a function. You're using the return value of _onActionClick(buttonId) which is undefined
// no good!
actionButton.attachEvent("onclick", _onActionClick(buttonId));
Try using an actual function
actionButton.attachEvent("onclick", function(event) {
_onActionClick(buttonId)
})
Or you can define _onActionClick in curried form
var _onActionClick = function(buttonId) {
return function(event) {
console.log(buttonId, event)
}
}
// now when you call _onActionClick(buttonId) it will return a function ...
actionButton.attachEvent("onclick", _onActionClick("action"))

Related

javascript DOM object (window) extended property is null on page reload after being idle

I have a custom extended property attached to the window object in JavaScript as follows:
Community.js
(function (window, document, $) {
'use strict';
var containerScrollPositionOnHideList = [];
var scrollToTopOnShowContainerList = [];
var userProfileInfo = {};
window.Community = $.extend({
//init
init: function () {
var Site = window.Site;
Site.run();
this.enableHideShowEventTrigger();
},
setUserInfo: function (userObj) {
if (UtilModule.allowDebug) { debugger; }
window.localStorage.setItem('userInfo', JSON.stringify(userObj));
var d = new $.Deferred();
$.when(this.initUserProfile(userObj.UserId)).done(function () {
d.resolve("ok");
});
},
getUserInfo: function () {
var userJson = window.localStorage.getItem('userInfo');
var userObj = JSON.parse(userJson);
return userObj;
},
})(window, document, jQuery);
The problem is that this extension property window.Community is null in certian scenarios when i refresh the page which i am going to describe below along with flow of code.
and here is a module in JavaScript to force reload scripts even if they are cached every time the page is refreshed as my code heavily depends on javascript calls so I just enabled it to make sure while I am still writing the code page reloads every time, the code is below as follows:
Util.js
var UtilModule = (function () {
var allowDebug = false;
var currentVersion = 0;
var properlyLoadScript = function (scriptPath, callBackAfterLoadScript) {
//get the number of `<script>` elements that have the correct `src` attribute
//debugger;
var d = $.Deferred();
$('script').each(function () {
console.log($(this).attr('src'));
});
if (typeof window.Community == 'undefined') {
//debugger;
console.log('community was undefined till this point');
//the flag was not found, so the code has not run
$.when(forceReloadScript(scriptPath)).done(function () {
callBackAfterLoadScript();
d.resolve("ok");
});
}
else {
console.log('Community loaded already and running now : ' + scriptPath);
callBackAfterLoadScript();
}
return d.promise();
};
var forceReloadScript = function (scriptPath) {
if (UtilModule.allowDebug) { debugger; }
var d = $.Deferred();
initCurrentVersion();
var JSLink = scriptPath + "?version=" + currentVersion;
var JSElement = document.createElement('script');
JSElement.src = JSLink;
JSElement.onload = customCallBack;
document.getElementsByTagName('head')[0].appendChild(JSElement);
function customCallBack() {
d.resolve("ok");
}
return d.promise();
};
var enableDebugger = function () {
allowDebug = true;
};
var disableDebugger = function () {
allowDebug = false;
};
var debugBreakPoint = function () {
if (allowDebug) {
}
};
var initCurrentVersion = function () {
if (currentVersion == 0) {
var dt = new Date();
var ttime = dt.getTime();
currentVersion = ttime;
}
};
var getCurrentVersion = function () {
return currentVersion;
};
return {
forceReloadScript,
properlyLoadScript,
enableDebugger,
disableDebugger,
debugBreakPoint,
allowDebug,
getCurrentVersion
};
})();
Note: I have made deferred objects to resolve only when the JSElement.onload has been called successfully. This step was taken just for testing purpose to make sure that I am not missing something before reaching a point to call the method where I am getting an error.
After that the code where I load scripts using UtilModule in my layout file look like as below:
_Layout.cshtml
<script src = "~/Scripts/Application/Modules/Util.js" ></script>
<script>
$.when(
UtilModule.properlyLoadScript('/Scripts/Application/Community.js', () => {
// Community.init() was supposed to be called here but i was still getting the error so i implemented this using promise that is returned from properlyLoadScript and call Community.init() further in .done callback to make sure that script is properly loading till this point.
//window.Community.init();
})
).done(function() {
window.Community.init();
});
</script>
#RenderSection("scripts", required: false)
Now coming to my main file where My index file is executing having (_layout.chsmtl) as parent layout
is
Index.cshtml
#{
ViewBag.Title = "My Blog";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<article id="BlogPage" style="margin: 5px;">
</article>
#section scripts{
<script type="text/javascript">
$(document).ready(function () {
$.when(UtilModule.properlyLoadScript('/Scripts/Application/Modules/Blog.js', () => {
})).done(function () {
BlogModule.init();
});
});
//});
</script>
}
from what I know is that #section scripts is executed only once all the scripts in the layout page are loaded first so seems like a safe place to initialize the code which is dependent on some script in _Layout.HTML file and further enclosed with $(document).ready() for testing just to make sure that this script loads after everything else is loaded already.
Note: I am running all this code in in-cognito mode in chrome so nothing is cached while this code is running
now my Blog.js file looks like as below
var BlogModule = (function () {
var moduleReference = this;
var PageId = "#BlogPage ";
var currentUser;
var BlogPostList = [];
var blogPostInfo = {};
//init
var init = function () {
if (UtilModule.allowDebug) { debugger; }
//This is where the problem happens
console.log(window.Community);
console.log(window.Community.getUserInfo());
currentUser = window.Community.getUserInfo();
initBlogInformation();
//window.Community.registerModule(BlogModule);
if (Object.keys(window.Community.getUserProfileObject()) <= 0) {
$.when(window.Community.initUserProfile(currentUser.UserId)).then(function () {
$.when(initBlogInformation()).done(function () {
//debugger;
console.log(BlogPostList);
window.WidgetManager.populateWidget(PageId, moduleReference);
loadBlogPostWidget();
loadBlogViewWidget();
loadBlogCommentsWidget();
});
});
}
else {
$.when(initBlogInformation()).done(function () {
window.WidgetManager.populateWidget(PageId, moduleReference);
loadBlogPostWidget();
loadBlogViewWidget();
loadBlogCommentsWidget();
});
}
};
var loadBlogIndexMenuWidget = function () {
if (UtilModule.allowDebug) { debugger; }
};
var loadBlogPostWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogPostWidget";
widgetOptions.container = PageId + "#BlogPostWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
}
var loadBlogViewWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogViewWidget";
widgetOptions.container = PageId + "#BlogViewWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
};
var loadBlogCommentsWidget = function () {
var widgetOptions = {};
widgetOptions.type = "BlogCommentsWidget";
widgetOptions.container = PageId + "#BlogCommentsWidgetContainer";
var settings = {};
settings.UserId = 1;
widgetOptions.settings = settings;
window.WidgetManager.loadWidget(widgetOptions);
};
var initBlogList = function () {
$.when(getBlogPosts()).then(function (results) {
if (UtilModule.allowDebug) { debugger; }
BlogPostList = results.Record;
console.log(BlogPostList);
});
};
var getBlogPosts = function () {
if (UtilModule.allowDebug) { debugger; }
var d = new $.Deferred();
var uri = '/Blog/GetBlogPosts?userId=' + currentUser.UserId;
$.post(uri).done(function (returnData) {
if (UtilModule.allowDebug) { debugger; }
if (returnData.Status == "OK") {
BlogPostList = returnData.Record;
BlogPostList.map(x => {
if (UtilModule.allowDebug) { debugger; }
x.UserName = window.Community.getUserProfileObject().UserName;
if (x.Comments != null) {
x.CommentsObject = JSON.parse(x.Comments);
x.CommentsCount = x.CommentsObject.length;
}
});
console.log(returnData.Record);
d.resolve("ok");
} else {
window.Community.showNotification("Error", returnData.Record, "error");
d.resolve("error");
}
});
return d.promise();
};
var initBlogInformation = function () {
//debugger;
var d = $.Deferred();
getBlogPosts().then(getBlogModelTemplate()).then(function () {
d.resolve("ok");
});
return d.promise();
};
//Get Blog Model
var getBlogModelTemplate = function () {
var d = new $.Deferred();
var uri = '/Blog/GetBlogModel';
$.post(uri).done(function (returnData) {
blogPostInfo = returnData.Record;
d.resolve("ok");
});
return d.promise();
};
return {
init: init,
};
})();
The error I have highlighted below
so the problem is in init function of BlogModule which is BlogModule.init() the page is idle for too long and I reload it I get the following error:
cannot call
window.Community.getUserInfo() of undefined implying that community is undefied
after couple of refreshes its fine and the issue doesn't happen unless I change reasonable portion of code for js files to be recompiled again by browser or the browser is idle for too long and I am not able to understand what is triggering this issue.
below is log from console
p.s. error occurs more repeatedly if i refresh page with f5 but happens rarely if i refresh page with ctrl + f5
Please any help would be of great value
Answering my own question, took a while to figure it out but it was a small mistake on my end just fixing the following function in Util.js fixed it for me
var properlyLoadScript = function(scriptPath, callBackAfterLoadScript) {
//get the number of `<script>` elements that have the correct `src` attribute
//debugger;
var d = $.Deferred();
$('script').each(function() {
console.log($(this).attr('src'));
});
if (typeof window.Community == 'undefined') {
//debugger;
console.log('community was undefined till this point');
//the flag was not found, so the code has not run
$.when(forceReloadScript('/Scripts/Application/Community.js')).done(function() {
//debugger;
$.when(forceReloadScript(scriptPath)).done(function() {
callBackAfterLoadScript();
});
d.resolve("ok");
});
} else {
console.log('Community loaded already and running now : ' + scriptPath);
$.when(forceReloadScript(scriptPath)).done(function() {
callBackAfterLoadScript();
});
}
return d.promise();
};

How to trigger a function with multiple Event Handler (change)

I would like to add the condition, that the function is only triggered if both
addEventListener('change', SwitchG) Events are True (=both have changed).
The code which I use currently activates the function already when one of the two has changed.
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
You need another variable, which checks if both have been changed and only executes the handler function if both changes already happened:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = 0; // <-- this tracks changes
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
countChanges += 1; // <-- count up
if (countChanges >= 2) {
countChanges = 0; // <-- reset (if needed)
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
A more robust implementation however, also tracks the elements which changed and ensures a repeating change event from a single element won't succeed to run the handler.
For example with this utility:
function ChangedCounter (minChanges) {
var elements = new Set();
return {
changed(element) {
elements.add(element);
},
clear() {
elements.clear();
},
isReady() {
return elements.size >= minChanges;
}
};
}
You'd write it like this:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = ChangedCounter(2);
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
countChanges.changed(e.target);
if (countChanges.isReady()) {
countChanges.clear();
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
You could create a "state" to store when the both has changed. I've created two variables, halloState and hallo1State. The snippet below shows how it could be done:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var halloState = false;
var hallo1State = false;
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
if(e.target.id === "S131_01") halloState = true;
else if(e.target.id === "S130_01") hallo1State = true;
if(halloState && hallo1State){
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
.css {
background-color:red;
}
<input id="S131_01" type="text"/>
<input id="S130_01" type="text"/>
<button id="submit">Submit</button>

why validate function invoke after page refresh and nothing happen on click

var asign = function(id){
return document.getElementById(id) ;
} ;
var f_name = asign('fname').value ;
var validate = function (a) {
this.a = a ;
if(!a){
alert("Somthing is require");
} else if(a.length<6){
alert("characters should be minimum 6") ;
}
}
asign('submit').addEventListener('click',validate(f_name),false) ;
validate function invoke in page refresh and after click the button nothing happen validate function nothing happen
You need pass reference to function as a argument in addEventListener but not call it,
1.you can wrap your code to function like this
asign('submit').addEventListener('click', function () {
validate();
}, false);
2.or use .bind
asign('submit').addEventListener('click', validate.bind({}), false);
Example
var asign = function(id) {
return document.getElementById(id);
};
var validate = function () {
var a = asign('fname').value;
if (!a) {
alert("Somthing is require");
} else if (a.length < 6) {
alert("characters should be minimum 6");
}
}
asign('submit').addEventListener('click', validate.bind({}), false);
<input id="fname">
<button id="submit">submit</button>

Send a variable to jquery function

I have been trying to pass a variable to _F.search in this but no luck, can someone please help?
(function(window, $) {
// 'use strict';
//setInterval(function () {alert("Hello")}, 3000);
var StreamTable = function(container, opts, data) {
return new _StreamTable(container, opts, data);
};
_F.search = function(text){
alert("search " + text);
var q = $.trim(text), count = 0;
// alert(this.last_search_text);
if (q == this.last_search_text) return;
this.last_search_text = q;
if(q.length == 0 ){
this.render(0);
}else{
this.searchInData(q);
this.render(0);
}
this.current_page = 0;
this.renderPagination(this.pageCount(), this.current_page);
this.execCallbacks('pagination');
};
}
I tried
onclick ="window.search(5)"
from a click button but still did not work.
The search function should be declared like this:
window.search = function(text){
This will attach the search function to the window object. This will allow you to attach it to the onclick event, like you have in your example:
onclick="window.search(5)"

reaching the btn event outside the revealing patterned applied class

I have an revealing patterned applied class.How can I reach btnMenu event outside of the model
thanks.
MyModel= (function () {
var btnClickEvents = function () {
var btnMenu = $('.btnMenu').on('click', function () {
var date= $(this).attr("data-rezerve-date");
var statu= $(this).attr("data-rezerve-statu");
alert("click"+date+'---'+statu);
});
};
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: btnClickEvents.btnMenu//how can I reach this function outside of model
};
})();
update
I change my code as u show.and add one return function
MyModel = (function () {
var dt = "";
var statu = "";
var rvalue = {};
var btnClickEvents = function () {
$('.btnMenu').on('click', onBtnMenuClick);
};
function onBtnMenuClick(e) {
dt = $(this).attr("data-rezerve-date");
statu = $(this).attr("data-rezerve-statu");
rvalue.date = dt;
rvalue.statu = statu;
console.log(dt);
}
var getRezervationDateAndStatus = function () {
return rvalue;
};
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: getRezervationDateAndStatus
};
})();
and after include my module to my web page calling is like this,
MyModel.asignValues(rezervasyonTable,data);
MyModel.initialize();
var result = MyModel.getRezervationDateAndStatus();
console.log(result.date);
bu console log empty.
As you say it is a " revealing" pattern. You could see what you expose. To be able to use this function outside of the module change your code like this:
MyModel = (function () {
var btnClickEvents = function () {
$('.btnMenu').on('click', onBtnMenuClick);
};
function onBtnMenuClick(e) {
var date = $(this).attr("data-rezerve-date");
var statu = $(this).attr("data-rezerve-statu");
alert("click" + date + '---' + statu);
}
return {
initialize: initialize,
asignValues: asignValues,
getRezervationDateAndStatus: onBtnMenuClick
};
})();

Categories