Unobtrusive JavaScript - Separate JS File Not Found - javascript

Using the concept unobtrusive JavaScript, I'm trying, for the first time, to place my JavaScript in a separate file from the HTML. But, no matter what I do, I get an error that the file wasn't found.
This is the actual error in the google chrome console (ctrl-shift-j):
GET http://localhost:14385/Home/TestPage.js 404 (Not Found)
I started with a new MVC 4 app. I created a new test page:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta name="viewport" content="width=device-width" />
<script src="TestPage.js"></script>
<title></title>
</head>
<body>
<div>
<input id="foo" value="snuh" />
</div>
</body>
</html>
And I created a new TestPage.js in the same folder:
$(document).ready(function() {
function dosomething() {
alert('snuh');
}
document.getElementById('foo').onclick = dosomething;
});
I've tried the tips posted here, but I always get an error that the JavaScript file isn't found. Any idea what's wrong with this simple test?
Note: The TestPage actually displays, with the input box showing.
This is the layout in solution explorer:

Make sure you reference your javascript from the correct location using server side helpers:
<script src="<%= Url.Content("~/TestPage.js") %>"></script>
This will properly reference the javascript file no matter from which location you have rendered this view. It assumes obviously that you have placed your javascript file in the root of your application. The The convention is to use the Scripts folder for this:
<script src="<%= Url.Content("~/Scripts/TestPage.js") %>"></script>
UPDATE:
Now that you have shown your project structure you seem to have placed the TestPage.js file inside the ~/Views folder. This won't work. This folder is not accessible from the client side. It is explicitly forbidden and not served by IIS. You should never place any static files inside. Move your javascript folder to the ~/Scripts folder.
Also you seem to be using jQuery inside your TestPage.js file but you never referenced it so your script won't work. If you want to use jQuery make sure that you have added it as well:
<script src="<%= Url.Content("~/Scripts/jquery-1.8.2.js") %>"></script>
<script src="<%= Url.Content("~/Scripts/TestPage.js") %>"></script>
or if you don't want to use jQuery fix your script so that it doesn't depend on it:
function dosomething() {
alert('snuh');
}
window.onload = function() {
document.getElementById('foo').onclick = dosomething;
};
or if you place your scripts at the end of your DOM you don't even need to wrap them in a document ready handler because at this stage the DOM will be ready and you can manipulate it:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<!DOCTYPE html>
<html>
<head runat="server">
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>
<input id="foo" value="snuh" />
</div>
<script src="<%= Url.Content("~/Scripts/TestPage.js") %>"></script>
</body>
</html>
and then inside your script:
function dosomething() {
alert('snuh');
}
document.getElementById('foo').onclick = dosomething;

Related

Knockout - Join Template with viewmodel

I am trying to associate the viewmodel with a html page in KnockoutJS.
The viewmodel is defined in an external file. And the html page has a reference to this viewmodel. I am using requirejs to load the file dependencies.
define(['knockout-latest'], function (ko) {
var SimpleListModel = function(items) {
this.items = ko.observableArray(items);
this.itemToAdd = ko.observable("");
this.addItem = function() {
if (this.itemToAdd() != "") {
this.items.push(this.itemToAdd()); // Adds the item. Writing to the "items" observableArray causes any associated UI to update.
this.itemToAdd(""); // Clears the text box, because it's bound to the "itemToAdd" observable
}
}.bind(this); // Ensure that "this" is always this view model
};
ko.applyBindings(new SimpleListModel(["Alpha", "Beta", "Gamma"]));
//return SimpleListModel;
});
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="styles.css" />
<script type="text/javascript" src="knockout-latest.js"></script>
<script type="text/javascript" data-main="viewmodel" src="require.js"></script>
<script type="text/javascript" src="jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="viewmodel.js"></script>
</head>
<body>
<form data-bind="submit: addItem">
New item:
<input data-bind='value: itemToAdd, valueUpdate: "afterkeydown"' />
<button type="submit" data-bind="enable: itemToAdd().length > 0">Add</button>
<p>Your items:</p>
<select multiple="multiple" width="50" data-bind="options: items"> </select>
</form>
</body>
</html>
I am getting the following error:
require.js:5 Uncaught Error: Mismatched anonymous define() module
I would like to know how can I join the html pages with its viewmodel in a separate file.
Looking at the code you posted, you have the links to the script files just listed on the page. With RequireJS, the list of script files should be removed, and only RequireJS and the script used for the application entry point should be included in the page. The application entry point can either be a <script> tag or as the data-main attribute in the RequireJS <script> tag.
I copied your code over to this example in plunker. I also moved the view model into a knockout component and loaded the HTML using the RequireJS text plugin. In main.js, there is a require.config() call that sets the paths for the text and knockout modules that point to a CDN. The paths could point to local files also, but note that the <script> tags for knockout and text are not in the index.html file. RequireJS will dynamically add them as it determines the dependencies based on the define() calls.

