a simple SPA example in backbone - backbone.js

I have a little problem in configuring the mistake in my code.
I have written index.html which includes the template, and a jscript file which includes the model, collection and view.
please let me know where i am doing wrong. I particularly doubt whether i am using el tag wrongly.. or is it wrong in fetching the json data or in render function.
index.php
<head>
<meta charset="utf-8">
<title>Backbone.js News List</title>
<link rel="stylesheet" href="newsList.css"/>
</head>
<body>
<script src="../../test/vendor/json2.js"></script>
<script src="../../test/vendor/jquery.js"></script>
<script src="../../test/vendor/underscore.js"></script>
<script src="../../backbone.js"></script>
<script src="newsList.js"></script>
<header>
<h1 id="center_text">News List</h1>
</header>
<h2>News Trending</h2>
<div id="news-list"></div>
<div id="footer">
<h3 id="center_text" >Copy Right</h3>
</div>
<!-- Templates -->
<script type="text/template" id="item-template">
<div class="container" id="news">
<img id="img" src = <%- img %> >
<section>
<b id="title" ><%- title %> </b>
<br><%- snippet %>
<p><small id ="date"> <%- date%> </small></p>
</section>
</div>
</script>
</body>
</html>
JavaScript code
newsList.js
$(function(){
var NewsList = Backbone.Model.extend({
// Default attributes for the todo item.
defaults: {
id:"",
title: "empty NewsList...",
img:"",
snippet:"",
date:""
},
initialize: function(){
console.log("model initialized");
}
});
var NewsListColln = Backbone.Collection.extend({
// Reference to this collection's model.
model: NewsList,
url: 'http://api.divum.in/training/json/newslist.php',
initialize: function(){
console.log("colln initialized");
}
});
//VIEW
// The DOM element for a news item...
var NewsListView = Backbone.View.extend({
//... is a list tag.
el:"#news-list",
template: _.template($('#item-template').html()),
initialize: function() {
console.log("in view");
this.render;
},
render: function(eventName) {
console.log("in render");
var n = newsLists.content;
$.each(n.news, function(newslist){
var newsTemplate= this.template(newslist.toJson());
$(this.el).append(newsTemplate);
}, this);
return this;
}
});
var AppView = Backbone.View.extend({
el: "body",
initialize: function() {
var newsLists = new NewsListcolln();
var newsView = new NewsListView({model: newsLists});
newsLists.bind('reset', function () { newsView.render();});
newsLists.fetch();
}
});
var App = new AppView();
/* var newsLists = new NewsListColln;
var newsListView = new NewsListView({model: newsLists});
newsLists.fetch({ url: "http://api.divum.in/training/json/newslist.php", success: function() {
console.log(newsLists);
}});
newsLists.bind('reset', function () { newsListView.render(); });*/
/*
render:function(){
this.$("news-list").append(newsView.render().el);
}*/
});
css-- newsList.css file
body {
padding:0px;
margin: 0px;
background-color: black;
color:white;
}
h1 {
padding:5px;
margin: 0;
background-color: #FFFF00;
color:black;`enter code here`
}
h3{
margin: 0;
background-color:#FFFF00;
color:black;
}
h2{
padding:5px;
margin:0px;
background-color: white;
color:black;
}
.container {
color:white;
}
div img {
float: left;
width: 128px;
height:: 85%;
}
.container section{
margin-left:128px;
}
#footer{
position: fixed;
width: 100%;
bottom: 0px;
}
#center_text{
text-align:center;
}
#left_text{
text-align:left;
}
div p{
text-align: right;
}
.clearfix{
overflow: auto;
}

Errors:
The site returns a object, but collections are arrays. You need to use the models in this case.
render is a function, so you have to call it: this.render();
After passing a model to a view, access it via this.model.
A model needs either a url or a urlRoot set if you want to fetch it seperately
fetch is asynchronous you have to wait until it finishes.
Use .get() to access model properties
Working code: http://jsfiddle.net/FHsrL/1/

Related

Angular JS expression not evaluating

