November 13, 2018
Walkthrough: Serving gzipped JavaScript files from Amazon S3
Posted by
Dan Shultz
at
9:45 PM
0
comments
October 10, 2018
Walkthrough: Creating a basic Chrome Extension
Posted by
Dan Shultz
at
3:21 PM
0
comments
Labels: Chrome Extension , JavaScript
October 19, 2017
Copy Code button with feedback when code has been successfully copied.
Posted by
Dan Shultz
at
12:34 PM
0
comments
June 30, 2017
The world's simplest AngularJS tab control
I had originally scoured the web for a bootstrap or other tab control available, but after playing around with some HTML & Angular, I came up with this simple, functional control: 1 line of JS, 2 css selectors and 4 divs.
See the Pen World's simplest AngularJS tab control by Dan Shultz (@danshultz11) on CodePen.
Posted by
Dan Shultz
at
2:56 PM
0
comments
October 31, 2015
Visual Studio TACO - Cordova WebView containing jQuery
If you're using Visual Studio Tools for Apache Cordova (TACO), you may notice a problem if you want to display an external webpage using the Cordova WebView, if the external page uses jQuery. Once you build and start debugging your app, as soon as you try to display the external page, an exception will be thrown in the jquery.js file used by the external page.
Before we look at what the problem is, here's a quick review of displaying external web pages in a Cordova app:
Whitelist the page/domain in config.xml in the Domain Access section under the Common tab
In JavaScript, call window.open(whitelistedUrl)
The good news about this problem, is it's not really a problem - except when you're debugging. After failing every time I tried testing opening the new window, I swapped in the non-minified jquery file (in the external page) to take a look at where we were failing. It ends up in the jquery file itself, it does a try-catch that should throw an error for all non-gecko browsers, then swallows the error:
try {
matches.call( div, "[test!='']:sizzle" );
rbuggyMatches.push( "!=", pseudos );
} catch ( e ) {}
...But it ends up that even though this error is swallowed, The Visual Studio TACO debugger stops the processing at the point where the error is thrown, and even if you continue processing, it usually won't display the page. Even though this code is executed on any page on the www containing jquery, when those pages are pulled into a Cordova WebView using Visual Studio TACO debugging, processing stops and the app appears to error out for no reason.
But if you run your app in Release Mode, you'll see that the page gets pulled into the Cordova WebView just fine, now that the debugger doesn't halt on the swallowed error. So the answer is that you can't debug past the point where you pull an external page into a Cordova WebView. You'll need to test that part in release mode, and if there are any problems, you can debug the page using Chrome Dev Tools on the site itself.
If this is unacceptable, another alternative would be to look into using the Cordova InAppBrowser plugin, which has no problem with external jQuery files, but the downside is that it does pop up a new browser window.
Posted by
Dan Shultz
at
9:45 PM
0
comments
Labels: Cordova , JavaScript , jQuery , PhoneGap , Visual Studio TACO
October 22, 2015
First Take on Visual Studio Tools for Apache Cordova (TACO)
I installed the Visual Studio Tools for Apache Cordova last week to see how feasible it would be to use with an existing PhoneGap Android codebase.
I still haven't gotten to the point of publishing to Google Play yet (next post), but I thought I'd share a few of the pain points/errors I've encountered during setup and steps to resolve them:
(Note that these are specific to Android)
1) "Could not create the Java Virtual Machine" error
This is a memory issue with the JVM. The recommendation is to set your _JAVA_OPTIONS TO -Xmx512M
Full instructions
2) Error DEP10201 (No device found)
The Android emulator is a slow klunky experience. When you graduate to using your personal device to debug, you'll need to set up USB debugging. First, make sure USB debugging is enabled on your phone. On some Android phones, you first have to go to Apps..Settings..About Phone, then tap 7 times on the Build Number to enable Developer Options.
Full instructions on how to enable USB debugging on an Android phone
After enabling USB debugging on your device you will then need to
install a USB driver for debugging.
So now that we're set up to test and debug on our phone, we'll look at some of the TACO nuances and the deployment process next week - hopefully with an app successfully deployed to Google Play.
Posted by
Dan Shultz
at
9:24 PM
0
comments
Labels: Cordova , JavaScript , jQuery , PhoneGap , Visual Studio TACO
July 08, 2014
JavaScript Variable Hoisting
One of the little known nuances of JavaScript, is that the interpreter organizes functions and variables per scope by declaring them at the beginning of the scoping container, regardless of their order in the written script. Here's an example:
Displays:
x=1
Uncaught ReferenceError: y is not defined
undefinedwhereas y throws an error. So what's the difference? Neither variable has been declared when we are accessing them. Why do we only get an error when referencing y?
The reason is that the JavaScript interpreter reorganizes the declaration of ALL varibles within a scope to the top of the scope - in our case our scope is the function
showVariableValues(). So in reality, our above code will be reorganized as shown below:
Notice that the declaration of var x has been "hoisted" to the top of the scope, but only the declaration. The initialization of the variable remains in its original spot. Once this variable was declared, JavaScript set its value to
undefined- the JavaScript default. So that's why when we write the value of x, it's value is
undefined, whereas y just throws an error because it has not been declared.
So the lesson is: always declare your variables at the beginning of their scope - if you don't, JavaScript will reorganize your code for you. If you think about it, you could probably come up with scenarios with much more confusing results than this simple example.
Posted by
Dan Shultz
at
2:15 PM
0
comments
Labels: hoisting , JavaScript , variable
February 26, 2014
This Fine Morning
I like V8 juice. Every morning, on the way into work, I drink a glass of V8 juice.
Today was a bit strange - we had some flurries overnight, and I had left my car outside, so it had a coating of snow, so I took a few minutes and brushed the snow off the windows before leaving.
Since I was running late, I had to take our daily Skype call via cell. Usually I do it from my laptop at my desk, but in a pinch like this, I had to take it on my Android in the car.
But during the call, I noticed out of the corner of my eye that someone was gesturing to me from the car beside me...
After watching her for a few seconds, she then started gesturing like she was taking a drink, and pointing to my roof... and it hit me... I'd left my V8 on the roof of my car! Then, double-yikes, we were out of plastic cups, and I'd used a GLASS today! - Holy crap, there was a glass balancing on my roof driving 70 MPH on the interstate!
So the first thing I did was try to get as far ahead / away from everyone else as I could, and look for the first place I could
When I finally was able to pull over and come to a stop, I got out among some curious looks, and sure enough my glass of V8 was still precariously perched on my roof. Between the snow on my roof, the wetness of the glass, and the cold temperature, the glass had become soldered to my roof with ice. In fact, it was attached so firmly that I had to pry it off. I probably could have done donuts and would have only spilled the juice. Happy ending.
Posted by
Dan Shultz
at
12:49 PM
0
comments
January 21, 2014
Using custom binding to manage large datasets with the Kendo Grid
The KendoUI grid comes with robust client-side functionality, and Ajax-capabilities - sorting, filtering, paging is all just built in. With the Razor wrapper, the .Pageable(), .Sortable(), and .Filterable() extension methods take care of it all. If the data you’re displaying is minimal or even a few thousand rows, this is probably the route to go – just set the grid's dataSource to Ajax, create a read action on your controller, and you’ve got a pretty robust grid.
But once you get into dealing with “large” datasets, you may want to consider implementing custom binding to get data in front of the user without the wait. When I say “large”, I mean data that takes more than a few seconds to display, or data that is likely grow quickly to an unmanageable size. In our scenario the size of the dataset could be up to 25 Mb, but even after compressing it to 800k, it was taking several seconds to send the data from the server to the browser and then display the data in the grid. After the painful initial wait though, paging, sorting, filtering was then instantaneous since the data was all client side. But what to do about the initial wait?
That’s where custom binding can help out. By implementing custom binding, you can combine the best of Ajax and Server binding to quickly deliver large datasets to your users. A small drawback is that all the sorting, filtering, paging has to be handled in the controller method. Fortunately Kendo makes this fairly easy by automatically passing collections of criteria on the request object – here’s a quick overview of server code required to manually implement paging, sorting and filtering when implementing custom binding.
One other thing to remember when implementing custom binding is that Server caching of the dataset is something to keep in mind – especially if the db call takes more than a second or two. With custom binding, we’re calling back to the server on every filter, page, or sort event – so we don’t want to make a db call on top of that every time. This is true even (and especially) if we use Kendo’s Server databinding instead of Ajax databinding. So anyway, if you’re using Kendo’s data grids, the out of the box Ajax binding is a good, easily implementable solution, but if you’re dealing with large amounts of data, you’ll want to look into custom binding.
Full Razor code for grid with custom binding enabled:
Full controller method for grid Read event:
Posted by
Dan Shultz
at
1:19 PM
2
comments
Labels: Binding , DataSource , Grid , HTML5 , JavaScript , Kendo , KendoUI , UI
August 02, 2013
Manipulating Kendo's RangeSlider via JavaScript
Kendo's RangeSlider control:

