How to use Gulp with Razor and Layout.cshtml - asp.net-mvc

What is the best way to use Gulp in MVC template files? The problem is that my layout.cshtml files contain links to JavaScript files, gulp would need to modify these files to point at the optimized minified files. The problem is that I cannot see how I can use gulp to modify these files to point at the optimized files for debug and release because the source file would need to be the destination file and the mechanism would need to work with TFS. The best idea I have had would be to use the bundling mechanism. Before investing time into this I want to see if there are simpler alternatives.

Here is my solution, please let me know if there is a better way of doing this.
I ran:
Install-Package System.Web.Optimization.HashCache
Then I modified the BundleConfig.cs to include
var myBundle = new ScriptBundle("~/bundle_virtual_path").Include("~/Scripts/CombinedFile.js");
myBundle.Transforms.Add(new HashCacheTransform());
bundles.Add(myBundle);
Then I modified _Layout.cshtml to include
#{
if (HttpContext.Current.IsDebuggingEnabled)
{
<script src = "~/Scripts/App/File1.js" ></script>
<script src = "~/Scripts/App/File2.js" ></script>
}
else
{
#Scripts.Render("~/bundle_virtual_path");
}
}
In this way I use bundles to do cache busting on the output of a gulp script which can be attached to the before build event in the Task Runner Explorer. For completeness here is a extremely simple funtion that generates the CombinedFile.js in this sample
gulp.task('myTest', function () {
return gulp.src(['Scripts/App/File1.js', 'Scripts/App/File2.js'])
.pipe(concat('CombinedFile.js'))
.pipe(gulp.dest('Scripts'));
});
Gulp file listening functions should be attached to the Project Open event

I found a solution for this without bringing .net bundling into the picture.
using the gulp plugin gulp-rev and the nuget package called FileTagger
gulp.js
var gulp = require('gulp'),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify"),
filter = require("gulp-filter"),
rename = require("gulp-rename"),
rev = require('gulp-rev');
var paths = {};
paths.jsSource = mainBowerFiles();
paths.baseReleaseFolder = "app";
///these names get alter by rev()
paths.baseJSReleaseFile = "site.min.js";
gulp.task("min:js", function () {
var jsFilter = filter('**/*.js', { restore: true });
return gulp
.src(paths.jsSource)
.pipe(jsFilter)
.pipe(uglify())
.pipe(concat(paths.baseReleaseFolder + "/" + paths.baseJSReleaseFile))
.pipe(rev())
.pipe(gulp.dest("."))
.pipe(jsFilter.restore);
});
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App</title>
#FileTagger.Render.Script("~/app/site-*.min.js")
</head>
<body>#RenderBody()</body>
</html>

Related

access custom dom function from firefox add-on

I am working on a Firefox Add, using the newest SDK. The problem I am having, is that when ever I try to run a custom dom function it doesn't work.
Scenario:
The firefox add-on must be able to loop through all tabs, and if the correct one is open based on the title, run a specific function, like: mydom.checkIt();
<!DOCTYPE html>
<html>
<head>
<title>My Web</title>
</head>
<body>
<script>
mydom = {};
mydom.checkIt = function (){
alert('Hi');
};
</script>
</body>
</html>
Then the add-on source code would be something like:
var tabs = require('sdk/tabs');
for (let tab of tabs)
{
if(tab.title=='My Web')
{
tab.activate();
}
}
tabs.on('activate', function(tab) {
tab.attach({
contentScript: "if(typeof(mydom)!=='undefined')mydom.checkIt();else console.log('no defined');"
});
});
But this doesn't work and it says always: "no defined"
Any ideas?
You have to get into the dom js scope with unsafeWindow or wrappedJSObject. So contentWindow.wrappedJSOBject.checkIt() works from bootstrap addon (not sure about sdk)
Warning though, this may not be e10s friendly and we should find a way to support that

What is the /packages/$sdk/ folder inside a Google Dart build for?