I have written a simple Angular JS code. I'm a beginner. However, one of my expressions is not getting evaluated. Need help. Please check the code below -
var myAppModule = angular.module('myAppModule', []);
myAppModule.controller('myController', function($scope){
// Hide colors by default
$scope.isHidden = true;
// a function, placed into the scope, which
// can toggle the value of the isHidden variable
$scope.showHideColors = function () {
$scope.isHidden = !$scope.isHidden;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="myAppModule">
<head>
<title>Angular JS</title>
<script src="js/angular.min.js"></script>
<script src="js/myAppModule.js"></script>
<style>
body {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
}
div {
margin: 20px;
padding: 20px;
font-size: 16px;
color:#ffffff;
}
#red {
background-color: red;
}
#green {
background-color: green;
}
#blue {
background-color: blue;
}
#purple {
background-color: purple;
}
#gray {
background-color: gray;
}
#olive {
background-color: olive;
}
</style>
</head>
<body ng-controller="myController">
<h2>AngularJS Socks</h2>
<p>Keep warm this winter with our 100% wool, 100% cool, AngularJS socks!</p>
<button ng-click="showHideColors()" type="button">
{{isHidden ? 'Show Available Colors' : 'Hide Available Colors'}}
</button>
<div id="red" ng-hide="isHidden">Red</div>
<div id="green" ng-hide="isHidden">Green</div>
<div id="blue" ng-hide="isHidden">Blue</div>
<div id="purple" ng-hide="isHidden">Purple</div>
<div id="gray" ng-hide="isHidden">Dark Slate Gray</div>
<div id="olive" ng-hide="isHidden">Olive</div>
</body>
</html>
The expression - {{isHidden ? 'Show Available Colors' : 'Hide Available Colors'}} is not getting evaluated but displaying as is on the button. No clue as to what i missed. Thanks in advance.
The code is missing closing bracket. You can see the working demo here - http://jsfiddle.net/me8j3zyc/
var app = angular.module('myAppModule', []);
app.controller('myController', function($scope) {
$scope.isHidden = true;
// a function, placed into the scope, which
// can toggle the value of the isHidden variable
$scope.showHideColors = function() {
$scope.isHidden = !$scope.isHidden;
} // <- This is missing.
});
This is because you havent closed your function
myAppModule.controller('myController', function($scope){
// Hide colors by default
$scope.isHidden = true;
// a function, placed into the scope, which
// can toggle the value of the isHidden variable
$scope.showHideColors = function() {
$scope.isHidden = !$scope.isHidden;
}})
Your expression is fine, but you have a typo error in your JS file:
var myAppModule = angular.module('myAppModule', []);
myAppModule.controller('myController', function($scope) {
// Hide colors by default
$scope.isHidden = true;
// a function, placed into the scope, which
// can toggle the value of the isHidden variable
$scope.showHideColors = function() {
$scope.isHidden = !$scope.isHidden;
} //MISSING
});
You can try this:
<button ng-if="isHidden" ng-click="showHideColors()" type="button">Show Available Colors</button>
<button ng-if="!isHidden" ng-click="showHideColors()" type="button">Hide Available Colors</button>

cordova ionic app seems to load controller twice