We're creating this control in an ASP.Net MVC project using Razor syntax:
@(Html.Kendo().RangeSlider()
.Name("RangeSlider")
.Max((double)Model.RevenueUpperBound)
.Min((double)Model.RevenueLowerBound)
.Values(Model.MinVal, Model.MaxVal)
.Events(events => events.Change(x => "updateVals")))
But after the page is rendered, we want to programmatically change the start and end points via JavaScript. Looking at the object in FireBug, you can see several promising properties and methods like selectionStart, selectionEnd, bind(), etc... But ultimately, you'll just want to new up a JavaScript array containing the two integer values you want to use as the start and end values.
The example below resets our RangeSlider to a start value of 10 and an end value of 111. (Make sure your start and end values are between the upper and lower boundaries of the control itself).
function resetSlider(){
//Get a handle on our element's RangeSlider
var slider = $('#RangeSlider').data('kendoRangeSlider')
//Feed it an array of two numbers.
slider.value(new Array(10, 111))
}
That's it... As easy as 3.14.
Posted by
Dan Shultz
at
5:00 AM
1 comments
Labels: Change , Client Side , Control , HTML5 , JavaScript , Kendo , Method , RangeSlider , Razor
April 17, 2013
Multitudes / Animal Collective names
A Murder of Crows.
Posted by
Dan Shultz
at
1:38 PM
2
comments
November 20, 2012
Hats off to CodeProject, Intel
160Gb HD, 5 Touchpoint Screen, Windows 8 OS.
But Chris at CodeProject pointed me to Premier Intel support, which came with the laptop, and they swapped it out for me as soon as I could give them a UPS tracking number. Five days later, I'm up and running on the replacement, and it's the best laptop I've ever owned. Fast, responsive, and boots to a functional Windows 8 login screen within 5 seconds. Thanks, CodeProject!
Posted by
Dan Shultz
at
6:07 PM
0
comments
Labels: CodeProject , CSS , HTML5 , JavaScript , Metro , Responsive Design , Ultrabook , Windows 8
November 13, 2012
Windows 8 Store Deployment - Lessons Learned
The second interview dealt more with Win8/Metro standards and things like using Settings and the positioning of elements on the screen. At that point I was ready to deploy to the web store, which is a time-consuming process. I did find that having concise notes pertinent to each deployment did help speed up the turnaround time - the first submission took about 5 days to be rejected. By the time it was finally approved, I had deployed 3 times in one day, entering very specific details of the changes I was submitting.
A few things that bit me especially hard:
Certification Requirement #4.1 - Privacy Statement. If you use ANY user information, which includes accessing geolocation, you have to mention this in the privacy statement.
Also, if you have a privacy statement you must include it in your settings, AS WELL AS a link to a privacy statement HTML page in your store description.
Certification Requirement #6.2 - Age Rating. You have a clean app, right? Clean content, and you just implement the Sharing source contract so people can share text or an image from your app to Twitter, Facebook or whatever social network. Well, you'll have to make sure your age rating is 12+ for "uncontrolled sharing", or else you'll surely be rejected.
If you want to "control" sharing, you'll have to create some custom code to enable the user to "allow" other users to share from your application. So, assuming you're not targeting the 3 to 11-year-old crowd, you'll want to set your app's age rating to 12+ any time you implement the Sharing Source contract.
Posted by
Dan Shultz
at
5:55 PM
0
comments
September 24, 2012
Responsive Design and Portability into Windows 8
There are easy ways to implement this in Windows 8, but one striking things about the width of our SnapView window is the fact that it is 320 pixels wide, which happens to be the standard screen width of many mobile devices in portrait mode.
So if we have an existing web application that is "mobile-friendly" - meaning we've used Responsive Design and CSS Media Queries to ensure it will adapt to whatever environment it is being viewed in - this HTML code is not only portable into Windows 8, it also satisfies the SnapView requirement.
That’s one of the great stories about Windows 8 HTML apps that isn’t really being played up as much as it should – the fact that portability of traditional web applications INTO a Windows 8 HTML project is fairly seamless. As a web developer, one of the things that first impressed me about Windows 8 was the ease of running a traditional HTML application within a default new Metro* HTML project. Even an app that uses jQuery or other JavaScript frameworks.
After merely adding a traditional app’s .html, .css, and .js files to a new, empty Visual Studio 2012 HTML application, the only thing that prevented it from running as a full-screen Windows 8 app was the fact that the references to the WinJS javascript files needed to be added. Once these 3 JavaScript includes were added to the page, the application was instantly running full-screen, like any other Metro* application. Here are the required .js files
<!-- WinJS references --> <script src="//Microsoft.WinJS.1.0/js/base.js"> </script> <script src="//Microsoft.WinJS.1.0/js/ui.js"> </script> <script src="/js/default.js"></script> <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
Of course, referencing these WinJS-specific files excludes the reuse of this HTML code outside of the Windows 8 environment. But the “portability in” story is still nice – I say this as a web developer who originally came across Windows 8 as part of an experiment in HTML portability.
Posted by
Dan Shultz
at
12:22 PM
0
comments
August 24, 2012
Deploying HTML5 Metro apps to the Windows Store
...some common gotchas
1). Read the Certification Requirements. Really.
2). No items in the left and right swipe margins. No exceptions.
3). Buttons, in app functionality, credits, go down in the app bar or under Settings, not on screen.
4). Snapview - your app has to be usable when "snapped" to the 320 pixel sidebar section in Windows 8.
There are standard ways to handle the switch to Snapview in Windows 8, but for Metro HTML5/JavaScript apps you also should consider using Responsive Design, Which I'll talk about next week.
Posted by
Dan Shultz
at
5:00 AM
0
comments
Labels: CSS , CSS3 , HTML5 , JavaScript , Metro , Responsive Design , Windows 8
March 06, 2012
PhoneGap HTML5 Portability II - Chrome Web Store Hosted Apps
One of the first issues I encountered with my Packaged App in this new outlet was with advertising. The ads displayed just fine, as they do on the main website, except for one thing - for every click, the earnings were always $0.00. That's not good. After an exhaustive search, I came across this promising answer, but still, $0.00 every time.
The actual problem was that I was using a Packaged App, which essentially is your entire codebase running locally on the user's machine. It ends up that ads within a Packaged App don't have a "legitimate" source URL, according to AdSense, since it's really just local code on the user's machine. The Chrome Web Store's alternative to a Packaged app is a Hosted App - which is a link to the URL of your application.
The Hosted App solution is not only appealing as a valid source to display ads, but from a maintainability standpoint I now have one less place to deploy to. All I need now for deployment is my manifest file and app icons - the Web Store app just piggybacks on my already-existing website.
Here's a sample manifest file for a hosted app:
{
"name": "My Cool App",
"description": "This is a test of the Chrome Web Store",
"version": "1.0.0.1",
"app": {
"urls": [
"*://www.yourwebsite.com /mail/",
"*://www.yourwebsite.com /otherarea/"
],
"launch": {
"web_url": "http://www.yourwebsite.com/"
}
},
"icons": {
"128": "icon_128.png"
},
"permissions": [
"unlimitedStorage",
"notifications"
]
}
Note that you need to specify a launch URL, as well as any other non-asset URLs you'll be using. And you will need to verify that you are the owner of this site using Google's Webmaster Tools.So the quest for a solution to the AdSense problem sent me down the path of investigating Chrome Web Store "Hosted Apps", which not only resolved my advertising issue, but ended up being a better solution in general for my needs.
If you're debating which type of app would work best for you, here is a good comparison of Hosted vs Packaged apps
Posted by
Dan Shultz
at
5:00 AM
0
comments
Labels: AdSense , Android , Build , Chrome , Chrome Web Store , CSS , Hosted App , HTML , HTML5 , M3 , Packaged App , PhoneGap , Progressive Enhancement , Responsive Design
February 27, 2012
HTML5 Portability beyond PhoneGap - The Chrome Web Store
One of the great benefits of doing mobile development using PhoneGap is the portability of the codebase. The same HTML application is easily wrapped and built for all major devices using PhoneGap and/or PhoneGap Build. And since your app is written using HTML, CSS and Javascript, you can make it accessible as a web app as well.
After I had already published a few apps to the Android Market using this technique, I read about the Chrome Web Store. And once I digested their publishing and deployment specs, I noticed that the same PhoneGap codebase could easily be deployed to this outlet as well. I re-deployed the same apps to the Chrome Web Store a few months ago, and my experience was so positive, I wanted to share a quick overview of how to deploy to this store, and some things you'll want to think about:
The deployment is simple for Chrome Web Store Packaged Apps - basically you create a .zip file of your HTML app, along with a simple .manifest file, the app icons, and preview images. Here's a sample manifest that launches splash.html at the root of your app:
{
"name": "My Cool App",
"description": "This is a test of the Chrome Web Store",
"version": "1",
"app": {
"launch": {
"local_path": "splash.html"
}
},
"icons": {
"16": "icon_16.png",
"128": "icon_128.png"
}
}
(Full documentation)
The preview images are not required, but you'll never get very high in the rankings without them... and of course the image sizes don't match the Android Market sizings, so you'll need to create new ones. And they will not accept them until the images meet their aesthetic criteria - I had two go-arounds with them because of font sizing.
...but the pleasant surprise was the traffic:
The identical app in the Android Market after 6 months or so has about 2400 downloads, and is approaching 1000 active installs.
In the Chrome Web Store, there are 3500+ users in less than two months, and 250+ users daily, 14,000+ total. Rarely is there inactivity when using Google Analytics' real-time tools.
The manifest sample I showed was for a Chrome Web Store "Packaged App", but for my needs I found that a "Hosted App" was the better way to go - and even easier. My post next week will highlight the advantages of using a Hosted App, plus some tips on using advertising.
Posted by
Dan Shultz
at
5:27 PM
0
comments
Labels: AdSense , Android , Build , Chrome , Chrome Web Store , CSS , Hosted App , HTML , HTML5 , M3 , Packaged App , PhoneGap , Progressive Enhancement , Responsive Design
November 22, 2011
Achieving Broad Reach with Responsive Design + PhoneGap
When you need to create an application with a specific look and feel across multiple platforms and devices, PhoneGap can be the perfect tool. But before you just wrap your application up and ship it, you'll want to use Responsive Design techniques to ensure all users get an appropriate experience regardless of their device. For instance, you don't want the 320 x 480 version of your app appearing scrunched to that size in the middle of an iPad, or even worse, in the upper left corner. Conversely, you don't want your beautiful iPad app scrolling horizontally and vertically on every smaller device. So you'll want to use Responsive Design to tailor your HTML5 application to as many devices as possible, and then use PhoneGap to progressively enhance the experience when viewed natively on mobile devices as well.
Flexible grids and media queries are important part of implementing Responsive Design in your website/application. Once the application is looking and functioning the way we want it on our desired device(s), we can use PhoneGap to access additional functionality if we are being viewed on a mobile device, and PhoneGap Build to automatically generate the native binaries for many smartphone devices using our single HTML5 codebase.
We're going to target Android and iPhone devices, including tablets, as well as most current web browsers, and the Chrome Web Store for our HTML application.
Our sample app (links to all versions below) is going to call the Google Geocode API as well as the Heavens Above API to display viewing information for the next pass of the International Space Station based on the desired position. For progressive enhancement, our app will allow mobile device users to merely use their device coordinates, and allow HTML5-enabled users to have access to their history of locations using HTML5 LocalStorage.
PhoneGap Build then compiles the latest version of the application checked into the Git repository, but most intrepid web developers can access all the necessary source code using any web browser.
The Sample Application:
(All versions compiled using identical codebase)
(all browsers and devices)
Posted by
Dan Shultz
at
5:05 AM
2
comments
Labels: Android , Chrome Web Store , ISS , M3 , PhoneGap , Progressive Enhancement , Responsive Design , Space Station
September 21, 2011
Installing Windows 8 Developer Preview on VirtualBox (and resolving error 0x8007045D)
Basically, the fix is to make sure to check "Use host I/O cache" under Admin...Storage...(highlight SATA Controller):
Posted by
Dan Shultz
at
5:25 PM
4
comments
Labels: Build , Metro , Virtual Box , Windows 8
August 16, 2011
Sitefinity 4 News Items Not Displaying Author Name
We just got through a minor issue involving NewsItems in a Sitefinity 4.1 implementation. The problem is that even though the administrators were specifying an author when creating NewsItems, THEIR NAME was being displayed instead of the author no matter what.
The solution is actually pretty straightforward - The layouttemplate for news items doesn't contain a field for author, even though it's entered on the back end. Instead it uses <sf:personprofileview runat="server"> which displays the first name and last name of the user posting the NewsItem. You'll have to go into the LayoutTemplate for single NewsItems (Design..WidgetTemplates...FullNewsItem in Sitefinity admin) and replace the personprofileview tag with the author name:
Default layouttemplate code:
<div class="sfnewsAuthorAndDate">
<asp:literal runat="server" text="<%$ Resources:Labels, By %>">
<sf:personprofileview runat="server">|<sf:fieldlistview format="{PublicationDate.ToLocal():MMM dd, yyyy}" id="PublicationDate" runat="server">
</sf:fieldlistview>
</div>
Revised:
<div class="sfnewsAuthorAndDate">
<asp:literal runat="server" text="<%$ Resources:Labels, By %>">
<asp:Literal runat="server" Text='<%# Eval("Author")%>' /> | <sf:fieldlistview format="{PublicationDate.ToLocal():MMM dd, yyyy}" id="PublicationDate" runat="server">
</sf:fieldlistview>
</div>
Posted by
Dan Shultz
at
5:00 AM
0
comments
Labels: NewsItem Author error , Sitefinity 4.1