After building a Google Dart web app in Dart Editor (the Pub Build (Generates JS) option) the folder layout is like this. My app imports both dart:html and dart:async but It seems I can upload everything but the $sdk folder to my server and the app will run fine in both Dartium and in other browsers. Is there some reason I need to upload the $sdk folder, and what is it for? Tried googling but I see no answer, thanks in advance!
Edit: Here's a working example of my project from DartEditor 1.5.8 and below is the code for it.
hexclock.dart:
import 'dart:html';
import 'dart:async';
DateTime theTime;
String theHour, theMinute, theSecond;
Timer theTimer;
void main() {
theTimer = new Timer.periodic(new Duration(seconds: 1), getTime);
}
void updateColours(){
String bgcol = "#" + theHour + theMinute + theSecond;
querySelector("body").style.backgroundColor = bgcol;
}
void printTime() {
querySelector("#hour").text = theHour;
querySelector("#minute").text = theMinute;
querySelector("#second").text = theSecond;
}
void getTimeInit(){
theTime = new DateTime.now();
theHour = "${checkZero(theTime.hour)}";
theMinute = "${checkZero(theTime.minute)}";
theSecond = "${checkZero(theTime.second)}";
printTime();
updateColours();
}
void getTime(Timer t){
theTime = new DateTime.now();
theHour = "${checkZero(theTime.hour)}";
theMinute = "${checkZero(theTime.minute)}";
theSecond = "${checkZero(theTime.second)}";
querySelector("#title").style.opacity = "0";
querySelector("#clock").style.opacity = "1";
printTime();
updateColours();
}
String checkZero(int anInt){
if (anInt < 10)
return "0${anInt}";
else
return "${anInt}";
}
hexclock.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HexClock</title>
<script async type="application/dart" src="hexclock.dart"></script>
<script async src="packages/browser/dart.js"></script>
<link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="hexclock.css">
</head>
<body>
<div id="title" class="centre">hexclock</div>
<div id="clock" class="centre">#<span id="hour"> </span><span id="minute"> </span><span id="second"> </span></div>
</body>
</html>
pubspec.yaml:
name: HexClock
description: A sample web application
dependencies:
browser: any
In the pub source code I found this:
// "$sdk" is a pseudo-package that allows the dart2js transformer to find
// the Dart core libraries without hitting the file system directly. This
// ensures they work with source maps.
var libPath = path.join(sdk.rootDirectory, "lib");
var sdkSources = listDir(libPath, recursive: true)
.where((file) => path.extension(file) == ".dart")
.map((file) {
var idPath = path.join("lib",
path.relative(file, from: sdk.rootDirectory));
return new AssetId('\$sdk', path.toUri(idPath).toString());
});
I don't know if this matches exactly what you're seeing, but my guess is that it's related. This would in theory allow client-side debugging even through SDK functions, which could be very useful.
Basically the entire build folder is intended to be deployed.
There are some redundant files like the *.dart.pecompiled.js which are only necessary for CSP environments (Chrome App for example).
I think there was a recent change so that these files are not generated anymore.
There might be other things redundant too but I haven't seen any information about it yet.
You could try with a Dart 1.6 release (stable should be out) and check if this was dropped or if there has to be another explanation.
I use always bleeding_edge which is currently 1.7+.
Another explanation is that this is only created when you build in debug mode.
DartEditor does this by default.
Try pub build from the command line to see if it is still generated.

Trigger.io load page dynamically

