What is the standard workaround for dynamic js files - javascript

Is there a standard workaround for something like this in ASP.NET:
//myinclude.js
$(document).ready(function() {
for(recs=0; recs < {{server-side-value}}; recs++) {
// process records
}
});
Note this is a js file. I know about WinForms ability to insert dynamic quoted scripts into the page. But how about a page's js file that is dependent on server-side values? I know you can use something like:
//myview.cshtml
var instance = new MyObject(<%= ServerSideValue =%>);
and include it on the page to pass it to the js file, but I'm wondering about the architecture of keeping js separate from html code so that an html/css designer can work with the template free of javascript; keeping everything separate. I primarily use MVC now.
What are some of the patterns to deal with this? Is the only solution dynamically inserting js into the actual page or having partial views included separately into the page.? Or is there a way to sprinkle server-side values in separated js? In short, no dynamic js files?
I'm not trying to fix an exact project at this time, I have just been curious about this on past projects.
Thanks...

There are multiple ways to achieve this. One of the ways would be populating your data into a Javascript objects on the HTML page directly.
//myview.cshtml
<script>
var pageData = {
name : '#variable1',
value1: #value1
};
</script>
And, in the javascript file:
//pageUI.js
if (pageData) {
$('#page_tile').html(pageData.name);
}
I am sure you can optimize a whole lot (for example, having a single communication between the server side data and the client side code). At the end of the day, you want to make sure that your javascript code can be resusable.

for example one can do this:
A. have the main .js code read any context-specific parameters from the current window like this (page.js):
!function(window){
var configData = window.MyAppNameConfigData;
// rest app code here..
}(window);
B. the server side script can inject these context-specific data in the page's html like this:
<script>
window.MyAppNameConfigData = {
param1: //..
param2: //..
// etc..
};
</script>
Note if needed make sure that the page.js is enqueued/loaded after the data have been injected/inserted (using a script dependency chain for example)

If it's not "inline" (on the View/Page itself), you could do a Partial View/Page:
Trivial example: _PartialJs.cshtml
$(document).ready(function() {
var foo = "#DateTime.Now.Year";
});
Then in your view:
<script>
#Html.Partial("_PartialJs")
</script>
Renders:
<script>
$(document).ready(function() {
var foo = "2015";
});
</script>
Hth...

Related

Object paths in javascript

I have an asp.net boilerplate project. I am trying to create a form and write it into database. I have a Index.cshtml file and Index.js file. I cant create object of c# class in javascript. It says "MyProject" is undefined.
var requestService = MyCompany.MyProject.Requests.RequestService;
is this valid?
What is the syntax of Paths in javascript?
Is it possible that creating an object in cshtml file and passing it to javascript file?
Alas, this is not how you do it. The js is client side only, and isn't aware that the .net code exists.
So, in ASP.NET Boilerplate there are services that we use in controllers. This services can be used in JavaScript file such as
var _tenantService = abp.services.app.tenant;
In view (cshtml) when we click on submit button, form is being sent to app services.
_$form.find('button[type="submit"]').click(function (e) {
e.preventDefault();
if (!_$form.valid()) {
return;
}
var tenant = _$form.serializeFormToObject();
abp.ui.setBusy(_$modal);
_tenantService.create(tenant).done(function () {
_$modal.modal('hide');
location.reload(true); //reload page to see new tenant!
}).always(function () {
abp.ui.clearBusy(_$modal);
});
});
And if we want to add new services or add new methods to services, we have to use camel notation in javascript files. Otherwise it says undefined. For example: I created a method named "NewCreate". I had to call it like "newCreate".
But I still don't know how Javascript accesses to "abp.services.app.tenant;"

Get model values in separate Javascript file

I'm using ASP.NET MVC 2 and stuck with the situation when needed to store all javascripts in separate javascript files.
But in some pages Javascript's contains information from server-side, so I need a way to do something like this.
I want to make separate JS files and include them in Site.Master. But still I want to make workable code blocks like this
loadNews("<%= Model.A%>", "<%= Model.B%>");
Is there any way to do some trick?
I'm a newbie on MVC and also facing that situation. I'm dealing with it by calling the javascript functions via a script block on the view.
Something like this:
--On MyFile.js
function loadNews(a, b) {
//Do fun stuff
}
--On Index.cshtml
<script type="text/javascript">
loadNews("<%= Model.A%>", "<%= Model.B%>");
</script>
Another option could be declare the variables on the view's script block and referencing those variables on the javascript, since their scope would be global. Would be an ugly thing and a bit harder to mantain, but also could do the job. Like this:
--On MyFile.js
function loadNews() {
doSomethingWithA(a);
doSomethingElseWithB(b);
}
--On Index.cshtml
<script type="text/javascript">
var a = "<%= Model.A%>";
var b = "<%= Model.B%>";
</script>
We had the same issue previous and found a nice solution using jQuery.
Firstly, we extend jQuery with our own namespace (we placed the following in a separate JS file and included it on the masterpage):
$.extend({
myProject: {
dataitem: {},
dataitems: function (a) {
$.extend($.myProject.dataitem, a);
}
}
});
Now, whenever we have a value that we want to pass to our JS file from the ASP view, we simply add the following to the view:
<script type="text/javascript">
$.myProject.dataitems({
foo: Model.Bar,
bar: Model.Foo
});
</script>
Now, for your separate JS file (which would be included below the aforementioned <script></script> block) accessing the value is simple:
$('#foo').click(function () {
alert($.myProject.dataitem.foo);
});
Can you put the data in hidden fields, then access them with Javascript?
<%= Html.HiddenFor(x => x.A) %>
loadNews($('#A').val());
EDIT: Sorry, MVC2

