Back button not appearing in Metro style app - javascript

I have followed the tutorial on MSDN. The default back button for html/javascript metro style apps does not appear anywhere.
I then created new projects (grid app, blank app, navigation app) and even though it is defined in code, it does not display. However, other apps that have been installed from the Windows Store all display the back button.
Anybody else having this issue with the back button?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>homePage</title>
<!-- WinJS references -->
<link href="//Microsoft.WinJS.1.0.RC/css/ui-light.css" rel="stylesheet" />
<script src="//Microsoft.WinJS.1.0.RC/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0.RC/js/ui.js"></script>
<link href="/css/default.css" rel="stylesheet" />
<link href="/pages/home/home.css" rel="stylesheet" />
<script src="/pages/home/home.js"></script>
</head>
<body>
<!-- The content that will be loaded and displayed. -->
<div class="fragment homepage">
<header aria-label="Header content" role="banner">
<button class="win-backbutton" aria-label="Back" disabled></button>
<h1 class="titlearea win-type-ellipsis">
<span class="pagetitle">Dude!</span>
</h1>
</header>
<section aria-label="Main content" role="main">
<p>Content goes here.</p>
</section>
</div>
</body>
</html>

Maybe you've already tried this, but the HTML by itself won't be enough. The button added by the templates requires JavaScript to enable the back button.
By default, the button is added with the disabled attribute set, but script removes that attribute if it determines there's something to navigate back to.
For example, here's the relevant part from the Grid app template (in /js/navigator.js):
// This function updates application controls once a navigation
// has completed.
navigated: function () {
// Do application specific on-navigated work here
var backButton = this.pageElement.querySelector("header[role=banner] .win-backbutton");
if (backButton) {
backButton.onclick = function () { nav.back(); };
if (nav.canGoBack) {
backButton.removeAttribute("disabled");
} else {
backButton.setAttribute("disabled", "disabled");
}
}
},
You can see it looks for the back button by class .win-backbutton and, if nav.canGoBack is true, enables the back button by, er, removing the disabling. :)

Related

JavaScript modal not opening on all pages

I have created a JavaScript modal that opens on click it's isolated in one file and I want to reuse it on other pages, it works fine on the index.html page, but when I want to use it on another page it gives me Cannot read property 'addEventListener' of null I tried wrapping my js modal code in a window.onload = function() {} because I believed that the DOM had not been loaded fully but again it didn't work, how can I make it work on every page?
here is the index.html content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="./css/main.css">
<link rel="stylesheet" type="text/css" href="./css/modal.css">
<title>Word Spelling Game</title>
</head>
<body>
<div class="menu">
<audio controls autoplay loop>
<source src="./sounds/menu-song.mp3" type="audio/mp3">
Your browser does not support the audio element.
</audio>
<a href="./pages/game-menu.html">
<img src="./images/choose-game-sign.png" class="board">
</a>
<div>
<img src="./images/help-sign.png" class="board trigger">
<div class="modal">
<div class="modal-content">
<span class="close-button">×</span>
<h1>Welcome!</h1>
<article>
This is a collection of interactive games designed for children, each game
aims to further develop the childs skill set in a variety of tasks that involve
spelling, writing and simple math. It is designed in a fun way so that your kid will never become bored!
There are different levels of difficulty for different ages. To select and play
a level click on the Choose level tab above this one. You can see each game's rules
by clicking on the rules tab that is located on the right corner on each level. The instructions are written in
a way that every kid can understand in case that he get's stuck at some point.
</article>
</div>
</div>
</div>
</div>
<script src="./scripts/help-modal.js"></script>
</body>
</html>
The other page on which I want to use it that the user reaches after he clicks the Choose Game link:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../css//game-menu.css">
<link rel="stylesheet" type="text/css" href="../css/modal.css">
<script src="../scripts/help-modal.js"></script>
<title>Levels</title>
</head>
<body>
<a href="../index.html">
<img src="../images/back-sign.png">
</a>
<div class="help">
<p class="question-mark">?</p>
<div class="modal">
<div class="modal-content">
<span class="close-button">×</span>
<h1>Welcome!</h1>
<article>
This is a collection of interactive games designed for children, each game
aims to further develop the childs skill set in a variety of tasks that involve
spelling, writing and simple math. It is designed in a fun way so that your kid will never become bored!
There are different levels of difficulty for different ages. To select and play
a level click on the Choose level tab above this one. You can see each game's rules
by clicking on the rules tab that is located on the right corner on each level. The instructions are written in
a way that every kid can understand in case that he get's stuck at some point.
</article>
</div>
</div>
</div>
</body>
</html>
and my help-modal.js file:
var modal = document.querySelector(".modal");
var trigger = document.querySelector(".trigger");
var closeButton = document.querySelector(".close-button");
function toggleModal() {
modal.classList.toggle("show-modal");
}
function windowOnClick(event) {
if (event.target === modal) {
toggleModal();
}
}
trigger.addEventListener("click", toggleModal);
closeButton.addEventListener("click", toggleModal);
window.addEventListener("click", windowOnClick);
On your second HTML file you seem to not have any element with trigger class. This is the reason for your error in Console.
Including your JavaScript files in the end of body(just how you did in your intex.html) is also a good practice, in order to make sure that JavaScript will run after all HTML elements were loaded.
1) On the "other" page, move the <script> tag to the bottom of the markup, like it is in the "index" page, or add a window.onload = function() {} wrapper around the code in the .js file.
The reason for this is that currently in the "other" page, the script is loading first. When it loads, it is immediately executed by the browser. So it immediately runs var modal = document.querySelector(".modal");. However, since the script was loaded before any of the HTML in the <body>, there is no element available which matches the selector .modal. So nothing is selected, and consequently the event listeners are not attached to any element, and so are never triggered.
2) Added to that, your "other" page doesn't contain any element with the class "trigger". So even once you fix the loading issue, the line var trigger = document.querySelector(".trigger"); will still not select anything, and you'll still get a similar error when it tries to attach an event handler to nothing. So you need to correct that too. (This will be why your earlier attempt at window.onload = function() {} failed).
In summary - the HTML elements you're targeting must exist before the JavaScript you're using to target them is executed.

