Get input name array key in JQuery

By: Ryan Wong at

When you want to retrieve the key value in an input element that has a name array you need to do the following:

1
<input type="text" name="tag[1]" value="blah"/>


1
2
3
4
5
6
7
var tagSelect = [];
$('input[name^="tag"]').each(function(oneTag){
var oneValue = $(this).val();
var name = $(this).attr('name');
var id = parseInt(name.match(/[0-9]+/));
tagSelect.push(id);
});

Hope it helps you out.

devbridge/jQuery-Autocomplete clashes with jquery-ui autocomplete when used together

By: Ryan Wong at

I first started using the devbridge autocomplete since it look pretty good and then I needed a tagging plugin called tagedit.

What I found was that tagedit was using jquery-ui autocomplete and it would not work at all when devbridgeautocomplete was called above.

I tried to alias it like other people said but it didn’t help.

So in the end I removed devbridge autocomplete and used jquery-ui autocomplete

Hope it helps

Calculate distance between two gps location using mysql

By: Ryan Wong at

When you need to calculate the distance between 2 gps cordinates(latitude, longitude) you can use this mysql query.

1
2
3
4
5
'SELECT (((acos(sin((' + latitude +
'*pi()/180)) * sin((`latitude`*pi()/180))+cos((' + latitude +
'*pi()/180)) * cos((`latitude`*pi()/180))' +
'* cos(((' + longitude + '- `longitude`)* pi()/180))))*180/pi())*60*1.1515* 1.609344) as distance ' +
'FROM table WHERE 1 ORDER BY distance ASC

You can add a having statement or distance conditional to filter out rows.
Hope this helps.

Calculate distance between two gps location using javascript

By: Ryan Wong at

When you need to calculate the distance between 2 gps cordinates(latitude, longitude) you can use this function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

function distanceGPS (lat1, lon1, lat2, lon2) {
var radlat1 = Math.PI * lat1 / 180;
var radlat2 = Math.PI * lat2 / 180;
var radlon1 = Math.PI * lon1 / 180;
var radlon2 = Math.PI * lon2 / 180;
var theta = lon1 - lon2;
var radtheta = Math.PI * theta / 180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) +
Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
dist = Math.acos(dist);
dist = dist * 180 / Math.PI;
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
return dist.toFixed(3);
}

There are many variation of this function on the internet but mine returns the answer in kilometers.

Next post I’ll show how to calculate the distance between GPS in the back end.

Hope this helps.

How to setup jwt authentication laravel 4

By: Ryan Wong at

When trying to authenticate mobile application with laravel back end server, you cannot use the default session you would use in php. The common practice for authenticating is using json web tokens.

##Steps:
1.Depending on which version of laravel you are using install the correct plugin for laravel cors with composer.
I’m using laravel 4 so I used:

1
composer require barryvdh/laravel-cors:0.2.x

2.Next I created the config file with

1
php artisan config:publish barryvdh/laravel-cors

3.Next I modified the config file in app/config/packages/barryvdh/laravel-cors/config.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'defaults' => array(
'supportsCredentials' => false,
'allowedOrigins' => array(),
'allowedHeaders' => array(),
'allowedMethods' => array(),
'exposedHeaders' => array(),
'maxAge' => 0,
'hosts' => array(),
),

'paths' => array(
'api/v1/*' => array(
'allowedOrigins' => array('*'),
'allowedHeaders' => array('*'),
'allowedMethods' => array('*'),
'maxAge' => 3600,
)
)

You can use whatever route you want, I just used /api/v1.

4.Next install jwt plugin. Depending on your version of laravel, install a different version of the plugin with composer.

1
composer require tymon/jwt-auth:0.4.*

5.Next I created the config file with

1
php artisan config:publish tymon/jwt-auth

You can change the jwt settings here if you want.

6.Next you will create a filter to check for jwt token before processing a route. I put the filter in my route.php file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Route::filter('authMobile', function($route, $request)
{

try{
$token = JWTAuth::getToken();
$user = JWTAuth::toUser($token);
$tokenStr = JWTAuth::getToken()->__toString();
if ($user->loginToken != $tokenStr){
throw new Exception("Login Token don't match");
}
Session::put('user',$user->id);
}catch(Exception $e){
return Response::json(array(
'error' => true,
'message' => 'Invalid Session'
));
}
});

7.So an example route will look like the following:

1
2
3
4
Route::get('/api/v1/user', array(
'before' => 'authMobile',
'uses' =>'UsersController@getUserProfile'
));

