Page Navigation On Win Phone 8 App Load - javascript

I am developing a Windows 8 application for phones and created a new project using 'Navigation App' template, since I want to use a few pages in my app.
The default start page is home.html, as stated in the default.html:
<body class="phone">
<div id="contenthost" data-win-control="Application.PageControlNavigator" data-win-options="{home: '/pages/home/home.html'}"></div>
</body>
I want to check data I am saving in
Windows.Storage.ApplicationData.current.localFolder
BEFORE the app is finish loading.
Depends on the data result, I want to continue to home.html or navigate to a different page.
I idea is to process everything I need in the 'splash' time and then deiced which page to load. I'm just not sure It's possible in Win Phone Development.
I though the best place for that is default.js file in onloaded event, but I have 2 problems:
Trying to navigate from onloaded to a different page doesn't seem to work. The app always get into home.html
Getting data is async so the app keeps loading before I got the data and able to check it.
app.onloaded = function (args) {
var storageFolder = Windows.Storage.ApplicationData.current.localFolder;
storageFolder.getFileAsync('settings.txt').then(
function (file) {
if (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (contents) {
if (contents.length > 0 && contents != '{}') {
var settingsObj = JSON.parse(contents);
if ('id' in settingsObj && settingsObj.id > 0) {
//Go to Home
WinJS.Navigation.navigate('/pages/home/home.html');
return;
}
}
//Go To Login
WinJS.Navigation.navigate('/pages/login/login.html');
});
}
},
function (e) {
storageFolder.createFileAsync('settings.txt');
}
);
};

You can try putting that code in app.xaml.cs where the default page is normally loaded.
Check the Application data for what you are looking for then use if statements to see if the results satisfy what you want e.g
if(true)
{
Frame.Navigate(typeof(MainPage));
}else
{
Frame.Navigate(typeof(AnotherPage));
}

Related

Chrome Extension: Clear Chrome Local Storage on Page Reload (not on Update)

I'm working on a Chrome Extension that will sort a DOM structure. On the extension popup I'm using a button that will activate / desactivate the sort. In order to save the state of my button I'm saving via Chrome Local Storage the "state" of my button this way:
function save_button_state() {
var buttonStateText = $("#js-toggleSorting").html();
var buttonStateAttribute = $("#js-toggleSorting").attr("data-click-state");
var sortMessage = $(".message").html();
chrome.storage.local.set(
{
buttonStateText: buttonStateText,
buttonStateAttribute: buttonStateAttribute,
sortMessage: sortMessage,
},
function () {
console.log(
`Saved State is: ${buttonStateText} and Saved Attribute is: ${buttonStateAttribute} and Saved Message is: ${sortMessage}`
);
}
);
}
That save the dom node and keep the information in order to save it when the popup is closed. Then, in order to get that info back from the local storage I'm using this function:
function get_button_state() {
chrome.storage.local.get(
["buttonStateText", "buttonStateAttribute", "sortMessage"],
function (data) {
$(".message").html(data.sortMessage);
$("#js-toggleSorting").html(data.buttonStateText);
$("#js-toggleSorting").attr(
"data-click-state",
data.buttonStateAttribute
);
console.log(
`Get State is ${data.buttonStateText} and Get Attribute is ${data.buttonStateAttribute}`
);
}
);
}
And then when the document is ready I'm processing the button onclick event changing the dom from "Sorting" to "Not Sorting" this way:
$(document).ready(() => {
get_button_state();
//Some Code to pass parameters from the extension to a content script
$("#js-toggleSorting").on("click", function () {
$(".message").html("");
if ($(this).attr("data-click-state") == 1) {
$(this).attr("data-click-state", 0);
$(this).html("SORT INCOMING CHATS");
$(".message").append("<p>STATUS: NOT SORTING CHATS</p>");
sortFunction(false);
} else {
$(this).attr("data-click-state", 1);
$(this).html("STOP SORTING INCOMING CHATS");
$(".message").append("<p>STATUS: SORTING CHATS</p>");
sortFunction(true);
}
save_button_state();
});
});
Then in the Chrome Extension background js file I'm trying to clear the local storage when I reload the page (the same page, with the same URL):
chrome.tabs.onUpdated.addListener(function (changeInfo) {
if (changeInfo.url === undefined) {
chrome.storage.local.clear();
}
});
But apparently this will not only clear the local storage when I reload the page but when something change in it causing a lot of buggy behavior on the popup (basically changing very randomly the text of the button when the user interact/click on it everytime they open the popup). My question is which is the right way to clear the local storage just when the page is reloaded / refreshed. I'm sorry if this seems pretty obvious but I'm new on the Chrome Extension development world.