I'm having some issues with an app I'm creating in Cordova (5.3.3) using ionic (1.6.5) and angular js and building for iOS and Android.
I have a menu item that when I click should load the next state with other menu items. However it seems like it loads the next state once without the animation, then loads the state again with the animation resulting in a "jerky" effect. It's best shown in a video I have uploaded here: https://www.youtube.com/watch?v=YCEQeqFyNl4&feature=youtu.be
I was wondering if anybody has an idea of what could be the issue here and where I should start looking, or if there are known bugs about this?
Any help would be appreciated!
// the controller
.controller('ProgramCtrl', ['$scope', 'FacProgram',
function($scope, FacProgram) {
$scope.refresh = function() {
FacProgram.refresh()
.finally(function() {
$scope.$broadcast('scroll.refreshComplete');
});
};
$scope.temp_articles = function() {
return FacProgram.all();
};
}
])
.controller('ProgramDetailCtrl', ['$scope', '$stateParams', 'FacProgram',
function($scope, $stateParams, FacProgram) {
$scope.art = FacProgram.get($stateParams.programId);
}
])
// The factory in a different js file:
.factory('FacProgram', ['$http', '$q', 'FacJson',
function($http, $q, FacJson) {
var temp_articles = [];
function findHeader(src, headTag, index) {
var head = $(src).find(headTag).get(0);
temp_articles[index].headlinethumb = head.textContent;
temp_articles[index].headline = head.textContent;
}
function refresh() {
var q = $q.defer();
... // A fucntion that get's URL's from .json file
////////////////////////////////////////////////////////////
angular.forEach(urls, function(URL, index) {
//add the articles to the dictionary
temp_articles.push({
inx: index,
img: img_logos[index]
});
$http.get(URL)
.then(function(sc) {
// The will parse the html looking for thumbnail text, main body text etc
var src = sc.data.substring(sc.data.indexOf('<html>'));
... // code that parses website for content etc
////////////////////////////////////////////////////////
q.resolve();
},
function() {
q.reject();
});
});
});
return q.promise
}
return {
all: function() {
return temp_articles;
},
get: function(programId) {
return temp_articles[programId];
},
refresh: function() {
console.log('DPG programs refresh triggered');
temp_articles = []; // a catch to prevent duplicates and to allow other templates to use without
//contamination
return refresh()
}
}
}]);
<!-- the start state for progams of the DPG -->
<ion-view>
<ion-content>
<div class="list">
<a class="item item-thumbnail-left item-icon-right item-text-wrap" ng-repeat="art in temp_articles()" href="#/program/{{$index}}">
<img ng-src="{{art.img}}">
<h2 class="padding-top" style="font-weight: 300;">{{art.headlinethumb}}</h2>
<i class="icon ion-chevron-right" style="font-size: 18px"></i>
</a>
</div>
</ion-content>
</ion-view>
<!-- the datailed view of the application -->
<ion-view>
<ion-content>
<div style="text-align: left; padding-top: 30px; padding-left: 20px; padding-right: 20px">
<h2 style="font-weight: 500; font-size: 17px">{{art.headline}}</h2>
</div>
<!--<p style="padding-left: 10px; font-size: 13px; font-weight: 300">Datum</p>-->
<div style="text-align: center">
<img style="max-height: 300px; max-width: 300px; width: auto;" ng-src="{{art.img}}">
</div>
<div class="padding" style="font-weight: 300">
<div ng-bind-html="art.text | hrefToJS"></div>
</div>
</ion-content>
</ion-view>
the same happened to me if you put your controller in app.js try removing it from there and only applying it in controller or viceversa.
your state in app.js should look like this:
.state('state-name', {
url: '/state-name',
templateUrl: "templates/walkthrough/state-name.html"
//Notice no controller here
})

Angularjs directive css not working

