Hello I'm trying to get value of hidden element in my OOP function. Here is code:
var refreshTimeout;
var rms = new RMS();
rms.refresh();
function RMS() {
this.refresh = function(){
alert($("#ids").val());
$.post(refreshUrl, {ids: $("#ids").val()}, function(response){
var result = $.parseJSON(response);
if (result != null) {
$("#rms").attr("value", result.rms);
}
refreshTimeout = setTimeout(function() { rms.refresh(); }, 2000);
});
}
}
The problem is that $("#ids").val() works in firebug console but not inside rms.refresh()...
What I'm doing wrong?
Your invocation of $('#ids').val() looks fine, so long as the DOM is loaded at this point (i.e. inside a $(document).ready() block).
Your timer function looks a little suspect, though. You're referring to rms which is in the outer scope, when you should be referring to whatever the current object is.
Similarly your timer-related values should be properly encapsulated inside the class, since otherwise you can't have more than one instance.
// class definition - can be loaded anywhere
var RMS = function(ids, rms) {
var self = this;
var timer = null;
var delay = 2000;
this.refresh = function() {
$.post(refreshUrl, {ids: $(ids).val()},
function(response) {
var result = $.parseJSON(response);
if (result != null) {
$(rms).attr("value", result.rms);
}
timer = setTimeout(function() {
self.refresh();
}, delay);
}
);
};
};
// invocation deferred until the DOM is ready
$(document).ready(function() {
var rms = new RMS('#ids', '#rms');
rms.refresh();
});
Try this code:
$(document).ready(function(){
var refreshTimeout,
rms = new RMS();
rms.refresh();
function RMS() {
this.refresh = function(){
$.post(refreshUrl, {ids: $('#ids').val()}, function(response){
if (typeof(response) != 'undefined') {
$('#rms').attr('value', response.rms);
}
refreshTimeout = setTimeout(function() { rms.refresh(); }, 2000);
}, 'json');
}
}
});
Related
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();
};
I am trying to create an observableArray of "Board" objects to populate a view.
I can currently add new Board objects to the array after each timed page refresh. But instead of clearing the array and then adding new boards from the foreach loop, it just adds to the existing ones causing duplicates.
$(document).ready(function() {
refreshPage();
});
function refreshPage() {
getGames();
setTimeout(refreshPage, 10000);
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
this.HomeTeamImage = ko.observable(data.HomeTeamImage);
this.HomeTeamName = ko.observable(data.HomeTeamName);
this.HomeBeerPrice = ko.observable(data.HomeBeerPrice);
this.HomeTeamArrow = ko.observable(data.HomeTeamArrow);
this.HomeBeer = ko.observable(data.HomeBeer);
this.HomeBeerAdjustedPrice = ko.observable(data.HomeBeerAdjustedPrice);
this.AwayTeamArrow = ko.observable(data.AwayTeamArrow);
this.AwayBeerPrice = ko.observable(data.AwayBeerPrice);
this.AwayTeamName = ko.observable(data.AwayTeamName);
this.AwayBeerAdjustedPrice = ko.observable(data.AwayBeerAdjustedPrice);
this.AwayBeer = ko.observable(data.AwayBeer);
this.awayTeamImage = ko.observable(data.AwayTeamImage);
this.FullScore = ko.computed(function() {
return data.HomeTeamScore + " | " + data.AwayTeamScore;
}, this);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
}
getGames = function() {
var _vm = new vm();
$.ajax({
type: "GET",
dataType: "json",
url: "/Dashboard/PopulateMonitor/",
error: errorFunc,
success: function(data) {
_vm.gameCollection = [];
$.each(data, function() {
_vm.gameCollection.push(new Board(this));
});
}
});
function errorFunc() {
alert("Error, could not load gameboards");
}
ko.applyBindings(_vm);
}
The issue appears within the getGames() function on or around the line
_vm.gameCollection = [];
I appreciate any help available. Not very well versed with Knockout.js
Every time you're calling getGames you're creating a new '_vm':
getGames = function () {
var _vm = new vm();
Move var _vm = new vm(); to
$(document).ready(function () {
var _vm = new vm(); // <-- HERE
refreshPage();
});
Some lines have to be moved too, see the snippet :
$(document).ready(function() {
_vm = new vm();
refreshPage();
});
function refreshPage() {
getGames();
setTimeout(refreshPage, 10000);
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
this.HomeTeamImage = ko.observable(data.HomeTeamImage);
this.HomeTeamName = ko.observable(data.HomeTeamName);
this.HomeBeerPrice = ko.observable(data.HomeBeerPrice);
this.HomeTeamArrow = ko.observable(data.HomeTeamArrow);
this.HomeBeer = ko.observable(data.HomeBeer);
this.HomeBeerAdjustedPrice = ko.observable(data.HomeBeerAdjustedPrice);
this.AwayTeamArrow = ko.observable(data.AwayTeamArrow);
this.AwayBeerPrice = ko.observable(data.AwayBeerPrice);
this.AwayTeamName = ko.observable(data.AwayTeamName);
this.AwayBeerAdjustedPrice = ko.observable(data.AwayBeerAdjustedPrice);
this.AwayBeer = ko.observable(data.AwayBeer);
this.awayTeamImage = ko.observable(data.AwayTeamImage);
this.FullScore = ko.computed(function() {
return data.HomeTeamScore + " | " + data.AwayTeamScore;
}, this);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
ko.applyBindings(this);
}
getGames = function() {
$.ajax({
type: "GET",
dataType: "json",
// placeholder:
url: 'data:application/json;utf8,[]',
//url: "/Dashboard/PopulateMonitor/",
error: errorFunc,
success: function(data) {
_vm.gameCollection.removeAll();
$.each(data, function() {
_vm.gameCollection.push(new Board(this));
});
}
});
function errorFunc() {
alert("Error, could not load gameboards");
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
Couple of things:
You shouldn't call applyBindings more than once. So, move it outside of your setTimeout.
_vm.gameCollection = [] won't work. To clear your observableArray, use removeAll. You can also set it to an empty array like this: _vm.gameCollection([])
Also, if you want to call the same function after an interval of time, you can make use of setInterval.
Here's a minimal version of your code. Click on Run code snippet to test it out. I have created a counter variable which updates gameCollection with new data every second.
let counter = 0;
function refreshPage() {
getGames();
console.log("Page refreshed");
};
function Board(data) {
this.gameChannel = ko.observable(data.GameChannel);
}
function vm() {
var self = this;
self.gameCollection = ko.observableArray([]);
}
getGames = function() {
let data = [
{
GameChannel: `GameChannel ${++counter}`
},
{
GameChannel: `GameChannel ${++counter}`
}];
_vm.gameCollection.removeAll(); // <- Change here
data.forEach(function(item) {
_vm.gameCollection.push(new Board(item));
});
}
var _vm = new vm();
ko.applyBindings(_vm); // this needs to be only called once per page (or element)
setInterval(refreshPage, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko foreach: gameCollection -->
<span data-bind="text: gameChannel"></span><br>
<!-- /ko -->
I'm trying to clear an interval when the user hovers over an element and then start it up again when they hover off an element. I think this is a closure but I'm not sure, hopefully my code will make sense what I'm trying to do.
var rotatorInterval = function(elem){
var interval = setInterval(function(){
var active = elem.find('.dot.active');
if(active.is('.dot:last-of-type',elem)){
elem.find('.dot').first().click();
}else{
active.next().click();
}
},6000);
interval;
return interval;
};
if($('.rotator').length){
$('.rotator').each(function(){
var self = $(this);
rotatorInterval(self);
self.find('.slide, .dot').on('mouseenter',function(){
console.log('hovered');
clearInterval(interval);
});
});
}
I tried returning the interval from that closure but when I hovered it said interval (the name of the variable I returned) is not defined, so it's like it didn't return it or something.
You just have to actually return the interval reference somewhere
var rotatorInterval = function (elem) {
var interval = setInterval(function () {
var active = elem.find('.dot.active');
if (active.is('.dot:last-of-type', elem)) {
elem.find('.dot').first().click();
} else {
active.next().click();
}
}, 6000);
return interval;
};
if ($('.rotator').length) {
$('.rotator').each(function () {
var self = $(this);
var return_interval = rotatorInterval(self);
self.find('.slide, .dot').on('mouseenter', function () {
clearInterval(return_interval);
});
});
}
Probably a really easy question
I've been searching, but I could not find what window.h means? Only some articles about C++ but not about javascript.
view: {
fc: "",
init: function() {
var iframe = $("iframe")[0];
var focused = true;
var unfocusedTimeStart = null;
var unfocusedTime = null;
var loaded = false;
var prevent_bust = 0;
var done = false;
window.onbeforeunload = function() {
prevent_bust++;
};
setInterval(function() {
if (prevent_bust > 0 && !done) {
prevent_bust -= 2;
}
}, 1);
var mySwfStore = new SwfStore({
namespace: "BTCClicks",
swf_url: "/js/storage.swf",
onready: function() {
var fcookie = mySwfStore.get("fcookie");
var randomstring = md5(randomstring);
if (fcookie == null) {
mySwfStore.set("fcookie", randomstring);
}
fcookie = mySwfStore.get("fcookie");
if (fcookie != null) {
BTCClicks.view.fc = fcookie;
}
},
onerror: function() {}
});
$("#viewFrame").load(function() {
if (!loaded) {
$.post("/ajax/vrequest", {
ad: window.h,
fc: BTCClicks.view.fc
}).done(function() {
startTimer();
});
loaded = true;
}
});
Could someone explain what that means?
If refers to a variable named h in the global (window) scope
Whenever you make a global variable in JavaScript you can either refer to it by name or window.[variableName]
In this case you can either do
ad: window.h
or
ad: h
As long as there isn't another local variable named h
I have the following code snippet that controls an embedded youtube player. It works great on Chrome and Safari but not on Firefox.
jsfiddle : http://jsfiddle.net/fuSSn/4/
Code from my app:
the iframe:
<div class="tubeframe" id="video-frame-155" style="">
<iframe title="YouTube video player" width="350" height="262" src="http://www.youtube.com/embed/hc5xkf9JqoE?HD=1;rel=0;showinfo=0;autohide=1" frameborder="0" allowfullscreen="" id="video-frame-155-frame"></iframe>
</div>
my javascript:
var source_tag = document.createElement("script");
var first_source_tag = document.getElementsByTagName("script")[0];
first_source_tag.parentNode.insertBefore(source_tag, first_source_tag);
// This function will be called when the API is fully loaded
function onYouTubeIframeAPIReady() {
YT_ready(true)
console.log("api loaded! yikes")
}
function getFrameID(id){
var elem = document.getElementById(id);
if (elem) {
if(/^iframe$/i.test(elem.tagName)) return id; //Frame, OK
// else: Look for frame
var elems = elem.getElementsByTagName("iframe");
if (!elems.length) return null; //No iframe found, FAILURE
for (var i=0; i<elems.length; i++) {
if (/^https?:\/\/(?:www\.)?youtube(?:-nocookie)?\.com(\/|$)/i.test(elems[i].src)) break;
}
elem = elems[i]; //The only, or the best iFrame
if (elem.id) return elem.id; //Existing ID, return it
// else: Create a new ID
do { //Keep postfixing `-frame` until the ID is unique
id += "-frame";
} while (document.getElementById(id));
elem.id = id;
return id;
}
// If no element, return null.
return null;
}
// Define YT_ready function.
var YT_ready = (function(){
var onReady_funcs = [], api_isReady = false;
return function(func, b_before){
if (func === true) {
api_isReady = true;
while(onReady_funcs.length > 0){
// Removes the first func from the array, and execute func
onReady_funcs.shift()();
}
}
else if(typeof func == "function") {
if (api_isReady) func();
else onReady_funcs[b_before?"unshift":"push"](func);
}
}
})();
var video = function ( videoid, frameid) {
var player;
var that;
var seconds;
var duration;
var stateChangeCallback;
var update_play = 0;
return {
setOnStateChangeCallback: function(callback) {
stateChangeCallback = callback;
},
getCurrentTime: function() {
return player.getCurrentTime();
},
getPlayer: function () {
return player;
},
getVideoFrameId: function () {
return "video-frame-" + videoid;
},
initVideo: function (second) {
console.log("initing")
that = this;
YT_ready(function(){
var frameID = getFrameID("video-frame-" + videoid);
console.log("creating player")
console.log(frameID)
if (frameID) { //If the frame exists
console.log("frame exists")
player = new YT.Player(frameID, {
events: {
"onStateChange": that.stateChange
}
});
console.log("Player Created!");
if (second) {
console.log(second)
setTimeout(function() { console.log("seek to"); player.seekTo(second, false); player.stopVideo()}, 1000);
}
}
});
},
stateChange: function (event) {
console.log("event.data = ", event.data);
switch(event.data) {
case YT.PlayerState.PLAYING:
{
if (stateChangeCallback)
stateChangeCallback("play", player.getCurrentTime(), player.getDuration());
onsole.log("play");
}
break;
case YT.PlayerState.PAUSED:
case YT.PlayerState.CUED:
case YT.PlayerState.ENDED:
{
if (stateChangeCallback)
stateChangeCallback("pause", player.getCurrentTime(), player.getDuration());
console.log("pause");
}
break;
}
},
pauseVideo: function () {
player.stopVideo();
console.log('player.stopVid()');
},
seekTo: function(second) {
player.seekTo(second, false);
}
};
};
function onStateChange(vid, action, second, total) {
if (Videos[vid]) {
console.log( (second / total) * 100);
}
};
$(document).ready(function () {
var Videos = {};
logger.info("heyyy")
var videoId=155;
//if (videoId) {
Videos[videoId] = video(videoId, 155);
console.log(Videos[155])
Videos[155].initVideo();
Videos[155].setOnStateChangeCallback(function(action, second, total) {
onStateChange(155, action, second, total);
});
//}
Videos[155].seekTo(1000, false);
onStateChange(155, "start", 0, 0);
});
I know that the required script tags are being added, I can test that from console. I also know that onYouTubePlayerAPIReady() is actually called. But I still receive errors like
TypeError: player.stopVideo is not a function
When I run the three lines that adds the source tag again from the web console on firefox, the api seems to load and everything starts working again.
I have been struggling with this for days and I really need help figuring out what might be wrong. If it helps my application is developed in ruby on rails but I don't think this is relevant information.
Thanks
There is no problem with the above code. My video was loaded in a bootstrap modal. Modal's hide property would make it invisible to firefox and firefox would not load the api at all. So I removed the modal hide class and instead of display:none I used item.css("visibility", "visible"); and item.css("visibility", "hidden"); which made firefox load the api.