28. April 2010 14:40
I was reading an article on Google's use of hash-bang in order to provide a consistent means of Ajaxy content for crawling/display. There are three points to resolve here. 1. Handling those cases where someone posts an ajaxy url, with the hash endpoint to facebook or twitter so that the search engines have a convention to handle these types of urls. 2. Being able to deal with the Ajaxy endpoint, the original content and the ajax callback content. 3. Being able to deal with those browsers that don't have scripting.
It got me thinking, how would one could work with progressive URL's via MVC and a few thoughts occurred to me. First, if the controller name is always the first portion of the url from the application base, if the MVC routing engine could simply replace the ?_escaped_fragment_= portion of the uri to be equal to the original route. For example http://mysite/controller/action/1?_escaped_fragment_=/otheraction/2 would be equivalent to http://mysite/controller/otheraction/2 on the backend. Second, How difficult would it be for the default view engine to be transposed in the instances of an expected response type give html, vs js. Similar to how WCF over http handles JSON via the same endpoints as XML. I know this has been discussed in the past.
Where this leads me, is thinking it might be nice to have an ASP.Net MVC 2 based framework, with conventions for handling these scenarios as a default. I like ASP.Net MVC quite a bit, and have followed Castle and Fubu as well. I'm merely thinking that it would be nice if there were a default starter kit towards creating a browser and search engine friendly Ajaxy application. It really isn't easy. I think that the google hash-bang solution leaves out the people that don't have scripting enabled, getting a hash-bang endpoint is near worthless, save for a <noscript>script disabled indexable links here</noscript>. And progressive enhancement (aka Hijax) techniques don't allow for a browser engine to properly index copy/pasted urls. Having some level of convention to support both is necessary. I think it's equally necessary for google to post the _escaped_fragment_ based urls in the search results for those users who have scripting disabled.
20. April 2010 09:44
Thinking it would be cool to put this on a T-Shirt, with the jsninja.org logo on the front, and the following code snippet on the back.
var a = ["lawn","off","get","my"];
var o = (function(){
var u = function(){
var t = this;
var s = arguments;
return [t[s[0]],t[s[1]],t[s[2]],t[s[3]]];
};
var b = Array.prototype.slice.call(arguments);
var a = b.shift();
return u.apply(a,b).join().replace(/\,/g,' ');
}(a,2,1,3,0));
alert(o[0].toUpperCase() + o.substr(1) + '!');
13. April 2010 10:59
I've been working on a number of web based applications recently, and have taken to using a few techniques that I thought I would share. I won't be sharing the code so much, which is ASP.Net centric, but will discuss what I am trying to accomplish.More...
1. April 2010 15:19
I'm currently working on a project where one of the applications has a subform, or child form that has interactions that are separate from the main page within the application. The main page is essentially a filter form, with a results grid. Each item in the grid displays a child form, when the child form is completed, the original screen is displayed again.
Sounds simple enough right? Well, the business desire is to have the filter option form keep its' settings when returning to the page. My initial solution was to use a jQueryUI dialog based option (via an IFrame). Which works great, except in certain conditions IE7 flickers when the mouse moves in/out of the IFrame itself if there are scroll bars present. ugh.
I didn't want to use cookies, or server-side session state as these will affect all windows using the main form. If a user launches the app in a new window, with different filters set, I didn't want these windows to effect each other. Then it occurred to me, I could use window.name to store the state of the form when entering, and leaving the page. I tend to store an "__original_value__" for each form element when a page loads, that way its' easy enough to return to default values later on via code. More...
19. February 2010 12:13
I hate to admit it, but I do read Stephen Chapman's Blog, and to be honest I tend to find a lot of the things he covers as incomplete, or outright not the best way to do something. A lot of entries are simple repeats of past entries as well. In the past I've had comments censored, specifically when he stated that you should just ignore IE in a prior post, I had a bit of a strongly worded response. In any case, today's entry covered Optional Function Arguments. There's one small point he missed the boat with here regarding the arguments instance.
"That is as far as the similarity to arrays goes though as none of the other methods and properties that can be used with arrays can be used with the arguments object."
It is possible to easily convert the arguments object to an Array instance though. Here's a simple example.
function argumentsToArray() {
//convert object arguments to args Array
var args = Array.prototype.slice(arguments, 0);
//alerts true
alert(args instanceof Array);
}
I've thought about, and may actually do more of these annotation posts. I've also been thinking about doing some compilation posts with information from Ajaxian, DailyJS and a few other sites.
15. February 2010 11:14
Okay, this is a quick one. There are several states that can be considered empty in JavaScript, a non-numeric value in a number, an invalid date, and empty string, an undefined value, and a null value. The issue is that some of these require testing against isNaN, and others will evaluate as matching null or an empty string (ex: the number zero and the boolean false). What I wanted was a simple method to check for a non-empty object or string, here it is.
function isEmpty(obj) {
if (typeof obj == 'undefined' || obj === null || obj === '') return true;
if (typeof obj == 'number' && isNaN(obj)) return true;
if (obj instanceof Date && isNaN(Number(obj))) return true;
return false;
}
How it works, is first it tests for an 'undefined' object, an object that is explicitly equal to null, or explicitly equal to an empty string. If it matches, it's empty. From here there's some more specific checking, if it's a number type of variable, and isNaN (Not a Number), then it's empty. If it's a date, and Number(obj) (which gets the value of the date as a Number) isNaN, then it's an invalid date, and ergo isEmpty. Otherwise the isEmpty returns false (valid, non-empty value). Hope this helps some of you. :)
11. February 2010 13:26
Okay, so you really want to be able to have some of your JavaScript methods to have access to a variable that is private, but maintains state between calls. The first piece of knowledge, is that you can have the contents of a function execute itself at runtime.
(function(){ /*Your actions here*/ })();
This is a very common method of defining complex classes and libraries, that can have their own variables or methods that aren't otherwise available to the object model outside this closure. When you utilize "this" within the function's closure it will be default to the global object, which in the Browser DOM is "window".
(function(){
this.test = "Test Value";
})();
alert(test); //alerts "Test Value"
Usually when creating libraries in JavaScript it's a good idea to create namespaces for your library. More...
7. January 2010 10:44
Okay, so you want to utilize some of the niceties of the new EcmaScript 5 extensions to Date. Namely they've added a nice instantiation from an ISO-8601-style string, as well as a Date.prototype.toISOString method definition. In addition there are Date.UTC and Date.now methods defined. As the nice guys over at Mozilla have offered script based extensions to Arrays to support their method extensions there, I wanted to do something similar for Date instances. I've managed to do this, and have had it done since the ES5 specs were released, but figured I should put this out there for anyone interested.
var epoch1 = new Date("1970-01-01T00:00:00.000Z");
var epoch2 = new Date(0);
if (epoch1.getTime() == epoch2.getTime())
alert("Epochs match!");
alert(epoch1.toString()); //localized date instance of the JS epoch
alert(epoch2.toISOString()); // "1970-01-01T00:00:00.000Z"
alert(epoch1 instanceof Date); // true
alert(epoch1.constructor == Date); //true
alert(Date.UTC(1970,0,1,0,0,0,0)); // 0
I also have a few convenience methods for handling Microsoft's JSON encoded strings. As well as rolling a date from a "Local" or "UTC" version.
DateExtensions.js (11.67 kb)
Edit 2010-01-08: I added missing support for .constructor == Date
3. September 2009 16:50
Just in case anyone else needs it, here's my method for getting the millisecond offset of a server's local time to UTC time in milliseconds, for use in client-side JavaScript.
private int ServerSideJsUtcOffset
{
get {
DateTime epoch = new DateTime(1970,1,1);
int offset = (int)epoch.ToUniversalTime().Subtract(epoch).TotalMilliseconds;
return offset;
}
}
There's really not much to it, it's mainly so that I can handle converting serialized dates to a proper local time on the client. The DateTime objects in question are stored in a database as the UTC date-time, via an ORM tool, and sent to the client with System.Web.Script.Serialization.JavaScriptSerializer. All the server-side code uses the same ORM tool, and all the client-side JSON is processed via the same local parser. So it was simply easier adjusting the client-side parser than it was to adjust the server-side class hierarchy.
I should note that I could have set the initial date to DateTime.Now instead of implicitely using the JS epoch, as the difference would be the same for any localized DateTime, just felt the clarity was worth it.
22. July 2009 10:52
Okay, so you love the Firebug Console, and related output to the console tab within Firebug. Don't we all, however there is a minor problem in leaving in all your log, and debug (etc) statements, and that is the fact that the console object doesn't exist in other browsers, or Firefox without Firebug. You will want to put the script segments below into a file that is called before other scripts on your page. More...