How can I tell all Angular commands are complete from Javascript? - javascript

I am using the following to detect when my page has finished loading, but it is evidently wrong. The Angular stuff has not been executed yet when document.readyState is complete:
page.open(url, function (status) {
function checkReadyState() {
setTimeout(function () {
var readyState = page.evaluate(function () {
return document.readyState;
});
if ("complete" === readyState) {
// onPageReady();
doRender();
} else {
checkReadyState();
}
});
}
checkReadyState();
});

I didn't get the purpose exactly but you can use $timeout inside angular code which gets executed only after all execution is finished for that particular angular page, and pass a global method which is defined inside your javascript code.
Something like this-
Inside JS file -
var callBack = function(){
console.log('I have finished execution');
}
Inside Angular Controller -
$timeout(function(){
callBack();
});
If it doesn't solve your problem please elaborate more.

Related

A js code is working fine from developer tool but not from js file

I can run the following code from my developer console:
jQuery(".skiptranslate").contents().filter(function () {
alert('works again');
return this.nodeType != 1;
}).replaceWith("");
But when I put this same code in js file it has no effect. I put this code in js file inside $(document).ready() function. What's wrong with my code?
You can create a recursive function to check if skiptranslate is ready (rendered/loaded) using $('.skiptranslate').length. If founded run your code if not, wait 100ms then call yourself (do another check), keep check until you found the element.
Use setTimeout to set the delay, my example here is 100ms.
Don't forget to init the function for the first time skiptranslateFn();
My example here simulated the class skiptranslate to be added after 1sec (1000ms).
$(document).ready(function() {
function skiptranslateFn() {
if ($('.skiptranslate').length) {
jQuery(".skiptranslate").contents().filter(function() {
alert('works again');
return this.nodeType != 1;
}).replaceWith("");
console.log('---skiptranslate FOUNDED! ----');
} else {
console.log('skiptranslate not found yet');
setTimeout(function() {
skiptranslateFn()
}, 100);
}
}
//init
skiptranslateFn();
setTimeout(function() {
$('#test').addClass('skiptranslate');
console.log('element loaded!');
}, 1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
test div
</div>

Angularjs code not running in anonymous function

I wrote an anonymous javascript function that dynamically loads jQuery and Angular. However, my angular code is not running for some reason. The code works find until i hit my main function. I then try to make an http request and print the results in my angular controller, but theyre not printing for some reason.. Can someone help? Here are my fiddle and code:
https://jsfiddle.net/5f44yb7k/1/
Thanks in advance!
(function() {
var jQuery;
var jquery_tag = document.createElement('script');
var angular_tag = document.createElement('script');
function getJqueryTag() {
console.log('getting jquery tag');
jquery_tag.setAttribute("type","text/javascript");
jquery_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js");
jquery_tag.onload = scriptLoadHandler;
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(jquery_tag);
if(jquery_tag.onload) { //ensure angular loads after jQuery
getAngularTag();
}
}
function getAngularTag() {
console.log('now getting angular tag...');
angular_tag.setAttribute("type","text/javascript");
angular_tag.setAttribute("src", "https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js");
angular_tag.onload = scriptLoadHandler;
(document.getElementsByTagName("head")[0] || document.documentElement).appendChild(angular_tag);
}
getJqueryTag();
function scriptLoadHandler() {
if(window.jQuery) {
jQuery = window.jQuery
main();
}
}
function main() {
jQuery(document).ready(function($) {
console.log('now in main function'); //this prints fine
var test = angular.module('test', []);
function main_controller($scope, $http) {
$http.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22fairfax%2C%20va%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys')
.success(function(data) {
console.log('---data returned---'); //not printing
console.log(data); //not printing
})
.error(function(data) {
console.log('error: ' + data);
});
}
});
}
})();
Angular is falling out of scope. You'll need to call the bootstrap function to get angular up and running if you're loading it in this fashion.
I've never loaded it this way, but see: https://docs.angularjs.org/guide/bootstrap, specifically the section on Manual Initialization.

Backbone.Marionette extending region stops onClose() function from calling

I've created a Backbone, Marionette and Require.js application and am now trying to add smooth transitioning between regions.
To do this easily* ive decided to extend the marionette code so it works across all my pages (theres a lot of pages so doing it manually would be too much)
Im extending the marionette.region open and close function. Problem is that it now doesnt call the onClose function inside each of my views.
If I add the code directly to the marionette file it works fine. So I'm probably merging the functions incorrectly, right?
Here is my code:
extendMarrionette: function () {
_.extend(Marionette.Region.prototype, {
open : function (view) {
var that = this;
// if this is the main content and should transition
if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
this.$el.empty().append(view.el);
$(document).trigger("WrapperContentChanged")
} else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {
$(document).on("WrapperIsHidden:open", function () {
//swap content
that.$el.empty().append(view.el);
//tell router to transition in
$(document).trigger("WrapperContentChanged");
//remove this event listener
$(document).off("WrapperIsHidden:open", that);
});
} else {
this.$el.empty().append(view.el);
}
},
//A new function Ive added - was originally inside the close function below. Now the close function calls this function.
kill : function (that) {
var view = this.currentView;
$(document).off("WrapperIsHidden:close", that)
if (!view || view.isClosed) {
return;
}
// call 'close' or 'remove', depending on which is found
if (view.close) {
view.close();
}
else if (view.remove) {
view.remove();
}
Marionette.triggerMethod.call(that, "close", view);
delete this.currentView;
},
// Close the current view, if there is one. If there is no
// current view, it does nothing and returns immediately.
close : function () {
var view = this.currentView;
var that = this;
if (!view || view.isClosed) {
return;
}
if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
this.kill(this);
} else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {
//Browser bug fix - needs set time out
setTimeout(function () {
$(document).on("WrapperIsHidden:close", that.kill(that));
}, 10)
} else {
this.kill(this);
}
}
});
}
Why don't you extend the Marionette.Region? That way you can choose between using your custom Region class, or the original one if you don't need the smooth transition in all cases. (And you can always extend it again if you need some specific behavior for some specific case).
https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.region.md#region-class
var MyRegion = Marionette.Region.extend({
open: function() {
//Your open function
}
kill: function() {
//Your kill function
}
close: function() {
//Your close function
}
});
App.addRegions({
navigationRegion: MyRegion
});
Perhaps your issue is that you are not passing a function to your event listener, but instead calling the code directly in the code below.
setTimeout(function(){
$(document).on("WrapperIsHidden:close", that.kill(that));
}, 10)
It is likely that you want something like this:
setTimeout(function(){
$(document).on("WrapperIsHidden:close", function (){ that.kill(that); });
}, 10)
Another possible problem is that you are mixing up your references to this/that in your kill function. It seems like you probably want var view to either be assigned to that.view or to use this rather than that throughout the method.
Answer to your additional problems:
You should try passing the view variable from the close function directly into your kill function because the reference to currentView is already changed to the new view object when you actually want to old view object. The reason this is happening is that you are setting a timeout before executing the kill function. You can see this if you look at the show source code. It expects close, open and then currentView assignment to happen synchronously in order.

issue with an asynchronous while in WinJS

I have an app which invokes a WebService (callPathsToMultiTiffWS) which have two possibilities:
complete = true
complete = false
in the case complete = false I want to show a dialog which notifies to user than webService failed and two buttons:
retry action (reinvoke WS)
Exit
this is my code so far:
callPathsToMultiTiffWS(UID_KEY[9], stringCapturePaths, UID_KEY[1], UID_KEY[2], UID_KEY[3], UID_KEY[4], UID_KEY[5], UID_KEY[6]).then(
function (complete) {
if (complete == true) {//if true, it stores the id of the picture to delete
Windows.UI.Popups.MessageDialog("WS executed successfully", "Info").showAsync().then(function (complete) {window.close();});
} else {
var messageDialogPopup = new Windows.UI.Popups.MessageDialog("An error occur while calling WS, retry??", "Info");
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Retry', function () { /*code for recall element*/ }));
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Exit', function () { /*code for exit*/ }));
messageDialogPopup.showAsync();
_divInput.innerHTML = "";
}
},
function (error) { console.log("function error"); });
This works good so far, but I want the recall feature working
so I thought to embedd my code inside a loop like this
var ban = true;
while (true) {
callPathsToMultiTiffWS(UID_KEY[9], stringCapturePaths, UID_KEY[1], UID_KEY[2], UID_KEY[3], UID_KEY[4], UID_KEY[5], UID_KEY[6]).then(
function (complete) {
if (complete == true) {//if true, it stores the id of the picture to delete
Windows.UI.Popups.MessageDialog("WS executed successfully", "Info").showAsync().then(function (complete) { window.close(); });
} else {
var messageDialogPopup = new Windows.UI.Popups.MessageDialog("An error occur while calling WS, retry??", "Info");
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Retry', function () { ban == true; }));
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Exit', function () { ban == false; }));
messageDialogPopup.showAsync().then(function (complete) {
console.log("no ps no");
});
}
},
function (error) { console.log("function error"); });
if (ban == false) break;
}
this loop executes the webService, but it doesn't wait for user interaction to trigger the webservice by touching one of the buttons, it is an endless loop with calls to my webService, how to fix this??
thanks in advance for the support
If I'm not missing something, it looks like the error is caused because your code isn't designed to run the next set of tasks after the asynchronous call to showAsync returns. Because the call to showAsync is non-blocking, the while loop will start over again and make another call to the Web service. And because THAT call (callPathsToMultiTiffWS) is also non-blocking, the loop will start over again, triggering another call to callPathsToMultiTiffWS. And over again, and again.
My recommendation is to break out the next call to the Web service so that it will only be triggered when the user makes a selection. If you separate your concerns (move the calls to the Web service into different function or module than the UI that informs the user of an issue), then you can probably fix this.
Kraig BrockSchmidt has a great blog post about the finer details of Promises:
http://blogs.msdn.com/b/windowsappdev/archive/2013/06/11/all-about-promises-for-windows-store-apps-written-in-javascript.aspx
-edit-
Here's some code that I wrote to try to demonstrate how you might accomplish what you're trying:
function tryWebServiceCall(/* args */) {
var url = "some Web service URL";
return new WinJS.xhr({ url: url }).then(
function (complete) {
if (complete) {
return new Windows.UI.Popups.MessageDialog("WS executed successfully", "Info").showAsync().then(
function () { /*do something */ });
} else {
var messageDialogPopup = new Windows.UI.Popups.MessageDialog("An error occur while calling WS, retry??", "Info");
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Retry', function () {
return tryWebServiceCall( /* args */);
}));
messageDialogPopup.commands.append(new Windows.UI.Popups.UICommand('Exit', function () { return; }));
return messageDialogPopup.showAsync();
}
});
}

