Pixelastic

You can cut our wings but we will always remember what it was like to fly.

Posts tagged with "Javascript"

Facebook https mixed content warning on IE9

When browsing the web, you might have seen a "mixed content warning" popup show in your browser. They are most of the time poorly worded and their meaning is quite obscure.

What it means is that your are currently browsing a page with both http and https content. Typically, if your page is https but one of the css, js or image file it contains is requested through http, the warning will pop.

(It's interesting to note here that not all assets are treated equal. Loading a flash movie through http does not trigger the warning).

The IE special case

Now, what's special about IE is that it also trigger the mixed content warning when content is the other way around. If you're serving a page through http and load assets through https, it will consider it a mixed content too.

In a sense, that's logical, but it needlessly prompt the user with a dialog that block downloading of all https assets until confirmed.

The solution is to make sure that all your assets are loaded with the same protocol as the host page. An easy way to do so is to use the // relative protocol url. This will use http or https automatically based on the page protocol.

And adding Facebook to the mix

A few months ago, Facebook forced all apps to serve content through https. In the meantime, they suggested that all their users browse their website using https too.

Unfortunatly for us, some of our own users had bookmarks in their browsers and Facebook pages referencing our old http://apps.facebook.com/appname/ url. And following that link triggered the dreaded mixed content warning in IE.

When accessing this page, Facebook was loaded in classic http but our inner iframe was loaded through https. So far, so good.

The problem came from one of Facebook own javascript SDK included in our app. This script loaded other scripts based on what it needed.

Unfortunatly, it loaded the other scripts from an http (not https) server. The SDK has two distinct sets of urls, based on the current page protocol.

It was wrongly considering being in an http page, not an https one, and thus used the wrong set of urls. This confusing comes from the fact that it checks the top page protocol instead of checking the current page protocol.

After some googling, I found a solution that consisted in forcing the SDK to consider that we are in https mode by calling : FB._https = true before the call to FB.init()

Almost there

If correctly forced FB to use the correct set of urls, thus removing the mixed content warning. And I almost thought it would be that easy.

It was not.

This did not fixed the payment popup. All Facebook UI element loaded correctly (feeds, permissions, requests), but the payment popup.

I couldn't find a way to fix that, so I reverted to a more brutal approach.

Final and brutal solution

All my problems came from the fact that FB thought we were serving http while in fact we were serving https. So the solution, might be to force FB to serve https from start to end.

I wanted to detect if the page was loaded through http://apps.facebook.com/appname/ or https://apps.facebook.com/appname/.

Unfortunatly, due to cross domain restrictions in Javascript, we are not able to read, from inside and iframe, the parent frame properties. So I couldn't read top.location.protocol to easily check if I needed to redirect.

But, as I mentionned earlier, FB._https incorrectly report that we are not in https because it checks the top protocol. So I used this var, to know if the parent frame was in the correct protocol or not. Using this own FB bug to fix itself.

Now, for the redirect : even if I couldn't read the top.location, I could modify it. I just had to call top.location.url = 'https://apps.facebook.com/appname/' to redirect the whole page.

I hardcoded the app url because there was no way to get it from js, and I took care of keeping any GET parameter passed before the redirect, and I ended up with this :

if (!FB._https) {
var appUrl = 'https://apps.facebook.com/appname/';
var iframeUrl = location.protocol+'//'+location.host+location.pathname;
var redirectUrl = location.href.replace(iframeUrl, appUrl);
top.location.href = redirectUrl;
return;
}
FB.init(options);

Conclusion

I'm not really proud of this solution, as it is mostly a hack and will force a useless loading of the http version before loading the https one, but that's the best I've found. If any of you have a better solution, feel free to comment.

 

 

Web and dev events in Paris

For the past month or so, I've attended quite a bunch of dev and web events, here in Paris.

Every time I get back from one, I wanted to post something about it. But I never did, as I always seems to have something more important to do. That's quite a shame, because those events were (for the most part) really interesting, some were even really motivating.

So, expect a full blog post on each of them in the coming days. For the time being, here is just an overview.

Paris Web is THE french web event. Two days of conferences about the web, not too technical, but very practical. Here we speak equally about the "why" than about the "how". Very great speakers, team and place. The third day is for workshops, in smaller groups.

Then comes Paris JS, held each month. It's an evening of informal talks about Javascript, a few speakers will demo an app, a framework, or talk about anything JS related. Very great to meet interesting JS fellows, and exchange about frameworks and projects.

Paris Hacker is an other informal event, where everyone is free to speak about any hacky/geeky subject. Most of the time we review the last Hacker news posts and discuss them, talk about incoming events, and so on. There almost no trolling. Most of the time.

JsGuru is a completly different kind of event. This one is a one-day Javascript formation. It costs real money this time, but you got to learn a few tricks and get your started on some frameworks and libraries like Backbone, Mustache, Lawnchair, etc.

And the final one is the Hack Day Paris. Partially organized by the same team as Paris Hacker, it was a 40hrs hackathon, with no constraint except to "build something brilliant". More than 180 fellow geeks attended, and 43 projects were finally demoed on stage. This was one of the most motivating experience I ever did.

A few days after the Hack Day, an other event was held by SFR were all the Hack Day participants were invited. Along with participant from two other events (Designer Weekend and Museomix), the goal was to help all those people to meet, and to showcase some of SFR latest innovation. This is clearly the event that I liked less.

ParisJS #8

(The whole conferences were in french, but as I'm writing every post on my blog in english, I'll write this one too.)

Tonight I was attenting the 8th parisjs meetup. We had the chance to have it hosted at Valtech, in a very wealthy part of Paris, in somptuous quarters and a large room with giant screen (and great pizzas too).

Anyway, this time the meetup was split in two : first part was made of complete talks, while second part only had small lightning talks. With pizza and beer in between.

Wakanda

The first talk was about Wakanda. Wakanda is a complete suite of client/server Javascript which goal is to help create business oriented apps. It is created by the same company as 4D, but this time is completly open source.

The product seemed well done, but kinda monolithic : server side js, client side javascript framework, application studio, debugguer.

I can surely see it used for creating Intranet applications, for some very specific business cases. I have an ambiguous feeling about Wakanda. I think they did a very good job, the whole package seems really neat, the IDE is clear, client/server communication is smooth, etc. On the other hand I'm always suspicious of apps that can do everything.

(Note that I didn't try the product, I only heard about it tonight for the first time and watched a 20min presentation so that's a little light for me to give a precise opinion)

Joshfire Framework

A few months ago, @sylvinus from Joshfire told us that they planned to realease their framework, modeslty named Joshfire.

This is by far the most interesting presentation of the meetup. Joshfire is a javascript framework aimed at working seamlessly between any devices : desktop, mobile, iPad, TV, anything.

It's basic idea is to abstract to its bare bone any interaction. From what I remember, for any "page" you want to define you have to write two JSON structures.

One defines the data tree (what your data is), the other defines the UI tree (how your data can be interacted with). It also ships with some adapters (an adapter is the link between the UI Tree and a specific device).

All you have to do to port your Joshfire app to a new device is to write (or grab if it already exists) an adapter. The main logic and data code is the same for every device, the maintenance is now only focused on any specific device.

Even if the main idea of Joshfire is awesome, their documentation and licensing is even more awesome : the project is already completly documented, with examples and is also completly free and available on github.

CSON, no sorry, JISON

@jie was supposed to talk about CSON, a compressed JSON. But as he already gave a very similar talk (about BSON) at the last #parisnode event, he changed the subject.

I'm not really sure what the real subject of the talk was. I think he mentionned compiling Javascript into Javascript (much like CoffeeScript), but it eventually turned into a Jison demo.

Jison seems to be a tool for automating lexing and parsing languages, to output new code. In effect, this could allow for transforming a custom language into an existing language. CoffeeScript, Haml or Sass works that way : they take a new language as input, and return Js, Html or Css as output.

The advantages are that the custom language is usually much more concise, easy to write and easy to read.

Anyway, this presentation was full of nice quotes :

The language I'm about to show you is totally useless.

Pipe ? What is that ? Oh, you mean the strokes.

The bad thing about Jison is that its documentation is crap

Why does it work ? It was supposed to fail !

Overview of a dev life

This talk wasn't about any new shiny technology. It was about those old browsers and bad habits we had 10 years ago, and how we still managed to make great websites.

This remind me of the "good ol' days" when I discovered the web with FrontPage and ClaraSoft. When IE6 was considered a modern browser.

@molokoloco show us that he managed to simulate ajax using nested iframe, had a website still online and running even after 10 years, was able to code full websites in 3 days, and had read more than 50.000 blog posts. And all that while still using Windows and Dreamweaver.

(Small side note : I praise both @molokoloco and @jie for what they managed to do. I know how easy it is to procrastinate and configure UI, test new tools and IDE instead of getting things done. That didn't seem to be an issue for them.)

mongoDB

This talk was the first in the serie of lightning talks (less than 20mn). It was about mongoDB and how to integrate it in a nodejs app.

As I had never tried nor nodejs nor mongoDB I didn't quite grasp what it was really about. All I get is that in order to get a result from a mongoDB query, one have to go through 3 steps of connection to the DB. In the asynchronous world of nodejs, this doesn't work well, so each step has to fire a callback once executed.

From there, I was lost. There was something about manually calling a callback once initialized, but honestly I didn't get it.

Anyway, I learned from a small talk during pizza time that mongoDB was better than couchDB (performance-wise), and that one have to sacrifice binding to the altar of redundancy to get really fast response time.

Audio demo in less than 1kB. No, 800B. No, wait, 200B

This time the talk was a very fun demo. Using some simple minification techniques, Js was able to play a random music.

This involved encoding the wav file in base64 (taking special care of some chars), and then playing it in an audio tag. Adding a bit of random to play a different note on each loop.

Fun, but interesting.

Some words about the Observer Pattern

This talk was more about theory than practice. Maybe it was the late hour, but it didn't catch my attention as the other did. Maybe someone would re-explain it to me ?

Well, I got the general idea : coding a js snippet that hard code the name of the elements that should react is bad practice because of the maintanability nightmare it cause when elements are removed.

Instead, the speaker advocate the use of a MessageBroker. Some kind of general listener that then dispatch event to element registered to that event (am I right ?).

Then someone in the audience noted that the opposite pattern should work better : that every element registered itself to an event and react when such event is fired (am I still right ?)

Honestly, I really am not sure about this talk, so if anyone could fill the blanks and correct me, I'd be glad.

Sencha and Sencha Touch

I won't go into too much detail on that talk. This was a generic presentation of Sencha (formerly known as ExtJs). I already had the basic understanding of ExtJs (but not the expertise of some of the ExtJs experts in the room), so I was really only half listening.

Sencha is a great product. It is very similar to what Wakanda was showing in the first talk. It is destined to data-heavy applications with lots of numbers, columns, charts, pies, etc.

Sencha Touch is a mobile version of Sencha. It is iOS oriented and emulate the standard UI elements in HTML.

Mozilla Labs

A quick list of the Mozilla Labs projects. I honestly don't remember them all, except Tilt that is a 3D viewer of any web page. It simply calculate the DOM depth and create a pyramid-like structure that you can browser in 3D.

I'm sure that beyond the cool and shiny aspect, it can be useful as a debug/optimisation tool.

Conclusion

Once again, thanks to #parisjs for those talks, always inspiring and a way to meet new people.

For all the new readers, I have an unfixed bug in my comment section : your post can be invalidated if your are using Chrome with an email auto-filler. My custom anti-spam will flag you as spam because Chrome fills an hidden honeypot field.

SWFObject must be included in the <head>

We just discovered a strange behavior on one of our test VM (one without Flash installed). I don't know how we've missed it before.

When embedding the main flash file of our application, the alternate content wasn't displayed to players. In fact it seemed to be displayed very briefly then disappear.

I had correctly embeded it with the static publishing method and added a call to swfobject.registerObject to soften the edges. I remembered it working correctly in my tests, so I quickly made a small test case.

It occurs that the alternate content was corretcly displayed if I removed the swfobject.registerObject call and only used the static publishing.

I also found that everything worked fine if I called the swfobject.js file in the head, but started to bug when I moved it at the end of the page.

As I didn't want to add a call to a .js file in my head, I google a bit and I finally found that one have to call swfobject.switchOffAutoHideShow(); right before the swfobject.registerObject call. This seems to fix things by not hiding the alternate text

Edit

I spent some more hours trying to debug the last corner cases. We had a user using Firefox 3.5.3 with Flash 10.0.42.34. Using SWFObject, we required at least version 10.1. Unfortunatly, the app was still loading, but was buggy because of features not present in the user flash version.

After some tests, I discovered that the swfobject.js code MUST be included in the <head> of the document (well, before any .swf in the page, so better put it in the <head>).

Doing so, you won't even need the previous fix (swfobject.switchOffAutoHideShow()).

I would have loved putting it at the end of the page, with the others JS files, but I guess I won't have a choice here.

Ghost posting on FB.ui streams

We had a bit of an issue when launching our app a few weeks ago. Everything was working fine on our test apps, but when live, all the stream messages we posted (we call them "Sharings") had a random text appended.

Most of the time it was a generic Facebook text, but sometimes it was a creepier SQL request just displayed plain on the user feed.

The Facebook text was (for the sake of search engine goodness):

Facebook is a social utility that connects people with friends and others who work, study and live around them. People use Facebook to keep up with friends, upload an unlimited number of photos, post links and videos, and learn more about the people they meet.

As the issue only occurs in production mode and never on any of our test environments, this was pretty difficult to debug.

Here was the code used to post the Sharing :

FB.ui({
[...],
'title' : 'Title of the Sharing',
'caption' : 'Text of the Sharing'
});

As I later found out, the caption key is not supposed to hold the Sharing text. The description key should be used for that. I'm not exactly sure was caption was for, but it seems that if you let the description key empty, then Facebook fills it automatically with a placeholder text.

The solution simply was to put the text in the description text, and leaving the caption key empty :

FB.ui({
'title' : 'Title of the Sharing',
'caption' : '',
'description' : 'Text of the Sharing'
});

As this behaviour is counter-intuitive, undocumented and random, I think posting it here could help other lost souls like me.

Hard limits using FB.ui to post Requests

I hate Facebook documentation. All pages seems out of date, displaying wrong function signature, obsolete parameters, documentation link pointing to 404 pages, etc, etc.

I've lost some hours debugging those calls, finding whatever hard limit Facebook forced on some of the arguments.

Let us write a very basic example code :

FB.ui({
'method' : 'apprequests',
'display': 'iframe',
'message' : "Hey, this Request is awesome, just accept it, ok ?",
'title' : "Awesome request incoming",
'filters' : [
{ "name" : "Some friends", "user_ids" : [ "97841578", "548673131", "[...]"]  },
{ "name" : "Some other friends", "user_ids" : [ "97841578", "56867134", "[...]"]  },
]
});

This should open a Request popup with the custom title and message, as well as provide a list of friends that you can filter based on two criterias : "Some friends" and "Some other friends".

What will go wrong

First, you have to know that both the message and title have a character limit. If you go over it, the popup will simply display something like "An error occurred, blah blah blah".

After some fiddling, I discovered that the limit is 50 chars for the title and 255 for the message.

Also, there is no limit (as far as I know) to the limit of custom filters you can set. See update below. But there is one to the max number of users you can define in a filter. And that number is 1000.

This means that if my user_ids list for any of my custom filters contains more than 1000 users, the popup will fail. However, you can have as many filters with 999 users as you want.

Took me a little while to find, and I thought that this could be shared.

Update

I found a new hard limit : You can't set more than 5 filters at a time. If you add one more, the Request popup will fail.

New Update

Also, if you define a callback, don't forget to return true. Otherwise Webkit will refuse to close the FB popup and you'll have to click twice for it to really close itself.

Update (bis repetita)

This one was pretty hard to find but if your filter contains a facebook id of someone that is not a friend of the currently loggued user, the filter will display nothing.

In our app, we have a filter of "Neighbors" (as most social games do). But one of thoses neighbors removed the user from its friends, and we didn't update the neighbor list to reflect that, resulting in our "Neighbors" filter being empty.

Making Flash and Javascript speaks to each other

I needed a Flash app and my Javascript code to be able to communicate. The Flash needed to call some methods in the Javascript, and in turn the Javascript needed to inject back some data into the Flash.

I let my Flash coder colleague took care of the Flash side, he needed to implement ExternalInterface, register some callbacks methods that I could call and more importantly change some security settings to make it work.

On my side, I just needed to get the object element holding the Flash (thanks to swfobject.getObjectById it was pretty easy) and call the callback method registered in Flash on it.

Piece of cake.

Have a look at this blog post from CircleCube, it does a pretty neat job at explaining all of that.

Update :

I finally had some issues with this implementation. It was working perfectly on some servers but not on others. We finally found that calling Security.allowDomain('*.mainhost.com') wasn't working.

You have to explicitly allow each domain/subdomain.

As our code would be deployed on various duplicate domains, we had to manually pass as a flash var the domain to allow.

Detecting fullscreen in tinyMCE

I wanted one of my tinyMCE plugins to fire a certain set of actions whenever the full screen mode was activated.

I search for an onFullScren event or somethin similar but to no avail. I finally discovered that the full screen actually creates a whole new tinymce editor instance.

So the only thing I had to do was writing my little piece of code in the init method of my plugin and check to see if the fullscreen was enabled.

The initial fullscreen plugin exposes a fullscreen_is_enabled param that can be checked.

All I had to do was a simple condition like : if (editor.getParam('fullscreen_is_enabled')) {}. And once in the condition I tried to execute my custom code. I needed the editor.execCommand method but all I got was an error because t.selection was not set.

It appears that the execCommand can only be executed when the full editor instance is loaded (and thus a t.selection is created). So I wrap my little piece of code into a setInterval checking for editor.selection and finally executed my code when the .selection was set.

Here is my final snippet, to be included in my plugin init method :

if (editor.getParam('fullscreen_is_enabled')) {
var fullScreenInterval = setInterval(function() {
if (!editor.selection) return false;
clearInterval(fullScreenInterval);
editor.execCommand('anyTinyMCECommand');
}, 1000);
}

 

The dreaded <noscript> on IE7

This <noscript> tag on IE7 is making me crazy. Here are some "interesting" facts about it :

No content through Javascript

You can't get its content though javascript. It can be targeted but neither .innerHTML nor .textContent is set. It does not have any .childNodes either.

Gets displayed even when scripts are enabled

If you set noscript { display:block; border:15px solid red;}, it will get displayed even if Javascript is enabled. But with no content inside, you'll only have borders and background...

Styling it anyway

If you want to style it, just add an inner element and style this one :

<noscript><p>Lorem ipsum</p></noscript>
noscript p { background:blue; }

Disabling Javascript on IE7

If you want to disable Javascript on IE7, you'll have to go to Tools > Internet Options > Security > Custom and setting the "Enable ASP scripts" to No.

Yes, this doesn't make any sense.


Deleting an element from an Array/Object in Javascript

I'm going to post that here because it's the second time I stumble upon this "problem" and the second time I lost some precious time to understand what was going on.

I had a Javascript Array, named elements and I wanted to remove one of its properties by its index i.

I know that merely calling elements[i] = null won't work (the property will still be present in the array and the length won't be updated.

Calling delete elements[i] won't work either. Same result.

I had to use elements.splice(i, 1) to effectively remove the element and update the length value.

Also note that sometimes I accidentally declare an Array when what I really want is an Object. I tend to forgot that associative Arrays in Javascript do not really exists, they just are Objects.

Previous123