How to set value of textarea in different HTML file?

I am building a chrome/firefox web extension. When the user clicks the button in the extension's popup, the extension's UI changes.
Here's a visual example:
Before pressing one of three buttons:
After pressing one of three buttons:
As you can see from the screenshot, after pressing the button, a textarea is created.
Here is the code that does that (this function is called when one of the three original buttons is pressed):
function createSummaryBox(summary) {
console.log("Setting textarea content to: " + summary)
window.location.href = "../summary_page/summary_page.html";
document.getElementById('summary-field').value = summary;
}
However, even when this function is called, the content inside of the textarea does not change.
Instead, I get the following error:
TypeError: document.getElementById(...) is null
Here is the code for "summary_page.html":
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="../common/common_styles.css" />
<link rel="stylesheet" href="summary_page.css" />
</head>
<body>
<div class = container>
<textarea class="summary-field" type="text" disabled="disabled" id = "summary-field"></textarea>
<div class="btn-group">
<button class="btn">Back</button>
<button class="btn">Copy</button>
<button class="btn">Enlarge</button>
<script src="summary_page.js"></script>
</div>
</div>
</body>
</html>
Also, the sole content of "summary_page.js" is console.log("Summary Page Loaded);, which is printed out to the console.
How do I fix this?

How to apply Css/JQuery files to an external page inside Android WebView

Not sure if what I had in mind is possible or not, but why now.
I have a MVC4 Master page as follows
<head runat="server">
<meta charset="utf-8" />
<title>RYTE HCMS</title>
<meta name="viewport" content="width=device-width" />
<link href="<%: Url.Content("~/favicon.ico") %>" rel="shortcut icon" type="image/x-icon" />
<link rel="stylesheet" href="~/Content/jquery/jquery.mobile.theme-1.4.3.min.css" />
<link rel="stylesheet" href="~/Content/jquery/jquery.mobile.icons.min.css" />
<link href="~/Content/jquery-ui.datepicker.min.css" rel="stylesheet" />
<link href="~/Content/jquery.mobile.structure-1.4.5.min.css" rel="stylesheet" />
<%: Scripts.Render("~/bundles/modernizr") %>
<style type="text/css">
.wrap {
white-space: normal !important;
}
</style>
</head>
<body>
<div data-role="page" data-theme="a" data-url="master-page" id="master-page">
<div data-role="header" data-position="fixed">
<asp:ContentPlaceHolder ID="Header" runat="server">
<h1>
<asp:ContentPlaceHolder ID="TitleContent" runat="server" />
</h1>
<% Html.RenderPartial("LoginUserControl"); %>
</asp:ContentPlaceHolder>
</div>
<div data-role="content">
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
</div>
</div>
<script src="<%=Url.Content("~/Scripts/jquery-1.11.1.min.js")%>"></script>
<script>
$(document).on("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
</script>
<script src="<%=Url.Content("~/Scripts/jquery.mobile-1.4.5.min.js")%>"></script>
<script type="text/javascript">
$(document).on("pageinit", "#master-page", function () {
$(document).on("swipeleft swiperight", "#master-page", function (e) {
// We check if there is no open panel on the page because otherwise
// a swipe to close the left panel would also open the right panel (and v.v.).
// We do this by checking the data that the framework stores on the page element (panel: open).
if ($.mobile.activePage.jqmData("panel") !== "open") {
if (e.type === "swipeleft") {
$("#right-panel").panel("open");
} else if (e.type === "swiperight") {
$("#leftpanel").panel("open");
}
}
});
});
</script>
<asp:ContentPlaceHolder ID="ScriptsSection" runat="server" />
</body>
I want to load and apply CSS/JQuery in the Android WebView. I want to keep the files in android mobile app and apply them as the page loads inside the webView.
If I don't load these files in specific order the design breaks. The reason I want to do this to make sure user don't feel its a web app. At present at each refresh/reload it takes about 1-2 seconds for jquery mobile and css to load.
Since MVC4 pages are compiled on remote server, Is it possible?
Okay, so the comment on your question basically sums it up. You need to add the js/css code into your assets files.
If you want an example, you can take a look at this sample project (I only load js code, but it's the same principle for css) here
To go over the general idea:
Make your webview use a custom WebViewClient (called MailWebViewClient in the example). You don't need a custom webview (as was done in the example) wv.setWebViewClient(webViewClient);
In your webview client, override the onPageFinished() method and load your javascript code in a string (src) view.loadUrl("javascript: " + src);
That's it. It should work fine
In the example, I'm loading a script that will resize all tables and images to fit inside the webview (a common requirement for android). There's also some haphazard linkify code (to identify and mark links). I wouldn't use the js code, since it's a little buggy, but it's a good example for the principle.
put All Css and JS in assets folder.
and try to load web view with :
webView.loadDataWithBaseURL("file:///android_asset/", <HTMLDATA> ,"text/html", "UTF-8", null);

Jquery mobile pageshow event does not fire when second page is shown

I have working javascript mobile app which I have been trying to restructure (correctly or incorrectly). The index.html file contained one page (using data-role="page") with various <div> elements that I hide and show depending what the user wants to do. I thought I could improve the structure by putting each of these <div> elements each in their own page (still in the index.html file) using data-role again. However, the subsequent pages lose their javascript functionality. I have created a very simple index.html file to demonstrate:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/jquery.mobile-1.3.2.min.css" />
<script type="text/javascript" src="js/jquery-1.9.1.min.js"/></script>
<script type="text/javascript" src="js/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
<div data-role="page" id="mainPage">
<INPUT type="button" id="showPageTwo" value="Show Next Page" />
</div>
<div data-role="page" id="secondPage">
<INPUT type="button" id="showMainPage" value="Show Main Page" />
</div>
<script>
$(document).on("pageshow", "#mainPage", function(e) {
alert("Main page");
$("#showPageTwo").click(function()
{
$("#secondPage").show();
$("#mainPage").hide();
});
});
$(document).on("pageshow", "#secondPage", function(e) {
alert("Second page");
$("#showMainPage").click(function()
{
$("#mainPage").show();
$("#secondPage").hide();
});
});
</script>
</body>
</html>
Main page displays correctly, the alert is displayed $("#showPageTwo").click(function() works. But none of the javascript runs when secondPage loads.
Additionally when secondPage is shown it does not have the styling from jquery.mobile-1.3.2.min.css that mainPage has.
What am I doing wrong or misunderstanding? (This is when running the app in the Eclipse AVD)
Additionally, I would like to know:
Is the way I am trying to restructure my code using data-role="page" good or bad practice? Is there a recommended way to structure "pages" in a mobile app?
I also want to put my custom script(s) in their own .js file(s). Can I only load the script shown in the above code before the </body> tag? Is there any way to load it in the header along with all the other scripts?

call jquery changePage() on localStorage

I have a simple jquery mobile page:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.2">
<link rel="stylesheet" href="js/jquery.mobile-1.2.0.css" />
<script src="js/jquery-1.8.2.js"></script>
<script src="js/jquery.mobile-1.2.0.js"></script>
</head>
<body>
<div id="MyContainer">
<!-- ##################### Raw Part ##################### -->
<div data-role="page">
<div data-role="header">
<h1> Hello World </h1>
</div>
</div>
</div>
</body>
</html>
when I execute that page it renders fine with a black header and title.
The reason why that page loads correctly is because jquery-mobile placed new attributes where needed in fact the innerHTML of MyContainer after the page loads is:
<!-- ##################### Parsed Part ##################### -->
<div data-role="page" data-url="/jqueryMobile/TC_Page/main2.html" tabindex="0" class="ui-page ui-body-c ui-page-active" style="min-height: 1464px;">
<div data-role="header" class="ui-header ui-bar-a" role="banner">
<h1 class="ui-title" role="heading" aria-level="1">
Hello World
</h1>
</div>
</div>
In other words the Raw Part turn into the Parsed Part .
I will like to know what jquery.mobile function made the conversion from the Raw Part to the Parsed Part!
The functions $.mobile.changePage(), $.mobile.loadPage() enables me to do that For example I could do:
// place response from SomeUrl inside the div MyContainer and convert it from raw to parsed!
$.mobile.loadPage('SomeUrl', { pageContainer: $('#MyContainer') });
// later then get the child child (note second child) of MyContainer and make that the child of MyContainer
The problem now is:
All those functions: loadPage, ChangePage etc make an ajax call. What if I already have the html that I want to inject ( I have it in webBrowser local storage or in a Cookie)! In other words how can I make this work:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.2">
<link rel="stylesheet" href="js/jquery.mobile-1.2.0.css" />
<script src="js/jquery-1.8.2.js"></script>
<script src="js/jquery.mobile-1.2.0.js"></script>
</head>
<body>
<div id="MyContainer">
</div>
<script>
function SomeFunction(){
var someHTML = localStorate.html1; // html1 = raw part = <div data-role="page"><div data-role="header"><h1> Hello World </h1></div></div>
$("#MyContainer").html(someHTML);
// now here I am stuck!!!!!!!!!!!!!!!
// how can I make the content of MyContainer go from the raw part to the Parsed Part!
// I am looking for something like:
$JqueryMobile.ParseHTML($("#MyContainer"));
}
</script>
</body>
</html>
Solution
jQuery Mobile provides numerous functions for widget restyling but only one of them will restyle whole page.
$('#index').trigger('pagecreate');
Where #index should be an id of your page DIV.
There is also on other function that can be used here, but unlike trigger('pagecreat'); this function will style only DIV wit data-role="content" attribute. To test this, jsFiddle example trigger('pagecreate'); should be replaced with trigger('create');
$('#index').trigger('create');
If possible SCRIPT tag should not be used inside a BODY tag, while it will work it can cause additional problems. If you want to find more about this topic and how jQuery Mobile handles dynamically added content take a look at this ARTICLE which is a part of my personal blog.
Example
Working example: jsFiddle
This part of code should interest you:
$('#index').append('<div data-role="footer" data-position="fixed"><h1>Dynamicaly added footer</h1></div> ');
$('#index [data-role="content"]').append('<fieldset data-role="controlgroup"><legend>Choose:</legend><input type="radio" name="radio" id="radio1" value="1" checked="checked" /><label for="radio1">option 1</label></fieldset>');
$('#index').trigger('pagecreate');
This code is used to dynamically append page footer and a radio button to page content.

Categories

Resources