How can I combine my JavaScript files and still have my callbacks wait for a ready state?

I have lots of functions and event handlers that are split across multiple javascript files which are included on different pages throughout my site.
For performance reasons I want to combine all of those files into 1 file that is global across the site.
The problem is I will have event handlers called on elements that won't necessarily exist and same function names.
This is an example of a typical javascript file...
$(document).ready(function(){
$('#blah').keypress(function(e){
if (e.which == 13) {
checkMap();
return false;
}
});
});
function checkMap() {
// code
}
function loadMap() {
// code
}
I would need to seperate this code into an object that is called on that specific page.
My thoughts are I could re-write it like this:
(function($) {
$.homepage = {
checkMap: function(){
// code
},
loadMap: function(){
//code
}
};
})(jQuery);
And then on the page that requires it I could call $.homepage.checkMap() etc.
But then how would I declare event handlers like document.ready without containing it in it's own function?
First of all: Depending on how much code you have, you should consider, if serving all your code in one file is really a good idea. It's okay to save http-requests, but if you load a huge chunk of code, from which you use 5% on a single page, you might be better of by keeping those js files separated (especially in mobile environments!).
Remember, you can let the browser cache those files. Depending on how frequent your code changes, and how much of the source changes, you might want to separate your code into stable core-functionality and additional .js packages for special purposes. This way you might be better off traffic- and maintainance-wise.
Encapsulating your functions into different objects is a good idea to prevent unnecessary function-hoisting and global namespace pollution.
Finally you can prevent calling needless event handlers by either:
Introducing some kind of pagetype which helps you decide calling only the necessary functions.
or
checking for the existence of certain elements like this if( $("specialelement").length > 0 ){ callhandlers}
to speed up your JS, you could use the Google Closure Compiler. It minifies and optimizes your code.
I think that all you need is a namespace for you application. A namespace is a simple JSON object that could look like this:
var myApp = {
homepage : {
showHeader : function(){},
hideHeader : function(){},
animationDelay : 3400,
start : function(){} // the function that start the entire homepage logic
},
about : {
....
}
}
You can split it in more files:
MyApp will contain the myApp = { } object, maybe with some useful utilities like object.create or what have you.
Homepage.js will contain myApp.homepage = { ... } with all the methods of your homepage page.
The list goes on and on with the rest of the pages.
Think of it as packages. You don't need to use $ as the main object.
<script src="myapp.js"></script>
<script src="homepage.js"></script>
<-....->
<script>
myApp.homepage.start();
</script>
Would be the way I would use the homepage object.
When compressing with YUI, you should have:
<script src="scripts.min.js"></script>
<script>
myApp.homepage.start();
</script>
Just to make sure I've understood you correctly, you have one js file with all your code, but you want to still be in control of what is executed on a certain page?
If that is the case, then the Terrific JS framework could interest you. It allows you to apply javascript functionality to a module. A module is a component on your webpage, like the navigation, header, a currency converter. Terrific JS scans the dom and executes the js for the modules it finds so you don't have to worry about execution. Terrific JS requires OOCSS naming conventions to identify modules. It's no quick solution to your problem but it will help if you're willing to take the time. Here are some more links you may find useful:
Hello World Example:
http://jsfiddle.net/brunschgi/uzjSM/
Blogpost on using:
http://thomas.junghans.co.za/blog/2011/10/14/using-terrificjs-in-your-website/
I would use something like YUI compressor to merge all files into one min.js file that is minified. If you are looking for performance both merging and minifiying is the way to go. http://developer.yahoo.com/yui/compressor/
Example:
Javascript input files: jquery.js, ads.js support.js
run yui with jquery.js, ads.js, support.js output it into min.js
Javascript output files: min.js
then use min.js in your html code.

Javascript and jQuery file structure