Move javascript files into inline html

I have an application that allows the use of inline javascript, but not javascript from source files. I'm trying to modify a webpage to open on this browser, and need to know how to put the javascript files from the webpage inline.
Use <script> tags in your HTML. They can go anywhere - I prefer inside the <head> tag:
<head>
<script type="text/javascript">
// put anything here - any type of valid javascript works
// if you import jquery, you can use jquery here too!
</script>
</head>
You should place your imported code into the script tag in your HTML page (application in your case), look at the following example:
<html>
<head>
<script type="text/javascript">
//Import your JS script here, e.g.:
function doSomething(){
..
}
</script>
</head>
<body>...</body>
</html>

WebView.InvokeScriptAsync not working in universal app

I am using a webview to display a certain html file, However, when I call InvokeScriptAsync, I keep encountering the error.
"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))". This occurs eventhough the script is called in NavigationComplete or DOMContentLoaded.
I prepared a simple app to debug this problem and I noticed that when the script is in a separate .js file, the error occurs. But if it is placed in the html file, the error would not occur.
I am hoping to have the script in a separate file since I have a quite a lot of functions to implement and I would be using some third party scripts so it would not be maintainable having all the scripts on the html file.
BTW, I did try the same code in a non-universal app and just used Windows 8.1 store app and it would work correctly even with the script stored in a separate file. That is why there must be some setting I am missing to make this work in a universal app.
This is my MainPage code:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
MapWebView.NavigationCompleted +=MapWebView_NavigationCompleted;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Uri url = new Uri("ms-appx-web:///Common/Web/SamplePage.html");
MapWebView.Navigate(url);
}
private async void MapWebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
try
{
await MapWebView.InvokeScriptAsync("SayHello", new string[] { "Hello! This is a test parameter" });
}
catch(Exception e)
{
string error = e.Message;
}
}
}
NOT WORKING (script is in a separate file which is sample.js):
html file:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script type="text/javascript" src="sample.js"></script>
<p>Parameter From Script File:</p> <div id="paramDiv"></div>
</body>
</html>
sample.js file:
function SayHello(parameter)
{
document.getElementById('paramDiv').innerHTML = parameter;
}
WORKING (script is in the html file):
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script>
function SayHello(parameter) {
document.getElementById('paramDiv').innerHTML = parameter;
}
</script>
<p>Parameter From Script File:</p> <div id="paramDiv"></div>
</body>
</html>
Here is the setup of my project:
I have my project setup as a universal app. In the shared code part of the universal app, I have the following files
Common (folder)
Web
SamplePage.html
sample.js
I found the solution to this problem after wasting my whole day on it.
It is caused by incorrect tagging of javascript files in *.Shared.projitem.
The javascript files are tagged as NONE in the ItemGroup which seems to cause it not being found. To make it visible to the project, change it to Content.
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)Common\Web\sample.js" />
</ItemGroup>
Kindly refer to this link where I also posted the solution.
https://social.msdn.microsoft.com/Forums/windowsapps/en-US/b29feddb-ae39-4580-9114-43839aabbcf2/webviewinvokescriptasync-not-working-in-universal-app?forum=winappswithcsharp