How to know if document has loaded

I have a piece of JS code which needs to determine if DOM has loaded. I know there are several ways of executing JS code when DOM has loaded like:
$(document).ready(function() { ... }); // Jquery version
document.body.onload = function() { ... } // Vanila JS way
I am looking for some method which looks like
function isDOMLoaded() {
// Do something to check if DOM is loaded or not
// return true/false depending upon logic
}
PS: Update (Post Answer Accept)
I happen to see jquery also use the same approach to check if DOM has loaded. Take a look at the Implementation of jquery.ready() here
bindReady: function() {
if ( readyBound ) {
return;
}
readyBound = true;
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
return jQuery.ready();
}
...
function isDOMLoaded(){
return document.readyState == 'complete';
}
You can use something like this
function isLoaded() {
return (document.readyState === 'ready' ||
document.readyState === 'complete')
}
Check for ready and complete status.
ready is only there for a short moment but do reflect when the DOM is ready. When the page is completely loaded however the status is changed to 'complete'. If you happen to check only for ready the function will fail, so we also check for this status.
How about this?
var flgDOMLoaded=false; //Set a global variable
$(document).ready(function() {
flgDOMLoaded= true;
// Some code
});
function isDOMLoaded() {
return flgDOMLoaded; // return it.
//You don't need this function at all. You could just access window.flgDOMLoaded
}

Categories

Resources