ng-repeat with draggable or how to correctly use AngularJS with jQuery UI

AngularJS is an amazing framework. Together with jQuery and jQuery UI is a killer combo. But sometimes it’s really difficult to make them work together.

Task

Imagine we have a box (div) and inside some elements that we can drag around.

Solution #1

We will attach the jQuery UI draggable inside of the directive that we added to html (items-drag)

and create an app with a directive.

This works, but it’s totally unrealistic. In real life we probably load items from somewhere and populate the div. So let’s try that.

Solution #2

We add the controller ItemsController to the HTML with ng-repeat

and add controller to our app.

This will NOT work. Because when directive is loaded, it will find all spans and attach draggable to them. But because items are empty, it won’t find any spans. When they are loaded from the server ($timeout executes), ng-repeat will repeat and show items, but draggable will not be attached.

We can solve this by adding $watch and watching when items update and attach draggable. Let’s just update our directive.

This works. Great. But actually there is a big problem. When ng-repeat is adding the elements into the DOM, $watch method is fired and draggable is attached to items. Problem is that this happens during ng-repeat so draggable is not attached to all elements. What now?

Solution #3

We need to somehow wait for ng-repeat to finish and that all elements/items are loaded into DOM. Based on my research, there is no bulletproof way. Some suggest to use timeout.

This solution has one big problem. We cannot never set the right timeout time. If we set too small, it won’t work if we have a long list of items. If we set too large, then we can impact the user experience.

Solution #4 – The working one

The working solution is actually really simple and works for small or large lists of items without impacting the user experience.

We updated the directive’s element. We don’t attach directive to div#items anymore, but to each span. When each element/item is added to DOM, directive is fired and attaches draggable. So there is no timeouts or watching if $scope.items changed.

For me, this is the best way to combine AngularJS with jQuery UI – Draggable. Of course it also works for any plugin.

How to read local JSON file with Phonegap + jQuery Mobile

While working on my Phonegap project I wanted to load initial data into SQLite. One option is to download it from the internet, but it’s always annoying to notify the user to turn on internet and to wait for all the files to download (especially if you have to download 50 images).

The other option is to load local data. Problem is that identifying the right path to local file can be tricky. But the solution is actually easy.

All we need is to get current location, remove index.html to get root folder, append it to path of JSON file and voila.

How to get random element from array with JavaScript

Imagine you have an array of numbers.

Goal is to get a random element of an array. There are several solutions posted on stackoverflow.com. But most of them are just too complicated, so I created my solution.

I have extend Array to add function random. What is does it uses random number and length of array to create a random index. Let’s use it in action.

That’s it. Happy coding.

Update:

Actually it’s very bad practice to extend prototype. Reasons are problems with browser compatibility. It’s better to create a function and use it. Or you can always use libs like underscore and it’s method sample.

How to remove related videos when using YT.Player for embedding YouTube videos

Today while working on MEDinar we had a problem with our presentation videos. We are using YouTube to host it. But when our customer finishes watching, they are suggested related videos. All of them were not related plus it’s not good for them to get distracted. The video is about how MEDinar is awesome and not some cat videos.

We are using YT.Player to embed video.

The reason is why we are using this way is to also track events when usre pauses and completes watching videos.

Many solutions on the internet suggested to specify additional parameter rel=0 to end of the URL. But how to do this with YT.Player? We needed to check official Google documentation https://developers.google.com/youtube/player_parameters#rel. By adding additional parameter in YT.Player initialization, we were able to remove related videos. The final code is.

Simple, right?