Referencing JQuery correctly

I am trying to use Jquery for the first time and I am getting an issue. I am using VS 2013, asp.net and VB.
My head tag is as follows.
<head runat="server">
<title></title>
<link href="StyleSheet.css" rel="stylesheet" type="text/css" />
<meta http-equiv="X-UA-Compatible" content="IE=EDGE" />
<script src="Bin/jquery-1.10.2.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$('#LowerText').hide();
$('#UpperText').hide();
$('#AssetStatusChoice').change(function () {
if($('#AssetStatusChoice').val("Fully Available"))
{
$('#CommentsText').hide();
}
if ($('#AssetStatusChoice').val("Restricted"))
{
$('#UpperLimit').show();
$('#LowerLimit').show();
}
if ($('#AssetStatusChoice').val("Unavailable"))
{
$('#Commentstext').show();
}
});
});
</script>
</head>
When I debug the page I get the following error.
0x800a1391 - JavaScript runtime error: '$' is undefined
It seems from Googling the error that I am not referencing the js file correctly. Can anyone help?
Add <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script> and Remove the
<script src="Bin/jquery-1.10.2.js" type="text/javascript"></script>
<script> Just use a host Jquery instead of adding it to you source. Read more :
3 reasons why you should use hosted jQuery
IIS doesn't serve content in the /bin directory.
Move it to another directory like /scripts or /js or /scripts/lib, something like that. The bin directory is a bad place to put script files.
You have a number of options here. You could use the Google CDN by adding the following to your header:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
Or, as it appears you're using .NET, you could do this:
<script type="text/javascript" src="<%=ResolveClientUrl("~/Bin/jquery-1.10.2.js") %>"></script>
The second option gives you the additional advantage that when used in a master page can be used in any content pages at any file system level and it will still resolve correctly.
As Stefan has also said, I'd recommend moving your jQuery file from your bin directory.
Copy the jQuery file in some other folder, like Scripts, or js, and in Solution Explorer check to see all files. Find the jQuery file you just copied, include it in the project, then drag it on the page where you want to place it. A correct script tag will be created.

Accessing Javascript globals from aspx page to another

Here's the underlying folder structure:
| ...
| Top.aspx
| ...
|
\---Include
...
ClientScriptGlobals.aspx
...
\---Config
...
Project.config
...
Here's a snippet of Top.aspx:
<%# Page Language="vb" AutoEventWireup="false" Codebehind="Top.aspx.vb" Inherits="Project.Top"%>
<!--DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"-->
<html>
<head><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE10" />
<title>....</title>
<META HTTP-EQUIV="imagetoolbar" CONTENT="no">
<!--#include virtual="..."-->
<!--#include virtual="Include/ClientScriptGlobals.aspx" -->
<!--#include virtual="...." -->
....
</head>
</html>
And finally ClientScriptsGlobal.aspx:
<script language="javascript">
//Globals
...
var FullTextSearchStatus = "<%= FullTextSearchStatus %>"
...
</script>
To give some context, Top.aspx includes ClientScriptGlobals.aspx so that I can access its global variables, which are also being used throughout the application.
My issue arises when I use aspnet_compiler.exe to pre-compile my application. Once it reaches ClientScriptsGlobal.aspx, it returns a bunch of errors like this:
error BC30451: Name 'FullTextSearchStatus" is not declared.
So now my question is, how can I tell ClientScriptsGlobal.aspx the location of FullTextSearchStatus's definition?
Keep in mind that when I opt to not pre-compile the application, these errors do not occur because the Javascript is not being compiled beforehand and therefore, its references have already been established (if that's the correct way describe this).

Categories