To access the user in the action, you can retrieve it from the session.

  1. When creating the login, you would return the following JSON to the mobile app.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //validation happens jere
    $row = User::find(Auth::user()->id);
    $token = JWTAuth::fromUser($row);

    DB::table('users')->where('id', '=',$row->id )->update(array(
    'last_login' => date("Y-m-d H:i:s"),
    'loginToken' => $token
    ));
    return Response::json(array(
    'token' => $token
    ));
    }

9.Now everytime the mobile app makes a request to the server, they must add a header

1
Authorization bearer Y2E1YTc2MmFkMWU4NjJmZTBiZDU1NmEzMmJhZjBmYjc3MmNkYzBiYjE3YWM5MTkxNDg2Zg...

10.Make sure your .htaccess file allows HTTP authorization.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>

RewriteEngine On

RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

Hope this helps you out.

How to upload images to a server and input them into tinymce version 4

By: Ryan Wong at

##My Goal:

  1. Create/Find a tinymce version 4 plugin to upload images to the server, save this image to the database and place this image in my tinymce editor

  2. This plugin must also be able to view a list of media files(image/video) that are in my database in a gallery format where the user can click an image and place it into tinymce

Some plugins I looked into are:

  • moxiemanager plugin (problem is it cost 100$ and only forfills part of what I want)
  • open manager (may have worked for tinymce version 3 but broke when I used it)
  • default image uploader (could not tag the images uploaded, had to be external sources)

After much distress, I created my own plugin.

Hopefully this will save you countless hours trying to figure out how to make an image uploader in tinymce 4.