Swift 3 Detect when WKWebView finishes loading AJAX site

I am trying to inject some javascript into my web view when it is navigated to a product page URL. The website doesn't reload when navigating to different pages, so to my understanding that means it is using Ajax.
The problem is I need the page to be fully loaded because the purpose of the javascript I am using is to automatically select the size drop down.
I tried to use the navigation delegate but since it's not reloading between pages it only gets called when the web view is first loaded.
What I have done is setup and observer by
webView.addObserver(self, forKeyPath: "URL", options: .new, context: nil)
and check if the current URL is the URL I want to inject the javascript on by
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "URL" {
guard var currentURL = webView.url?.absoluteString else { return }
if currentURL.lowercased().range(of: "products") != nil {
webView.evaluateJavaScript("document.getElementById('size-options').selectedIndex = 1")
}
}
}
The problem with this is it gets called right when the URL changes but not when the page finishes loading. I have got it to successfully work by adding a delay but that isn't a good solution because if the page doesn't load in time it won't work. Is there any way to know when a page like this finishes loading all its elements? The website I am working with is http://www.supremenewyork.com/mobile/#categories mobile site.

Implementing Dropbox API V2 in Cordova Application

I have a Cordova application with previous Dropbox implementation using rossmartin/phonegap-dropbox-sync-android. Now as the API V1 is going to be deprecated I want to upgrade to Dropbox API V2. I have searched for plugins for Cordova applications using Dropbox API V2 but didn't find any.So I am trying to implement it using dropbox/dropbox-sdk-js.
For Authentication, I am using authenticateWithCordova method which returns me the Access token (Full documentation here).This method returns Access token once the user completes authentication with Dropbox and uses the redirect URL to redirect the user to Cordova application.
This method works perfectly when the user clicks the button for the first time, but when the user clicks the button again calling this method shows a blank screen and return a new access token. How to avoid seeing the blank screen?
This is the method from Dropbox-sdk.js file, which I have called from my application,
DropboxBase.prototype.authenticateWithCordova = function (successCallback, errorCallback)
{
var redirect_url = 'https://www.dropbox.com/1/oauth2/redirect_receiver';
var url = this.getAuthenticationUrl(redirect_url);
var browser = window.open(url, '_blank');
var removed = false;
var onLoadError = function(event) {
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
errorCallback();
}
var onLoadStop = function(event) {
var error_label = '&error=';
var error_index = event.url.indexOf(error_label);
if (error_index > -1) {
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
errorCallback();
} else {
var access_token_label = '#access_token=';
var access_token_index = event.url.indexOf(access_token_label);
var token_type_index = event.url.indexOf('&token_type=');
if (access_token_index > -1) {
access_token_index += access_token_label.length;
// Try to avoid a browser crash on browser.close().
window.setTimeout(function() { browser.close() }, 10);
var access_token = event.url.substring(access_token_index, token_type_index);
successCallback(access_token);
}
}
};
Here is my code which I use to call the method,
function authenticateWithCordova()
{
var dbx = new Dropbox({ clientId: CLIENT_ID });
dbx.authenticateWithCordova(AuthSuccess,AuthFail);
}
function AuthSuccess(accessToken)
{
localStorage.accessToken = accessToken;
}
function AuthFail()
{
alert("Auth Fail");
}
I have found an analog issue right yesterday. This is the way I solved it.
First, I have set var dbx as global. In my index.js I put these lines immediately after app.initialize():
var CLIENT_ID = 'xxxxxxxxxxxxxxx';
var dbxt;
var dbx = new Dropbox({clientId: CLIENT_ID});
Then I check if dbxt is null: if it is, I create a new Dropbox object using accessToken, otherwise I go with the dropbox connection already established:
if (dbxt == null) {
dbx.authenticateWithCordova(function (accessToken) {
dbxt = new Dropbox({accessToken: accessToken});
dbxt.filesUpload({
path: '/mydump.sql',
contents: sql,
mode: 'overwrite',
mute: true
}).then(function (response) {
alert('Your backup has been successfully uploaded to your Dropbox!')
}).catch(function (error) {
alert('Error saving file to your Dropbox!')
console.error(error);
});
}, function (e){
console.log("failed Dropbox authentication");
}
}else{//dbxt already created
dbxt.filesUpload... //and the rest
}
This is just to avoid to create a new connection and get a new access token everytime and I confess I'm not sure this is a good practice: I only know that before to apply this code I got a lot of bad requests responses by Dropbox server:)
When I used the above code, after the first login, I started to see the blank page: that's is the inappbrowser page which Dropbox OAuth2 uses as redirect URI (set to https://www.dropbox.com/1/oauth2/redirect_receiver in your Dropbox app page).
So the problem was how to make this page invisible. I found a dirty trick applying a small tweak to inappbrowser.js script.
Near the bottom of the script, immediately before this line:
strWindowFeatures = strWindowFeatures || "";
I have put this small block:
if (strUrl.indexOf('dropbox') > -1){
strWindowFeatures += "location=no,hidden=yes";
}
I would have expected to can just use 'hidden=yes' but surprisingly if I remoce 'location=no' the blkank page appears again.
Notice 1: you don't have to modify the script inappbrowser.js located at plugins\cordova-plugin-inappbrowser\www\ but the one you find in platforms\android\platform_www\plugins\cordova-plugin-inappbrowser\www\
Notice 2: I have found this workaround right now so I'm not 100% sure it works perfectly.
Notice 3: making the inappbrowser page invisible, depending on the Internet connection, it could look like nothing is happening for a while, so you'll have to add some loader to inform your user that the app is working.
Hope this help.
UPDATE
I've just realized we can tweak directly the dropbox-sdk instead of inappbrowser.
If you are using Dropbox with browserify you have to open dropbox-base.js and look for authenticateWithCordova() method (it should be at line 107. Then change the line
var browser = window.open(url, '_blank');
to
var browser = window.open(url, '_blank', "location=no,hidden=yes");
If you are using Dropbox-sdk.min.js, you have to look for 'window.open' using the search function of your code editor. It will be easy because 'window.open' is used only once. So you'll have to change the following:
i=window.open(n,"_blank"),
to
i=window.open(n,"_blank","location=no,hidden=yes"),
And this seems to work fine (I prefer to be careful before I get excited).
UPDATE 2
Forgive previous update. My previous check:
if (strUrl.indexOf('dropbox') > -1){
strWindowFeatures += "location=no,hidden=yes";
}
is wrong because it makes invisible any inappbrowser window which tries to connect to dropbox so it prevent us from even logging into Dropbox. So we need to change it to
if (strUrl == 'https://www.dropbox.com/1/oauth2/redirect_receiver') {
strWindowFeatures += "location=no,hidden=yes";
}
This way we can do the login correctly and next connections won't show the inappbrowser window, as we want.
So summarizing:
Ignore my first update
Use UPDATE 2 to modify the url check in inappbrowser.js
Forgive me for the confusion...

iron-router: How to load a route completely just as when hitting refresh after loading a route?

I have a sign-in method in my Meteor application that redirects users to different routes after login in to the system. Here is my method:
Meteor.loginWithPassword(emailVar, passwordVar, function (err) {
if (err !== undefined) {
// error handling code
} else {
if (!Roles.userIsInRole(Meteor.userId(), 'active')) {
return Router.go('account-deactivated');
}
if (Roles.userIsInRole(Meteor.userId(), 'pharmacist')) {
return Router.go('pharmacist-dashboard');
}
if (Roles.userIsInRole(Meteor.userId(), 'admin')) {
return Router.go('admin-dashboard');
}
}
});
While this method works as expected, it produces some issues with my theme (AdminLTE) due to JavaScript loading problems (ex: app.min.js etc.). For example the sliding effects doesn't work on redirected page. But when I reload the page from the browser it starts to work as expected.
I know this is a separate issue that needs to be addressed. But if there is a way to completely reload a link in Meteor using iron-router it would be helpful. Specially when a page is transfered to a completely different user environment where a new set of JavaScript and CSS are used.
I went through the user documentations of iron-router but the fixes do not provide a solution.
Try using window.location.href to redirect.
Using Router.go is merely loading the template for the route you are linking to, whereas using window.location.href is loading the url as if it was a link you just clicked (actual refresh).
You'll need to use the actual url though, not the 'route name'.
window.location.href = "http://yourapp.com/route/here";

Retrieve html content of a page several seconds after it's loaded

I'm coding a script in nodejs to automatically retrieve data from an online directory.
Knowing that I had never done this, I chose javascript because it is a language I use every day.
I therefore from the few tips I could find on google use request with cheerios to easily access components of dom of the page.
I found and retrieved all the necessary information, the only missing step is to recover the link to the next page except that the one is generated 4 seconds after loading of page and link contains a hash so that this step Is unavoidable.
What I would like to do is to recover dom of page 4-5 seconds after its loading to be able to recover the link
I looked on the internet, and much advice to use PhantomJS for this manipulation, but I can not get it to work after many attempts with node.
This is my code :
#!/usr/bin/env node
require('babel-register');
import request from 'request'
import cheerio from 'cheerio'
import phantom from 'node-phantom'
phantom.create(function(err,ph) {
return ph.createPage(function(err,page) {
return page.open(url, function(err,status) {
console.log("opened site? ", status);
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function(err) {
//jQuery Loaded.
//Wait for a bit for AJAX content to load on the page. Here, we are waiting 5 seconds.
setTimeout(function() {
return page.evaluate(function() {
var tt = cheerio.load($this.html())
console.log(tt)
}, function(err,result) {
console.log(result);
ph.exit();
});
}, 5000);
});
});
});
});
but i get this error :
return ph.createPage(function (page) {
^
TypeError: ph.createPage is not a function
Is what I am about to do is the best way to do what I want to do? If not what is the simplest way? If so, where does my error come from?
If You dont have to use phantomjs You can use nightmare to do it.
It is pretty neat library to solve problems like yours, it uses electron as web browser and You can run it with or without showing window (You can also open developer tools like in Google Chrome)
It has only one flaw if You want to run it on server without graphical interface that You must install at least framebuffer.
Nightmare has method like wait(cssSelector) that will wait until some element appears on website.
Your code would be something like:
const Nightmare = require('nightmare');
const nightmare = Nightmare({
show: true, // will show browser window
openDevTools: true // will open dev tools in browser window
});
const url = 'http://hakier.pl';
const selector = '#someElementSelectorWitchWillAppearAfterSomeDelay';
nightmare
.goto(url)
.wait(selector)
.evaluate(selector => {
return {
nextPage: document.querySelector(selector).getAttribute('href')
};
}, selector)
.then(extracted => {
console.log(extracted.nextPage); //Your extracted data from evaluate
});
//this variable will be injected into evaluate callback
//it is required to inject required variables like this,
// because You have different - browser scope inside this
// callback and You will not has access to node.js variables not injected
Happy hacking!

Categories