iOS UIView, WebApps and iFrames


One of our existing responsive websites (built using Angular) was being pulled in as part a Cordova project to make an iOS and Android app, and the developers had some weird issues on iOS. Inside the Cordova app, our app was loaded in an iframe. I wanted to write about a few of the issues that came up, particularly with the iOS UIView, and some of the hackery I resorted to in order to resolve the issues.

Issue 1: Fun with iOS Iframes

First issue we had was that the app kept bouncing between the small and xlarge media query. This turned out to be due to what I consider a bug in iOS, in that iframes size to their content, rather than sizing based on the attributes/styles on the iframe itself or parent constraints. We had logic that enabled some functionality on small, which in turned created a wide html element for a carousel and due to the iframe bug in iOS, would cause the width of the iframe to grow to the xlarge size again. The carousel functionality would be destroyed, as it was only for small, causing the element that was created to hold the slides to be destroyed, causing the iframe to shrink back down to the small size again. And then the cycle would repeat, infinitely.

I was able to fix this issue by immediately setting an explicit width on the body before any of the rest of the HTML was loaded/parsed. This worked in our case because the application will always be in portrait mode, we would need to also watch for resize events and things would get more complicated. Right at the top of the body, I added the following code:

<script>
  document.body.style.width = document.body.clientWidth + 'px';
</script>

Issue 2: iOS WebApp links open in Mobile Safari

The second issue we had was that any link clicked in the website being wrapped in this iframe would load in Safari. It didn’t matter if the link was relative or fully qualified, or what kind of target (or lack thereof) it had. Turns out that is normal behavior for web apps on iOS. I’m not proud of the solution, but the fix was to grab all links in the app, watch the click event, stop the default browser action, and load the new page with window.location. It looked something like this:

$('html').on('click', 'a', function (event) {
  var href = $(this).attr('href');
  if(href && href.indexOf('http') !== -1 && !event.defaultPrevented) {
    event.preventDefault();
    document.location.href = href;
  }
});

I had jQuery available, but for a non-jQuery version, check this out here: https://gist.github.com/kylebarrow/1042026

My initial solution broke links in the site that already had JavaScript functionality attached to them, so the click event was delayed briefly from being attached by wrapping it in a timeout. That way it should be the last event attached, and be skipped if the event had already had preventDefault called on it.

Overall, it’s two hacks that fixed the issues we were seeing. Mileage may definitely vary given, but hopefully this will prove useful to the reader (or more likely, a future me trying to figure this out again).

Vanilla JavaScript vs. Framework Functions


Had a quick conversation at work today about whether or not it was good to use built-in framework functions for tasks that are simple to write in vanilla JavaScript. For example:

angular.isFunction(fn) 

vs

typeof fn === 'function'

I’ve tended to do the vanilla JavaScript, but while checking if something is a function is almost identical in complexity/length, while others can be (slightly) more complex:

angular.isObject(yourVariable) 

vs. 

yourVariable !== null && typeof yourVariable === 'object'

Still, either way is pretty readable, and fairly clear what it is doing. I wonder if this is what leads to people bashing frameworks like Angular for teaching people the “framework” rather than vanilla JavaScript, as newer coders who may not have ever had to check variable types who are learning Angular may use the framework checks without knowing how to do a similar thing in vanilla JavaScript.

I like to collect snippets that will help me, and reuse them where appropriate. This probably tends to skew me towards vanilla JavaScript, because I want my snippets to work no matter what project I am working on. For example, the following snippet gets the class (or type) of a JavaScript variable.

/**
 * getClass - get real type of JavaScript object 
 * @param object
 * @returns {string}
 */
function getClass(object) {
    return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
}

/*
getClass({}) // "object"
getClass([]) // "array"
getClass(function(){}) // "function"
getClass('') // "string"
getClass(1) // "number"
*/

I came away from the conversation thinking there was not one right way. If you are writing an app with the help of of a framework, there is nothing wrong with using the tools the framework provides. At the same time, it shouldn’t become a crutch where a framework is needed because a developer isn’t comfortable doing the same thing in vanilla JavaScript.

