I am just starting out with Windows 8 development using HTML/JS. I've spent the last few months immersed in jQuery development for apps targeting vehicle head-units and televisions.
Jumping into this, I thought the transition would be simple. I have the design and structure of my site all figured out for the most part and was hoping to follow some of the practices I had been using for my previous work.
That is, I want to essentially create a single page app. The main default.html file will house the top navigation/title and one other div. The other div will be used to load in all the other pages, all separate HTML files within the project.
All of the global functions and major functionality will reside in a javascript file, application.js. Then any page-specific javascript will reside at the top of each HTML file.
I'm quickly realizing that this is a problem. Using jQuery.load() to load in my pages causes security errors in my app.
JavaScript runtime error: Unable to add dynamic content. A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement.
I was really hoping to avoid having to learn a bunch of Microsoft-specific stuff. I think it's great that they've provided a lot of tools and what not, and maybe I just haven't used them enough, but everything just feels too rigid for me and for what I'm trying to do or can already be accomplished with jQuery. I'm one who likes to know EXACTLY what is happening and have full control over it.
Also looking through the templates and sample projects, I really don't like all the repeated code. For instance, every single HTML file declaring all the same references. I want to write my references and sections like my title bar just once, and not have to copy/paste that code all over my project.
Is there a way to do things the way I was hoping, and create a single page app? Do they have their own substitute for jQuery's .load()?
Any help pointing me in the right direction would be much appreciated!
EDIT 8/14/2012:
I have tried using the fix from this question:
Using jQuery with Windows 8 Metro JavaScript App causes security error
This gets rid of the security warning and I can load in HTML using jQuery.load(). However, looking at DOM explorer, my HTML is being stripped of my scripts.
I have also tried wrapping my .load() call inside of MSApp.execUnsafeLocalFunction(), but yet again my file still gets stripped of all scripts. What gives?
I fixed by simply changing the line of jQuery that was causing the error.
jQuery-1.8.0, line 5566:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
self.appendChild(elem); // problem line
}
});
},
Changed to:
append: function () {
return this.domManip(arguments, true, function (elem) {
if (this.nodeType === 1 || this.nodeType === 11) {
var self = this;
MSApp.execUnsafeLocalFunction(function () {
self.appendChild(elem);
});
}
});
},
There is a "formal" way to do what you are seeking.
WinJS.Navigation is provided to support "single page apps". For example, the default.html would contain a markup that would represent where the dynamically loaded page content would go:
<div id="contenthost"
data-win-control="Application.PageControlNavigator"
data-win-options="{home: '/pages/home/home.html'}">
</div>
In the example above, the actual content page loaded is at /pages/home/home.html
In event handlers, you can simply do the following to load or navigate to another page:
WinJS.Navigation.nav("/pages/other/page.html");
True, it is not jQuery, but it works great :)
Depending on your app, if you are not intending to access any WinRT components, you can navigate your page to ms-appx-web which will change the security policy around the page, but you can't specify this from start up. You would have to do a navigate, and leverage that new securyt context.
The other option you have it to wrap the calls to JQuery with msWWA.execUnsafeLocalFunction function, which will enable all that unsafe code be pushed into the DOM
Related
I have searched ALOT for this question and didnt find an answer,
I designed a complex HTML template and I tried to make a Joomla template based on it
I found the whole process time consuming and I cant get exactly same result as I wanted, also even If I do this I dont have a user friendly Joomla panel and for changing every module and component the Admin should know a basic HTML understanding to edit my tags and doesnt mess up my code
so I realized what If I use modern Joomla template instead with a user friendly panel
and bring the content to the page and rewrite the whole DOM via Javascript like this
1)first make variables and store the content on the rendered template
2)$('body').innerHTML = "" (make the DOM empty)
3)$('body').innerHTML => rerwrite my structure using variables I stored
then every element is exactly the same and my css, js files do the rest
Is it usual to do this way?
whats the problem with this method?
Thanks
In an ASP.NET Core app, I've a dashboard with widgets. Every widget has its own PartialViews, so the full page is generated in the following way:
-Layout.cshtml
--Dashboard.cshtml
--- Widget1.cshtml
--- Widget2.cshtml
Following best practices according to fast page load times, JavaScript is loaded before the closing </body> tag in Layout.cshtml. After that, there is a section for custom JS, which I commonly use to initiate objects on page load. So this section looks like this:
<script asp-append-version="true" type="text/javascript" src="~/clientscript/page.min.js"></script>
#RenderSection("Js", required: false)
In my Views, which are using the Layout.cshtml as layout (in this example, its Dashboard.cshtml), I can define a section like
#section Js {
// Js Code here
}
which is rendered after the script tag containing all script files. So I can be sure, that all dependencies like jQuery or custom classes are avaliable here.
But I also need to do this in widgets like Widget1.cshtml for example. The problem is: I load the PartialView Widget1.cshtml in Dashboard.cshtml. In the documentation is written, that this is not possible:
If you declare a Razor section in a partial view, it will not be visible to its parent(s); it will be limited to the partial view.
But that's exactly what I need. Is there a way to work around this limitation? Shortly, the goal is to inject JavaScript from a PartialView to the LayoutView, with an regular View between them.
The only way I know is the usage of setInterval() with a low interval like 50ms, and check there if jQuery or some of my custom class is defined in a loop until they are. Its a JS solution yes. But it makes it possible to include the script-block directly in the PartialView without making usage of sections. It fits well when you depend on a single variable like jQuery.
But I need to wait for custom classes to get loaded. They're included after jQuery. So writing a generic function like waitForTypeLoaded(type, callback) is not possible. It would cause me to write always the raw setInterval() code, which seems not a smart solution for me.
Something I did to get my scripts to run after Jquery was done loading was in my Partial Views and View Components I used the "DOMContentLoaded" event to load all my jQuery js script after the page was done loading. That way I could defer the Load of jQuery and Still Have jQuery code on my pages.
<script>
window.addEventListener('DOMContentLoaded',
function() {
$('body')....
});
</script>
Your problem can be solved as mentioned in my answer to this post:
How to render scripts, generated in TagHelper process method, to the bottom of the page rather than next to the tag element?
To sum up, you can create a pair of tag helpers, one that can be located in a partial view and just stores its content in a temporary dictionary, and the other that renders the content at the appropriate position (e.g. in the layout page). I use it extensively to render small dynamically created scripts as the final scripts of the body.
Hope it helps.
Honestly, I would make one step back and look at architecture once again if you have such dilemmas.
Why not add to required scripts which will be used on a couple of views/partial views to the main layout? In ASP.NET MVC you can use bundling mechanism (or you can write our own) - minify and bundle them with other required. It won't be heavy...
Your approach looks like unnecessary complicated.
I have read many posts on the internet, but in the end I still haven't found a nice solution to deal with Turbolinks + inline scripts.
Turbolinks does give a nice feeling and I don't really want to stop using it, but in some cases I have a hard time debugging duplicate event handlers.
I have some views with inline javascript : I actually prefer having the (small) javascript codes near the element(s) that are interacted with, saving only big javascripts functions for app.js.
So imagine I have a search page with several filters, but only on that specific page. When the user changes the search filters, it is supposed to GET (using remote/AJAX) the new results. The easiest way was to introduce
$(document).on('ready turbolinks:load', function() {
// Submit on every change
$('#myform input').change(function() {
$('#myform').submit()
}
})
When navigating with turbolinks and going back to the search page, I naturally end up with several duplicate bindings on every select, causing multiple form submits.
I have tried adding
$('#sidebar-search input').unbind()
Just before the .change() line but it doesn't seem to work, and for some reason the form is still posted several times : once with AJAX, several other duplicates (that thankfully are cancelled) and another non-remote request (my server replies with HTML).
Using turbolinks 5
As far as I can tell, there is no way to avoid this problem when using inline JavaScript. The section of the Turbolinks README “Working with Script Elements” advises avoiding inline <script>s when installing event handlers:
Turbolinks evaluates <script> elements in a page’s <body> each time it renders the page. You can use inline body scripts to set up per-page JavaScript state or bootstrap client-side models. To install behavior, or to perform more complex operations when the page changes, avoid script elements and use the turbolinks:load event instead.
It sounds like the reason you prefer inline scripts is the convenience of having relevant JS and HTML next to each other. This is a matter of workflow. While I’m afraid I don’t know any way to make separate JS files as convenient as inline JS, you can make it close by putting a comment in the HTML where the JS used to be, saying “this template has JS that is only for it”. When you are editing a template, if you see that comment, open the corresponding JS file in a horizontal split in your editor, so you can view both files at once. If you are using an editor that supports opening paths in files, you could even write the path to the JS file in the comment so you can open it just by following the link.
You have various choices for organizing which files your single-page JS snippets go in. You could put them in per-controller JS files like products.js, or the global file application.js, or you could create a new global file single_page_js.js. Then you could put comments above each section, labeling which template that code affects. Alternatively, you could also use some sort of naming convention to match JS files to templates. For example, when writing event handlers for the template app/views/products/index.html.erb, you could put the JS in app/assets/javascripts/products_index.js.
The ideal for you would be some sort of plugin that preprocesses your HTML templates to remove <script> elements, copies their contents to the global JS file, and adds wrapping code that ensures that that bit of JS is only run once, when the page is first visited. But I don’t know of any such plugin.
I used todo like this, and never had any issue with turbolink except disabled for specific links.
function run_after_turbo(){
$('#myform input').change(function() {
$('#myform').submit()
}
}
$(run_after_turbo);
$(document).on("turbolinks:load", run_after_turbo);
I had a similar issue and solved switching to plain js
// Old
$(document).on('click', 'a[data-toggle="submenu"]', function(event){
$(this).next('ul.submenu').slideToggle();
return false;
});
// new
var subMenus = document.querySelectorAll('a[data-oggle="submenu"]');
subMenus.forEach(function(subMenu){
subMenu.addEventListener('click',function(event){
$(subMenu).next('ul.submenu').slideToggle();
event.preventDefault();
event.stopPropagation();
});
});
So in your case should be like this
var form = doucument.querySelector('#myform input');
form.addEventListener('change', function() {
$('#myform').submit();
});
In teaching students in an intro web class, I want to find the most straight-forward way of building a multipage static site of about 7 pages without having them have to make 7 different pages.
Obviously, I can have them make a separate header, footer, and menu file, and use server side includes, and just put the includes onto 7 different pages of content - but that feels dirty.
In the past I had them doing it this way: http://www.tropicalteachers.com/web110/?Ignore_WEB_119_CLEAN:MX_-old_Extra_Credit:Dynamic_PHP - this was a quick experiment using the assignment as a model: http://www.yetirobotics.org/index2.php?pagename=team_yeti
but i feel like there should be a cleaner/simpler way to do it using javascript, or maybe in php - but i'm not sure of how.
Basically i'd like one main page with a menu -and when the menu items are clicked, it loads different content. I believe it's better to have the content in seven different files, but i could imagine it all being in the same JS within one page- remember, this site should be pretty simple.
I'd like to limit it to html/css/js/php, and preferably js OR php and not both.
with just the index page controlling (and loading) everything.
Thanks!
If you want to create a more modern framework then you should look into using javascript for displaying content dynamically (as you suggested in your question). To do this I would make use of a framework like jQuery as it makes asynchronous request calling far more simple. To do this you would code a single page with a specific area marked for the dynamic content.
Server side you would setup either pages or a database to return the main content area that will change upon request.
Client side you can use jQuery's load to place the requested content into the content area.
$('#contentArea').load('url', function() {
//callback area in case there is other stuff you want to do with js
location.hash = 'blah';
});
It would probably make sense to change the page's hashmark so that pages still seem static and are linkable as content changes.
location.hash = 'blah';
In addition you will need to override default link behavior by returning false when they are clicked.
myLink.click = function() {
$('#contentArea').load('url', function() {
//callback area in case there is other stuff you want to do with js
location.hash = 'blah';
});
return false;
}
I think this would be a good lesson for students as it shows the differentiation between client-side, server-side, and how to connect them dynamically via javascript.
Let's say I want to create a website that contains one page. All the content is dynamic and generated using JavaScript with DOM replacement. The good thing about this is that it creates a better user experience, especially for applications that contain catalogues (online stores, galleries, etc). The problem now comes with linking. Let's say I'm browsing the site and I feel like sharing that particular thing I'm looking at with someone, but the problem is the link is always the same since it's JavaScript that's doing the magic. So the question comes: how can I create a fully JavaScript run website while maintaining the ability to link?
Now there's hash linking, but I'm failing miserably. I've tried overriding all <a> tags, changing the hash, and preventing the default action like so
$("a").click( function(){
window.location.hash = $(this).attr("id");
processHash();
return false;
});
Yet, it will randomly scroll my body for no reason.
I'd like some insights on the restrictions of linking in a fully dynamic website. Thanks.
Here is one simple thing you can do:
window.onload = function () {
processHash();
}
or it can be using jquery $(function () {...});
what happens here is when the page is loaded example http://www.example.com/#some-link
the page content is loaded first then your function that handle links processHash(); will do its work
not even the new and shiny jQuery mobile library is 100% ajax, but it's close. Obviously with a very modern browser, checkout this doc site done in jQuery mobile: http://jquerymobile.com/test/
If you dig in the docs a little you see how they use hash linking with the framework and html5 data-content="page"
each <div data-content="page">Is an independent page, if I remember right</div>