This tutorial is inspired from this one. A few changes were made to have things working with the 2.5 version of cordova.
Attention: The push notification can only work on a real device, not a simulator.
Steps:
What is the push notification?
How does it work?
Create a certificate.
Create a Cordova 2.5 project.
Integrate ios-phonegap-plugin to the project.
Add some native code.
Add some JavaScript to use the push notification API.
Server side
What is the push notification?
If we ask wikipedia
The Apple Push Notification Service is a service created by Apple Inc. that was launched together with iOS 3.0 on June 17, 2009… not really interesting
If we ask Apple
It’s something who gonna revolutionize our phone … our life… the world!!
So, what is realy the push notification?
Push notification allows an app to notify you of new messages or events without the need to actually open the application, similar to how a text message will make a sound and pop up on your screen. This is a great way for apps to interact with us in the background, whether it be a game notifying us of some event occurring in our game world or simply the iPad’s mail application beeping as a new message appears in our inbox.
Is it the first time you create a certificate for iOS? No? So you can move to the next section, just don’t forget to enable “Apple Push Notification service”.
In this case the certificate is used secure the connection between the server and the application. To make sure that no one else can send notifications to your applications.
You can use this great tutorial to create a certificate, without forgetting to, create the ck.pem file, we will use this later.
Create a Cordova 2.5 project.
If you don’t already have a Cordova project on your xcode, you can follow the getting started guide of Cordova to create one.
Integrate ios-phonegap-plugin to the project.
After downloading the plugin from github, rename the bin folder to PushNotification, and drop it on the xcode project, then select Create groups for any added folders.
Drag and drop the plugin folder to the xcode project.
Now, from the finder, copy the PushNotification.js file to your www folder (or under a sub folder of www).
Then, add a script tag in your index.html to refer to it.
And finally, into the didFinishLaunchingWithOptions method, add this code before the return YES to handle opening the application from a push notification
Add some JavaScript to use the push notification API.
Add on onResume listener next to your ondeviceready listener, to handle the case when the application receives a push message while it is running in the background.
In the on device ready, add the following code to handle, the case of the application recive a push when she is active, register the application to the APNs server, and the case where the application is closed while received a push
CibulCalendar is a date picker that enables users to easily pick dates or date ranges.
You can download the latest version by clicking here or visit the github repo. The minified version of the script is around 10.9kb.
Here is a demo that shows how to select a range with a mouse drag&drop or a touch and drag gesture:
functiononload(){
setCibulCalendar('basic');// will stick to element <input type="text" id="basic"/> }
It is also used in the header of the website cibul.net. It works on most major modern browser and IE 8.0+ as well as Android and iOS devices.
Features include:
Drag and drop range selection
Single date selection
Multilingual
Helper function for single line setup
Fully Customizable (see details below)
How to use
There are two ways to use the calendar:
setCibulCalendar(id, options): simplest setup for use with an input field.
var cCal =new CibulCalendar(canvasElem, options): more flexible approach to handle date selections as you wish through a callback and keep a reference to the calendar for later use.
Options
range (default: true): if false, range date picking is disabled. Here is an example.
enabled (default: true): state of the calendar at init
lang (default: ‘en’): Language of the calendar. can be english (en), french (fr), italian (it) or spanish (es). You can extend this with any other language (see below).
firstDayOfWeek (default: 1): first day of the week on the calendar. 0 for sunday and onwards.
selected (default: false): default selection at initialization. Should be a object: {begin: Date, end: Date}
filter: (default: false): callback called on each calendar render to handle date classes. If set, function is given a date and an array of classes and should return the array of classes that will be set on the rendered calendar. Click here for an example highlighting weekends.
navDomContent (default: {prev: ‘<', next: '>‘}): html content for the month navigation links. In case you want to set something more fancy like icons or images.
classes: in case you want to change the name of the classes used in the calendar.
monthNames: add a new month set in the language of your choice. See here for an example of a calendar in icelandic
weekDays: add a new week set in the language of your choice
switchMonthOnHoverDelay: on a range selection spanning over multiple months, the delay during which next month days should be hovered over before the calendar goes to the neighboring month
Methods
disable: disable the calendar
enable: enable the calendar
showNext: render following month
showPrevious: render previous month
setSelected(newSelection, updateMonth): set new selection. newSelection is an object containing two indexes: begin and end, each referring to a date. updateMonth is a boolean indicating if the month of the start of the selection should be displayed.
Here we will see how to upload an image without a page refresh using an iframe and some javascript.
There are a bunch of jquery plugins that do this, but you’ll see here that there is nothing really complicated about it and it can easily be achieved with a couple of javascript lines.
Principle
Normally when you want to upload an image to the server you create a post form with a ‘file’ input to allow the user to pick the image, and a submit button for posting the contents to the server. The user clicks on ‘Choose file’, picks his image and clicks on submit… and sees the browser waiting for a full page response after the file is uploaded.
The trick to avoid this full page refresh is to use a ‘target’ attribute on the form and have it point to an iframe. As the submit button is clicked, the browser will load up the response in the targeted iframe without refreshing the whole page.
Pretty simple.. Note the target attribute with the name of the iframe
Second, the upload script:
<?php
// I'm skipping a lloooot of verification steps on the file here. // Also, I'm assuming you uploaded a jpg.
move_uploaded_file($_FILES['image']['tmp_name'], 'uploaded/pic.jpg'); ?> <!DOCTYPE html> <html> <head></head> <body> <imgstyle="width: 100%;"src="uploaded/pic.jpg?v=<?php echo rand(0,1000) // rand() prevents the browser from displaying a previously cached image ?>"/> </body> </html>
Nothing more.
Already with this, you have a basic solution which uploads and displays images without a page refresh, and without having event started writing any javascript.
Pure eye candy.
But with javascript it is easy to come up with a more flexible solution in only a few steps:
First, we’ll have a page both serving up the form and processing it. Normally two different resources handle this to avoid reposts, but we’ll keep it simple for now.
Then, we prepare a javascript function that handles the iframe creation and form tweaking to make a sleeker image submission
That function will change the destination of the form post, to a script which we write to process the image and prepare the content for the iframe.
And finally, we write a function to handle the response
A regular form submission
The following form submits the image and serves up the result directly with a full refresh:
Your form works now fine on its own, and reloads itself with whatever image was submitted.
The js function enabling the iframe
Now we need a function that replicates the behavior described earlier in this tutorial: it needs to create an iframe, and have the form point to it through a target attribute. The function will also divert the submission to a dedicated php script that will generate the contents of the iframe. Here it is (don’t forget to add a reference to it in your main file (<scripttype="text/javascript"src="iframeSubmit.js"></script>:
function iframeSubmit(formElem, action, callback){
// we name a callback that will be called from inside the iframe var callbackName ='iframe'+ Math.ceil(Math.random()*10000);
// we create an iframe and use the callback as its name (why not). var iframe = document.createElement('iframe');
iframe.setAttribute('name', callbackName);
iframe.style.display='none';
// we add the target and edit the action of the form
formElem.setAttribute('target', callbackName);
formElem.setAttribute('action', action);
// we add the hidden iframe after the form
formElem.parentNode.appendChild(iframe);
window[callbackName]= callback; };
Preparing the response for the iframe
When we use the iframeSubmit function, we’ll have the form point to upload.php for image submissions and the result will be loaded within the iframe (which is now a hidden element in the page). The upload.php script should process the submission and generate an iframe content which will call the function defined and passed by iframeSubmit, with the results of the operation. The function will be called from within the iframe, which is possible only when the page and iframes have the same domain origin. Here it is:
<?php
// I'm skipping a lloooot of verification steps on the file here. // Also, I'm assuming you uploaded a jpg. $imagePath ='uploaded/pic.jpg'; move_uploaded_file($_FILES['image']['tmp_name'], $imagePath);
There. Once the response of upload.php is loaded in the iframe, it will only contain the execution of the callback defined in the iframeSubmit script
Wrapping it up
The only thing missing now is the bit in the index page where the javascript function is called and the response processed. Add this to the end of the index page:
There, you can put in the callback of the iframeSubmit function all the image handling you want! (The function here only piles up the images received in a list)
Here is a function that transitions a pane element to a new one by using either a drag of your mouse or a pan/slide gesture on touch enabled devices.
Give it a try if you are looking for a simple solution to handle pane transition or a tab navigation system without using a fully featured tab navigation script.
Drag the pane to the left, or wait for the transition to be triggered
Basic usage
Pass it the element you want to transition from, specifying the elements you want to transition to, as such:
slide(paneElement, {right: newPaneElement});
The function returns a trigger function, should you want to call the transition by yourself.
You can define several slide directions with different destination panes by just passing them in the second parameter like this:
Once the transition is complete, all but the displayed element are removed from the dom.
You’ll find a simple demo page here and a github library here
Compatibility
This was tested with IE8, chrome, firefox, opera and mobile webkit browsers. Write me a note if you have a browser (a recent-ish one) that throws errors
The last post was about deploying the plugin offering the same functionality on and android device, here is how to get the iOS version running. Find the github page of the plugin here. There’s also a more detailed procedure here
Get a basic phonegap project running
Get the plugin files. Copy the LocalNotification.h and .m in your project’s Plugins xcode folder and the plugin js file in the www folder.
If you are using cordova 1.7 or above, the content of LocalNotification.h should be something like:
//
// LocalNotification.h
// Phonegap LocalNotification Plugin
// Copyright (c) Greg Allen 2011 & 2012 Drew Dahlman
// MIT Licensed
/*
NOTES:
We will be creating LocalNotifications that can be set to fire while app is inactive,
and create a callback for the JS to know when the app has come back from a notification.
One thing that is deceptive about the LocalNotifications plugin is that when it shows a notification
has been created it shows it based on the timezone +0000 which can throw you off.
in the call for setting the notification we simply call notification.local_timed("13:00") - note that I supplied a string.
The ability to set repeating notifications has been added!
- daily
- weekly
- monthly
- yearly
*/
// NOTIFICATION CENTER
/*
I like to set up one object that's only job is to manage notifications
*/
var notification = {
init:function(){
},
// This will fire after 60 seconds
local_min:function(){
var d = new Date();
d = d.getTime() + 60*1000; //60 seconds from now
d = new Date(d);
plugins.localNotification.add({
date: d,
repeat:'daily',
message: 'This just fired after a minute!',
hasAction: true,
badge: 1,
id: '1',
sound:'horn.caf',
background:'app.background',
foreground:'app.running'
});
},
// This will fire based on the time provided.
// Something to note is that the iPhone goes off of 24hr time
// it defaults to no timezone adjustment so +0000 !IMPORTANT
local_timed:function(hh,mm){
// the example time we provide is 13:00
// This means the alarm will go off at 1pm +0000
// how does this translate to your time? While the phone schedules 1pm +0000
// it will still go off at your desired time base on your phones time.
console.log(hh+" "+mm);
// Now lets make a new date
var d = new Date();
d = d.setSeconds(00);
d = new Date(d);
d = d.setMinutes(mm);
d = new Date(d);
d = d.setHours(hh);
d = new Date(d);
plugins.localNotification.add({
date: d,
repeat:'daily',
message: 'This went off just as expected!',
hasAction: true,
badge: 1,
id: '2',
sound:'horn.caf',
background:'app.background',
foreground:'app.running'
});
},
clear:function(){
plugins.localNotification.cancelAll();
},
tomorrow:function(hh,mm,days){
// Now lets make a new date
var d = new Date();
d = d.setSeconds(00);
d = new Date(d);
d = d.setMinutes(mm);
d = new Date(d);
d = d.setHours(hh);
d = new Date(d);
// add a day
d = d.setDate(d.getDate()+days);
d = new Date(d);
plugins.localNotification.add({
date: d,
repeat:'daily',
message: 'This went off just as expected!',
hasAction: true,
badge: 1,
id: '3',
sound:'horn.caf',
background:'app.background',
foreground:'app.running'
});
}
},
background:function(id){
console.log("I was in the background but i'm back now! ID="+id);
},
running:function(id){
console.log("I am currently running, what should I do? ID="+id);
}
};
Here is an edit of the readme file found in the LocalNotification plugin for phonegap on Android. I’ve stumbled on a couple of issues which were not covered there and decided to make a version of the step through that worked for me. Assuming you already have a basic project setup (with a 2.0-ish cordova version), follow these steps:
Get a basic phonegap project running for Android.
Add the LocalNotification.js file to your project js files and add a reference in your index.html file. If you are using phonegap 2.0.0 or above, edit it and replace all occurrences of PhoneGap with cordova
Create a package ‘com.phonegap.plugin.localnotification’ (in Eclipse, right click on the project, new > Package)
Copy all plugin java files in your project’s package (drag and drop the files)
Edit AlarmReceiver.java and add import your.project.name.R; in the end of the import list
Edit the LocalNotification.java file by replacing alarm = new AlarmHelper(this.ctx); with alarm = new AlarmHelper(cordova.getContext());
Make sure the package reference in the first line of each of those java files matches the folder you actually placed them in.
Update your res/xml/plugins.xml file with the following line: <plugin name="LocalNotification" value="com.phonegap.plugin.localnotification.LocalNotification" />
Add the following fragment in the AndroidManifest.xml inside the application tag:
Here is a little function that can be used to turn urls found in text on a page into clickable links. I assembled it and tweaked it taking bits and pieces from several forums.
In this article we’ll use the google maps v3 API to show two draggable markers on a map linked with a line. As the markers are dragged, we want the line position to be updated so that it appears to always be linked and we also want to an updated indicator displaying the distance between the two markers in kilometers.
To achieve this, we will use the Markers MVCObject properties to bind their positions to a method which will update the line and indicator as the Markers are dragged around the map.
Getting started by creating a Map
We start with an empty html page in which we will write our script. This page shows a full page map with over it a box in which we’ll keep an updated value of the distance between the markers. Here we go:
var map = new google.maps.Map($('#map-canvas'), {
center: new google.maps.LatLng(48.860932,2.335925),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
With this we have a working full page map ready to receive some markers and a polyline. The libraries we are using are the google maps v3 (obviously) and the jquery library which we use to handle things on the page (like $(‘#map-canvas’)) and also to ensure that the javascript is not executed before the page is fully loaded (that is what the $(function(){}) is for).
Add two markers and a line
Now we add our two markers. One on the Louvre Museum and the second on the Eiffel Tower. Add this after the map declaration:
We also create the line, which is a Polyline with only two positions, one for each marker:
var line =new google.maps.Polyline({
path:[marker.getPosition(), marker2.getPosition()],
map: map });
Calculate the distance between two markers
Before we start binding the markers with the line, we need to be able to calculate the distance between the markers. There used to be a practical method to do this in a previous version the the google maps API but it does not exist in the latest version (last time I checked anyways). So we will add it to the LatLng class so that we can easily determine the distance between two points. This methods uses the Haversine formula to calculate the distance. Add it before the $(function(){… line:
Here we are calculating the distance, rounding it up to have something in kilometers and we put it in our display
Tie everything up using MVCObject properties
For the time being, everything is initialized, the two markers are displayed with a line in between them, the distance between the two markers is displayed as well at the bottom of the screen, but nothing happens when one of the markers is dragged. What we need is to update the position of the line and update the distance display as the drag occurs. This is where the MVCObject properties of our objects are useful. Using them, we can bind attributes (in our case, the position of the markers) to methods which will update the line position and the distance display any time the attributes are changed.
First we create the method that will update the line and the display (before the $(function(){ again):
var update_line_and_display =function(line, display, position1, position2){
// update the line
line.getPath().setAt(0, position1);
line.getPath().setAt(1, position2);
We want that function to be called whenever the position of the markers change. As markers inherit the MVCObject, their attributes are bound to methods which if defined are triggered any time the attribute is changed. The names of these methods derive from the attribute. In our case, we use the position_changed method for each marker. We add this at the end of the script and we are done!
Hi, welcome to the Cibul Tech blog! The purpose of this blog will be to post notes about whatever we think is worthwhile mentioning as we stumble upon them while we try to move forward with building web applications. Personnaly, I am fairly new to developping using PHP and javascript and I have only recently started fiddling with the symfony framework, and as I struggle with the bits and pieces, I find the documentation, tutorials and tips from blogs and other online resources really helpful and so this blog will be my attempt to contribute back to the PHP community.
Anyway, I hope you will find some of the stuff posted here useful, any feedback will be greatly appreciated.