So I'm sure this is something simple but i can't figure it out.. My directive is working, but the css is not. this is an ionic-framework project
my index.html is the main template loading the css
...
<link href="css/style.css" rel="stylesheet">
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/less.js/1.7.5/less.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="js/services.js"></script>
<script src="js/calendar.js"></script>
</head>
<body ng-app="starter">
...
tab-dash.html is being loaded via ionic
<ion-view view-title="Dashboard">
<ion-content class="padding">
<div class="list card">
<div class="item item-divider">Recent Updates</div>
<div class="item item-body">
<div>
There is a fire in <b>sector 3</b>
</div>
</div>
</div>
<div class="list card">
<div class="item item-divider">Health</div>
<div class="item item-body">
<div>
You ate an apple today!
</div>
</div>
</div>
<div class="list card">
<div class="item item-divider">Calendar</div>
<div class="item item-body">
<calendar selected="day"></calendar>
</div>
</div>
the style.css
calendar
{
float:left;
display:block;
.border-box;
background:white;
width:300px;
border:solid 1px #border-color;
margin-bottom:10px;
#secondary-color:#2875C7;
#spacing:10px;
#icon-width:40px;
#header-height:40px;
>div.header
{
float:left;
width:100%;
background:#secondary-color;
height:#header-height;
color:white;
>* { .vertical-center(#header-height); }
>i
{
float:left;
width:#icon-width;
font-size:1.125em;
font-weight:bold;
position:relative;
.border-box;
padding:0 #spacing;
cursor:pointer;
}
>i.fa-angle-left { text-align:left; }
>i.fa-angle-right
{
text-align:right;
margin-left:#icon-width*-1;
}
>span
{
float:left;
width:100%;
font-weight:bold;
text-transform:uppercase;
.border-box;
padding-left:#icon-width+#spacing;
margin-left:#icon-width*-1;
text-align:center;
padding-right:#icon-width;
color:inherit;
}
}
>div.week
{
float:left;
width:100%;
border-top:solid 1px #border-color;
&:first-child { border-top:none; }
>span.day {
float:left;
width:100%/7;
.border-box;
border-left:solid 1px #border-color;
font-size:0.75em;
text-align:center;
.vertical-centre(30px);
background:white;
cursor:pointer;
color:black;
&:first-child { border-left:none; }
&.today { background:#E3F2FF; }
&.different-month { color:#C0C0C0; }
&.selected {
background:#secondary-color;
color:white;
}
}
&.names>span {
color:#secondary-color;
font-weight:bold;
}
}
}
calendar.js
angular.module('starter.Directives', []);
angular.module('starter.Directives').directive("calendar", function(){
return {
restrict: "AEC",
templateUrl: "templates/calendar.html",
scope: { selected: "=" },
link: function(scope) {
scope.selected = _removeTime(scope.selected || moment());
scope.month = scope.selected.clone();
var start = scope.selected.clone();
start.date(1);
_removeTime(start.day(0));
_buildMonth(scope, start, scope.month);
scope.select = function(day) { scope.selected = day.date; };
scope.next = function() {
var next = scope.month.clone();
_removeTime(next.month(next.month()+1).date(1));
scope.month.month(scope.month.month()+1);
_buildMonth(scope, next, scope.month);
};
scope.previous = function() {
var previous = scope.month.clone();
_removeTime(previous.month(previous.month()-1).date(1));
scope.month.month(scope.month.month()-1);
_buildMonth(scope, previous, scope.month);
};
}
};
function _removeTime(date){
return date.day(0).hour(0).minute(0).second(0).millisecond(0); }
function _buildMonth(scope, start, month) {
scope.weeks = [];
var done = false, date = start.clone(), monthIndex = date.month(), count = 0;
while (!done) {
scope.weeks.push({ days: _buildWeek(date.clone(), month) });
date.add(1, "w");
done = count++ > 2 && monthIndex !== date.month();
monthIndex = date.month();
}
}
function _buildWeek(date, month) {
var days = [];
for (var i = 0; i < 7; i++) {
days.push({
name: date.format("dd").substring(0, 1),
number: date.date(),
isCurrentMonth: date.month() === month.month(),
isToday: date.isSame(new Date(), "day"),
date: date
});
date = date.clone();
date.add(1, "d");
}
return days;
}
});
Angular is clearly loading. Its working and generating a calendar like it should, but without any of the CSS. so what did i do wrong?
Looking at the debugger in safari there are no errors or warnings of any type. and same with chrome.

Not able to update the `scope` value from directive function

Basically, i am using a service for to manage the popup-modal. some point i made the mistake or wrongly i have understand the way of using the service, i am not able to update the scope value here.
my service.js
"use strict";
angular.module("tcpApp").service("modalService", function () {
this.Name = "My Modal";
this.showModal = false; //default false.
});
controller.js:
$scope.modalService.Name = "Mo!" //changing the name works!
$scope.showModal = true; //changing the ng-show works!
here is my directive :
"use strict";
var modalPopup = function ( modalService ) {
return {
restrict : "E",
replace : true,
scope : {
showModal:"=" //getting value from controller.js
},
templateUrl : "views/tools/modalPopup.html",
link : function ( scope, element, attrs ) {
scope.Name = modalService.Name; //if i remove this Name not working!
scope.hideModal = function () {
alert("i am called");
scope.showModal = false; //it's not updating the value!
}
}
}
}
angular.module("tcpApp")
.directive("modalPopup", modalPopup);
here is my html in the index.html :
<modal-popup ng-show="showModal" showModal="showModal"></modal-popup>
here is my template in views/tools/modalPopup.html
<div class='ng-modal'>
<div class='ng-modal-overlay'></div>
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-close' ng-click='hideModal()'>X</div>
<div class='ng-modal-dialog-content'>Please test me {{Name}}</div>
</div>
</div>
I am clicking on the hideModal(), But the showModal is not became false and the poup-up modal not closing.
where is the mistake here? and how the way i wrongly understand the service here? or what is the correct way to do this?
Thanks in advance.
You don't need to pass around anything in your view because you have a service setup to do this for you:
(function() {
"use strict";
var app = angular.module("tcpApp", []);
app.controller('someController', function($scope, modalService) {
$scope.modal = modalService;
$scope.modal.Name = "Mo!"
});
app.service("modalService", function() {
this.Name = "My Modal";
this.isOpen = false;
this.hide = function() {
this.isOpen = false;
};
this.show = function() {
this.isOpen = true;
};
});
})();
(function() {
"use strict";
angular.module("tcpApp").directive("modalPopup", function(modalService) {
return {
restrict: "E",
replace: true,
scope: {},
templateUrl: "modalPopup.html",
link: function(scope, element, attrs) {
scope.modal = modalService;
}
}
});
})();
.ng-modal {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ng-modal:after {
content: "";
display: block;
position: absolute;
height: 100%;
width: 100%;
z-index: 10;
background-color: rgba(0, 0, 0, 0.2);
}
.ng-modal-dialog {
width: 300px;
height: 150px;
position: absolute;
left: 50%;
top: 15px;
margin-left: -150px;
z-index: 100;
text-align: center;
background-color: white;
}
.ng-modal-close {
width: 32px;
height: 32px;
line-height: 32px;
border-radius: 50%;
background-color: red;
margin: 5px auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app='tcpApp'>
<div ng-controller='someController'>
<input type="text" ng-model="modal.Name" />
<button ng-click='modal.show()'>show modal</button>
<modal-popup></modal-popup>
</div>
<script type="text/ng-template" id="modalPopup.html">
<div class='ng-modal' ng-if="modal.isOpen">
<div class='ng-modal-dialog' ng-style='dialogStyle'>
<div class='ng-modal-close' ng-click='modal.hide()'>X</div>
<div class='ng-modal-dialog-content'>Please test me {{modal.Name}}</div>
<input type=text" ng-model="modal.Name"/>
</div>
</div>
</script>
</div>
Are you getting alert 'i am called'? If yes, try this
alert("i am called");
scope.showModal = false; //it's not updating the value!
scope.$apply(); // add this line it will update scope object value
try this
scope.$apply(function() {
scope.showModal = false;
});

Kendo UI + PhoneGap not working

I downloaded KENDO UI and imported /js and /css folders to my project directory. Now, I'm crreating new index.html project and referencing my all Kendo UI files in the /js and /css folders. But nothing happening. No styles, no js, nothing. Just plain HTML and nothing else. I just don't know what I'm doing wrong so I hope someone could help me with this. Here is my index.html file
<!DOCTYPE html>
<html>
<head>
<title>Where is my car?</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="js/jquery.min.js"></script>
<script src="js/kendo.mobile.min.js"></script>
<link href="styles/kendo.common.min.css" rel="stylesheet" />
<link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />
</head>
<body>
<header data-role="header">
<h1>Where is my car?</h1>
</header>
<div id="content" data-role="content">
<p>asfdasfdasdfasdfasdfasdfs</p>
<a class="button" data-role="button" href="map.html?requestType=set" id="set-car-position">Set position</a>
<a class="button" data-role="button" href="map.html?requestType=get" id="find-car" data-role="button">Find car</a>
<a class="button" data-role="button" href="positions.html" id="positions-history" data-role="button">Positions history</a>
</div>
<footer data-role="footer">
<h3>Created by </h3>
<a data-icon="info" data-iconpos="notext" class="ui-btn-right">Credits</a>
</footer>
<style scoped>
#button-badge .button {
margin-left: 1em;
text-align: center;
}
#button-home .head, #facility .head, #sports .head {
display: block;
margin: 1em;
height: 120px;
-webkit-background-size: 100% auto;
background-size: 100% auto;
}
.km-ios .head, .km-blackberry .head {
-webkit-border-radius: 10px;
border-radius: 10px;
}
</style>
</body>
</html>
DEMO in jsfiddle ->> http://jsfiddle.net/ep5e8/.
Thank you for any help.
EDIT:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Where is my car?</title>
<script src="cordova.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="js/functions.js"></script>
<script src="js/maps.js"></script>
<script src="js/positions.js"></script>
<!-- Kendo UI Mobile CSS -->
<link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />
<!-- jQuery JavaScript -->
<script src="js/jquery.min.js"></script>
<!-- Kendo UI Mobile combined JavaScript -->
<script src="js/kendo.mobile.min.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/kendo.mobile.min.js"></script>
<script src="content/shared/js/console.js"></script>
<link href="styles/kendo.common.min.css" rel="stylesheet" />
<link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />
<script>
$(document).one('deviceready', initApplication);
</script>
</head>
<body>
<div id="welcome-page" data-role="view">
<header data-role="header">
<div data-role="navbar">
<span data-role="view-title">Where is my car?</span>
</div>
</header>
<div id="content" data-role="content">
<p>Where is my car? lets you bookmark where you parked your car on a map and then find a route when you want to return to it. The app will also save a log of your saved positions (up to 50).</p>
Set position
Find car
Positions history
</div>
<!--Kendo Mobile Footer -->
<footer data-role="footer">
<!-- Kendo Mobile TabStrip widget -->
<div data-role="tabstrip">
<h3>Created by</h3>
</div>
</footer>
</div>
<script>
// Initialize a new Kendo Mobile Application
var app = new kendo.mobile.Application();
</script>
</body>
</html>
positions.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Positions' history</title>
</head>
<body>
<div id="positions-page" data-role="page">
<header data-role="header">
Back
<h1>Positions' history</h1>
</header>
<div id="content" data-role="content">
<ul id="positions-list" data-role="listview" data-inset="true" data-split-icon="delete" data-filter="true">
</ul>
</div>
<footer data-role="footer">
<h3>Created by </h3>
</footer>
</div>
</body>
</html>
map.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Where is my car?</title>
<script src="cordova.js"></script>
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="js/functions.js"></script>
<script src="js/maps.js"></script>
<script src="js/positions.js"></script>
<!-- Kendo UI Mobile CSS -->
<link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />
<!-- jQuery JavaScript -->
<script src="js/jquery.min.js"></script>
<!-- Kendo UI Mobile combined JavaScript -->
<script src="js/kendo.mobile.min.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/kendo.mobile.min.js"></script>
<script src="content/shared/js/console.js"></script>
<link href="styles/kendo.common.min.css" rel="stylesheet" />
<link href="styles/kendo.mobile.all.min.css" rel="stylesheet" />
<script>
$(document).one('deviceready', initApplication);
</script>
</head>
<body>
<div id="map-page" data-role="layout">
<header data-role="header">
<div data-role="navbar">
Back
<span data-role="view-title">Where is my car?</span>
</div>
</header>
<div id="content" data-role="content">
<div id="map">
</div>
</div>
</div>
<script>
// Initialize a new Kendo Mobile Application
var app = new kendo.mobile.Application();
</script>
</body>
</html>
functions.js:
function checkRequirements()
{
if (navigator.network.connection.type == Connection.NONE)
{
navigator.notification.alert(
'To use this app you must enable your internet connection',
function(){},
'Warning'
);
return false;
}
return true;
}
function updateIcons()
{
if ($(window).width() > 480)
{
$('a[data-icon], button[data-icon]').each(
function()
{
$(this).removeAttr('data-iconpos');
}
);
}
else
{
$('a[data-icon], button[data-icon]').each(
function()
{
$(this).attr('data-iconpos', 'notext');
}
);
}
}
function urlParam(name)
{
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results != null && typeof results[1] !== 'undefined')
return results[1];
else
return null;
}
/**
* Initialize the application
*/
function initApplication()
{
$('#set-car-position, #find-car').click(function() {
if (checkRequirements() === false)
{
$(this).removeClass('ui-btn-active');
return false;
}
});
$(document).on('pagebeforecreate orientationchange', updateIcons);
$('#map-page').live(
'pageshow',
function()
{
var requestType = urlParam('requestType');
var positionIndex = urlParam('index');
var geolocationOptions = {
timeout: 15 * 1000, // 15 seconds
maximumAge: 10 * 1000, // 10 seconds
enableHighAccuracy: true
};
var position = new Position();
$.mobile.loading('show');
// If the parameter requestType is 'set', the user wants to set
// his car position else he want to retrieve the position
if (requestType == 'set')
{
navigator.geolocation.getCurrentPosition(
function(location)
{
// Save the position in the history log
position.savePosition(
new Coords(
location.coords.latitude,
location.coords.longitude,
location.coords.accuracy
)
);
// Update the saved position to set the address name
Map.requestLocation(location);
Map.displayMap(location, null);
navigator.notification.alert(
'Your position has been saved',
function(){},
'Info'
);
},
function(error)
{
navigator.notification.alert(
'Unable to retrieve your position. Is your GPS enabled?',
function(){
alert("Unable to retrieve the position: " + error.message);
},
'Error'
);
$.mobile.changePage('index.html');
},
geolocationOptions
);
}
else
{
if (position.getPositions().length == 0)
{
navigator.notification.alert(
'You have not set a position',
function(){},
'Error'
);
$.mobile.changePage('index.html');
return false;
}
else
{
navigator.geolocation.watchPosition(
function(location)
{
// If positionIndex parameter isn't set, the user wants to retrieve
// the last saved position. Otherwise he accessed the map page
// from the history page, so he wants to see an old position
if (positionIndex == undefined)
Map.displayMap(location, position.getPositions()[0]);
else
Map.displayMap(location, position.getPositions()[positionIndex]);
},
function(error)
{
console.log("Unable to retrieve the position: " + error.message);
},
geolocationOptions
);
}
}
}
);
$('#positions-page').live(
'pageinit',
function()
{
createPositionsHistoryList('positions-list', (new Position()).getPositions());
}
);
}
/**
* Create the positions' history list
*/
function createPositionsHistoryList(idElement, positions)
{
if (positions == null || positions.length == 0)
return;
$('#' + idElement).empty();
var $listElement, $linkElement, dateTime;
for(var i = 0; i < positions.length; i++)
{
$listElement = $('<li>');
$linkElement = $('<a>');
$linkElement
.attr('href', '#')
.click(
function()
{
if (checkRequirements() === false)
return false;
$.mobile.changePage(
'map.html',
{
data: {
requestType: 'get',
index: $(this).closest('li').index()
}
}
);
}
);
if (positions[i].address == '' || positions[i].address == null)
$linkElement.text('Address not found');
else
$linkElement.text(positions[i].address);
dateTime = new Date(positions[i].datetime);
$linkElement.text(
$linkElement.text() + ' # ' +
dateTime.toLocaleDateString() + ' ' +
dateTime.toLocaleTimeString()
);
// Append the link to the <li> element
$listElement.append($linkElement);
$linkElement = $('<a>');
$linkElement.attr('href', '#')
.text('Delete')
.click(
function()
{
var position = new Position();
var oldLenght = position.getPositions().length;
var $parentUl = $(this).closest('ul');
position.deletePosition($(this).closest('li').index());
if (oldLenght == position.getPositions().length + 1)
{
$(this).closest('li').remove();
$parentUl.listview('refresh');
}
else
{
navigator.notification.alert(
'Position not deleted. Something gone wrong so please try again.',
function(){},
'Error'
);
}
}
);
// Append the link to the <li> element
$listElement.append($linkElement);
// Append the <li> element to the <ul> element
$('#' + idElement).append($listElement);
}
$('#' + idElement).listview('refresh');
}
maps.js:
function Map()
{
}
/**
* Display the map showing the user position or the latter and the car position
*/
Map.displayMap = function(userPosition, carPosition)
{
var userLatLng = null;
var carLatLng = null;
if (userPosition != null)
userLatLng = new google.maps.LatLng(userPosition.coords.latitude, userPosition.coords.longitude);
if (carPosition != null)
carLatLng = new google.maps.LatLng(carPosition.position.latitude, carPosition.position.longitude);
var options = {
zoom: 20,
disableDefaultUI: true,
streetViewControl: true,
center: userLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById('map'), options);
var marker = new google.maps.Marker({
position: userLatLng,
map: map,
title: 'Your position'
});
// If carLatLng is null means that the function has been called when the
// user set his current position and that is when he parked the car so the
// icon will be shown accordingly.
if (carLatLng == null)
marker.setIcon('images/car-marker.png');
else
marker.setIcon('images/user-marker.png');
var circle = new google.maps.Circle({
center: userLatLng,
radius: userPosition.coords.accuracy,
map: map,
fillColor: '#70E7FF',
fillOpacity: 0.2,
strokeColor: '#0000FF',
strokeOpacity: 1.0
});
map.fitBounds(circle.getBounds());
if (carLatLng != null)
{
marker = new google.maps.Marker({
position: carLatLng,
map: map,
icon: 'images/car-marker.png',
title: 'Car position'
});
circle = new google.maps.Circle({
center: carLatLng,
radius: carPosition.position.accuracy,
map: map,
fillColor: '#70E7FF',
fillOpacity: 0.2,
strokeColor: '#0000FF',
strokeOpacity: 1.0
});
// Display route to the car
options = {
suppressMarkers: true,
map: map,
preserveViewport: true
}
this.setRoute(new google.maps.DirectionsRenderer(options), userLatLng, carLatLng);
}
$.mobile.loading('hide');
}
/**
* Calculate the route from the user to his car
*/
Map.setRoute = function(directionsDisplay, userLatLng, carLatLng)
{
var directionsService = new google.maps.DirectionsService();
var request = {
origin: userLatLng,
destination: carLatLng,
travelMode: google.maps.DirectionsTravelMode.WALKING,
unitSystem: google.maps.UnitSystem.METRIC
};
directionsService.route(
request,
function(response, status)
{
if (status == google.maps.DirectionsStatus.OK)
directionsDisplay.setDirections(response);
else
{
navigator.notification.alert(
'Unable to retrieve a route to your car. However, you can still find it by your own.',
function(){},
'Warning'
);
}
}
);
}
/**
* Request the address of the retrieved location
*/
Map.requestLocation = function(position)
{
new google.maps.Geocoder().geocode(
{
'location': new google.maps.LatLng(position.coords.latitude, position.coords.longitude)
},
function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var positions = new Position();
positions.updatePosition(0, positions.getPositions()[0].coords, results[0].formatted_address);
}
}
);
}
positions.js
function Position(position, address, datetime)
{
var _db = window.localStorage;
var MAX_POSITIONS = 50;
this.position = position;
this.address = address;
this.datetime = datetime;
this.getMaxPositions = function()
{
return MAX_POSITIONS;
}
this.savePosition = function(position, address)
{
if (!_db)
{
console.log('The database is null. Unable to save position');
navigator.notification.alert(
'Unable to save position',
function(){},
'Error'
);
}
var positions = this.getPositions();
if (positions == null)
positions = [];
positions.unshift(new Position(position, address, new Date()));
// Only the top MAX_POSITIONS results are needed
if (positions.length > this.MAX_POSITIONS)
positions = positions.slice(0, this.MAX_POSITIONS);
_db.setItem('positions', JSON.stringify(positions));
return positions;
}
this.updatePosition = function(index, position, address)
{
if (!_db)
{
console.log('The database is null. Unable to update position');
navigator.notification.alert(
'Unable to update position',
function(){},
'Error'
);
}
var positions = this.getPositions();
if (positions != null && positions[index] != undefined)
{
positions[index].coords = position;
positions[index].address = address;
}
_db.setItem('positions', JSON.stringify(positions));
return positions;
}
this.deletePosition = function(index)
{
if (!_db)
{
console.log('The database is null. Unable to delete position');
navigator.notification.alert(
'Unable to delete position',
function(){},
'Error'
);
}
var positions = this.getPositions();
if (positions != null && positions[index] != undefined)
positions.splice(index, 1);
_db.setItem('positions', JSON.stringify(positions));
return positions;
}
this.getPositions = function()
{
if (!_db)
{
console.log('The database is null. Unable to retrieve positions');
navigator.notification.alert(
'Unable to retrieve positions',
function(){},
'Error'
);
}
var positions = JSON.parse(_db.getItem('positions'));
if (positions == null)
positions = [];
return positions;
}
}
function Coords(latitude, longitude, accuracy)
{
this.latitude = latitude;
this.longitude = longitude;
this.accuracy = accuracy;
}
style.css:
.ui-header .ui-title,
.ui-footer .ui-title,
.ui-btn-inner *
{
white-space: normal !important;
}
.photo
{
display: block;
margin: 0px auto;
}
dl.informations dt
{
font-weight: bold;
}
#map
{
width: 100%;
height: 600px;
}
Sorry for this amount of code, but I just can't convert a design and functionality from jQM to KendoUI Mobile.
Kendo initialization
You are missing the code bits that let kendo do its magic. I am assuming that you are using Kendo UI Mobile.
The following should be inserted before your closing body tag.
<script>
// Initialize a new Kendo Mobile Application
var app = new kendo.mobile.Application();
</script>
You can read the following doc with more related details:
http://docs.kendoui.com/getting-started/introduction
Kendo Views
Also I noticed that you are not using any view. I am not sure what you want to achieve but tipically when using Kendo you should have a view that wraps the header, content and footer code.
View documentation: http://docs.kendoui.com/getting-started/mobile/view
I suggest reading the documentation stated above (if you havenĀ“t already do so) and to try the examples first, and then start writing your code.
Snippet
<!-- Kendo Mobile View -->
<div data-role="view" data-title="View" id="index">
<!--Kendo Mobile Header -->
On the other hand, it is difficult to check the full code working as it should be in the jsfiddle as you are not linking or copy pasting the CSS and JS files that you are stating in the code.
EDIT
Regarding data source
I just skimmed your code but It seems you are not using the Kendo DataSource.
Read the following document which explains how to bind data to your controls.
http://docs.kendoui.com/howto/use-the-datasource-component
http://docs.kendoui.com/getting-started/data-attribute-initialization
Bear in mind that jQM and Kendo UI mobile have very different approaches. Kendo uses a Model View ViewModel (MVVM) so a bit of work should be required to move the jquery - jQM code to Kendo, it is basically a matters of structure.
Again, before start playing with Kendo I strongly recommend reading the documentation. You could think you are wasting time, however reading the doc will save you tons of time and headaches.

Resources