I have created a sizable application javascript and jQuery. However my file structure is getting a bit messy!
At the moment I have one large JS file with a if ($('#myDiv').length > 0) { test at the top to only execute the code on the correct page, is this good practice?
There is also a mixture of plain JS functions and jQuery extensions in the same file e.g $.fn.myFunction = function(e) {.
I also have a few bits of code that look like this:
function Product() {
this.sku = '';
this.name = '';
this.price = '';
}
var myProduct = new Product;
Basket = new Object;
My question is for pointers on good practice regarding javascript and jQuery projects.
The code if ($('#myDiv').length > 0) { is not good practice. Instead, make your page specific JS as functions and execute them in the corresponding page . Like this:
var T01 = function(){
// JS specific to Template 01
};
var T02 = function(){
// JS specific to Template 02
};
HTML head of Template 01:
<script type="text/javascript"> $(T01); </script>
Consistency is the golden rule.
You can discuss design patterns back and forth, but if you want to have easily maintainable code where new people can come in and get an overview fairly quickly, the most important part, whatever design patterns you chose, is to have a consistent code base.
It is also the hardest thing to do - keeping your codebase clean and consistent is probably the hardest thing you can do as a programmer, and especially as a team.
Of course the first tip I can give you is to separate the jQuery extensions in their own source files. You can always serve everything together with a minification tool, so you should not worry about performance.
About the code youo mention, it could be simplified to
var Product = {
sku: '',
name: '',
price: ''
}
var myProduct = objectCopy(Product);
var Basket = {};
provided you write a simple objectCopy function which loops through the object own properties and just copies them to a new object (you can make a shallow or a deep copy, according to your needs).
Finally, if you think your code is starting to get messy, you may want to learn some patterns to organize JS code, like the module pattern. Alternatively, if you are familiar with doing this on the backend, you may want to organize your application following the MVC pattern. personal advertisement - I have written myself a tiny library which helps organize your code in this fashion. There are also many other libraries for the same task, often adding other functionality as well.
If you follow the MVC pattern, your page will actually correspond to some action in some controller, and you could just start it with a call like
<script>someController.someAction()</script>
in the head of your document, hence removing the need for the manual check for #myDiv. If you use my library MCV, it will be enough to declare your body like
<body class="mcv:controller/action">
and start the application with
$(document).ready(function() {
mcv.autostart();
});
Yes it's good practice to put as much of your code into a seperate JS file as this could then be compressed before transmission and hence speed up download time. However no you should not have code that looks like
if ($('#myDiv').length > 0) {
on every page. Split your JS code up into manageable functions and call those as-and-when you need to.
I don't see a problem with mixing JS and jQuery functions up in the same file.

How to organize javascript file into smaller pieces?

I currently have one large external javascript file that is used on the page. I currently wrap the code in a self-invoking function because I have other sections that are loaded using ajax tabs, so I want to avoid naming clashes with those other external js files.
The code in the file is organized like below. I would like to split some of the code inside the plannerTab namespace into smaller files, yet still have it be part of that namespace.
How could I do this? Or, do you guys recommend a different approach? Thanks!
// Document Ready
$(function ()
{
// initializes table
plannerTab.plannerTable.init();
});
var plannerTab = (function ()
{
// All the code for the page is in here. I would like to extract sections
// from in here and put them into their own external files while still keeping
// the namespacing
}();
Update
How could I separate parts from within the plannerTab variable into smaller external js files, and still maintain that they are part of the plannerTab namespace? A small example below.
// Scope: plannerTab.config - Would like to store configuartion into a separate file
var config = {
selectors: {
tableId: '#plannerTable',
addTaskId: '#AddTask',
editTaskSelector: '#plannerTable .edit',
dateFilterSelector: '#plannerTable_TimeFilter li',
deleteTaskClass: '.delete',
searchFilter: '#plannerTable_filter',
selectedDateFilter: 'selected-dateFilter',
taskCellSelector: '#plannerTable .task-col',
taskClass: '.taskId'
},
urls: {
addTaskFormURL: '/Planner/Planner/LoadAddTaskForm',
editTaskFormURL: '/Planner/Planner/LoadEditTaskForm',
deleteTaskURL: '/Planner/Planner/DeleteTask',
getTasksByDateRangeURL: '/Planner/Planner/GetTasksByDateRange',
viewTaskURL: '/Planner/Planner/ViewTask'
}
};
Look at this example (from google)
<script type="text/javascript">
function importScript(url){
var tag = document.createElement("script");
tag.type="text/javascript";
tag.src = url;
document.body.appendChild(tag);
}
window.onload = function(){
// imports go here
importScript("foo.js"); // example
};
</script>
I'm assuming that plannerTab becomes an object return result of the self executing function. If you need to add properties or methods to that object dynamically, you can take a look at jQuery.extend() http://api.jquery.com/jQuery.extend/
You would need to modify the external JS to use the jQuery extend method to add onto existing properties and methods of plannerTab. As long as you keep plannerTab a global variable, you will continue adding to it as you import more external js files.
If you are using the module pattern to maintain private variables in plannerTab, be sure to test how those values behave once you use jQuery.extend().

Categories

Resources