Support Net Neutrality, tell the FCC!


PSA: Less than 14 hours to go. That’s how long we have to get pro-Net Neutrality comments submitted to the FCC in front of their first comment period deadline (midnight Tuesday) — and save the Internet from the clutches of Comcast, Time Warner, and their ilk.

This website makes it very easy to send the FCC a formal comment demanding support for Net Neutrality. It’ll only take a minute, although if you customize the message it may have even more impact.

https://www.battleforthenet.com/

Getting the number of Facebook shares and/or likes of a URL


So…you want to display the number of times your url has been shared/liked on Facebook, but you don’t want to just use the Like Button with the count?  I don’t blame you, while I use the Like button when appropriate (and that IS the easiest way to get that number, it doesn’t help you at all when you want to do something a bit cool with the information, or display it in a unique format.

So, there are 2 ways currently to get an URL’s Facebook Shares.  You can make a query against the Facebook REST API and use the links.getStats method, or you can use the Graph API to make an FQL (Facebook Query Language) call.

The REST API is really easy to use, but unfortunately, it is deprecated, so Facebook could shut it off tomorrow if they wanted to.  Personally, I doubt it gets shut off, but don’t come crying back here if you use it and something stops working because they do.

To make a call using the REST API, using one of my more popular posts as an example, you can make a query to the following URL like so:

http://api.facebook.com/restserver.php?method=links.getStats&urls=http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog

That will return a block of XML (yes, XML) that looks like this:

<links_getStats_response xmlns="http://api.facebook.com/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd" list="true">

    <link_stat>
        <url>
            http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog
        </url>

        <normalized_url>
            http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog
        </normalized_url>

        <share_count>22</share_count>
        <like_count>51</like_count>
        <comment_count>0</comment_count>
        <total_count>73</total_count>
        <click_count>0</click_count>
        <comments_fbid>468455836580018</comments_fbid>
        <commentsbox_count>0</commentsbox_count>

    </link_stat>

</links_getStats_response>

Then you’d just need to parse that returned XML into a usable format and grab the values that you want.  Generally you are going to want the total_count element, but sometimes you may want to differentiate between Shares and Likes.

Unfortunately, as mentioned, the REST API is deprecated, so if that concerns you, you can use FQL to query Facebook using the Graph API.

You can query the link_stat table with something like the following query:

SELECT 
    url, 
    normalized_url, 
    share_count, 
    like_count, 
    comment_count, 
    total_count, 
    commentsbox_count, 
    comments_fbid, 
    click_count 
FROM 
    link_stat 
WHERE 
    url="http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog"

You can make a GET request to the Graph API and the Graph API will give you back a JSON response listing the fields you requested.

https://graph.facebook.com/fql?q=[QUERY]
https://graph.facebook.com/fql?q=SELECT url, normalized_url, share_count, like_count, comment_count, total_count, commentsbox_count, comments_fbid, click_count FROM link_stat WHERE url="http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog"

The returned JSON should look like this, and is very easy to parse for the data you want.

{
   "data": [
      {
         "url": "http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog",
         "normalized_url": "http://www.local-pc-guy.com/web-dev/facebook-feed-dialog-vs-share-link-dialog",
         "share_count": 22,
         "like_count": 51,
         "comment_count": 0,
         "total_count": 73,
         "commentsbox_count": 0,
         "comments_fbid": 468455836580018,
         "click_count": 0
      }
   ]
}

 

My recommendation is to go ahead and get comfortable with, and use, the FQL query syntax and the Graph API.  That way you are protected against the REST API going away and you get JSON, which is slightly easier to work with than XML.

Enjoy querying against Facebook, FQL is quite powerful and there is quite a bit of information you can get with a bit of digging through the docs.

Error using SquishIt and an Ektron control together


Earlier at work I ran into a conflict between SquishIt (which is a great utility for .Net for concatenating and minifying your CSS and JavaScript files, more info) and an Ektron control (Ajax HTMLEditor) that was included on a .Net ASPX page .  SquishIt was set in the MasterPage, so just removing it for that page wasn’t really an option.

The error I was getting was:

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

Read more