So I was using trigger.io to create a page where there's a custom menu at the bottom and each button loads an external HTML page into main container. I had to hack around to make this work so I was wondering if there's a better way of doing it.
I started using the $('.main').load('pages/test.html') and it doesn't work. Instead I had to do:
forge.file.getLocal('pages/test.html', function (file) {
forge.file.string(file, function (str) {
$('.main').html(str);
});
});
which is kinda messy.
Also if the str HTML content as a img tag, the img doesn't show since the src attribute gets messed up. So I had to do another hack:
forge.file.getLocal('pages/test.html', function (file) {
forge.file.string(file, function (str) {
var $main = $('.main');
$main.html(str);
//Hack to resolve img src
var imgPath;
$main.find('img').each(function () {
var $this = $(this);
// First 8 chars is "file:///"
imgPath = $this.prop('src').substr(8);
forge.file.getLocal(imgPath, function (file) {
$this.prop('src', file.uri);
});
});
});
});
Any better way of purely loading an external HTML page without all the hassle?
Thanks!
Testing with forge platform v1.4 (at the time of writing, v1.4.18) on Android 4.1 and iOS (both the iPhone simulator and an iPad), I seem to be able to use jQuery's load method without any extra effort. Here's the structure for my testcase:
src/
index.html
face.png
pages/
hello.html
Here's the contents of index.html
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(function () {
$('.content').load('pages/hello.html');
});
</script>
</head>
<body>
<div class="content">
</div>
</body>
</html>
And pages/hello.html:
<b>hello world</b><img src="face.png">
Which resulted in this just after app launch:
One gotcha I can see with this approach is that the src attribute for the img tag had to be relative to index.html. If you're still having problems then a more specific testcase and/or details of forge platform version used as well as what devices/simulators you tested on might be useful.

Resources Plugin -- How To include all contents in a directory?

I have a grails app that contains a whole mess of individual javascript files in a series of nested directories. I want to manage them via the resources plugin, but don't want to have to explicitly register each one.
Web Dir Structure
webapp
app
controller
controller1.js
controller2.js
...
model
model1.js
...
view
view1.js
what would be great is to just declare in my AppResources.groovy file:
resource url: 'app/**/*.js'
but that doesn't work -- throws a null pointer. I've tried:
resource url: 'app/**' but with no luck
I've thought that i would put some code in the config file that would recurse through the directory structure, but that doesn't seem to be working. Here's what I've tried:
def iterClos = {
it.eachDir( iterClos );
it.eachFile {
resource url: ${it.canonicalPath};
}
}
iterClos( new File("$grails.app.context/app") )
Unfortunately that failed as well.
Does anyone have any ideas how I could achieve this?
problem solved.
As it turns out, the idea of running code to recuse through my javascript directories works. I just had the code incorrect. Here is the code that dynamically loads my javascript files:
--AppResources.groovy
import org.codehaus.groovy.grails.web.context.ServletContextHolder as SCH
modules = {
core {
resource url: '/resources/css/app.css', disposition: 'head'
resource url: '/resources/css/myapp.css', disposition: 'head'
resource url: '/extjs/ext-all-debug.js', dispostion: 'head'
getFilesForPath('/app').each {
resource url: it
}
}
}
def getFilesForPath(path) {
def webFileCachePaths = []
def servletContext = SCH.getServletContext()
//context isn't present when testing in integration mode. -jg
if(!servletContext) return webFileCachePaths
def realPath = servletContext.getRealPath('/')
def appDir = new File("$realPath/$path")
appDir.eachFileRecurse {File file ->
if (file.isDirectory() || file.isHidden()) return
webFileCachePaths << file.path.replace(realPath, '')
}
webFileCachePaths
}
The above will cause the Resource plugin to track my javascript files. Here's what the html looks like when Resources is in debug mode:
<script src="/myapp/extjs/ext-all-debug.js?_debugResources=y&n=1336614540164" type="text/javascript" ></script>
<script src="/myapp/app/controller/LogController.js?_debugResources=y&n=1336614540164" type="text/javascript" ></script>
<script src="/myapp/app/controller/LoginController.js?_debugResources=y&n=1336614540164" type="text/javascript" ></script>
<script src="/myapp/app/controller/ProfileController.js?_debugResources=y&n=1336614540164" type="text/javascript" ></script>
...
Being new to Grails, it is a very welcome fact that one can put executable code within a config file!

IIS7.5 not displaying Flash object

