<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8577099701499272209</id><updated>2011-12-14T17:09:18.550-08:00</updated><category term='asp.net mvc'/><title type='text'>Gold Creek Group</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8577099701499272209.post-467879185382956046</id><published>2011-12-13T18:55:00.000-08:00</published><updated>2011-12-14T17:09:18.563-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='asp.net mvc'/><title type='text'>Automatically set MAXLENGTH on text input fields in ASP.net MVC 3</title><content type='html'>It seemed to me that ASP.net MVC 3 should know what the max string length is for any given database field and set it in the MAXLENGTH attribute on the corresponding web form.&lt;br /&gt;&lt;br /&gt;I went looking for a way to get the built-in Html.EditorFor to do it, but didn't find any.&lt;br /&gt;&lt;br /&gt;Here's a new helper called "LimitedEditorFor" which automatically adds the correct MAXLENGTH attribute to the text input tag. Call this exactly the same way you would call Html.EditorFor.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre  style="font-family:arial;font-size:12px;border:1px dashed #CCCCCC;width:99%;height:auto;overflow:auto;background:#f0f0f0;;background-image:URL(http://2.bp.blogspot.com/_z5ltvMQPaa8/SjJXr_U2YBI/AAAAAAAAAAM/46OqEP32CJ8/s320/codebg.gif);padding:0px;color:#000000;text-align:left;line-height:20px;"&gt;&lt;code style="color:#000000;word-wrap:normal;"&gt; &lt;br /&gt;namespace ExtensionMethods&lt;br /&gt;{&lt;br /&gt;   public static class MyExtensions&lt;br /&gt;   {&lt;br /&gt;     public static MvcHtmlString LimitedEditorFor&amp;lt;TModel, TValue&amp;gt;(this HtmlHelper&amp;lt;TModel&amp;gt; htmlHelper, Expression&amp;lt;Func&amp;lt;TModel, TValue&amp;gt;&amp;gt; expression)&lt;br /&gt;     {&lt;br /&gt;       string S = htmlHelper.EditorFor(expression).ToString().Replace("/&amp;gt;", "MAXLENGTH=\"" + GetLengthLimit(expression) + "\"/&amp;gt;");&lt;br /&gt;       return new MvcHtmlString(S);&lt;br /&gt;     }&lt;br /&gt;  &lt;br /&gt;     private static int GetLengthLimit(Expression expression)&lt;br /&gt;     {&lt;br /&gt;       MemberExpression ME = GetMemberInfo(expression);&lt;br /&gt;       Type type = ME.Member.ReflectedType;&lt;br /&gt;       string field = ME.Member.Name;&lt;br /&gt;       PropertyInfo prop = type.GetProperty(field);&lt;br /&gt;       // Find the Linq 'Column' attribute&lt;br /&gt;       // e.g. [Column(Storage="_FileName", DbType="NChar(256) NOT NULL", CanBeNull=false)]&lt;br /&gt;       object[] info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);&lt;br /&gt;  &lt;br /&gt;       if (info.Length != 1) return 0;  // Assume there is just one&lt;br /&gt;  &lt;br /&gt;       ColumnAttribute ca = (ColumnAttribute)info[0];&lt;br /&gt;       string dbtype = ca.DbType;&lt;br /&gt;       if (!dbtype.StartsWith("NChar") &amp;amp;&amp;amp; !dbtype.StartsWith("NVarChar")) return 0;&lt;br /&gt;  &lt;br /&gt;       Regex pattern = new Regex("\\((.+)\\)");&lt;br /&gt;       Match m = pattern.Match(dbtype);&lt;br /&gt;       if (!m.Success) return 0;&lt;br /&gt;  &lt;br /&gt;       return Convert.ToInt16(m.Groups[1].Value);&lt;br /&gt;     }&lt;br /&gt;  &lt;br /&gt;     private static MemberExpression GetMemberInfo(Expression method)&lt;br /&gt;     {&lt;br /&gt;       LambdaExpression lambda = method as LambdaExpression; &lt;br /&gt;       if (lambda == null) throw new ArgumentNullException("method"); &lt;br /&gt;       MemberExpression memberExpr = null; &lt;br /&gt;  &lt;br /&gt;       if (lambda.Body.NodeType == ExpressionType.Convert)&lt;br /&gt;       {&lt;br /&gt;         memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;&lt;br /&gt;       } &lt;br /&gt;       else if (lambda.Body.NodeType == ExpressionType.MemberAccess)&lt;br /&gt;       {&lt;br /&gt;         memberExpr = lambda.Body as MemberExpression;&lt;br /&gt;       } &lt;br /&gt;  &lt;br /&gt;       if (memberExpr == null) throw new ArgumentException("method"); &lt;br /&gt;  &lt;br /&gt;       return memberExpr;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This was a huge help: &lt;a href="http://joaodepaula.com/articles/columnsizereflection.html"&gt;http://joaodepaula.com/articles/columnsizereflection.html&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8577099701499272209-467879185382956046?l=goldcreekgroup.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/467879185382956046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://goldcreekgroup.blogspot.com/2011/12/automatically-set-maxlength-on-text.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/467879185382956046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/467879185382956046'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/2011/12/automatically-set-maxlength-on-text.html' title='Automatically set MAXLENGTH on text input fields in ASP.net MVC 3'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8577099701499272209.post-8755297905894569482</id><published>2010-01-07T16:48:00.000-08:00</published><updated>2010-01-07T16:52:36.623-08:00</updated><title type='text'>Bare-Bones Script</title><content type='html'>&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:verdana;color:#000000;"&gt;This is the smaller version of the client-side code to capture Javascript errors. &lt;a href="http://goldcreekgroup.blogspot.com/2009/12/heres-fully-commented-version-of.html"&gt;See description here&lt;/a&gt;.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Verdana;"&gt;This version does not save code snippets, but does crunch down to 267 bytes.  The full-featured version requires 678 bytes of minimized Javascript.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Verdana;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:green;"&gt;// !!!! IMPORTANT !!!!  &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:green;"&gt;// This must be the first script that runs.  &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:green;"&gt;// It cannot catch errors in script that &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:green;"&gt;// appears higher up the page.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;onerror =   &lt;span style="color:green;"&gt;// assign our own handler to the Window.onerror event&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:blue;"&gt;function&lt;/span&gt;(d, p, l) &lt;span style="color:green;"&gt;// d: Error Description; p: Path; l: Line&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// NOTE!!  ScriptCanary will only log requests from registered customers.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// See http://ScriptCanary.com&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// ScriptCanary version number&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:blue;"&gt;new&lt;/span&gt; Image().src = &lt;span style="color:#a31515;"&gt;"http://ScriptCanary.com/log.aspx?v=1"&lt;/span&gt; +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// Error Description  &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;d="&lt;/span&gt; + encodeURIComponent(d) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// Error Line #&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;l="&lt;/span&gt; + l +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// User Agent&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;u="&lt;/span&gt; + encodeURIComponent(navigator.userAgent) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// OS/Device&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;o="&lt;/span&gt; + encodeURIComponent(navigator.platform) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// URL&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;p="&lt;/span&gt; + encodeURIComponent(p) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:green;"&gt;// Random # to circumvent caching&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  &lt;span style="color:#a31515;"&gt;"&amp;amp;r="&lt;/span&gt; + Math.random();           &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;  onerror = &lt;span style="color:blue;"&gt;null&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8577099701499272209-8755297905894569482?l=goldcreekgroup.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/8755297905894569482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://goldcreekgroup.blogspot.com/2010/01/bare-bones-script.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/8755297905894569482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/8755297905894569482'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/2010/01/bare-bones-script.html' title='Bare-Bones Script'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8577099701499272209.post-1717073229399723659</id><published>2009-12-23T11:01:00.000-08:00</published><updated>2009-12-23T14:09:32.197-08:00</updated><title type='text'>How to capture Javascript errors</title><content type='html'>&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Why let some bugs slip through the cracks when they're so easy to identify? This article explains how to trap all those pesky Javascript errors that would otherwise take much longer to find. &lt;a href="http://software.isixsigma.com/library/content/c060719b.asp"&gt;Early detection before release &lt;/a&gt;is the key to keeping development costs low, and early detection after release helps rein in support costs.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Root of the Problem&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;You can usually count on your test team to find serious rendering problems or 50x server errors -- they're too obvious to overlook.&lt;br /&gt;&lt;br /&gt;However, Javascript errors often go unnoticed before release. Testers can forget to turn on error notification in all the browsers they're using to test the new web site code. Overall test coverage is usually lower in the less-popular browsers. New browser variants can gain popularity before your team can react.&lt;br /&gt;&lt;br /&gt;After release, you're counting on customers to tell your support team about the problems they see. However, most browsers by default do not show error alerts. Certainly customers aren't bothered by seeing the yellow shield in the status bar. What if there's functionality they can't see because of the errors? What if it's a serious issue -- do you really want to wait through the support lag to find out?&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Solution&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;By adding a little bit of code to your web pages and building or using an existing error-capturing service, you can collect all of the errors that testers and real users are encountering.&lt;br /&gt;&lt;br /&gt;All you need to do is:&lt;br /&gt;&lt;br /&gt;1) Add code to your page that triggers on the first error event.&lt;br /&gt;2) Have that code send the details of the error to a web service. See the &lt;a href="http://goldcreekgroup.blogspot.com/2009/12/heres-fully-commented-version-of.html"&gt;description of the ScriptCanary.com code below&lt;/a&gt; to get started.&lt;br /&gt;3) Create a web service that captures the error reports and saves them in a database.&lt;br /&gt;4) Develop a reporting mechanism so that your team knows when there's a new error to review.&lt;br /&gt;&lt;br /&gt;For steps 3) and 4), use any platform and technology you prefer. Or, sign up with &lt;a href="http://scriptcanary.com/"&gt;ScriptCanary.com&lt;/a&gt; and skip those steps completely.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8577099701499272209-1717073229399723659?l=goldcreekgroup.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/1717073229399723659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/how-to-capture-javascript-errors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/1717073229399723659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/1717073229399723659'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/how-to-capture-javascript-errors.html' title='How to capture Javascript errors'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8577099701499272209.post-4870738315348111476</id><published>2009-12-18T16:18:00.000-08:00</published><updated>2010-01-13T13:56:57.784-08:00</updated><title type='text'>ScriptCanary's Client-Side Error Handling Code</title><content type='html'>&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt;Here's a detailed walk-through of the ScriptCanary client code.&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt; &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt;The first thing we're doing here is attaching an event handler to the Window.Onerror event.&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt; &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt;The handler's tasks are simple:&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt; &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;color:#000000;"&gt;1) Grab a few lines of the erroneous source code if possible.&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:arial;"&gt;2) Send the source code and other details of the error report to the ScriptCanary web service.&lt;/span&gt; &lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;"&gt;At the very top of the script we have:&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;onerror =   &lt;span style="color:green;"&gt;// assign our own handler to the Window.onerror event&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:blue;"&gt;function&lt;/span&gt;(d, p, l) &lt;span style="color:green;"&gt;// d: Error Description; p: Path; l: Line&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;Next, we make the standard bare-Javascript moves to get the XMLHTTPREQUEST object:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;    &lt;span style="color:blue;"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    {&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;        R = &lt;span style="color:blue;"&gt;new&lt;/span&gt; XMLHttpRequest();&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    }&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    &lt;span style="color:blue;"&gt;catch&lt;/span&gt; (E)&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    {&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;        &lt;span style="color:blue;"&gt;try&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:#0000ff;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;span style="font-family:arial;"&gt;...et cetera. &lt;/span&gt;&lt;span style="font-family:arial;"&gt;Next, we see why we need the XMLHTTP object.&lt;br /&gt;&lt;br /&gt;We're going to attempt to do a synchronous read of the problem source code file and grab the exact source lines as they appear at this moment.&lt;br /&gt;&lt;br /&gt;This guarantees that the lines will be available when it's time to view the error, and won't cause cross-site access errors when the user is reviewing the bug details later. &lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;R.open(&lt;span style="color:#a31515;"&gt;"GET"&lt;/span&gt;, p, &lt;span style="color:blue;"&gt;true&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;R.onreadystatechange =&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:blue;"&gt;function&lt;/span&gt;()&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    &lt;span style="color:blue;"&gt;if&lt;/span&gt; (R.readyState == 4)&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    {&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;        &lt;span style="color:blue;"&gt;if&lt;/span&gt; (R.status == 200)&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;        {&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;            &lt;span style="color:green;"&gt;// Split the file into an array of lines.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;            A = R.responseText.split(&lt;span style="color:blue;"&gt;new&lt;/span&gt; RegExp(&lt;span style="color:#a31515;"&gt;"(\r\n){1}"&lt;/span&gt;));&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;            &lt;span style="color:green;"&gt;// Find only the lines around the error,&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;            &lt;span style="color:green;"&gt;// and insert the line numbers            &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;            &lt;span style="color:blue;"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; A.length; i++)&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;                &lt;span style="color:blue;"&gt;if&lt;/span&gt; (i &amp;gt; l - 4 &amp;amp;&amp;amp; i &amp;lt; l + 2)&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;                s += (i + 1) + &lt;span style="color:#a31515;"&gt;': '&lt;/span&gt; + A[i] + &lt;span style="color:#a31515;"&gt;"\n"&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;        }&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;    }&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;R.send(&lt;span style="color:blue;"&gt;null&lt;/span&gt;);&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now we can send the log entry via a simple fire-and-forget GET request on a new Image object.&lt;br /&gt;&lt;br /&gt;NOTE!! ScriptCanary will only log requests from registered customers.&lt;/span&gt;&lt;/p&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:blue;"&gt;new&lt;/span&gt; Image().src =&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="color:#a31515;"&gt;"http://scriptcanary.com/log.aspx?"&lt;/span&gt; +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// Error Description&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;d="&lt;/span&gt; + encodeURIComponent(d) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// Error Line #&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;l="&lt;/span&gt; + l +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// User Agent&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;u="&lt;/span&gt; + encodeURIComponent(navigator.userAgent) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// OS/Device&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;o="&lt;/span&gt; + encodeURIComponent(navigator.platform) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// URL&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;p="&lt;/span&gt; + encodeURIComponent(p) +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// ScriptCanary version number&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;v=1"&lt;/span&gt; +&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:green;"&gt;// Source code (note this can be truncated by the browser to the max url length)                        &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;   &lt;span style="color:#a31515;"&gt;"&amp;amp;s="&lt;/span&gt; + encodeURIComponent(s);    &lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="BACKGROUND: white;font-family:Courier New;font-size:10pt;color:black;"   &gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="BACKGROUND: white" face="Courier New" size="10pt" color="black"&gt;&lt;span style="color:#000000;"&gt;&lt;span style="font-family:arial;"&gt;Finally, disable our error handler. Subsequent errors tend to be noise -- cascading effects from the first problem.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="FONT-SIZE: 10pt; BACKGROUND: white; COLOR: black; FONT-FAMILY: Courier New"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-size:100%;"&gt;    &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; onerror = &lt;span style="color:blue;"&gt;null&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;font-size:100%;color:#000000;"&gt;Huge thanks go out to Eric Lawrence for his help with this script. &lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;font-size:100%;color:#000000;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:arial;font-size:100%;color:#000000;"&gt;Please send along questions and feedback in the comments, or through our feedback form on ScriptCanary.com.&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;Coming soon: The less-is-more version of the ScriptCanary client code -- only 204 bytes of pure sizzle!&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="font-family:Arial;font-size:100%;"&gt;&lt;/span&gt; &lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8577099701499272209-4870738315348111476?l=goldcreekgroup.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/4870738315348111476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/heres-fully-commented-version-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/4870738315348111476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/4870738315348111476'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/heres-fully-commented-version-of.html' title='ScriptCanary&apos;s Client-Side Error Handling Code'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8577099701499272209.post-4921754693432737735</id><published>2009-12-17T14:41:00.000-08:00</published><updated>2009-12-17T14:44:12.651-08:00</updated><title type='text'>Announcing ScriptCanary.com - Javascript Error Reporting</title><content type='html'>Finally!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://scriptcanary.com/"&gt;http://ScriptCanary.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Check out the super low intro price for all you bleeding-edge early adopters.&lt;br /&gt;&lt;br /&gt;More blog posts to come, including a detailed explanation of the client-side code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8577099701499272209-4921754693432737735?l=goldcreekgroup.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://goldcreekgroup.blogspot.com/feeds/4921754693432737735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/announcing-scriptcanarycom-javascript.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/4921754693432737735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8577099701499272209/posts/default/4921754693432737735'/><link rel='alternate' type='text/html' href='http://goldcreekgroup.blogspot.com/2009/12/announcing-scriptcanarycom-javascript.html' title='Announcing ScriptCanary.com - Javascript Error Reporting'/><author><name>Dorian Garson,</name><uri>http://www.blogger.com/profile/16724352051107545711</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_7f1sLFTReMY/SzKJIHYUXZI/AAAAAAAAAB4/t30p-AgFtkQ/S220/blogpic.jpg'/></author><thr:total>0</thr:total></entry></feed>