Steps

  1. Download the latest tinymce.js file from their site.

  2. Define the textarea/element you want to run tinymce on

    1
    <textarea name='text' rows='2' id='editor' class='form-control'></textarea>
  3. Add the following to your javascript file:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $(document).ready(function() {
    tinymce.init({
    selector: "#editor",
    plugins: [
    "imageuploader"
    ],
    toolbar1: "imageuploader",
    toolbar_items_size: 'small',
    menubar: false,
    height: 800
    });

I called my plugin imageuploader and I removed all unnecessary plugins. All plugins in the toolbar or menu bar must
be in plugins.

4.Create the tinymce version 4 plugin and place it in the plugins folder inside tinymce. Call it plugin.min.js.

1
2
3
4
5
6
7
/js
/js/<vendor>
/js/<vendor>/tinymce4
/js/<vendor>/tinymce4/js
/js/<vendor>/tinymce4/js/tinymce
/js/<vendor>/tinymce4/js/tinymce/plugins/imageuploader
/js/<vendor>/tinymce4/js/tinymce/plugins/imageuploader/plugin.min.js

plugin.min.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
tinymce.PluginManager.add('imageuploader', function(editor, url) {
// Add a button that opens a window
editor.addButton('imageuploader', {
text: 'Add Media',
icon: 'image',
onclick: function() {
// Open window
editor.windowManager.open({
title: 'Select Media',
url: '/article/upload',
buttons: [{
text: 'Submit',
onclick: 'submit'
}, {
text: 'Cancel',
onclick: 'close'
}],
width: 800,
height: 600,
onsubmit: function(e) {
var newMedia = $('iframe').contents().find('#media-url');
var url = newMedia.val();
if (url.length > 0){
if (type == 'image'){
editor.insertContent('<img src="' + url + '" />');
return true;
}else if (type == 'video'){
editor.insertContent('<video autobuffer controls><source src="' + url + '" /></video>');
return true;
}
}else{
alert('something went wrong');
return false;
}
}
});
}
});


});

I’ll explain step by step.

1
tinymce.PluginManager.add('imageuploader', function(editor, url) {

This line creates the plugin in tinymce

1
editor.addButton('imageuploader', {options},{params});

This line creates a button in the toolbar where you pass in options and parameters to iframe you will open.

Some options:

1
title: 'Select Media',

Title is the title of the iframe

1
url: '/article/upload',

url is the route of the page the iframe opens.

1
2
3
4
5
6
7
  buttons: [{
text: 'Submit',
onclick: 'submit'
}, {
text: 'Cancel',
onclick: 'close'
}]

Created 2 buttons below the iframe. when either button is clicked, the iframe will close. However, you can bind submit to a function when clicked.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
onsubmit: function(e) {
var newMedia = $('iframe').contents().find('#media-url');
var url = newMedia.val();
var type = newMedia.attr('data-media-type');
if (url.length > 0){
if (type == 'image'){
editor.insertContent('<img src="' + url + '" />');
return true;
}else if (type == 'video'){
editor.insertContent('<video autobuffer controls><source src="' + url + '" /></video>');
return true;
}
}else{
alert('something went wrong');
return false;
}
}

The method I used to retrieve the url from the iframe is on line 2. After you uploaded your images/video, you would
save it to a hidden input field which you will retrieve when submit button is clicked.

At this point, you can call editor.insertContent() to add it to the tinymce editor.

5.Implementing the iframe page /article/upload

On this route I created 4 screens:

  • button to show options to upload new media and button to select existing media
  • upload form for new media with additional fields I need
  • image gallery of existing media that user can include in their article
  • success page

###Page to show 2 buttons

1
2
3
4
5
6
7
8
9
10
11
<div class="col-md-12 main-button-container">
<div class="well center-block first-upload-container">
<button type="button" class="btn btn-success btn-lg btn-block" id="upload-new">
Upload New Media
</button>
<button type="button" class="btn btn-info btn-lg btn-block" id="select-media">
Select Media
</button>
</div>
</div>
<input type="hidden" name="media-url" id="media-url" data-media-type="image" data-caption=""/>

###Page to upload new media

1
2
3
4
5
6
7
8
9
10
11
<div class="col-md-12 upload-new-container">
<h3>Upload New Media File</h3>
<p>Media File</p>
<input type="file" name="mediafile-new" id="mediafile-new" />
<br/>
<p>Caption</p>
<input type="text" name="caption-new" id="caption-new" class="form-control"/>
<br/>
<button class="btn btn-block btn-success" id="upload-new-media">Upload</button>
<button class="btn btn-block btn-error" id="upload-new-cancel">Cancel</button>
</div>

###Page to select old media

1
2
3
4
5
6
7
8
9
10
11
<div class="col-md-12 select-media-viewer well center-block">
<h3 class="media-viewer-title">Media On File</h3>
<p class="media-viewer-subtext">
Please click the media you want to add to your article. Then Click use media</p>
<br/>
<div class="gallery">

</div>
<button class="btn btn-block btn-info use-media"> Use Media</button>
<button class="btn btn-block btn-error" id="use-media-cancel">Cancel</button>
</div>

I am dynamically filling gallery div with media I have and displaying them with gridify.js

###Upload file to server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var data = new FormData();
data.append('filename', $('#mediafile-new').prop('files')[0]);
$.ajax({
type: 'POST',
processData: false, // important
contentType: false, // important
data: data,
url: '/api/v1/upload',
dataType : 'text',
success: function(jsonData){
//do something
},
error: function(){
//do something
}
});

Hope this helps you out.

Loading dynamic data with handlebars

By: Ryan Wong at

Its very fustrating when you have to create elements on the fly using the json data you got from the server.

The javascript gets very bulky and messy.

To solve this you could use handlebars.js. Handlebars.js is a templating library to help you preload templates
that you can pass in information and use.

Steps:
1.Download handlebars.js from their site.

2.Depending on which view engine you use, you have two options:

  • if your template engine uses double curly braces for tags, you must load your handlebar template by ajax
  • if your template does not use it, you can just include it in your html file like the following:
1
2
3
4
5
6
7
<script id="some-template-tpl" type="text/handlebars">
<a class="btn blue btn-block" href="/gosomewhere"><i class="icon-eye"></i> Blah</a>
{{#if isAdmin}}
<a class="btn btn-info btn-block" href="/gosomewhereelse">
<i class="icon-eye"></i> Blah Blah</a>
{{/if}}
</script>

3.You will need to compile the template and input the data into the template.

  • loading template in using ajax

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $.ajax({
    url: '/js/templates/some-template-tpl.js',
    cache: false,
    dataType: 'text',
    success: function(data) {
    var template = Handlebars.compile(data);
    var someDataLoadedBeforeThis = [...];
    someDataLoadedBeforeThis.map(function(oneData){
    $('#container').append(template({
    a: oneData.id,
    c: oneData.id == oneData.blah
    }));
    return false;
    });
    }, error: function(xhr, ajaxOptions, thrownError) {

    }
    });
  • loading template from script tag

    1
    2
    3
    4
    5
    6
    7
    var template  = Handlebars.compile($('#some-template-tpl').html());
    var someDataLoadedBeforeThis = [...];
    someDataLoadedBeforeThis.map(function(oneData){
    $('#container').append(template({
    a: oneData.id,
    c: oneData.id == oneData.blah
    }));

Hope this helps.

Targeting Select box with JQuery

By: Ryan Wong at

I always forget how to target select box that has been selected when I need it most.

So I decided to make a blog post so I can get the answer really fast.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//find out selected value
var type = $('#type :selected').val();

//get changed value
$('#type').on('change', function(e){
var value = this.value;

//dynamically making select box
$.getJSON("/api", {
//data
}).done(function(a) {
$.each(a, function(a, b) {
$("#select").append($("<option/>", {
value: b.value,
text: b.text
}))
});
});

Hope it helps.