I'm writing a MVC web app in ASP.NET MVC, which is supposed to be serving up a Flash object written by one of my colleagues. I don't know any Flash; he doesn't know any C#/ASP.NET; hence the question goes to SO!
The code on my web page looks like this:
<head>
(blah blah blah...)
<script type="text/javascript" src="/FlashStuff/js/swfobject.js"></script>
<script type="text/javascript">
var GP_MLM_flashvars = {};
GP_MLM_flashvars.remote = 'true';
GP_MLM_flashvars.streamprovider = 'localweb';
GP_MLM_flashvars.referer = '';
GP_MLM_flashvars.bgcolor = '#000033';
var GP_MLM_params = {};
GP_MLM_params.menu = 'false';
GP_MLM_params.allowFullScreen = 'true';
GP_MLM_params.salign = 'tl';
GP_MLM_params.scale = 'noscale';
GP_MLM_params.wmode = 'opaque';
GP_MLM_params.bgcolor = '#000033';
var GP_MLM_attributes = {};
GP_MLM_attributes.id = 'GP_MLM';
GP_MLM_attributes.name = 'GP_MLM';
swfobject.embedSWF('/FlashStuff/swf/GP_MLM.swf', 'GP_MLM', '100%', '100%', '9', '/FlashStuff/expressInstall.swf', GP_MLM_flashvars, GP_MLM_params, GP_MLM_attributes);
</script>
</head>
(etc.)
When I debug this page using the VS Development Server, it all appears very happily and works fine. But if I try to debug using my local IIS (7.5) server, the Flash object doesn't get loaded.
I'm guessing I need to do something on IIS to enable using the Flash object - but what?
EDIT: Problem partially solved; the clue came from the "404" error (thanks #Beliskner).
It appears that when you're running under the VS Development Server, your root folder is the project folder, and in my case "/FlashStuff" comes directly off my project folder, so that worked fine.
But when you run off the IIS server, the root folder is the Default Web Site (or whatever site you're using). Now, with a project URL set to "http://localhost/MyTestApp", I have to prefix all my paths with "/MyTestApp", e.g.:
<script type="text/javascript" src="/MyTestApp/FlashStuff/js/swfobject.js"></script>
Changed all the paths; works fine now.
This is a pretty ugly situation now, though - because I am now hard coding deployment-specific information into my app! So if I decide to deploy my app onto an IIS server in a folder called "MyLiveApp", I have to go around changing the file references everywhere! And if I want to debug it - then what? Go changing all the references back to "MyTestApp"?
Obviously I'm not the first developer to come up against this situation, and it is unthinkable that you have to do what I'm saying above. So what is the trick for dealing with this situation?
Have you setup the IIS MIME types? Have you used firefox firebug to check the request isn't 404ing?
Mime types
http://technet.microsoft.com/en-us/library/cc725608(WS.10).aspx - I suggest using the GUI
Extension: ".swf"
Type is: "application/x-shockwave-flash"
Firebug
Firebug network monitor: http://getfirebug.com/network
Edit
Use this to solve your problem: http://www.dailycoding.com/Posts/the_script_tag_runatserver_problem_solution_using_resolveurl.aspx
Try embedding the Flash object in the body of your html page
<head> (blah blah blah...)
<script type="text/javascript" src="/FlashStuff/js/swfobject.js"></script>
</head>
<body>
<script type="text/javascript">
var GP_MLM_flashvars = {};
GP_MLM_flashvars.remote = 'true';
GP_MLM_flashvars.streamprovider = 'localweb';
GP_MLM_flashvars.referer = '';
GP_MLM_flashvars.bgcolor = '#000033';
var GP_MLM_params = {};
GP_MLM_params.menu = 'false';
GP_MLM_params.allowFullScreen = 'true';
GP_MLM_params.salign = 'tl';
GP_MLM_params.scale = 'noscale';
GP_MLM_params.wmode = 'opaque';
GP_MLM_params.bgcolor = '#000033';
var GP_MLM_attributes = {};
GP_MLM_attributes.id = 'GP_MLM';
GP_MLM_attributes.name = 'GP_MLM';
swfobject.embedSWF('/FlashStuff/swf/GP_MLM.swf', 'GP_MLM', '100%', '100%', '9', '/FlashStuff/expressInstall.swf', GP_MLM_flashvars, GP_MLM_params, GP_MLM_attributes);
</script>
(etc.)
</body>
I guess embedSWF is a javascript function to write out the object tag
Yes, you need to add swf as a IIS 7 mime type per site.
I had this same issue with .mp4 files

Resources