0
0
mirror of https://github.com/Doodle3D/doodle3d-connect.git synced 2024-12-25 18:13:48 +01:00

Merge branch 'jqm'

This commit is contained in:
peteruithoven 2014-05-14 16:43:56 +02:00
commit 2de7bc1fc3
727 changed files with 137088 additions and 2227 deletions

7
.gitignore vendored
View File

@ -1,2 +1,7 @@
credentials.php credentials.php
.*
!/.gitignore
www/js/*.js
www/css/*.css
node_modules/*
www/css/images/**

176
Gruntfile.js Normal file
View File

@ -0,0 +1,176 @@
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('package.json'),
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
less: {
development: {
src: "less/*.less",
dest: ".tmp/<%= pkg.name %>.css"
}
},
concat: {
js: {
src: [
'js/libs/jquery-1.11.0.min.js', // make sure it's first
'js/libs/*.js',
'js/libs/jquery.mobile/*.min.js',
'js/api/*.js',
'js/*.js',
// make sure we put main.js last
'!js/main.js',
'js/main.js',
],
dest: 'www/js/<%= pkg.name %>.js'
},
less: {
src: [
'js/libs/jquery.mobile/jquery.mobile-1.4.2.css',
'less/*.css',
'.tmp/<%= pkg.name %>.css'
],
dest: 'www/css/<%= pkg.name %>.css' /* to css so it's replaced */
}
},
autoprefixer: {
options: {
browsers: ['> 1%', 'last 2 versions', 'ie 8', 'ie 9', 'ff 17', 'opera 12.1']
},
// prefix all specified files and save them separately
single_file: {
options: {},
// expand: true,
// flatten: true,
src: 'www/css/<%= pkg.name %>.css',
dest: 'www/css/<%= pkg.name %>.css'
}
},
cssmin: {
minify: {
expand: true,
cwd: 'www/css/',
src: ['*.css', '!*.min.css'],
dest: 'www/css/',
ext: '.min.css'
}
},
uglify: {
options: {
// banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
mangle: true,
beautify: false,
compress: {},
// report: 'min',
preserveComments: 'some'
},
js: {
files: {
'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js']
}
},
/*jslibs: {
cwd: "js/libs/",
// src: ['js/libs/*.js', '!js/libs/*.min.js'], // source files mask
src: ['*.js', '!*.min.js'], // source files mask
dest: 'www/js/libs/', // destination folder
expand: true, // allow dynamic building
flatten: true, // remove all unnecessary nesting
ext: '.min.js' // replace .js to .min.js
// files: {
// 'www/js/<%= pkg.name %>.min.js' : ['www/js/<%= pkg.name %>.js']
// }
}*/
},
jshint: {
options: {
globals: {
jQuery: true,
$: true,
console: false,
d3d: true,
ConnectAPI: true,
NetworkAPI: true,
InfoAPI: true,
ConfigAPI: true,
addToHomescreen: true
},
browser: true,
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
unused: false,
boss: true,
eqnull: true
},
// gruntfile: {
// src: 'Gruntfile.js'
// },
// lib_test: {
// src: ['www/js/*.js', '!www/js/<%= pkg.name %>.js', '!www/js/<%= pkg.name %>.min.js']
// }
src: ['js/**.js'],
},
clean: {
main: {
src: "www/css/images"
}
},
copy: {
main: {
expand: true,
nonull: true,
cwd: "js/libs/jquery.mobile/images/",
src: "**",
dest: "www/css/images/",
filter: grunt.file.exists
}
},
watch: {
javascript: {
files: ["js/**", '!www/js/<%= pkg.name %>.min.js', '!www/js/<%= pkg.name %>.js'],
tasks: ["jshint", "concat:js", "uglify:js"]
},
styles: {
files: ["less/**"],
tasks: ["less", "autoprefixer", "concat:less", "cssmin"]
}
},
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
// Default task.
grunt.registerTask('default', [
'less',
'autoprefixer',
'concat',
'cssmin',
'uglify',
'jshint',
'clean',
'copy',
'watch'
]);
};

View File

@ -1,180 +0,0 @@
/**
*
* Main container
*
*/
#addToHomeScreen {
z-index:9999;
-webkit-user-select:none;
user-select:none;
-webkit-box-sizing:border-box;
box-sizing:border-box;
-webkit-touch-callout:none;
touch-callout:none;
width:240px;
font-size:15px;
padding:12px 14px;
text-align:left;
font-family:helvetica;
background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(0,#fff),color-stop(0.02,#eee),color-stop(0.98,#ccc),color-stop(1,#a3a3a3));
border:1px solid #505050;
-webkit-border-radius:8px;
-webkit-background-clip:padding-box;
color:#333;
text-shadow:0 1px 0 rgba(255,255,255,0.75);
line-height:130%;
-webkit-box-shadow:0 0 4px rgba(0,0,0,0.5);
}
#addToHomeScreen.addToHomeIOS7 {
background:#f2f2f2 !important;
-webkit-border-radius:1px !important;
border:1px solid #ccc;
-webkit-box-shadow:0 0 4px rgba(0,0,0,0.2);
}
#addToHomeScreen.addToHomeIpad {
width:268px;
font-size:18px;
padding:14px;
}
/**
*
* The 'wide' class is added when the popup contains the touch icon
*
*/
#addToHomeScreen.addToHomeWide {
width:296px;
}
#addToHomeScreen.addToHomeIpad.addToHomeWide {
width:320px;
font-size:18px;
padding:14px;
}
/**
*
* The balloon arrow
*
*/
#addToHomeScreen .addToHomeArrow {
position:absolute;
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#ccc));
border-width:0 1px 1px 0;
border-style:solid;
border-color:#505050;
width:16px; height:16px;
-webkit-transform:rotateZ(45deg);
bottom:-9px;
left:50%;
margin-left:-8px;
-webkit-box-shadow:inset -1px -1px 0 #a9a9a9;
-webkit-border-bottom-right-radius:2px;
}
#addToHomeScreen.addToHomeIOS7 .addToHomeArrow {
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#f2f2f2)) !important;
-webkit-box-shadow:inset -1px -1px 0 #fff !important;
border-color:#ccc !important;
}
/**
*
* The balloon arrow for iPad
*
*/
#addToHomeScreen.addToHomeIpad .addToHomeArrow {
-webkit-transform:rotateZ(-135deg);
background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(238,238,238,0)),color-stop(0.4,rgba(238,238,238,0)),color-stop(0.4,#eee));
-webkit-box-shadow:inset -1px -1px 0 #fff;
top:-9px; bottom:auto; left:50%;
}
/**
*
* Close button
*
*/
#addToHomeScreen .addToHomeClose {
-webkit-box-sizing:border-box;
position:absolute;
right:4px;
top:4px;
width:18px;
height:18px; line-height:14px;
text-align:center;
text-indent:1px;
-webkit-border-radius:9px;
background:rgba(0,0,0,0.12);
color:#888;
-webkit-box-shadow:0 1px 0 #fff;
font-size:16px;
}
#addToHomeScreen.addToHomeIOS7 .addToHomeClose {
line-height:12px;
padding-right:1px;
background:transparent;
border: 1px solid #888;
-webkit-box-shadow:none;
}
/**
*
* The '+' icon, displayed only on iOS < 4.2
*
*/
#addToHomeScreen .addToHomePlus {
font-weight:bold;
font-size:1.3em;
}
/**
*
* The 'share' icon, displayed only on iOS >= 4.2
*
*/
#addToHomeScreen .addToHomeShare {
display:inline-block;
width:18px;
height:15px;
background-repeat:no-repeat;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAQAAADu6HTYAAADPElEQVR4Xq3TX2gcRRzA8e/M7mVv2+TSNpc/TZtrY6jUGqgaSAmEChKLrYK0YH0RFC2CSCkEfCghiKU04J8qNigq6os+iQV98MHWFwVBrQQRWs21lBw5cw3NNb1/udu72RGG5Y77IzXW77D7sAwf5scyYoL6BGXSDKFZwaGpLvIUaeoCkvX1MmsM0Ny6oRSQYOLuIS+YZOpfQdqslpUxcZrzTVAz4qPwW2O3CeIwC/RSzeY6Ow1QhUrkr+YOWfEKDkEP8Rij7CHKJmrFSDHBdwGEE5wiGChPN+PnT8VdRtEIl1d4gRj/1EVe5ZSBKGh8iqQpo/Fo5+3C/gz0MYg4zgwbqday1/Q4B8BGQ45d/Hi54lakCrU5obOcidJpu1+Lg9whjabyaOYLnrIBFFaRD+xe2ybMDWY66GmP/WA9cGfGp0CWhy0wkMN8inepFiH2rV1j0NQSNQbFLRQnS8/8YSDBBpadfv4CYDub2fmeHDNAsL1MBWUel0iA+Xik6eHcyvD3vAMSU1TGuA/YRS+dD7ovCQN43GKRFCU20Kd3V/avDVVyAZ5niTEuLA5/zBGWg9EEEhfJKN200Tat8CmRAQb9+wv7soPlHt2tQorsz1uPbr0HTY4sJwrH47zJZwABBAKLMBoQXepwgTwdHCo+fXMkQ4lrxEmQ5AaXipPqDY9V2vn09tgvTPI71EEGYxM+/uMJLJ4svpgaWGKOi/xKgmqLSUGSUd5f2vIVJ/CgBaTIUsZ7ZBsn0+NzfMOXLFCXQyTcybN6ep5ZZgUOHn7jpfUpsZshdugPGf+E5zjbyHTSRyQ8xfRPPM/s63RHeuknSoT22mjmmnAOIMkUZ6D1xSfPPAfd1WFKM3sO2CMaHx8M1NjnXKHaAGGkOW0C02WeYHUz4qMtx+w5gUDS8NckYe5lHsMYwCZEPyEEmjLDZFmAS7CDviMdxyTkMNVBKEmYLvbiQQBIBBbCQG04bGQvFWz6CfsCQLWCigILFwcfkGYBiOpbYuOizTAyYyDdCtrGaRG1LCkIgMYEFhI0WqQZoSlbGRyHKe4qOx7iv2bVQW9dp4dlM/x6kmwnWQcd/Q3FCqwTEiT5s+6D5v/pb0SSHyg7uhMWAAAAAElFTkSuQmCC);
background-size:18px 15px;
text-indent:-9999em;
overflow:hidden;
}
#addToHomeScreen.addToHomeIOS7 .addToHomeShare {
width:11px;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAA8CAYAAAAQTCjdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAASCQAAEgkB80sG3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKjSURBVGiB7dpPiFVVHMDxz7m9NCtMyI2bEJEC25WrEkzHUXCRraIwdNE8ZxfYIlcis1ZEbGEzT1QCF4XgH1CyWhUoJKIWNRGEiCNKmkSiYTzfcfGuOokx77x3ZlS8382959zfn+/invvn3RdijHIRBrwkOINCYXEcdjpb7VyiYdBsLScwt5y6IloYdzqXo36Ro0gY9IKWo+5JwmzBt2HQnBw9ehYNazyn5TBee8Dh+Vq+CWu92GufnkTDR6ab7gDeBNHouMM/l9tXTXM0fGBmL726Fg1Dam74EsvKqR8VNowL2Yzj5f7rnnE4DHq2235diYYhhTGfC94up35T0y+6di/ITU0rKVd+sEi0P7xr2pSJOu8zvF+OzqEv7vDH/WFxt7/cshy/ticsN8sXYUht0kXDOlsF9XJ4UaEvNoz9X3zc5bKaZThbyr5jzJ4wlNY7KTgM+ES0vhz+KeiPw36fKC/ucAF9uFBOrTZm26SJCtaV27+xIo7cXdkTEhvOoh+XyxprU1qnim7CQdGK2HAyKRexYVShT3RItDElN+mkjiP2Ym+S3f01hv2EVal5WW6hU0ElmptaqJuBpXg6MbeFH2LDpU6CQ93zWIKnEvs0cayGU3glMfkOo1jQYewZzOuyz7FC95Jwo5OgUFfgeg993hh/eTqCTxOSm/iuk8DY0Ap1b2GhtHXxsfZN4j/X0fOx4auEIknEhqv4OiUn1L13Z/+xWfWVaG4q0dxUormpRHNTieamEs1NJZqbJ1Q0jHvdiJo5S2cVjSNOCHZhn3/SnuYnIvl3yomIIz7MXZMn9hydRCrR3FSiualEc1OJ5qYSzU0lmptKNDePjWgwcPePT7/g+4cp8wCW4GXaryK3tL+mLdD5x62ppllgu7bso8q/2HIbzGWdNmWnSJwAAAAASUVORK5CYII=);
background-size:11px 15px;
}
/**
*
* The touch icon (if available)
*
*/
#addToHomeScreen .addToHomeTouchIcon {
display:block;
float:left;
-webkit-border-radius:6px;
border-radius:6px;
-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5),
inset 0 0 2px rgba(255,255,255,0.9);
box-shadow:0 1px 3px rgba(0,0,0,0.5),
inset 0 0 2px rgba(255,255,255,0.9);
background-repeat:no-repeat;
width:57px; height:57px;
-webkit-background-size:57px 57px;
background-size:57px 57px;
margin:0 12px 0 0;
border:1px solid #333;
-webkit-background-clip:padding-box;
background-clip:padding-box;
}

View File

@ -1,82 +0,0 @@
.uiButtonsContainer {
position: absolute;
max-width: 1024px;
/*min-width: 800px;*/
width: 100%;
height: 100%;
/*max-height: 768px;*/
/*min-height: 300px;*/
top: 0; left: 0; right: 0; bottom: 0;
/*overflow: hidden;*/
margin: 0 auto;
outline: 2px solid #5e8c71;
box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
/* height: 768px;*/
}
#d3dlogo {
position: absolute;
top: 2.5%;
/*left: 31%;*/
width: 100%;
margin: 0 auto;
height: 139px;
background: url('../img/logo_full.png') no-repeat center center;
cursor: pointer;
}
.bgContainer {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
.bgTop, .bgMiddle, .bgBottom {
opacity: 1.0;
transition: opacity .35s linear;
position: absolute;
left: 0;
z-index: -5;
}
.bgTop {
top: 0;
}
.bgMiddle {
top: 30%;
}
.bgBottom {
bottom: 0;
}
/* The code below is for resizing UI elements as the viewport becomes less high (suitable for tablets & smartphones) */
@media screen and (max-height: 655px) {
.bgMiddle { opacity: 0; }
}
@media screen and (max-height: 675px) {
#d3dlogo {
/*width: 399px;*/
height: 74px;
background-image: url('../img/logo_small.png');
top: 6%;
}
}
@media screen and (max-height: 560px) {
#d3dlogo {
/*width: 399px;*/
height: 57px;
background-image: url('../img/logo_smaller_wide.png');
top: 6%;
}
}
@media screen and (max-height: 420px) {
#d3dlogo {
top: 3%;
}
}

3
css/chosen.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -1,207 +0,0 @@
p, small {
line-height: 1.2em;
}
#container {
position:absolute;
width: 100%;
max-width: 1024px;
/*max-height: 768px;*/
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
margin: 0 auto;
box-shadow: 0 0 0 2px #5e8c71, 0 0 8px 4px rgba(8, 8, 8, 0.25);
}
a {
color: #5491D2;
text-decoration: none;
}
#preloader {
position: absolute;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
margin: -25px 0 0 -25px;
pointer-events: none;
}
#list {
padding: 0;
}
.box{
list-style-type: none;
float: left;
margin: 0 15px 15px 0;
/*padding: 25px;*/
padding: 0 0 25px 0;
display: block;
position: relative;
min-width: 200px; /*175px;*/
min-height: 175px; /*175px;*/
/*height: 275px;*/
border: 2px solid #333;
border-radius: 25px;
-moz-box-shadow: 0px 2px 7px 0px rgba(16, 16, 16, 0.60);
-webkit-box-shadow: 0px 2px 7px 0px rgba(16, 16, 16, 0.60);
box-shadow: 0px 2px 7px 0px rgba(16, 16, 16, 0.60);
transition:background-color 0.1s, color 0.1s;
}
.box:hover {
background-color: #5491D2;
}
.box:hover .link{
color: #fff;
}
.box.complex {
width: 375px; /*320px;*/
height: 350px;
/*border: 2px solid #00f;*/
}
box.connecting {
border: 2px solid #ff0;
}
.box .link{
display:block;
padding: 25px 25px 12px 25px;
text-align: center;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.box.complex .link {
position: relative;
top: auto;
right: auto;
bottom: auto;
left: auto;
}
.box small {
margin: 0.5em 0 0 0;
display: block;
}
#hint {
display:none;
position: absolute;
bottom: 1em;
}
#networkForm {
display: none;
}
.box .networkForm {
display: none;
}
.box.complex .networkForm {
display: block;
}
/* FORMS */
form label {
min-width: 110px;
display: block;
float: left;
margin: 1px 0 10px 0;
}
form label.inline {
display: inline;
float: none;
}
form input, form select {
margin-bottom: 5px;
}
form select {
margin-right: 5px;
}
form input[type="text"], form input[type="number"], form input[type="password"], form select {
width: 130px;
}
form input[type="text"], form input[type="number"], form input[type="password"] {
border: 1px solid rgb(144, 192, 255);
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
form .row {
clear: left;
}
form .row div {
/* float: left;*/
}
/* NETWORK PANEL */
.networkForm {
background-color: #fff;
/*border-radius: 0 0 25px 25px;*/
padding: 12px 25px 12px 25px;
}
.networkForm p {
margin: 0 0 10px 0;
}
.networkForm #network {
margin-right: 5px;
width: 180px;
}
.networkForm #ssid,
.networkForm #listNetworks,
.networkForm #passwordSettings {
display: none;
}
.networkForm.customNetwork #passwordSettings {
display: block;
}
.networkForm.customNetwork #ssid,
.networkForm.customNetwork #listNetworks{
display: inline-block;
}
.networkForm.customNetwork #network,
.networkForm.customNetwork #refreshNetworks {
display: none;
}
.networkForm #status {
position: relative;
top: 2px;
}
.networkForm #action {
/*clear: left;*/
display: block;
padding: 5px 4px 4px 4px;
}
.networkForm #action.error {
background: #EB313C;
color: #fff;
}
.networkForm #action.warning {
background: #E9A86E;
}
.networkForm #action.notice {
background: #93CAF4;
}
.networkForm #action.info {
background: #97DD8A;
}
.networkForm #action.none {
display: none;
}
.networkForm .chosen-container-single .chosen-default {
color: #333; /* let's not pretend it's disabled */
}

View File

@ -1,51 +0,0 @@
/* MOBILE */
@media only screen and (max-width: 480px),
only screen and (max-width: 720px) and (min-device-pixel-ratio : 1.5),
only screen and (max-width: 720px) and (-webkit-min-device-pixel-ratio : 1.5) {
body {
/*background-color: #f0f;*/
}
#d3dlogo {
/*width: 399px;*/
height: 57px;
background-image: url('../img/logo_smaller_wide.png');
top: 7px;
}
.popup {
/*background-color: rgba(255, 255, 255, 0.6);*/
background-color: rgba(245, 245, 245, 0.65);
position: absolute;
bottom: 0;
left: 0;
top: 75px;
width: 100%;
height: auto;
margin: 0;
/*-moz-box-shadow: 0 0 0 3px rgba(16, 16, 16, 1.0), 0 2px 6px 0 rgba(16, 16, 16, 0.65), 0 6px 6px -2px rgba(16, 16, 16, 0.2) inset;*/
/*-webkit-box-shadow: 0 0 0 3px rgba(16, 16, 16, 1.0), 0 2px 6px 0 rgba(16, 16, 16, 0.65), 0 6px 6px -2px rgba(16, 16, 16, 0.2) inset;*/
box-shadow: 0 0 0 2px rgba(16, 16, 16, 0.8), 0 2px 6px 0 rgba(16, 16, 16, 0.65), 0 6px 6px -2px rgba(16, 16, 16, 0.2) inset;
border: 0;
border-radius: 0;
/*-moz-border-radius: 15px;*/
/*-webkit-border-radius: 15px;*/
overflow-x: hidden;
overflow-y: scroll;
}
.bgContainer {
/*display: none;*/
}
#list {
padding: 0;
}
#list li {
list-style-type: none;
float: none;
}
}

534
css/normalize.css vendored
View File

@ -1,534 +0,0 @@
/*! normalize.css v1.0.2 | MIT License | git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/*
* Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/*
* Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
}
/*
* Prevents modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/*
* Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,
* and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/*
* 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevents iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/*
* Addresses `font-family` inconsistency between `textarea` and other form
* elements.
*/
html,
button,
input,
select,
textarea {
font-family: sans-serif;
}
/*
* Addresses margins handled incorrectly in IE 6/7.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/*
* Addresses `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/*
* Improves readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/*
* Addresses font sizes and margins set differently in IE 6/7.
* Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,
* and Chrome.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
h2 {
font-size: 1.5em;
margin: 0.83em 0;
}
h3 {
font-size: 1.17em;
margin: 1em 0;
}
h4 {
font-size: 1em;
margin: 1.33em 0;
}
h5 {
font-size: 0.83em;
margin: 1.67em 0;
}
h6 {
font-size: 0.67em;
margin: 2.33em 0;
}
/*
* Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.
*/
abbr[title] {
border-bottom: 1px dotted;
}
/*
* Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
blockquote {
margin: 1em 40px;
}
/*
* Addresses styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/*
* Addresses styling not present in IE 6/7/8/9.
*/
mark {
background: #ff0;
color: #000;
}
/*
* Addresses margins set differently in IE 6/7.
*/
p,
pre {
margin: 1em 0;
}
/*
* Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
_font-family: 'courier new', monospace;
font-size: 1em;
}
/*
* Improves readability of pre-formatted text in all browsers.
*/
pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
}
/*
* Addresses CSS quotes not supported in IE 6/7.
*/
q {
quotes: none;
}
/*
* Addresses `quotes` property not supported in Safari 4.
*/
q:before,
q:after {
content: '';
content: none;
}
/*
* Addresses inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/*
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* ==========================================================================
Lists
========================================================================== */
/*
* Addresses margins set differently in IE 6/7.
*/
dl,
menu,
ol,
ul {
margin: 1em 0;
}
dd {
margin: 0 0 0 40px;
}
/*
* Addresses paddings set differently in IE 6/7.
*/
menu,
ol,
ul {
padding: 0 0 0 40px;
}
/*
* Corrects list images handled incorrectly in IE 7.
*/
nav ul,
nav ol {
list-style: none;
list-style-image: none;
}
/* ==========================================================================
Embedded content
========================================================================== */
/*
* 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improves image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/*
* Corrects overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
/* ==========================================================================
Figures
========================================================================== */
/*
* Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/*
* Corrects margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/*
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/*
* 1. Corrects color not being inherited in IE 6/7/8/9.
* 2. Corrects text not wrapping in Firefox 3.
* 3. Corrects alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/*
* 1. Corrects font size not being inherited in all browsers.
* 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improves appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/*
* Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/*
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Corrects inability to style clickable `input` types in iOS.
* 3. Improves usability and consistency of cursor style between image-type
* `input` and others.
* 4. Removes inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/*
* Re-set default cursor for disabled elements.
*/
button[disabled],
input[disabled] {
cursor: default;
}
/*
* 1. Addresses box sizing set to content-box in IE 8/9.
* 2. Removes excess padding in IE 8/9.
* 3. Removes excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/*
* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/*
* Removes inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
* Removes inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/*
* 1. Removes default vertical scrollbar in IE 6/7/8/9.
* 2. Improves readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/*
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
/**
* For modern browsers
* 1. The space content is one way to avoid an Opera bug when the
* contenteditable attribute is included anywhere else in the document.
* Otherwise it causes space to appear at the top and bottom of elements
* that are clearfixed.
* 2. The use of `table` rather than `block` is only necessary if using
* `:before` to contain the top-margins of child elements.
*/
/**
* For IE 6/7 only
* Include this rule to trigger hasLayout and contain floats.
*/
.cf {
*zoom: 1;
}
.cf:before,
.cf:after {
content: " "; /* 1 */
display: table; /* 2 */
}
.cf:after {
clear: both;
}

View File

@ -1,41 +0,0 @@
#contentOverlay {
background-color: rgba(255, 255, 255, 0.65);
z-index: 10;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
max-width: 1024px;
height: 100%;
/*max-height: 768px;*/
}
.popup {
background-color: #fff;
z-index: 15;
position: absolute;
bottom: 6%;
left: 50%;
width: 80%;
height: 70%;
margin: -35% 0 0 -40%;
/*-moz-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);*/
/*-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);*/
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
border: 2px solid #222;
border-radius: 15px;
/*-moz-border-radius: 15px;*/
/*-webkit-border-radius: 15px;*/
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
.popup .content {
margin: 0 1em;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 872 B

View File

@ -1,94 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Doodle3D Connect</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="mobile-web-app-capable" content="yes">
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=yes,minimal-ui">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="./img/apple-touch-icon-144x144-precomposed.png">
<link rel="shortcut" sizes="144x144" href="./img/apple-touch-icon-144x144-precomposed.png">
<link rel="icon" type="image/ico" href="./img/favicon.ico">
<link href="css/normalize.css" rel="stylesheet" media="screen">
<link href="css/chosen.min.css" rel="stylesheet" media="screen">
<link href="css/add2home.css" rel="stylesheet" media="screen">
<link href="css/main.css" rel="stylesheet" media="screen">
<link href="css/bg.css" rel="stylesheet" media="screen">
<link href="css/popups.css" rel="stylesheet" media="screen">
<link href="css/mobile.css" rel="stylesheet" media="screen">
<script src="js/libs/jquery-1.8.3.min.js" type="text/javascript"></script>
<script src="js/libs/spin.min.js" type="text/javascript"></script>
<script src="js/libs/add2home.js" type="text/javascript"></script>
<script src="js/libs/jquery.showpassword.js" type="text/javascript"></script>
<script src="js/libs/chosen.jquery.min.js" type="text/javascript"></script>
<script src="js/libs/jquery.stayInWebApp.js" type="text/javascript"></script>
<script src="js/api/NetworkAPI.js" type="text/javascript"></script>
<script src="js/api/ConnectAPI.js" type="text/javascript"></script>
<script src="js/NetworkPanel.js" type="text/javascript"></script>
<script src="js/Box.js" type="text/javascript"></script>
<script src="js/main.js" type="text/javascript"></script>
</head>
<body>
<div id="container">
<div class="bgContainer">
<img class="bgTop" src="img/bg_top.png" />
<img class="bgMiddle" src="img/bg_middle.png" />
<img class="bgBottom" src="img/bg_bottom.png" />
</div>
<div class="uiButtonsContainer">
<div id="d3dlogo" onclick="location.reload()"></div>
<div id="contentOverlay">
<div id="settings" class="popup">
<div class="content">
<p id="intro"></p>
<ul id="list" class="cf"></ul>
<small id="hint">
Can&#8217;t find your box? <br/>
Maybe your box isn&#8217;t connected to your network yet, try to connect to a Doodle3D-... WiFi network. <br/>
Otherwise, make sure you&#8217;re on the same WiFi network. <br/>
You can always connect your box to your computer using an ethernet cable.
</small>
<div id="preloader"></div>
</div>
</div>
</div>
</div>
</div>
<form id="networkForm">
<p>Connect this box to your WiFi network:</p>
<div class="row">
<label for="ssid">Network:</label><input type="text" name="ssid" id="ssid"><input type="button" name="list" value="List" class="button" id="listNetworks"/>
<select id="network" data-placeholder="Please select"></select>
</div>
<div id="passwordSettings" class="row">
<div>
<label for="phrase" id="phraseLabel">Password:</label>
</div>
<div>
<input type="password" name="" id="phrase" data-typetoggle='#showPassword' ><br/>
<input id="showPassword" type="checkbox" name="showPassword" value="showPassword">
<label for="showPassword" class="inline">show password</label>
</div>
</div>
<div class="row">
<input type="submit" value="Connect" class="button" id="btnConnect"/>
<span id="status"></span>
</div>
<div class="row">
<span id="action"></span>
</div>
<div class="row">
<small>Connecting the box to your WiFi network makes it easier to connect to and allows you to update. You can also continue using the box on it&#8217;s own WiFi network by going to <a href="http://draw.doodle3d.com">draw.doodle3d.com</a>. </small>
</div>
</form>
</body>
</html>

View File

@ -1,79 +0,0 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function Box() {
this.localip;
this.wifiboxid;
this.connecting = false;
this.destroyedHandler;
var _element;
var _networkPanel;
var _delayedDestroy;
var _self = this;
this.init = function(boxData,parentElement) {
_self.localip = boxData.localip;
_self.wifiboxid = boxData.wifiboxid;
var url = "http://"+_self.localip;
// create box dom element
var link = (boxData.link)? boxData.link : url;
var linkElement = $("<a href='"+link+"' class='link'>"+_self.wifiboxid+"</a>");
_element = $("<li id='"+_self.localip+"' class='box'></li>");
_element.append(linkElement);
_element.hide().appendTo(parentElement).fadeIn(500);
// create network panel dom element
var networkPanelElement = $("#networkForm").clone();
networkPanelElement.addClass(networkPanelElement.attr("id"));
networkPanelElement.removeAttr("id");
_element.append(networkPanelElement);
// create network panel
_networkPanel = new NetworkPanel();
_networkPanel.id = _self.localip;
_networkPanel.init(url,networkPanelElement, networkStatusChangeHandler);
}
function networkStatusChangeHandler(networkStatus) {
console.log("Box:networkStatusChangeHandler: ",networkStatus);
_self.connecting = (networkStatus == NetworkAPI.STATUS.CONNECTING);
// because openwrt can be slow to update it's ssid, a box might
// report it failed connecting but is then slightly later connects
// so we correct CONNECTING_FAILED to CONNECTED unless the box is connected by wire
if(_self.localip != "192.168.5.1" && networkStatus == NetworkAPI.STATUS.CONNECTING_FAILED) {
networkStatus = NetworkAPI.STATUS.CONNECTED;
}
_element.toggleClass("complex",(networkStatus !== NetworkAPI.STATUS.CONNECTED));
if(_self.connecting) {
clearTimeout(_delayedDestroy);
_delayedDestroy = setTimeout(function() {
console.log("delayed remove");
//removeBox(box,true);
_self.destroy()
}, 10000);
}
}
this.destroy = function() {
console.log("Box:destroy");
clearTimeout(_delayedDestroy);
_networkPanel.destroy();
_element.fadeOut(500,function() {
_element.remove();
});
if(_self.destroyedHandler) _self.destroyedHandler(_self);
}
}

114
js/BoxPage.js Normal file
View File

@ -0,0 +1,114 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
(function (w) {
var _page;
var _list;
var _title;
var _intro;
var _drawItem;
//var _updateItem;
var _joinNetworkItem;
var _defaultItems;
var _networkStatus;
var _networkAPI = new NetworkAPI();
var _boxData = {};
var _retryRetrieveStatusDelay;
var _retryRetrieveStatusDelayTime = 3000;
var PAGE_ID = "#box";
var _self = this;
$.mobile.document.on( "pageinit", PAGE_ID, function( event, data ) {
//console.log("Box page pageinit");
_page = $(this);
_list = _page.find("ul[data-role=listview]");
_title = _page.find(".ui-title");
_intro = _page.find(".intro");
_defaultItems = _list.children();
_drawItem = _list.find("#drawItem");
//_updateItem = _list.find("#updateItem");
_joinNetworkItem = _list.find("#joinNetworkItem");
// make sure draw link is opened in same WebApp (added to homescreen)
// and it doesn't start a browser
$.stayInWebApp("#box #drawItem a",true);
});
$.mobile.document.on( "pagebeforeshow", PAGE_ID, function( event, data ) {
console.log("Box page pagebeforeshow");
_boxData = d3d.util.getPageParams(PAGE_ID);
if(_boxData === undefined) {
$.mobile.changePage("#boxes");
return;
}
var boxURL = "http://"+_boxData.localip;
//console.log(" _boxData: ",_boxData);
_title.text(_boxData.wifiboxid);
setNetworkStatus(NetworkAPI.STATUS.CONNECTED);
var drawLink = (_boxData.link)? _boxData.link : boxURL;
_page.find("#drawItem a").attr("href",drawLink);
_networkAPI.init(boxURL);
retrieveNetworkStatus();
});
$.mobile.document.on( "pagebeforehide", PAGE_ID, function( event, data ) {
clearTimeout(_retryRetrieveStatusDelay);
});
function retrieveNetworkStatus() {
_networkAPI.status(function(data) {
data.status = parseInt(data.status,10);
setNetworkStatus(data.status);
}, function() {
clearTimeout(_retryRetrieveStatusDelay);
_retryRetrieveStatusDelay = setTimeout(_self.retrieveStatus, _retryRetrieveStatusDelayTime); // retry after delay
});
}
function setNetworkStatus(status) {
console.log(PAGE_ID+":setNetworkStatus: ",status);
var introText = "";
if(status === NetworkAPI.STATUS.CONNECTED) { // online
//console.log("online");
_drawItem.find("a").text("Draw");
// display the right buttons
_defaultItems.toggleClass("ui-screen-hidden",false);
_joinNetworkItem.toggleClass("ui-screen-hidden",true);
// ToDo: retrieve update information
} else { // offline
//console.log("offline");
introText = "Please connect your WiFi-Box to the internet. You can also use it offline, but then you won't be able to update.";
_drawItem.find("a").text("Draw (offline)");
// display the right buttons
_defaultItems.toggleClass("ui-screen-hidden",true);
_drawItem.toggleClass("ui-screen-hidden",false);
_joinNetworkItem.toggleClass("ui-screen-hidden",false);
var joinLink = _joinNetworkItem.find("a").attr("href");
joinLink = d3d.util.replaceURLParameters(joinLink,_boxData);
_joinNetworkItem.find("a").attr("href",joinLink);
}
_intro.text(introText);
_intro.toggleClass("ui-screen-hidden",(introText === ""));
// ToDo: update footer with network info
_list.listview('refresh'); // jQuery mobile enhance content
_networkStatus = status;
}
})(window);

91
js/BoxesPage.js Normal file
View File

@ -0,0 +1,91 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
(function (w) {
var _connectAPI = new ConnectAPI();
var _page;
var _list;
var _findItem;
var PAGE_ID = "#boxes";
$.mobile.document.on( "pageinit", PAGE_ID, function( event, data ) {
//console.log("Boxes page pageinit");
_page = $(this);
_list = _page.find("#boxeslist");
_findItem = _list.find("#findItem");
_connectAPI.refreshing = onRefreshing;
_connectAPI.listFailed = onListFailed;
_connectAPI.listSuccess = onlistSuccess;
_connectAPI.listUpdated = onListUpdated;
_connectAPI.boxAppeared = onBoxAppeared;
_connectAPI.boxDisapeared = onBoxDisapeared;
});
$.mobile.document.on( "pagebeforeshow", PAGE_ID, function( event, data ) {
//console.log("Boxes page pagebeforeshow");
_connectAPI.start();
});
$.mobile.document.on( "pageshow", PAGE_ID, function( event, data ) {
//console.log("Boxes page pageshow");
addToHomescreen(/*{
debug: true, // activate debug mode in ios emulation
skipFirstVisit: false, // show at first access
startDelay: 0, // display the message right away
lifespan: 0, // do not automatically kill the call out
displayPace: 0, // do not obey the display pace
maxDisplayCount: 0 // do not obey the max display count
}*/);
});
$.mobile.document.on( "pagebeforehide", PAGE_ID, function( event, data ) {
//console.log("Boxes page pagehide");
_connectAPI.stop();
});
function onRefreshing() {
//console.log("onRefreshing");
d3d.util.showLoader(true);
}
function onListFailed() {
d3d.util.enableRefreshPrevention();
d3d.util.enableLeaveWarning("You're not connecting to the internet, leaving now will interrupt the connection proces");
}
function onlistSuccess() {
d3d.util.disableRefreshPrevention();
d3d.util.disableLeaveWarning();
}
function onListUpdated(boxesData) {
//console.log("onListUpdated: ",boxesData);
}
function onBoxAppeared(boxData) {
console.log("onBoxAppeared: ",boxData.localip);
var linkParams = {localip: boxData.localip,wifiboxid: boxData.wifiboxid};
if(boxData.link) { linkParams.link = boxData.link; }
var link = "#box";
link = d3d.util.replaceURLParameters(link,linkParams);
var id = boxData.localip.replace(/\./g,"-");
var linkElement = $("<a href='"+link+"' class='link'>"+boxData.wifiboxid+"</a>");
var box = $("<li id='"+id+"' class='box'></li>");
box.append(linkElement);
box.hide().appendTo(_list).fadeIn(500);
_list.append(_findItem); // make sure find is the last item
_list.listview('refresh'); // jQuery mobile enhance content
}
function onBoxDisapeared(boxData) {
console.log("onBoxDisapeared: ",boxData.localip);
var id = boxData.localip.replace(/\./g,"-");
var box = _list.find("#"+id);
console.log(" box: ",box);
box.fadeOut(500,function() {
box.remove();
//_list.listview('refresh');
});
}
})(window);

View File

@ -0,0 +1,202 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
(function (w) {
var _page;
var _statusField;
var _actionField;
var _networkAPI = new NetworkAPI();
var _connectAPI = new ConnectAPI();
var _connectedBoxNetworkAPI = new NetworkAPI();
var _infoAPI = new InfoAPI();
var _pageData = {};
var _formData;
var _wifiboxid;
var _wifiboxSSID;
var _connectedChecking = false;
var CONNECTED_REDIRECT_DELAY = 5000;
var _connectedRedirectDelay;
var BACKUP_REDIRECT_DELAY = 10*1000; // when the wifiboxid isn't retrievable we want to redirect anyway
var _backupRedirectDelay;
var PAGE_ID = "#connecting_to_network";
var _self = this;
$.mobile.document.on( "pageinit", PAGE_ID, function( event, data ) {
console.log(PAGE_ID+": pageinit");
_page = $(this);
_statusField = _page.find("#status");
_actionField = _page.find("#action");
});
$.mobile.document.on( "pagebeforeshow", PAGE_ID, function( event, data ) {
console.log(PAGE_ID+": pagebeforeshow");
_pageData = d3d.util.getPageParams(PAGE_ID);
var form = data.prevPage.find("form");
// check if there are url params and a form from a prev page
if(_pageData === undefined || form.length === 0) {
$.mobile.changePage("#boxes");
return;
}
var boxURL = "http://"+_pageData.localip;
_formData = d3d.util.getFormData(form);
_infoAPI.init(boxURL);
_networkAPI.init(boxURL);
retrieveWiFiBoxID(function() {
console.log(" _wifiboxid: ",_wifiboxid);
console.log(" _wifiboxSSID: ",_wifiboxSSID);
joinNetwork();
_networkAPI.refreshing = onRefreshing;
_networkAPI.updated = onStatusUpdated;
_networkAPI.startAutoRefresh();
});
});
$.mobile.document.on( "pagebeforehide", PAGE_ID, function( event, data ) {
console.log(PAGE_ID+": pagebeforehide");
_networkAPI.stopAutoRefresh();
_connectAPI.stop();
_connectedBoxNetworkAPI.stopAutoRefresh();
clearTimeout(_connectedRedirectDelay);
clearTimeout(_backupRedirectDelay);
});
function retrieveWiFiBoxID(completeHandler) {
console.log(PAGE_ID+":retrieveWiFiBoxID");
_infoAPI.getInfo(function(infoData) {
_wifiboxid = infoData.wifiboxid;
_wifiboxSSID = infoData.substituted_ssid;
completeHandler();
},function() {
_wifiboxid = undefined;
_wifiboxSSID = undefined;
// try connecting anyway (making sure wifiboxid retrieval isn't blocking)
completeHandler();
});
}
function joinNetwork() {
console.log(PAGE_ID+":joinNetwork");
_networkAPI.associate(_pageData.ssid,_formData.password,true);
_connectedChecking = false;
}
function onRefreshing() {
//console.log("ConnectingToNetworkPage:onRefreshing");
d3d.util.showLoader(true);
}
function onStatusUpdated(data) {
console.log("ConnectingToNetworkPage:onStatusUpdated");
//console.log(" data: ",data);
data.status = parseInt(data.status,10);
console.log(" data.status: ",data.status);
// update texts
var statusText = "";
var actionText = "";
switch(data.status) {
case NetworkAPI.STATUS.CONNECTING:
statusText = "Connecting to "+_pageData.ssid+"...";
//actionText = "Please reconnect yourself to <b>"+_pageData.ssid+"</b>. Once you are connected return to this page.";
actionText = "Please reconnect yourself to <b>"+_pageData.ssid+"</b>. Once you are connected return to this page.";
_actionField.attr("class","notice");
break;
case NetworkAPI.STATUS.CONNECTING_FAILED:
statusText = "Could not connect...";
actionText = "Please check password and try again";
_actionField.attr("class","error");
break;
case NetworkAPI.STATUS.CONNECTED:
statusText = "Connected to "+_pageData.ssid;
actionText = "Please reconnect yourself to <b>"+_pageData.ssid+"</b>. Once you are connected return to this page.";
_actionField.attr("class","notice");
break;
default:
actionText = "Something went wrong, please try again";
_actionField.attr("class","error");
break;
}
// TODO ignore connected?
_statusField.html(statusText);
_actionField.html(actionText);
// When the box is connecting we start checking connect.doodle3d.com
// for a box with the same wifiboxid
if(data.status === NetworkAPI.STATUS.CONNECTING && !_connectedChecking) {
if(_wifiboxid !== undefined || _wifiboxSSID !== undefined) {
console.log(" start checking for same box");
_connectAPI.boxAppeared = onBoxAppeared;
} else {
// if there is no wifiboxid or ssid available we'll check if we're online
console.log(" start checking for internet");
_connectAPI.listSuccess = onListSuccess;
}
_connectAPI.checkLocal = false;
_connectAPI.start();
_connectedChecking = true;
}
}
function onBoxAppeared(boxData) {
console.log(PAGE_ID+":onBoxAppeared: ",boxData.localip,boxData.wifiboxid);
// if same box is found...
if(_wifiboxid !== undefined && boxData.wifiboxid === _wifiboxid) {
console.log("found _wifiboxid");
checkBox(boxData);
// wifiboxid of older firmware isn't available, fallback to ssid
} else if(_wifiboxSSID !== undefined){
console.log("no _wifiboxid, falling back to _wifiboxSSID comparison");
var connectedBoxConfigAPI = new ConfigAPI();
connectedBoxConfigAPI.init("http://"+boxData.localip);
connectedBoxConfigAPI.save({},function(saveResponseData) {
if(saveResponseData.substituted_ssid === _wifiboxSSID) {
checkBox(boxData);
}
});
}
}
function checkBox(boxData) {
// check if it finished connecting
var boxURL = "http://"+boxData.localip;
_connectedBoxNetworkAPI = new NetworkAPI();
_connectedBoxNetworkAPI.init(boxURL);
_connectedBoxNetworkAPI.updated = function(data) {
data.status = parseInt(data.status,10);
console.log(PAGE_ID+":connectedBoxNetworkAPI:onStatusUpdated: ",data.status);
// if box finished connecting
if(data.status === NetworkAPI.STATUS.CONNECTED) {
console.log(" found connected box");
_statusField.html("Connected to "+_pageData.ssid);
_actionField.html("Congratulations the box is connected to <b>"+_pageData.ssid+"</b>. You will be redirected in a moment...");
_actionField.attr("class","info");
// prevent status changes by wired box
_networkAPI.stopAutoRefresh();
_connectedRedirectDelay = setTimeout(function () {
// redirect to it's box page
console.log(" redirect to box");
// replace this page with boxes page in history
window.history.replaceState(null, "", "#boxes");
var linkParams = {localip: boxData.localip,wifiboxid: boxData.wifiboxid};
var link = "#box";
link = d3d.util.replaceURLParameters(link,linkParams);
$.mobile.changePage(link);
_connectedBoxNetworkAPI.stopAutoRefresh();
// disable warnings that are enabled on boxes page
d3d.util.disableRefreshPrevention();
d3d.util.disableLeaveWarning();
},CONNECTED_REDIRECT_DELAY);
}
};
_connectedBoxNetworkAPI.startAutoRefresh();
}
// when no wifiboxid or wifiboxSSID is available but we are online, we redirect to the boxes page
function onListSuccess() {
console.log(PAGE_ID+":onListSuccess");
_backupRedirectDelay = setTimeout(function () {
$.mobile.changePage("#boxes");
},BACKUP_REDIRECT_DELAY);
}
})(window);

91
js/JoinNetworkPage.js Normal file
View File

@ -0,0 +1,91 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
(function (w) {
var _page;
var _list;
//var _joinOtherItem;
var _networks;
var _networkAPI = new NetworkAPI();
var _boxData = {};
var _refreshDelay;
var _refreshDelayTime = 3000;
var PAGE_ID = "#join_network";
var _self = this;
$.mobile.document.on( "pageinit", PAGE_ID, function( event, data ) {
console.log("Join network page pageinit");
_page = $(this);
_list = _page.find("ul[data-role=listview]");
//_joinOtherItem = _list.find("#joinOther");
});
$.mobile.document.on( "pagebeforeshow", PAGE_ID, function( event, data ) {
console.log("Join network page pagebeforeshow");
_boxData = d3d.util.getPageParams(PAGE_ID);
if(_boxData === undefined) {
$.mobile.changePage("#boxes");
return;
}
var boxURL = "http://"+_boxData.localip;
console.log(" _boxData: ",_boxData);
_networkAPI.init(boxURL);
refreshNetworks();
});
$.mobile.document.on( "pagebeforehide", PAGE_ID, function( event, data ) {
console.log("Join network page pagehide");
clearTimeout(_refreshDelay);
});
function refreshNetworks() {
//console.log("JoinNetwork:refreshNetworks");
d3d.util.showLoader();
_networkAPI.scan(function(data) { // completed
//console.log("JoinNetwork:refreshNetworks:scanned");
d3d.util.hideLoader();
_networks = {};
$.each(data.networks, function(index,network) {
_networks[network.ssid] = network;
});
// update list
updateList();
// keep refreshing
clearTimeout(_refreshDelay);
_refreshDelay = setTimeout(refreshNetworks, _refreshDelayTime);
});
}
function updateList() {
_list.empty();
var baseConnectingLink = _list.data("connecting-target");
var baseSecuredLink = _list.data("secured-target");
var linkParams = $.extend({}, _boxData);
//console.log(" linkParams: ",linkParams);
$.each(_networks, function(index,network) {
//console.log(" network: ",network);
linkParams.ssid = network.ssid;
var secured = (network.encryption !== "none" && network.encryption !== "");
var link;
var icon = "";
if(secured) {
linkParams.encryption = network.encryption;
link = d3d.util.replaceURLParameters(baseSecuredLink,linkParams);
icon = "lock";
} else {
link = d3d.util.replaceURLParameters(baseConnectingLink,linkParams);
}
//console.log(" link: ",link);
_list.append(
$('<li data-icon="'+icon+'"><a href="'+link+'">'+network.ssid+'</a></li>')
);
});
//_list.append(_joinOtherItem);
_list.listview('refresh'); // jQuery mobile enhance content
}
})(window);

View File

@ -0,0 +1,60 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
(function (w) {
var _page;
var _title;
var _form;
var _passwordField;
var _passwordCloneField;
var _submitButton;
var _pageData = {};
var PAGE_ID = "#join_secured_network";
var _self = this;
$.mobile.document.on( "pageinit", PAGE_ID, function( event, data ) {
console.log(PAGE_ID+" pageinit");
_page = $(this);
_title = _page.find("h3");
_form = _page.find("form");
_passwordField = _form.find("input[name=password]");
_passwordField.psswrd();
_passwordCloneField = _form.find("input[name=password-clone]");
_submitButton = _form.find("input[type=submit]");
_form.submit(join);
});
$.mobile.document.on( "pagebeforeshow", PAGE_ID, function( event, data ) {
console.log(PAGE_ID+" pagebeforeshow");
_pageData = d3d.util.getPageParams(PAGE_ID);
if(_pageData === undefined) {
$.mobile.changePage("#boxes");
return;
}
console.log(" _pageData: ",_pageData);
_title.text("Join "+_pageData.ssid);
_form.attr("id","Join "+_pageData.ssid);
_passwordField.val("");
_passwordCloneField.val("");
});
$.mobile.document.on( "pageshow", PAGE_ID, function( event, data ) {
d3d.util.autofocus(_form);
});
function join(){
console.log("JoinSecuredNetworkPage:submit");
// ToDo: validation
// http://www.raymondcamden.com/index.cfm/2012/7/30/Example-of-form-validation-in-a-jQuery-Mobile-Application
if(_passwordField.val().length === 0) { return false; }
var submitLink = _form.data("target");
submitLink = d3d.util.replaceURLParameters(submitLink,_pageData);
$.mobile.changePage(submitLink);
return false;
}
})(window);

View File

@ -1,317 +0,0 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function NetworkPanel() {
this.id;
var NETWORK_SELECTOR_DEFAULT = ""; // used as first item in networks list
//var NETWORK_SELECTOR_CUSTOM = "join other network...";
// network mode
NetworkPanel.NETWORK_MODE = {
NEITHER: "neither",
CLIENT: "clientMode",
ACCESS_POINT: "accessPointMode"
};
var _networkMode = NetworkPanel.NETWORK_MODE.NEITHER;
var _api = new NetworkAPI();
var _networks = {};
var _currentNetwork; // the ssid of the network the box is on
var _selectedNetwork; // the ssid of the selected network in the client mode settings
var _currentNetworkStatus;
var _customNetwork = false;
var _retryDelay = 2000;
var _retryRetrieveStatusDelayTime = 1000;
var _retryRetrieveStatusDelay;
var _retrieveStatusDelayTime = 1000;
var _retrieveStatusDelay;
var _statusChangeHandler;
// ui elements
var _element;
var _networkSelector;
var _btnRefreshNetworks;
var _networkField;
var _btnListNetworks;
var _passwordSettings;
var _passwordField;
var _btnConnect;
var _statusTextField;
var _actionTextField;
var _self = this;
this.init = function(wifiboxURL,panelElement,statusChangeHandler) {
//console.log(_self.id,"NetworkPanel:init");
_api.init(wifiboxURL);
_element = panelElement;
_networkSelector = _element.find("#network");
_btnRefreshNetworks = _element.find("#refreshNetworks");
_networkField = _element.find("#ssid");
_btnListNetworks = _element.find("#listNetworks");
_passwordSettings = _element.find("#passwordSettings");
_passwordField = _element.find("#phrase");
_btnConnect = _element.find("#btnConnect");
_statusTextField = _element.find("#status");
_actionTextField = _element.find("#action");
_btnRefreshNetworks.on('touchstart mousedown',onRefreshClick);
_btnListNetworks.on('touchstart mousedown',showNetworkSelector);
//_btnConnect.on('touchstart mousedown',_self.connectToNetwork);
_element.submit(connectToNetwork);
_networkSelector.change(networkSelectorChanged);
_networkSelector.chosen({width: "180px"});
_networkSelector.on('chosen:hiding_dropdown', function() {
_self.refreshNetworks
});
//_networkSelector.trigger("chosen:updated");
_passwordField.showPassword();
_statusChangeHandler = statusChangeHandler;
_self.retrieveStatus(function(networkStatus) {
if(networkStatus != NetworkAPI.STATUS.CONNECTED) {
_self.refreshNetworks();
}
});
}
/*
* Handlers
*/
function onRefreshClick() {
_btnRefreshNetworks.attr("disabled", true);
_self.refreshNetworks(function() {
_btnRefreshNetworks.removeAttr("disabled");
})
}
function networkSelectorChanged(e) {
var selectedOption = $(this).find("option:selected");
_self.selectNetwork(selectedOption.val());
};
this.retrieveStatus = function(completeHandler) {
//console.log(_self.id,"NetworkPanel:retrieveStatus");
_api.status(function(data) {
if(typeof data.status === 'string') {
data.status = parseInt(data.status);
}
//console.log(_self.id,"NetworkPanel:retrievedStatus status: ",data.status,data.statusMessage);
//console.log(" networkPanel ",_element[0]," parent: ",_element.parent()[0]);
// ToDo: update _currentNetwork when available
setStatus(data.status,data);
// Keep checking for updates?
switch(data.status) {
case NetworkAPI.STATUS.CONNECTING:
case NetworkAPI.STATUS.CREATING:
clearTimeout(_retryRetrieveStatusDelay);
_retryRetrieveStatusDelay = setTimeout(_self.retrieveStatus,_retryRetrieveStatusDelayTime); // retry after delay
break;
}
_currentNetworkStatus = data.status;
if(completeHandler) completeHandler(data.status);
}, function() {
//console.log("NetworkPanel:retrieveStatus failed");
clearTimeout(_retryRetrieveStatusDelay);
_retryRetrieveStatusDelay = setTimeout(_self.retrieveStatus, _retryRetrieveStatusDelayTime); // retry after delay
});
};
function setStatus(status,data) {
if(status == _currentNetworkStatus) return;
_currentNetworkStatus = status;
var targetNetwork;
// update info
switch(status) {
case NetworkAPI.STATUS.CONNECTED:
//console.log(" data.ssid: ",data.ssid);
if(data.ssid == "") {
_currentNetwork = undefined;
//data.status = NetworkAPI.STATUS.NOT_CONNECTED;
setStatus(NetworkAPI.STATUS.NOT_CONNECTED);
} else {
_currentNetwork = data.ssid;
}
break;
case NetworkAPI.STATUS.CONNECTING:
if(_selectedNetwork != undefined) {
targetNetwork = _selectedNetwork;
} else if(_currentNetwork != undefined) {
targetNetwork = _currentNetwork;
}
case NetworkAPI.STATUS.CREATING:
case NetworkAPI.STATUS.CREATED:
_currentNetwork = undefined;
break;
}
// network selector
switch(status) {
case NetworkAPI.STATUS.NOT_CONNECTED:
case NetworkAPI.STATUS.CREATING:
case NetworkAPI.STATUS.CREATED:
_networkSelector.val(NETWORK_SELECTOR_DEFAULT);
break;
case NetworkAPI.STATUS.CONNECTED:
_self.selectNetwork(_currentNetwork);
break;
case NetworkAPI.STATUS.CONNECTING:
case NetworkAPI.STATUS.CONNECTING_FAILED:
// ToDo
break;
}
// connect button
switch(status) {
case NetworkAPI.STATUS.CONNECTING:
case NetworkAPI.STATUS.CREATING:
_btnConnect.attr("disabled", true);
break;
default:
_btnConnect.removeAttr("disabled");
break;
}
// update status text
var statusText = "";
switch(status) {
case NetworkAPI.STATUS.CONNECTING:
statusText = "Connecting... ";
break;
case NetworkAPI.STATUS.CONNECTING_FAILED:
//msg = data.statusMessage;
statusText = "Could not connect.";
break;
}
_statusTextField.html(statusText);
// update action text
var actionText = "";
switch(status) {
case NetworkAPI.STATUS.CONNECTING:
if(targetNetwork != undefined) {
actionText = "Connect your device to <b>"+targetNetwork+"</b>.";
_actionTextField.attr("class","info");
}
break;
case NetworkAPI.STATUS.CONNECTING_FAILED:
actionText = "Please check password and try again";
_actionTextField.attr("class","error");
break;
default:
_actionTextField.attr("class","none");
break;
}
_actionTextField.html(actionText);
if(_statusChangeHandler) _statusChangeHandler(status);
}
this.refreshNetworks = function(completeHandler) {
//console.log("NetworkPanel:refreshNetworks");
_api.scan(function(data) { // completed
//console.log("NetworkPanel:scanned");
// order networks alphabetically
/*data.networks.sort(function (a, b) {
if (a.ssid > b.ssid)
return 1;
if (a.ssid < b.ssid)
return -1;
// a must be equal to b
return 0;
});*/
fillNetworkSelector(data.networks)
_networks = {};
$.each(data.networks, function(index,network) {
_networks[network.ssid] = network;
});
if(completeHandler) completeHandler();
});
};
function fillNetworkSelector(networks) {
var foundCurrentNetwork = false;
_networkSelector.empty();
_networkSelector.append(
$("<option></option>").val(NETWORK_SELECTOR_DEFAULT).html(NETWORK_SELECTOR_DEFAULT)
);
$.each(networks, function(index,network) {
if(network.ssid == _currentNetwork) {
foundCurrentNetwork = true;
}
_networkSelector.append(
$("<option></option>").val(network.ssid).html(network.ssid)
);
});
/*_networkSelector.append(
$("<option></option>").val(NETWORK_SELECTOR_CUSTOM).html(NETWORK_SELECTOR_CUSTOM)
);*/
if(foundCurrentNetwork) {
_networkSelector.val(_currentNetwork);
//_self.selectNetwork(_currentNetwork);
}
_networkSelector.trigger("chosen:updated");
}
this.selectNetwork = function(ssid) {
//console.log("NetworkPanel:selectNetwork: ",ssid);
if(ssid == "") return;
_selectedNetwork = ssid;
var network = _networks[ssid];
//console.log(" network: ",network);
/*if(ssid == NETWORK_SELECTOR_CUSTOM) {
showCustomNetworkInput();
_passwordSettings.show();
} else*/ if(network === undefined || network.encryption == "none" || ssid == NETWORK_SELECTOR_DEFAULT) {
_passwordSettings.hide();
} else {
_passwordSettings.show();
}
_passwordField.val("");
};
function showNetworkSelector() {
_customNetwork = false;
_element.removeClass("customNetwork");
_networkSelector.val(NETWORK_SELECTOR_DEFAULT);
}
/*function showCustomNetworkInput() {
_customNetwork = true;
_element.addClass("customNetwork");
}*/
function connectToNetwork() {
//console.log("NetworkPanel:connectToNetwork");
if(_selectedNetwork == NETWORK_SELECTOR_DEFAULT) return;
setStatus(NetworkAPI.STATUS.CONNECTING); // override status
var ssid = (_customNetwork)? _networkField.val() : _selectedNetwork;
_api.associate(ssid,_passwordField.val(),true);
// after switching wifi network or creating a access point we delay the status retrieval
// because the webserver needs time to switch it's status
clearTimeout(_retrieveStatusDelay);
_retrieveStatusDelay = setTimeout(_self.retrieveStatus, _retrieveStatusDelayTime);
return false;
};
this.destroy = function() {
clearTimeout(_retryRetrieveStatusDelay);
clearTimeout(_retrieveStatusDelay);
}
}

102
js/api/ConfigAPI.js Normal file
View File

@ -0,0 +1,102 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function ConfigAPI() {
var _apiPath = "/d3dapi";
var _apiCGIPath = "/cgi-bin"+_apiPath;
var _wifiboxURL;
var _wifiboxCGIBinURL;
var _timeoutTime = 3000;
var _saveSettingsTimeoutTime = 8000;
var _self = this;
this.init = function(wifiboxURL) {
//console.log("ConfigAPI:init");
_wifiboxURL = wifiboxURL+_apiPath;
_wifiboxCGIBinURL = wifiboxURL+_apiCGIPath;
}
this.loadAll = function(completeHandler,failedHandler) {
//console.log("ConfigAPI:loadAll");
$.ajax({
url: _wifiboxURL + "/config/all",
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.load = function(targetSettings,completeHandler,failedHandler) {
//console.log("ConfigAPI:load");
$.ajax({
url: _wifiboxURL + "/config/",
type: "GET",
dataType: 'json',
data: targetSettings,
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.save = function(newSettings,completeHandler,failedHandler) {
//console.log("ConfigAPI:save");
$.ajax({
url: _wifiboxCGIBinURL + "/config",
type: "POST",
data: newSettings,
dataType: 'json',
timeout: _saveSettingsTimeoutTime,
success: function(response){
//console.log("ConfigAPI:save response: ",response);
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
this.resetAll = function(completeHandler,failedHandler) {
//console.log("ConfigAPI:resetAll");
$.ajax({
url: _wifiboxCGIBinURL + "/config/resetall",
type: "POST",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
completeHandler(response.data);
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
}

View File

@ -7,9 +7,35 @@
*/ */
function ConnectAPI() { function ConnectAPI() {
// callbacks
this.refreshing; // I'm refreshing my list
this.listFailed; // list retrieval from connect.doodle3d.com failed
this.listSuccess; // list retrieval from connect.doodle3d.com succeeded
this.listUpdated; // the list of boxes is updated / changed
this.boxAppeared; // a new box appeared
this.boxDisapeared; // a box disappeared
//this.boxUpdated; // a box is updated / changed
this.checkLocal = true; // check for wired and access point boxes
var _apiURL = "http://connect.doodle3d.com/api"; var _apiURL = "http://connect.doodle3d.com/api";
var _networkAPI = new NetworkAPI();
var _timeoutTime = 3000; var _timeoutTime = 3000;
var _refreshDelay;
var _refreshInterval = 5000;
var _running;
var _listChanged = false;
var _wiredBox = {localip:"192.168.5.1",wifiboxid:"Wired WiFi-Box"};
var _apBox = {localip:"192.168.10.1",wifiboxid:"WiFi-Box",link:"http://draw.doodle3d.com"};
var _boxTimeoutTime = 500;
var _numBoxesChecking = 0; // count how many boxes we are checking
var _numBoxesFound = 0; // count how many boxes responded
var _boxes = {}; // current list of boxes
var _numBoxes = 0; // current number of boxes
var _checkedWiredBox = false;
var _self = this; var _self = this;
this.list = function(completeHandler,failedHandler) { this.list = function(completeHandler,failedHandler) {
@ -19,18 +45,143 @@ function ConnectAPI() {
type: "GET", type: "GET",
dataType: 'json', dataType: 'json',
timeout: _timeoutTime, timeout: _timeoutTime,
cache: false,
success: function(response){ success: function(response){
//console.log("ConnectAPI:list response: ",response); //console.log("ConnectAPI:list response: ",response);
if(response.status == "error" || response.status == "fail") { if(response.status == "error" || response.status == "fail") {
//console.log("ConnectAPI:list failed: ",response); //console.log("ConnectAPI:list failed: ",response);
if(failedHandler) failedHandler(response); if(failedHandler) failedHandler(response);
} else { } else {
if(_self.listSuccess) {_self.listSuccess(); }
completeHandler(response.data); completeHandler(response.data);
} }
} }
}).fail(function() { }).fail(function() {
//console.log("ConnectAPI:list failed"); //console.log("ConnectAPI:list failed");
if(failedHandler) failedHandler(); if(failedHandler) failedHandler();
if(_self.listFailed) {_self.listFailed(); }
}); });
}; };
this.start = function(interval,listUpdated) {
if(interval) {
_refreshInterval = interval;
}
if(listUpdated) {
_self.listUpdated = listUpdated;
}
_running = true;
_self.refresh();
}
this.stop = function() {
_running = false;
clearTimeout(_refreshDelay);
}
this.refresh = function(listUpdated) {
if(listUpdated) { _self.listUpdated = listUpdated; }
if(_self.refreshing) { _self.refreshing(); }
_self.list(function(foundBoxes) {
//console.log(" foundBoxes: ",foundBoxes);
if(_self.checkLocal) {
foundBoxes.push(_wiredBox); // check for a wired box
}
updateList(foundBoxes);
if(_running) {
clearTimeout(_refreshDelay);
_refreshDelay = setTimeout(_self.refresh, _refreshInterval);
}
}, function() {
console.log("ConnectAPI list retrieve failed");
if(_self.checkLocal) {
// if web is not accessible try to find a box as an accesspoint
// if not found, we look for a wired box
_networkAPI.alive(_apBox.localip,_boxTimeoutTime,function() {
updateList([_apBox]);
}, function() {
updateList([_wiredBox]);
});
}
if(_running) {
clearTimeout(_refreshDelay);
_refreshDelay = setTimeout(_self.refresh, _refreshInterval);
}
});
}
function updateList(foundBoxes) {
//console.log("updateList");
_numBoxesChecking = 0;
_numBoxesFound = 0;
_listChanged = false;
// remove stored, but not found boxes
jQuery.each(_boxes, function (index,box) {
var found = false;
jQuery.each(foundBoxes, function (index,foundBox) {
if(foundBox.localip == box.localip &&
foundBox.wifiboxid == box.wifiboxid) found = true;
});
if(!found) removeBox(box.localip);
})
// check if all found boxes are alive
jQuery.each(foundBoxes, function (index,foundBox) {
if(foundBox === _apBox) { // don't recheck apBox
addBox(foundBox);
} else {
checkBox(foundBox);
}
});
if(foundBoxes.length == 0 && _self.listUpdated) {
_self.listUpdated(_boxes);
}
}
function checkBox(boxData) {
//console.log(" checkBox: ",boxData.localip);
_numBoxesChecking++;
_networkAPI.alive(boxData.localip,_boxTimeoutTime,function() {
if(boxData.localip === _wiredBox.localip) {
// double check wired box (otherwise it shows up on switch to ap)
if(_checkedWiredBox) {
addBox(boxData);
_numBoxesFound++;
}
_checkedWiredBox = true;
} else {
addBox(boxData);
_numBoxesFound++;
}
}, function() {
removeBox(boxData.localip);
if(boxData === _wiredBox) {
_checkedWiredBox = false;
}
},function(){
_numBoxesChecking--;
if(_numBoxesChecking <= 0 && _listChanged && _self.listUpdated) {
_self.listUpdated(_boxes);
}
});
}
function getBox(localip) {
return _boxes[localip];
}
function addBox(box) {
if(getBox(box.localip) !== undefined) return;
_boxes[box.localip] = box;
_numBoxes++;
if(_self.boxAppeared) _self.boxAppeared(box);
_listChanged = true;
}
function removeBox(localip) {
var box = getBox(localip);
if(box === undefined) return;
delete _boxes[localip];
_numBoxes--;
if(_self.boxDisapeared) _self.boxDisapeared(box);
_listChanged = true;
}
} }

61
js/api/InfoAPI.js Normal file
View File

@ -0,0 +1,61 @@
/*
* This file is part of the Doodle3D project (http://doodle3d.com).
*
* Copyright (c) 2013, Doodle3D
* This software is licensed under the terms of the GNU GPL v2 or later.
* See file LICENSE.txt or visit http://www.gnu.org/licenses/gpl.html for full license details.
*/
function InfoAPI() {
var _apiPath = "/d3dapi";
var _apiCGIPath = "/cgi-bin"+_apiPath;
var _wifiboxURL;
var _wifiboxCGIBinURL;
var _timeoutTime = 3000;
var _configAPI = new ConfigAPI(); // needed for wifiboxid workaround
var _self = this;
this.init = function(wifiboxURL) {
console.log("InfoAPI:init");
_wifiboxURL = wifiboxURL+_apiPath;
_wifiboxCGIBinURL = wifiboxURL+_apiCGIPath;
_configAPI.init(wifiboxURL);
}
this.getInfo = function(completeHandler,failedHandler) {
$.ajax({
url: _wifiboxURL + "/info",
type: "GET",
dataType: 'json',
timeout: _timeoutTime,
success: function(response){
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
var infoData = response.data;
// Versions older than 0.10.2 don't include wifiboxid in info response
// so we use a workaround (saving to config to retrieve substituted_wifiboxid or substituted_ssid)
if(infoData.wifiboxid === undefined) {
_configAPI.save({},function(saveResponseData) {
infoData.wifiboxid = saveResponseData.substituted_wifiboxid;
// when no wifiboxid is available we could use the substituted_ssid to compare
infoData.substituted_ssid = saveResponseData.substituted_ssid;
completeHandler(infoData);
},function() {
failedHandler();
});
} else {
completeHandler(infoData);
}
}
}
}).fail(function() {
if(failedHandler) failedHandler();
});
};
}

View File

@ -23,6 +23,18 @@ function NetworkAPI() {
var _wifiboxCGIBinURL; var _wifiboxCGIBinURL;
var _timeoutTime = 3000; var _timeoutTime = 3000;
var _networkStatus;
var _networkSSID;
var _associateTime;
var _retrieveStatusDelayTime = 3000;
var _autoRefreshing = false;
var _refreshDelay;
this.refreshDelayTime = 2000;
//callbacks
this.refreshing; // I'm refreshing
this.updated; // New network status info
var _self = this; var _self = this;
this.init = function(wifiboxURL) { this.init = function(wifiboxURL) {
@ -55,26 +67,81 @@ function NetworkAPI() {
}; };
this.status = function(completeHandler,failedHandler) { this.status = function(completeHandler,failedHandler) {
//console.log("NetworkAPI:status"); //console.log("NetworkAPI:status");
$.ajax({ // After switching wifi network or creating a access point we delay the actual status
url: _wifiboxURL + "/network/status", // retrieval because the webserver needs time to switch it's status
type: "GET", var now = new Date().getTime();
dataType: 'json', if(now < _associateTime+_retrieveStatusDelayTime) {
timeout: _timeoutTime, var data = {status: NetworkAPI.STATUS.CONNECTING};
success: function(response){ completeHandler(data);
//console.log("NetworkAPI:status response: ",response); } else {
if(response.status == "error" || response.status == "fail") { $.ajax({
if(failedHandler) failedHandler(response); url: _wifiboxURL + "/network/status",
} else { type: "GET",
completeHandler(response.data); dataType: 'json',
timeout: _timeoutTime,
success: function(response){
//console.log("NetworkAPI:status response: ",response);
if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response);
} else {
var data = response.data;
// The WiFi-Box won't create a access point when it already is when booting,
// so when the status is empty it actually is a access point.
if(data.status === "") {
data.status = NetworkAPI.STATUS.CREATED.toString();
}
completeHandler(response.data);
}
} }
} }).fail(function() {
}).fail(function() { if(failedHandler) failedHandler();
if(failedHandler) failedHandler(); });
}); }
}; };
this.startAutoRefresh = function(delay,refreshingHandler,updatedHandler) {
if(delay !== undefined) { _self.refreshDelayTime = delay; }
if(refreshingHandler !== undefined) { _self.refreshing = refreshingHandler; }
if(updatedHandler !== undefined) { _self.updated = updatedHandler; }
_autoRefreshing = true;
_self.refresh();
}
this.stopAutoRefresh = function() {
_autoRefreshing = false;
clearTimeout(_refreshDelay);
}
this.refresh = function() {
//console.log("NetworkAPI:refresh");
if(_self.refreshing) { _self.refreshing(); }
_self.status(function(data) { // completed
//console.log("NetworkAPI:refresh:completed");
//console.log(" data: ",data);
if(_self.updated !== undefined &&
(_networkStatus !== data.status || _networkSSID !== data.ssid)) {
_networkStatus = data.status;
_networkSSID = data.ssid;
_self.updated(data);
}
if(_autoRefreshing) {
// keep refreshing
clearTimeout(_refreshDelay);
_refreshDelay = setTimeout(_self.refresh, _self.refreshDelayTime);
}
},function() { // failed
if(_autoRefreshing) {
// retry
clearTimeout(_refreshDelay);
_refreshDelay = setTimeout(_self.refresh, _self.refreshDelayTime);
}
});
}
this.associate = function(ssid,phrase,recreate) { this.associate = function(ssid,phrase,recreate) {
//console.log("NetworkAPI:associate"); console.log("NetworkAPI:associate");
console.log(" ssid: ",ssid);
console.log(" recreate: ",recreate);
if(phrase === undefined) { phrase = ""; }
console.log(" phrase: ",phrase);
var postData = { var postData = {
ssid:ssid, ssid:ssid,
phrase:phrase, phrase:phrase,
@ -92,6 +159,7 @@ function NetworkAPI() {
}).fail(function() { }).fail(function() {
//console.log("NetworkAPI:associate: timeout (normal behavior)"); //console.log("NetworkAPI:associate: timeout (normal behavior)");
}); });
_associateTime = new Date().getTime();
}; };
this.openAP = function() { this.openAP = function() {
@ -123,7 +191,7 @@ function NetworkAPI() {
}); });
}; };
this.alive = function(wifiboxURL,timeoutTime,completeHandler,failedHandler) { this.alive = function(wifiboxURL,timeoutTime,successHandler,failedHandler, completeHandler) {
if(wifiboxURL.indexOf("http://") != 0) { if(wifiboxURL.indexOf("http://") != 0) {
wifiboxURL = "http://" + wifiboxURL; wifiboxURL = "http://" + wifiboxURL;
} }
@ -134,17 +202,21 @@ function NetworkAPI() {
type: "GET", type: "GET",
dataType: 'json', dataType: 'json',
timeout: timeoutTime, timeout: timeoutTime,
cache: false,
success: function(response){ success: function(response){
//console.log("NetworkAPI:alive response: ",response); //console.log("NetworkAPI:alive response: ",response);
if(response.status == "error" || response.status == "fail") { if(response.status == "error" || response.status == "fail") {
if(failedHandler) failedHandler(response); if(failedHandler) failedHandler(response);
if(completeHandler) completeHandler(false, response);
} else { } else {
completeHandler(response.data); successHandler(response.data);
if(completeHandler) completeHandler(true, response.data);
} }
} }
}).fail(function() { }).fail(function() {
//console.log("NetworkAPI:alive failed"); //console.log("NetworkAPI:alive failed");
if(failedHandler) failedHandler(); if(failedHandler) failedHandler();
if(completeHandler) completeHandler(false);
}); });
}; };
} }

4
js/libs/.jquery-1.11.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,732 @@
/* JQM Demos custom CSS */
/* Header */
.jqm-demos .jqm-header {
background: #fff;
border-top: 4px solid #3eb249;
border-bottom-color: #eee;
}
.jqm-demos .jqm-header h2 {
padding: .4em 0 .1em;
margin: 0 3em;
}
.jqm-demos .jqm-header h2 a {
display: inline-block;
text-decoration: none;
min-height: 40px;
}
.jqm-demos .jqm-header h2 img {
display: block;
width: 140px;
height: auto;
}
.jqm-demos .jqm-header h2 > img {
display: inline-block;
}
.jqm-demos .jqm-header p {
position: absolute;
bottom: -2em;
left: 1em;
margin: 0;
color: #666;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
text-transform: uppercase;
}
.jqm-demos .jqm-header .ui-btn {
width: 2em;
height: 2em;
background: none;
border: 0;
top: 50%;
margin-top: -1em;
-webkit-border-radius: .3125em;
border-radius: .3125em;
opacity: .4;
filter: Alpha(Opacity=40);
}
/* Footer */
.jqm-demos .jqm-footer.ui-footer {
position: absolute;
bottom: 0;
padding-bottom: 0;
}
.jqm-demos .jqm-footer {
border-top: 1px solid #3eb249;
}
.jqm-demos .jqm-footer p {
font-size: .8em;
color: #999;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
margin: 0 1.25em 1.25em;
}
.jqm-demos .jqm-footer p:first-child {
font-size: 1em;
color: #666;
font-weight: 400;
margin: 1em 1em .75em;
}
/* Content */
.jqm-demos .jqm-content {
padding-top: 3em;
}
.jqm-demos .jqm-content > h1,
.jqm-demos .jqm-content > h2,
.jqm-demos .jqm-content > h3,
.jqm-demos .jqm-content > p,
.jqm-demos .jqm-content > ul li,
.jqm-demos .jqm-content > a {
font-family: 'Open Sans', sans-serif;
font-weight: 300;
}
.jqm-demos .jqm-content > h1 {
font-size: 2.4em;
margin: 0 0 .625em;
}
.jqm-demos .jqm-content > h2 {
color: #3eb249;
background-color: transparent;
border-bottom: 1px solid #ddd;
font-size: 1.6em;
padding-bottom: .2em;
margin: 0 0 .7375em;
}
.jqm-demos .jqm-content > h3 {
color: #3eb249;
background-color: transparent;
font-size: 1.4em;
margin: 0 0 1em;
}
.jqm-demos .jqm-content > p {
font-size: 1.2em;
line-height: 1.5;
}
.jqm-demos .jqm-content > ul:not(.jqm-list) li {
font-size: 1.2em;
line-height: 1.5;
}
.jqm-demos .jqm-content > p {
margin: 0 0 1.25em;
}
.jqm-demos .jqm-content > ul,
.jqm-demos .jqm-content > ol {
padding-left: 1.3em;
}
.jqm-demos .jqm-content > .ui-listview {
padding-left: 0;
}
.jqm-demos .jqm-content > a,
.jqm-demos .jqm-content > p a,
.jqm-demos .jqm-content > ul:not(.jqm-list) li a {
font-weight: 400;
text-decoration: none;
}
.jqm-demos .jqm-content strong {
font-weight: 700;
}
.jqm-demos .jqm-content > p strong {
font-weight: 400;
}
/* Homepage */
.jqm-home > .jqm-content > img {
width: 400px;
max-width: 100%;
display: block;
margin: 2.5em 0;
}
.jqm-home .ui-grid-a {
margin: 2.5em -.5em -.5em;
}
.jqm-block-content {
margin: .5em;
padding: 1em;
background: #fff;
border: 1px solid #eee;
-webkit-border-radius: .3125em;
border-radius: .3125em;
font-family: 'Open Sans', sans-serif;
}
.jqm-block-content h3 {
font-size: 1.5em;
font-weight: 300;
color: #3eb249;
border-bottom: 1px solid #ddd;
padding-bottom: .25em;
margin: 0 0 .5em;
}
.jqm-block-content p {
font-size: 1.1em;
font-weight: 300;
line-height: 1.4;
margin: .7em 0;
}
.jqm-block-content p:last-child {
margin-bottom: 0;
}
.jqm-block-content a:link {
font-weight: 300;
text-decoration: none;
}
/* Code */
.jqm-content pre,
.jqm-content code {
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
background: #e5e5e5;
background: rgba(0,0,0,.05);
padding: 0 .125em;
}
.jqm-content pre {
padding: 0 1em 1.2em;
white-space: pre-wrap;
}
.jqm-content pre > code {
padding: 0;
background: none;
font-size: .9em;
}
/* Lists */
.jqm-demos .jqm-search .jqm-list {
margin: 0 -1em 1em;
}
.jqm-demos .jqm-list .ui-btn,
.jqm-demos .jqm-list .ui-btn:visited,
.jqm-demos .jqm-list .ui-li-divider {
font-family: 'Open Sans', sans-serif;
font-weight: 300;
text-shadow: none !important;
}
.jqm-demos .jqm-list .ui-btn:hover,
.jqm-demos .jqm-list .ui-btn:active {
color: #3388cc;
}
.jqm-demos .jqm-list .ui-btn.ui-btn-active {
color: #fff;
}
.jqm-demos .jqm-list .ui-li-divider {
color: #3eb249;
}
/* Navmenu */
.jqm-navmenu-panel .ui-listview > li .ui-collapsible-heading {
margin: 0;
}
.jqm-navmenu-panel .ui-collapsible.ui-li-static {
padding: 0;
border: none !important;
}
.jqm-navmenu-panel .ui-collapsible + li > .ui-btn,
.jqm-navmenu-panel .ui-collapsible + .ui-collapsible > .ui-collapsible-heading > .ui-btn,
.jqm-navmenu-panel .ui-panel-inner > .ui-listview > li.ui-first-child .ui-btn {
border-top: none !important;
}
.jqm-navmenu-panel .ui-listview .ui-listview .ui-btn {
padding-left: 1.5em;
color: #999;
}
.jqm-navmenu-panel .ui-listview .ui-listview .ui-btn.ui-btn-active {
color: #fff;
}
.jqm-navmenu-panel .ui-btn:after {
opacity: .4;
filter: Alpha(Opacity=40);
}
.jqm-demos .jqm-navmenu-panel.jqm-panel-page-nav {
display: none;
position: absolute;
top: 178px;
left: 12px;
}
.jqm-demos .jqm-navmenu-panel.jqm-panel-page-nav ul li:first-child a{
border-top: none;
}
/* Search */
.jqm-search-panel .ui-panel-inner {
padding-top: 0;
}
.jqm-search-panel .ui-input-search {
margin: 1em 0;
}
.jqm-search-panel .ui-input-search.ui-focus {
-webkit-box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
box-shadow: inset 0 1px 3px rgba(0,0,0,.2);
}
.jqm-list .jqm-search-results-keywords {
padding: .46857em 0 0;
font-size: .8em;
font-weight: 300;
color: #999;
display: block;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.ui-btn-active .jqm-search-results-keywords {
color: #fff;
}
.jqm-search-results-highlight {
color: #3388cc;
font-weight: 400;
}
.ui-btn-active .jqm-search-results-highlight {
color: #fff;
font-weight: 300;
}
/* Quick links */
.jqm-demos .jqm-content .jqm-deeplink {
display: block;
color: #999;
font-weight: 300;
border-top: 1px solid #eee;
text-align: right;
padding-top: .2em;
margin: 0 0 1.5em;
}
.jqm-demos .jqm-content .jqm-deeplink:after {
content: "";
display: block;
float: right;
margin: .1em 0 0 .5em;
width: 1em;
height: 1em;
background-position: center center;
background-repeat: no-repeat;
opacity: .4;
filter: Alpha(Opacity=40);
}
/* View source links */
.jqm-demos .jqm-content .jqm-view-source-link,
.jqm-demos .jqm-content .jqm-view-source-link:visited,
.jqm-demos .jqm-content .jqm-view-source-link:hover,
.jqm-demos .jqm-content .jqm-view-source-link:active {
color: #3eb249;
font-family: 'Open Sans', sans-serif;
font-weight: 400;
margin: 2em 0 1.5em 1em;
}
.jqm-demos .jqm-content .jqm-view-source-link.ui-btn-active:link {
color: #fff;
}
@media (min-width: 60em) {
.jqm-demos .jqm-header h2 {
padding: 1em 0 .7em;
margin: 0 1em 0 3%;
text-align: left;
}
.jqm-demos .jqm-header h2 img {
width: 275px;
height: 78px;
}
.jqm-demos .jqm-header p {
bottom: auto;
left: auto;
top: 50%;
right: 15%;
font-size: 1.2em;
margin-top: -.625em;
}
.jqm-demos .jqm-navmenu-link {
display: none;
}
.jqm-demos .jqm-search-link {
right: 3%;
}
.jqm-demos .jqm-footer p {
float: right;
margin: 1.5em 3% 1.5em 1.5em;
}
.jqm-demos .jqm-footer p:first-child {
float: left;
margin: 1.25em 1.25em 1.25em 3%;
}
.jqm-demos .jqm-navmenu-panel {
visibility: visible;
position: relative;
left: 0;
float: left;
width: 25%;
background: none;
-webkit-transition: none !important;
-moz-transition: none !important;
transition: none !important;
-webkit-transform: none !important;
-moz-transform: none !important;
transform: none !important;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.jqm-demos.jqm-panel-page .jqm-navmenu-panel {
display: none;
}
html .jqm-demos.jqm-panel-page .jqm-navmenu-panel.jqm-panel-page-nav {
display: block;
}
.jqm-demos .jqm-navmenu-panel .ui-panel-inner {
margin-top: 3em;
margin-bottom: 3em;
}
.jqm-demos .jqm-content {
width: 67%;
padding-top: 2em;
padding-left: 5%;
padding-right: 3%;
float: right;
}
.jqm-demos .jqm-content.jqm-fullwidth {
width: auto;
padding-left: 15%;
padding-right: 15%;
float: none;
}
.jqm-navmenu-panel .ui-listview .ui-btn {
padding-left: 12.5%;
}
.jqm-navmenu-panel .ui-listview .ui-listview .ui-btn {
padding-left: 15%;
}
.jqm-navmenu-panel .ui-collapsible,
.jqm-navmenu-panel .ui-collapsible-content,
.jqm-navmenu-panel .ui-btn {
background: none !important;
border-color: #ddd !important;
}
.jqm-navmenu-panel .ui-btn.ui-btn-active {
color: #3388cc !important;
}
.jqm-navmenu-panel .ui-btn::after {
opacity: 0;
-webkit-transition: opacity 500ms ease;
-moz-transition: opacity 500ms ease;
transition: opacity 500ms ease;
}
.jqm-navmenu-panel .ui-btn:hover::after {
opacity: .4;
}
.jqm-search-panel {
width: 26em;
right: -26em;
z-index: 1003; /* Puts the panel on top of the dismiss modal which is not adjusted to custom width */
}
.jqm-search-panel.ui-panel-animate.ui-panel-position-right {
-webkit-transform: translate3d(26em,0,0);
-moz-transform: translate3d(26em,0,0);
transform: translate3d(26em,0,0);
}
.ui-panel-dismiss-open.ui-panel-dismiss-position-right {
left: -17em;
right: 17em;
}
}
@media (min-width: 35em) {
.jqm-block-content {
min-height: 18em;
}
}
/* View source popup */
#jqm-view-source-popup.ui-popup-container {
width: 90%;
max-width: 1500px;
}
.jqm-view-source .ui-collapsible-set {
margin: 0;
}
.jqm-view-source .ui-collapsible-heading .ui-btn {
font-family: 'Open Sans', sans-serif;
font-weight: 400;
}
.jqm-view-source .ui-collapsible-heading .ui-btn-inner {
padding: .4em;
}
.jqm-view-source .ui-collapsible-content {
padding: 0;
overflow: auto;
}
.jqm-view-source .ui-collapsible-content .phpStatus {
padding: 1em;
}
.jqm-view-source .ui-collapsible-content > div,
.jqm-view-source .ui-collapsible-content .syntaxhighlighter {
border-bottom-right-radius: inherit;
border-bottom-left-radius: inherit;
}
.jqm-view-source .ui-collapsible-content::-webkit-scrollbar {
width: 5px;
}
.jqm-view-source .ui-collapsible-content::-webkit-scrollbar-track {
background: transparent;
}
.jqm-view-source .ui-collapsible-content::-webkit-scrollbar-thumb {
background: #435A5F;
border: solid #222;
border-width: 12px 2px 12px 0;
border-bottom-right-radius: 5px;
}
.jqm-view-source .ui-collapsible-content td.code .container > textarea {
resize: none;
}
/* Button C - HTML */
.jqm-view-source .ui-btn.ui-btn-c,
.jqm-view-source .ui-btn.ui-btn-c:visited,
.jqm-view-source .ui-btn.ui-btn-c:hover,
.jqm-view-source .ui-btn.ui-btn-c:active,
.jqm-view-source .ui-btn.ui-btn-c.ui-btn-active {
background: #005aff;
border-color: #0033cc;
color: #fff;
text-shadow: 0 1px 0 #0033cc;
}
/* Button D - PHP */
.jqm-view-source .ui-btn.ui-btn-d,
.jqm-view-source .ui-btn.ui-btn-d:visited,
.jqm-view-source .ui-btn.ui-btn-d:hover,
.jqm-view-source .ui-btn.ui-btn-d:active,
.jqm-view-source .ui-btn.ui-btn-d.ui-btn-active {
background: #ed1c24;
border-color: #ff0000;
color: #fff;
text-shadow: 0 1px 0 #ff0000;
}
/* Button E - JS */
.jqm-view-source .ui-btn.ui-btn-e,
.jqm-view-source .ui-btn.ui-btn-e:visited,
.jqm-view-source .ui-btn.ui-btn-e:hover,
.jqm-view-source .ui-btn.ui-btn-e:active,
.jqm-view-source .ui-btn.ui-btn-e.ui-btn-active {
background: #3EB249;
border-color: #108040;
color: #fff;
text-shadow: 0 1px 0 #108040;
}
/* Button F - CSS */
.jqm-view-source .ui-btn.ui-btn-f,
.jqm-view-source .ui-btn.ui-btn-f:visited,
.jqm-view-source .ui-btn.ui-btn-f:hover,
.jqm-view-source .ui-btn.ui-btn-f:active,
.jqm-view-source .ui-btn.ui-btn-f.ui-btn-active {
background: #ec008c;
border-color: #cc0099;
color: #fff;
text-shadow: 0 1px 0 #cc0099;
}
/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter a,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody,
.syntaxhighlighter table thead,
.syntaxhighlighter table caption,
.syntaxhighlighter textarea {
background: none;
border: 0;
bottom: auto;
float: none;
left: auto;
height: auto;
line-height: 18px;
margin: 0;
outline: 0;
overflow: visible;
padding: 0;
position: static;
right: auto;
text-align: left;
top: auto;
vertical-align: baseline;
width: auto;
box-sizing: content-box;
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
font-weight: normal;
font-style: normal;
font-size: 14px;
min-height: inherit;
min-height: auto;
}
.syntaxhighlighter {
width: auto;
margin: 0;
padding: 1em 0;
position: relative;
overflow: auto;
font-size: 13px;
}
.syntaxhighlighter.source {
overflow: hidden;
}
.syntaxhighlighter .bold {
font-weight: bold;
}
.syntaxhighlighter .italic {
font-style: italic;
}
.syntaxhighlighter .line {
white-space: pre;
white-space: pre-wrap;
}
.syntaxhighlighter table {
width: 100%;
}
.syntaxhighlighter table caption {
text-align: left;
padding: .5em 0 0.5em 1em;
}
.syntaxhighlighter table td.code {
width: 100%;
}
.syntaxhighlighter table td.code .container {
position: relative;
}
.syntaxhighlighter table td.code .container textarea {
box-sizing: border-box;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border: none;
background: white;
padding-left: 1em;
overflow: hidden;
white-space: pre;
}
.syntaxhighlighter table td.gutter .line {
text-align: right;
padding: 0 0.5em 0 1em;
}
.syntaxhighlighter table td.code .line {
padding: 0 1em;
}
.syntaxhighlighter.show {
display: block;
}
.syntaxhighlighter.collapsed table {
display: none;
}
.syntaxhighlighter .line.alt1 {
background-color: transparent;
}
.syntaxhighlighter .line.alt2 {
background-color: transparent;
}
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
background-color: #253e5a;
}
.syntaxhighlighter .line.highlighted.number {
color: #38566f;
}
.syntaxhighlighter table caption {
color: #d1edff;
}
.syntaxhighlighter .gutter {
color: #afafaf;
}
.syntaxhighlighter .gutter .line {
border-right: 3px solid #435a5f;
}
.syntaxhighlighter .gutter .line.highlighted {
background-color: #435a5f;
color: #0f192a;
}
.syntaxhighlighter.collapsed {
overflow: visible;
}
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
color: #eee;
}
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
color: #5ba1cf;
}
.syntaxhighlighter .string {
color: #98da31;
}
.syntaxhighlighter .string a {
color: #1dc116;
}
.syntaxhighlighter .keyword {
color: #ffae00;
}
.syntaxhighlighter .preprocessor {
color: #8aa6c1;
}
.syntaxhighlighter .variable {
color: #ffaa3e;
}
.syntaxhighlighter .value {
color: #f7e741;
}
.syntaxhighlighter .functions {
color: #ffaa3e;
}
.syntaxhighlighter .constants {
color: #e0e8ff;
}
.syntaxhighlighter .script {
font-weight: bold;
color: #b43d3d;
background-color: none;
}
.syntaxhighlighter .color1 {
color: #8df;
}
.syntaxhighlighter .color1 a {
color: #f8bb00;
}
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
color: white;
}
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
color: #ffaa3e;
}
.syntaxhighlighter table td.code {
cursor: text;
}
.syntaxhighlighter table td.code .container textarea {
background: #eee;
white-space: pre;
white-space: pre-wrap;
}
.syntaxhighlighter ::-moz-selection {
background-color: #3399ff;
color: #fff;
text-shadow: none;
}
.syntaxhighlighter ::-webkit-selection {
background-color: #3399ff;
color: #fff;
text-shadow: none;
}
.syntaxhighlighter ::selection {
background-color: #3399ff;
color: #fff;
text-shadow: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,13 @@
Created by Joseph Wain (see http://penandthink.com) at and probably downloaded from http://glyphish.com
This work is licensed under the Creative Commons Attribution 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
You are free to share it and to remix it remix under the following conditions:
* You must attribute the work in the manner specified by the author (SEE BELOW).
* For any reuse or distribution, you must make clear to others the license terms of this work.
* The above conditions can be waived if you get permission from the copyright holder (send me an email!).
ATTRIBUTION -- a note reading "icons by Joseph Wain / glyphish.com" or similar, plus a link back to glyphish.com from your app's website, is the preferred form of attribution. Also acceptable would be, like, a link from within your iPhone application, or from the iTunes store page, but those aren't as useful to other people. If none of these work for you, please contact hello@glyphish.com and we can work something out.
USE WITHOUT ATTRIBUTION -- If attribution is not possible, workable or desirable for your application, contact hello@glyphish.com for commercial non-attributed licensing terms.

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

View File

@ -0,0 +1,169 @@
(function( $, undefined ) {
//special click handling to make widget work remove after nav changes in 1.4
var href,
ele = "";
$( document ).on( "click", "a", function( e ) {
href = $( this ).attr( "href" );
var hash = $.mobile.path.parseUrl( href );
if( typeof href !== "undefined" && hash !== "" && href !== href.replace( hash,"" ) && hash.search( "/" ) !== -1 ){
//remove the hash from the link to allow normal loading of the page.
var newHref = href.replace( hash,"" );
$( this ).attr( "href", newHref );
}
ele = $( this );
});
$( document ).on( "pagebeforechange", function( e, f ){
f.originalHref = href;
});
$( document ).on("pagebeforechange", function( e,f ){
var hash = $.mobile.path.parseUrl(f.toPage).hash,
hashEl, hashElInPage;
try {
hashEl = $( hash );
} catch( e ) {
hashEl = $();
}
try {
hashElInPage = $( ".ui-page-active " + hash );
} catch( e ) {
hashElInPage = $();
}
if( typeof hash !== "undefined" &&
hash.search( "/" ) === -1 &&
hash !== "" &&
hashEl.length > 0 &&
!hashEl.hasClass( "ui-page" ) &&
!hashEl.hasClass( "ui-popup" ) &&
hashEl.data('role') !== "page" &&
!hashElInPage.hasClass( "ui-panel" ) &&
!hashElInPage.hasClass( "ui-popup" ) ) {
//scroll to the id
var pos = hashEl.offset().top;
$.mobile.silentScroll( pos );
$.mobile.navigate( hash, '', true );
} else if( typeof f.toPage !== "object" &&
hash !== "" &&
$.mobile.path.parseUrl( href ).hash !== "" &&
!hashEl.hasClass( "ui-page" ) && hashEl.attr('data-role') !== "page" &&
!hashElInPage.hasClass( "ui-panel" ) &&
!hashElInPage.hasClass( "ui-popup" ) ) {
$( ele ).attr( "href", href );
$.mobile.document.one( "pagechange", function() {
if( typeof hash !== "undefined" &&
hash.search( "/" ) === -1 &&
hash !== "" &&
hashEl.length > 0 &&
hashElInPage.length > 0 &&
!hashEl.hasClass( "ui-page" ) &&
hashEl.data('role') !== "page" &&
!hashElInPage.hasClass( "ui-panel" ) &&
!hashElInPage.hasClass( "ui-popup" ) ) {
hash = $.mobile.path.parseUrl( href ).hash;
var pos = hashElInPage.offset().top;
$.mobile.silentScroll( pos );
}
} );
}
});
$( document ).on( "mobileinit", function(){
hash = window.location.hash;
$.mobile.document.one( "pageshow", function(){
var hashEl, hashElInPage;
try {
hashEl = $( hash );
} catch( e ) {
hashEl = $();
}
try {
hashElInPage = $( ".ui-page-active " + hash );
} catch( e ) {
hashElInPage = $();
}
if( hash !== "" &&
hashEl.length > 0 &&
hashElInPage.length > 0 &&
hashEl.attr('data-role') !== "page" &&
!hashEl.hasClass( "ui-page" ) &&
!hashElInPage.hasClass( "ui-panel" ) &&
!hashElInPage.hasClass( "ui-popup" ) &&
!hashEl.is( "body" ) ){
var pos = hashElInPage.offset().top;
setTimeout( function(){
$.mobile.silentScroll( pos );
}, 100 );
}
});
});
//h2 widget
$( document ).on( "mobileinit", function(){
$.widget( "mobile.h2linker", {
options:{
initSelector: ":jqmData(quicklinks='true')"
},
_create:function(){
var self = this,
bodyid = "ui-page-top",
panel = "<div data-role='panel' class='jqm-nav-panel jqm-quicklink-panel' data-position='right' data-display='overlay' data-theme='a'><ul data-role='listview' data-inset='false' data-theme='a' data-divider-theme='a' data-icon='false' class='jqm-list'><li data-role='list-divider'>Quick Links</li></ul></div>",
first = true,
h2dictionary = new Object();
if(typeof $("body").attr("id") === "undefined"){
$("body").attr("id",bodyid);
} else {
bodyid = $("body").attr("id");
}
this.element.find("div.jqm-content>h2").each(function(){
var id, text = $(this).text();
if(typeof $(this).attr("id") === "undefined"){
id = text.replace(/[^\.a-z0-9:_-]+/gi,"");
$(this).attr( "id", id );
} else {
id = $(this).attr("id");
}
h2dictionary[id] = text;
if(!first){
$(this).before( "<a href='#" + bodyid + "' class='jqm-deeplink ui-icon-carat-u ui-alt-icon'>Top</a>");
} else {
$(this).before("<a href='#' data-ajax='false' class='jqm-deeplink jqm-open-quicklink-panel ui-icon-carat-l ui-alt-icon'>Quick Links</a>");
}
first = false;
});
this._on(".jqm-open-quicklink-panel", {
"click": function(){
$(".ui-page-active .jqm-quicklink-panel").panel("open");
return false;
}
});
this._on( document, {
"pagebeforechange": function(){
this.element.find(".jqm-quicklink-panel").panel("close");
this.element.find(".jqm-quicklink-panel .ui-btn-active").removeClass("ui-btn-active");
}
});
if( $(h2dictionary).length > 0 ){
this.element.prepend(panel)
this.element.find(".jqm-quicklink-panel").panel().find("ul").listview();
}
$.each(h2dictionary,function(id,text){
self.element.find(".jqm-quicklink-panel ul").append("<li><a href='#"+id+"'>"+text+"</a></li>");
});
self.element.find(".jqm-quicklink-panel ul").listview("refresh");
}
});
});
$( document ).bind( "pagecreate create", function( e ) {
var initselector = $.mobile.h2linker.prototype.options.initSelector;
if($(e.target).data("quicklinks")){
$(e.target).h2linker();
}
});
})( jQuery );

View File

@ -0,0 +1,9 @@
<?php
$type = 'text/javascript';
$files = array(
'jqm-demos.js',
'view-source.js',
'h2widget.js'
);
require_once('../../../combine.html');

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,311 @@
// Turn off Ajax for local file browsing
if ( location.protocol.substr(0,4) === 'file' ||
location.protocol.substr(0,11) === '*-extension' ||
location.protocol.substr(0,6) === 'widget' ) {
// Start with links with only the trailing slash and that aren't external links
var fixLinks = function() {
$( "a[href$='/'], a[href='.'], a[href='..']" ).not( "[rel='external']" ).each( function() {
if( !$( this ).attr( "href" ).match("http") ){
this.href = $( this ).attr( "href" ).replace( /\/$/, "" ) + "/index.html";
}
});
};
// Fix the links for the initial page
$( fixLinks );
// Fix the links for subsequent ajax page loads
$( document ).on( "pagecreate", fixLinks );
// Check to see if ajax can be used. This does a quick ajax request and blocks the page until its done
$.ajax({
url: '.',
async: false,
isLocal: true
}).error(function() {
// Ajax doesn't work so turn it off
$( document ).on( "mobileinit", function() {
$.mobile.ajaxEnabled = false;
var message = $( '<div>' , {
'class': "jqm-content",
style: "border:none; padding: 10px 15px; overflow: auto;",
'data-ajax-warning': true
});
message
.append( "<h3>Note: Navigation may not work if viewed locally</h3>" )
.append( "<p>The Ajax-based navigation used throughout the jQuery Mobile docs may need to be viewed on a web server to work in certain browsers. If you see an error message when you click a link, please try a different browser.</p>" );
$( document ).on( "pagecreate", function( event ) {
$( event.target ).append( message );
});
});
});
}
$( document ).on( "pagecreate", ".jqm-demos", function( event ) {
var search,
page = $( this ),
that = this,
searchUrl = ( $( this ).hasClass( "jqm-home" ) ) ? "_search/" : "../_search/",
searchContents = $( ".jqm-search ul.jqm-list" ).find( "li:not(.ui-collapsible)" ),
version = $.mobile.version || "dev",
words = version.split( "-" ),
ver = words[0],
str = words[1] || "",
text = ver;
// Insert jqm version in header
if ( str.indexOf( "rc" ) == -1 ) {
str = str.charAt( 0 ).toUpperCase() + str.slice( 1 );
} else {
str = str.toUpperCase().replace( ".", "" );
}
if ( $.mobile.version && str ) {
text += " " + str;
}
$( ".jqm-version" ).html( text );
// Global navmenu panel
$( ".jqm-navmenu-panel ul" ).listview();
$( document ).on( "panelopen", ".jqm-search-panel", function() {
$( this ).find( "input" ).focus();
})
$( ".jqm-navmenu-link" ).on( "click", function() {
page.find( ".jqm-navmenu-panel:not(.jqm-panel-page-nav)" ).panel( "open" );
});
// Turn off autocomplete / correct for demos search
$( this ).find( ".jqm-search input" ).attr( "autocomplete", "off" ).attr( "autocorrect", "off" );
// Global search
$( ".jqm-search-link" ).on( "click", function() {
page.find( ".jqm-search-panel" ).panel( "open" );
});
// Initalize search panel list and filter also remove collapsibles
$( this ).find( ".jqm-search ul.jqm-list" ).html( searchContents ).listview({
inset: false,
theme: null,
dividerTheme: null,
icon: false,
autodividers: true,
autodividersSelector: function ( li ) {
return "";
},
arrowKeyNav: true,
enterToNav: true,
highlight: true,
submitTo: searchUrl
}).filterable();
// Initalize search page list and remove collapsibles
$( this ).find( ".jqm-search-results-wrap ul.jqm-list" ).html( searchContents ).listview({
inset: true,
theme: null,
dividerTheme: null,
icon: false,
arrowKeyNav: true,
enterToNav: true,
highlight: true
}).filterable();
// Fix links on homepage to point to sub directories
if ( $( event.target ).hasClass( "jqm-home") ) {
$( this ).find( "a" ).each( function() {
$( this ).attr( "href", $( this ).attr( "href" ).replace( "../", "" ) );
});
}
// Search results page get search query string and enter it into filter then trigger keyup to filter
if ( $( event.target ).hasClass( "jqm-demos-search-results") ) {
search = $.mobile.path.parseUrl( window.location.href ).search.split( "=" )[ 1 ];
setTimeout(function() {
e = $.Event( "keyup" );
e.which = 65;
$( that ).find( ".jqm-content .jqm-search-results-wrap input" ).val( search ).trigger(e).trigger( "change" );
}, 0 );
}
});
// Append keywords list to each list item
$( document ).one( "pagecreate", ".jqm-demos", function( event ) {
$( this ).find( ".jqm-search-results-list li, .jqm-search li" ).each(function() {
var text = $( this ).attr( "data-filtertext" );
$( this )
.find( "a" )
.append( "<span class='jqm-search-results-keywords ui-li-desc'>" + text + "</span>" );
});
});
// Functions for highlighting text used for keywords highlight in search
jQuery.fn.highlight = function( pat ) {
function innerHighlight( node, pat ) {
var skip = 0;
if ( node.nodeType == 3 ) {
var pos = node.data.toUpperCase().indexOf( pat );
if ( pos >= 0 ) {
var spannode = document.createElement( "span" );
spannode.className = "jqm-search-results-highlight";
var middlebit = node.splitText( pos );
var endbit = middlebit.splitText( pat.length );
var middleclone = middlebit.cloneNode( true );
spannode.appendChild( middleclone );
middlebit.parentNode.replaceChild( spannode, middlebit );
skip = 1;
}
} else if ( node.nodeType == 1 && node.childNodes && !/(script|style)/i.test( node.tagName ) ) {
for ( var i = 0; i < node.childNodes.length; ++i ) {
i += innerHighlight( node.childNodes[i], pat );
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight( this, pat.toUpperCase() );
}) : this;
};
// Function to remove highlights in text
jQuery.fn.removeHighlight = function() {
return this.find( "span.jqm-search-results-highlight" ).each(function() {
this.parentNode.firstChild.nodeName;
with ( this.parentNode ) {
replaceChild( this.firstChild, this );
normalize();
}
}).end();
};
// Extension to listview to add keyboard navigation
$( document ).on( "mobileinit", function() {
(function( $, undefined ) {
$.widget( "mobile.listview", $.mobile.listview, {
options: {
arrowKeyNav: false,
enterToNav: false,
highlight: false,
submitTo: false
},
_create: function() {
this._super();
if ( this.options.arrowKeyNav ) {
this._on( document, { "pageshow": "arrowKeyNav" });
}
if ( this.options.enterToNav ) {
this._on( document, { "pageshow": "enterToNav" });
}
},
submitTo: function() {
var url,
form = this.element.parent().find( "form" );
form.attr( "method", "get" )
.attr( "action", this.options.submitTo );
url = this.options.submitTo + "?search=" + this.element.parent().find( "input" ).val();
window.location = url;
},
enterToNav: function() {
var form = this.element.parent().find( "form" );
form.append( "<button type='submit' data-icon='carat-r' data-inline='true' class='ui-hidden-accessible' data-iconpos='notext'>Submit</button>" )
.parent()
.trigger( "create" );
this.element.parent().find( "form" ).children( ".ui-btn" ).addClass( "ui-hidden-accessible" );
this._on( form, {
"submit": "submitHandler"
});
},
enhanced: false,
arrowKeyNav: function() {
var input = this.element.prev("form").find( "input" );
if ( !this.enhanced ) {
this._on( input, {
"keyup": "handleKeyUp"
});
this.enhanced = true;
}
},
handleKeyUp: function( e ) {
var search,
input = this.element.prev("form").find( "input" );
if ( e.which === $.ui.keyCode.DOWN ) {
if ( this.element.find( "li.ui-btn-active" ).length === 0 ) {
this.element.find( "li:first" ).toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
} else {
this.element.find( "li.ui-btn-active a" ).toggleClass( "ui-btn-active");
this.element.find( "li.ui-btn-active" ).toggleClass( "ui-btn-active" ).next().toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
}
this.highlightDown();
} else if ( e.which === $.ui.keyCode.UP ) {
if ( this.element.find( "li.ui-btn-active" ).length !== 0 ) {
this.element.find( "li.ui-btn-active a" ).toggleClass( "ui-btn-active");
this.element.find( "li.ui-btn-active" ).toggleClass( "ui-btn-active" ).prev().toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
} else {
this.element.find( "li:last" ).toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
}
this.highlightUp();
} else if ( typeof e.which !== "undefined" ) {
this.element.find( "li.ui-btn-active" ).removeClass( "ui-btn-active" );
if ( this.options.highlight ) {
search = input.val();
this.element.find( "li" ).each(function() {
$( this ).removeHighlight();
$( this ).highlight( search );
});
}
}
},
submitHandler: function() {
if ( this.element.find( "li.ui-btn-active" ).length !== 0 ) {
var href = this.element.find( "li.ui-btn-active a" ).attr( "href" );
$( ":mobile-pagecontainer" ).pagecontainer( "change", href );
return false;
}
if ( this.options.submitTo ) {
this.submitTo();
}
},
highlightDown: function() {
if ( this.element.find( "li.ui-btn-active" ).hasClass( "ui-screen-hidden" ) ) {
this.element.find( "li.ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
this.element.find( "li.ui-btn-active" ).toggleClass( "ui-btn-active" ).next().toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
this.highlightDown();
}
return;
},
highlightUp: function() {
if ( this.element.find( "li.ui-btn-active" ).hasClass( "ui-screen-hidden" ) ) {
this.element.find( "li.ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
this.element.find( "li.ui-btn-active" ).toggleClass( "ui-btn-active" ).prev().toggleClass( "ui-btn-active" ).find("a").toggleClass( "ui-btn-active" );
this.highlightUp();
}
return;
}
});
})( jQuery );
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,616 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile Demos</title>
<link rel="stylesheet" href="../css/themes/default/jquery.mobile-1.4.2.min.css">
<link rel="stylesheet" href="../_assets/css/jqm-demos.css">
<link rel="shortcut icon" href="../_assets/favicon.ico">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:300,400,700">
<script src="../js/jquery.js"></script>
<script src="../_assets/js/index.js"></script>
<script src="../js/jquery.mobile-1.4.2.min.js"></script>
</head>
<body>
<div data-role="page" class="jqm-demos jqm-demos-index jqm-demos-search-results">
<div data-role="header" class="jqm-header">
<h2><a href="../" title="jQuery Mobile Demos home"><img src="../_assets/img/jquery-logo.png" alt="jQuery Mobile"></a></h2>
<p><span class="jqm-version"></span> Demos</p>
<a href="#" class="jqm-navmenu-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-bars ui-nodisc-icon ui-alt-icon ui-btn-left">Menu</a>
<a href="#" class="jqm-search-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-search ui-nodisc-icon ui-alt-icon ui-btn-right">Search</a>
</div><!-- /header -->
<div role="main" class="ui-content jqm-content">
<h1>Search Results</h1>
<div class="jqm-search-results-wrap">
<ul class="jqm-list jqm-search-results-list">
<li data-filtertext="demos homepage" data-icon="home"><a href=".././">Home</a></li>
<li data-filtertext="introduction overview getting started"><a href="../intro/" data-ajax="false">Introduction</a></li>
<li data-filtertext="buttons button markup buttonmarkup method anchor link button element"><a href="../button-markup/" data-ajax="false">Buttons</a></li>
<li data-filtertext="form button widget input button submit reset"><a href="../button/" data-ajax="false">Button widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Checkboxradio widget</h3>
<ul>
<li data-filtertext="form checkboxradio widget checkbox input checkboxes controlgroups"><a href="../checkboxradio-checkbox/" data-ajax="false">Checkboxes</a></li>
<li data-filtertext="form checkboxradio widget radio input radio buttons controlgroups"><a href="../checkboxradio-radio/" data-ajax="false">Radio buttons</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Collapsible (set) widget</h3>
<ul>
<li data-filtertext="collapsibles content formatting"><a href="../collapsible/" data-ajax="false">Collapsible</a></li>
<li data-filtertext="dynamic collapsible set accordion append expand"><a href="../collapsible-dynamic/" data-ajax="false">Dynamic collapsibles</a></li>
<li data-filtertext="accordions collapsible set widget content formatting grouped collapsibles"><a href="../collapsibleset/" data-ajax="false">Collapsible set</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Controlgroup widget</h3>
<ul>
<li data-filtertext="controlgroups selectmenu checkboxradio input grouped buttons horizontal vertical"><a href="../controlgroup/" data-ajax="false">Controlgroup</a></li>
<li data-filtertext="dynamic controlgroup dynamically add buttons"><a href="../controlgroup-dynamic/" data-ajax="false">Dynamic controlgroups</a></li>
</ul>
</li>
<li data-filtertext="form datepicker widget date input"><a href="../datepicker/" data-ajax="false">Datepicker</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Events</h3>
<ul>
<li data-filtertext="swipe to delete list items listviews swipe events"><a href="../swipe-list/" data-ajax="false">Swipe list items</a></li>
<li data-filtertext="swipe to navigate swipe page navigation swipe events"><a href="../swipe-page/" data-ajax="false">Swipe page navigation</a></li>
</ul>
</li>
<li data-filtertext="filterable filter elements sorting searching listview table"><a href="../filterable/" data-ajax="false">Filterable widget</a></li>
<li data-filtertext="form flipswitch widget flip toggle switch binary select checkbox input"><a href="../flipswitch/" data-ajax="false">Flipswitch widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Forms</h3>
<ul>
<li data-filtertext="forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms/" data-ajax="false">Forms</a></li>
<li data-filtertext="form hide labels hidden accessible ui-hidden-accessible forms"><a href="../forms-label-hidden-accessible/" data-ajax="false">Hide labels</a></li>
<li data-filtertext="form field containers fieldcontain ui-field-contain forms"><a href="../forms-field-contain/" data-ajax="false">Field containers</a></li>
<li data-filtertext="forms disabled form elements"><a href="../forms-disabled/" data-ajax="false">Forms disabled</a></li>
<li data-filtertext="forms gallery examples overview forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms-gallery/" data-ajax="false">Forms gallery</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Grids</h3>
<ul>
<li data-filtertext="grids columns blocks content formatting rwd responsive css framework"><a href="../grids/" data-ajax="false">Grids</a></li>
<li data-filtertext="buttons in grids css framework"><a href="../grids-buttons/" data-ajax="false">Buttons in grids</a></li>
<li data-filtertext="custom responsive grids rwd css framework"><a href="../grids-custom-responsive/" data-ajax="false">Custom responsive grids</a></li>
</ul>
</li>
<li data-filtertext="blocks content formatting sections heading"><a href="../body-bar-classes/" data-ajax="false">Grouping and dividing content</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Icons</h3>
<ul>
<li data-filtertext="button icons svg disc alt custom icon position"><a href="../icons/" data-ajax="false">Icons</a></li>
<li data-filtertext=""><a href="../icons-grunticon/" data-ajax="false">Grunticon loader</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Listview widget</h3>
<ul>
<li data-filtertext="listview widget thumbnails icons nested split button collapsible ul ol"><a href="../listview/" data-ajax="false">Listview</a></li>
<li data-filtertext="autocomplete filterable reveal listview filtertextbeforefilter placeholder"><a href="../listview-autocomplete/" data-ajax="false">Listview autocomplete</a></li>
<li data-filtertext="autocomplete filterable reveal listview remote data filtertextbeforefilter placeholder"><a href="../listview-autocomplete-remote/" data-ajax="false">Listview autocomplete remote data</a></li>
<li data-filtertext="autodividers anchor jump scroll linkbars listview lists ul ol"><a href="../listview-autodividers-linkbar/" data-ajax="false">Listview autodividers linkbar</a></li>
<li data-filtertext="listview autodividers selector autodividersselector lists ul ol"><a href="../listview-autodividers-selector/" data-ajax="false">Listview autodividers selector</a></li>
<li data-filtertext="listview nested list items"><a href="../listview-nested-lists/" data-ajax="false">Listview Nested Listviews</a></li>
<li data-filtertext="listview collapsible list items flat"><a href="../listview-collapsible-item-flat/" data-ajax="false">Listview collapsible list items (flat)</a></li>
<li data-filtertext="listview collapsible list indented"><a href="../listview-collapsible-item-indented/" data-ajax="false">Listview collapsible list items (indented)</a></li>
<li data-filtertext="grid listview responsive grids responsive listviews lists ul"><a href="../listview-grid/" data-ajax="false">Listview responsive grid</a></li>
</ul>
</li>
<li data-filtertext="loader widget page loading navigation overlay spinner"><a href="../loader/" data-ajax="false">Loader widget</a></li>
<li data-filtertext="navbar widget navmenu toolbars header footer"><a href="../navbar/" data-ajax="false">Navbar widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Navigation</h3>
<ul>
<li data-filtertext="ajax navigation navigate widget history event method"><a href="../navigation/" data-ajax="false">Navigation</a></li>
<li data-filtertext="linking pages page links navigation ajax prefetch cache"><a href="../navigation-linking-pages/" data-ajax="false">Linking pages</a></li>
<li data-filtertext="php redirect server redirection server-side navigation"><a href="../navigation-php-redirect/" data-ajax="false">PHP redirect demo</a></li>
<li data-filtertext="navigation redirection hash query"><a href="../navigation-hash-processing/" data-ajax="false">Hash processing demo</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Pages</h3>
<ul>
<li data-filtertext="pages page widget ajax navigation"><a href="../pages/" data-ajax="false">Pages</a></li>
<li data-filtertext="single page"><a href="../pages-single-page/" data-ajax="false">Single page</a></li>
<li data-filtertext="multipage multi-page page"><a href="../pages-multi-page/" data-ajax="false">Multi-page template</a></li>
<li data-filtertext="dialog page widget modal popup"><a href="../pages-dialog/" data-ajax="false">Dialog page</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Panel widget</h3>
<ul>
<li data-filtertext="panel widget sliding panels reveal push overlay responsive"><a href="../panel/" data-ajax="false">Panel</a></li>
<li data-filtertext=""><a href="../panel-external/" data-ajax="false">External panels</a></li>
<li data-filtertext="panel "><a href="../panel-fixed/" data-ajax="false">Fixed panels</a></li>
<li data-filtertext="panel slide panels sliding panels shadow rwd responsive breakpoint"><a href="../panel-responsive/" data-ajax="false">Panels responsive</a></li>
<li data-filtertext="panel custom style custom panel width reveal shadow listview panel styling page background wrapper"><a href="../panel-styling/" data-ajax="false">Custom panel style</a></li>
<li data-filtertext="panel open on swipe"><a href="../panel-swipe-open/" data-ajax="false">Panel open on swipe</a></li>
<li data-filtertext="panels outside page internal external toolbars"><a href="../panel-external-internal/" data-ajax="false">Panel external and internal</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Popup widget</h3>
<ul>
<li data-filtertext="popup widget popups dialog modal transition tooltip lightbox form overlay screen flip pop fade transition"><a href="../popup/" data-ajax="false">Popup</a></li>
<li data-filtertext="popup alignment position"><a href="../popup-alignment/" data-ajax="false">Popup alignment</a></li>
<li data-filtertext="popup arrow size popups popover"><a href="../popup-arrow-size/" data-ajax="false">Popup arrow size</a></li>
<li data-filtertext="dynamic popups popup images lightbox"><a href="../popup-dynamic/" data-ajax="false">Dynamic popups</a></li>
<li data-filtertext="popups with iframes scaling"><a href="../popup-iframe/" data-ajax="false">Popups with iframes</a></li>
<li data-filtertext="popup image scaling"><a href="../popup-image-scaling/" data-ajax="false">Popup image scaling</a></li>
<li data-filtertext="external popup outside multi-page"><a href="../popup-outside-multipage" data-ajax="false">Popup outside multi-page</a></li>
</ul>
</li>
<li data-filtertext="form rangeslider widget dual sliders dual handle sliders range input"><a href="../rangeslider/" data-ajax="false">Rangeslider widget</a></li>
<li data-filtertext="responsive web design rwd adaptive progressive enhancement PE accessible mobile breakpoints media query media queries"><a href="../rwd/" data-ajax="false">Responsive Web Design</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Selectmenu widget</h3>
<ul>
<li data-filtertext="form selectmenu widget select input custom select menu selects"><a href="../selectmenu/" data-ajax="false">Selectmenu</a></li>
<li data-filtertext="form custom select menu selectmenu widget custom menu option optgroup multiple selects"><a href="../selectmenu-custom/" data-ajax="false">Custom select menu</a></li>
<li data-filtertext="filterable select filter popup dialog"><a href="../selectmenu-custom-filter/" data-ajax="false">Custom select menu with filter</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Slider widget</h3>
<ul>
<li data-filtertext="form slider widget range input single sliders"><a href="../slider/" data-ajax="false">Slider</a></li>
<li data-filtertext="form slider widget flipswitch slider binary select flip toggle switch"><a href="../slider-flipswitch/" data-ajax="false">Slider flip toggle switch</a></li>
<li data-filtertext="form slider tooltip handle value input range sliders"><a href="../slider-tooltip/" data-ajax="false">Slider tooltip</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Table widget</h3>
<ul>
<li data-filtertext="table widget reflow column toggle th td responsive tables rwd hide show tabular"><a href="../table-column-toggle/" data-ajax="false">Table Column Toggle</a></li>
<li data-filtertext="table column toggle phone comparison demo"><a href="../table-column-toggle-example/" data-ajax="false">Table Column Toggle demo</a></li>
<li data-filtertext="responsive tables table column toggle heading groups rwd breakpoint"><a href="../table-column-toggle-heading-groups/" data-ajax="false">Table Column Toggle heading groups</a></li>
<li data-filtertext="responsive tables table column toggle hide rwd breakpoint customization options"><a href="../table-column-toggle-options/" data-ajax="false">Table Column Toggle options</a></li>
<li data-filtertext="table reflow th td responsive rwd columns tabular"><a href="../table-reflow/" data-ajax="false">Table Reflow</a></li>
<li data-filtertext="responsive tables table reflow heading groups rwd breakpoint"><a href="../table-reflow-heading-groups/" data-ajax="false">Table Reflow heading groups</a></li>
<li data-filtertext="responsive tables table reflow stripes strokes table style"><a href="../table-reflow-stripes-strokes/" data-ajax="false">Table Reflow stripes and strokes</a></li>
<li data-filtertext="responsive tables table reflow stack custom styles"><a href="../table-reflow-styling/" data-ajax="false">Table Reflow custom styles</a></li>
</ul>
</li>
<li data-filtertext="ui tabs widget"><a href="../tabs/" data-ajax="false">Tabs widget</a></li>
<li data-filtertext="form textinput widget text input textarea number date time tel email file color password"><a href="../textinput/" data-ajax="false">Textinput widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Theming</h3>
<ul>
<li data-filtertext="default theme swatches theming style css"><a href="../theme-default/" data-ajax="false">Default theme</a></li>
<li data-filtertext="classic theme old theme swatches theming style css"><a href="../theme-classic/" data-ajax="false">Classic theme</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Toolbar widget</h3>
<ul>
<li data-filtertext="toolbar widget header footer toolbars fixed fullscreen external sections"><a href="../toolbar/" data-ajax="false">Toolbar</a></li>
<li data-filtertext="dynamic toolbars dynamically add toolbar header footer"><a href="../toolbar-dynamic/" data-ajax="false">Dynamic toolbars</a></li>
<li data-filtertext="external toolbars header footer"><a href="../toolbar-external/" data-ajax="false">External toolbars</a></li>
<li data-filtertext="fixed toolbars header footer"><a href="../toolbar-fixed/" data-ajax="false">Fixed toolbars</a></li>
<li data-filtertext="fixed fullscreen toolbars header footer"><a href="../toolbar-fixed-fullscreen/" data-ajax="false">Fullscreen toolbars</a></li>
<li data-filtertext="external fixed toolbars header footer"><a href="../toolbar-fixed-external/" data-ajax="false">Fixed external toolbars</a></li>
<li data-filtertext="external persistent toolbars header footer navbar navmenu"><a href="../toolbar-fixed-persistent/" data-ajax="false">Persistent toolbars</a></li>
<li data-filtertext="external ajax optimized toolbars persistent toolbars header footer navbar"><a href="../toolbar-fixed-persistent-optimized/" data-ajax="false">Ajax optimized toolbars</a></li>
<li data-filtertext="form in toolbars header footer"><a href="../toolbar-fixed-forms/" data-ajax="false">Form in toolbar</a></li>
</ul>
</li>
<li data-filtertext="page transitions animated pages popup navigation flip slide fade pop"><a href="../transitions/" data-ajax="false">Transitions</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>3rd party API demos</h3>
<ul>
<li data-filtertext="backbone requirejs navigation router"><a href="../backbone-requirejs/" data-ajax="false">Backbone RequireJS</a></li>
<li data-filtertext="google maps geolocation demo"><a href="../map-geolocation/" data-ajax="false">Google Maps geolocation</a></li>
<li data-filtertext="google maps hybrid"><a href="../map-list-toggle/" data-ajax="false">Google Maps list toggle</a></li>
</ul>
</li>
</ul>
</div>
</div><!-- /content -->
<div data-role="panel" class="jqm-navmenu-panel" data-position="left" data-display="overlay" data-theme="a">
<ul class="jqm-list ui-alt-icon ui-nodisc-icon">
<li data-filtertext="demos homepage" data-icon="home"><a href=".././">Home</a></li>
<li data-filtertext="introduction overview getting started"><a href="../intro/" data-ajax="false">Introduction</a></li>
<li data-filtertext="buttons button markup buttonmarkup method anchor link button element"><a href="../button-markup/" data-ajax="false">Buttons</a></li>
<li data-filtertext="form button widget input button submit reset"><a href="../button/" data-ajax="false">Button widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Checkboxradio widget</h3>
<ul>
<li data-filtertext="form checkboxradio widget checkbox input checkboxes controlgroups"><a href="../checkboxradio-checkbox/" data-ajax="false">Checkboxes</a></li>
<li data-filtertext="form checkboxradio widget radio input radio buttons controlgroups"><a href="../checkboxradio-radio/" data-ajax="false">Radio buttons</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Collapsible (set) widget</h3>
<ul>
<li data-filtertext="collapsibles content formatting"><a href="../collapsible/" data-ajax="false">Collapsible</a></li>
<li data-filtertext="dynamic collapsible set accordion append expand"><a href="../collapsible-dynamic/" data-ajax="false">Dynamic collapsibles</a></li>
<li data-filtertext="accordions collapsible set widget content formatting grouped collapsibles"><a href="../collapsibleset/" data-ajax="false">Collapsible set</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Controlgroup widget</h3>
<ul>
<li data-filtertext="controlgroups selectmenu checkboxradio input grouped buttons horizontal vertical"><a href="../controlgroup/" data-ajax="false">Controlgroup</a></li>
<li data-filtertext="dynamic controlgroup dynamically add buttons"><a href="../controlgroup-dynamic/" data-ajax="false">Dynamic controlgroups</a></li>
</ul>
</li>
<li data-filtertext="form datepicker widget date input"><a href="../datepicker/" data-ajax="false">Datepicker</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Events</h3>
<ul>
<li data-filtertext="swipe to delete list items listviews swipe events"><a href="../swipe-list/" data-ajax="false">Swipe list items</a></li>
<li data-filtertext="swipe to navigate swipe page navigation swipe events"><a href="../swipe-page/" data-ajax="false">Swipe page navigation</a></li>
</ul>
</li>
<li data-filtertext="filterable filter elements sorting searching listview table"><a href="../filterable/" data-ajax="false">Filterable widget</a></li>
<li data-filtertext="form flipswitch widget flip toggle switch binary select checkbox input"><a href="../flipswitch/" data-ajax="false">Flipswitch widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Forms</h3>
<ul>
<li data-filtertext="forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms/" data-ajax="false">Forms</a></li>
<li data-filtertext="form hide labels hidden accessible ui-hidden-accessible forms"><a href="../forms-label-hidden-accessible/" data-ajax="false">Hide labels</a></li>
<li data-filtertext="form field containers fieldcontain ui-field-contain forms"><a href="../forms-field-contain/" data-ajax="false">Field containers</a></li>
<li data-filtertext="forms disabled form elements"><a href="../forms-disabled/" data-ajax="false">Forms disabled</a></li>
<li data-filtertext="forms gallery examples overview forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms-gallery/" data-ajax="false">Forms gallery</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Grids</h3>
<ul>
<li data-filtertext="grids columns blocks content formatting rwd responsive css framework"><a href="../grids/" data-ajax="false">Grids</a></li>
<li data-filtertext="buttons in grids css framework"><a href="../grids-buttons/" data-ajax="false">Buttons in grids</a></li>
<li data-filtertext="custom responsive grids rwd css framework"><a href="../grids-custom-responsive/" data-ajax="false">Custom responsive grids</a></li>
</ul>
</li>
<li data-filtertext="blocks content formatting sections heading"><a href="../body-bar-classes/" data-ajax="false">Grouping and dividing content</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Icons</h3>
<ul>
<li data-filtertext="button icons svg disc alt custom icon position"><a href="../icons/" data-ajax="false">Icons</a></li>
<li data-filtertext=""><a href="../icons-grunticon/" data-ajax="false">Grunticon loader</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Listview widget</h3>
<ul>
<li data-filtertext="listview widget thumbnails icons nested split button collapsible ul ol"><a href="../listview/" data-ajax="false">Listview</a></li>
<li data-filtertext="autocomplete filterable reveal listview filtertextbeforefilter placeholder"><a href="../listview-autocomplete/" data-ajax="false">Listview autocomplete</a></li>
<li data-filtertext="autocomplete filterable reveal listview remote data filtertextbeforefilter placeholder"><a href="../listview-autocomplete-remote/" data-ajax="false">Listview autocomplete remote data</a></li>
<li data-filtertext="autodividers anchor jump scroll linkbars listview lists ul ol"><a href="../listview-autodividers-linkbar/" data-ajax="false">Listview autodividers linkbar</a></li>
<li data-filtertext="listview autodividers selector autodividersselector lists ul ol"><a href="../listview-autodividers-selector/" data-ajax="false">Listview autodividers selector</a></li>
<li data-filtertext="listview nested list items"><a href="../listview-nested-lists/" data-ajax="false">Listview Nested Listviews</a></li>
<li data-filtertext="listview collapsible list items flat"><a href="../listview-collapsible-item-flat/" data-ajax="false">Listview collapsible list items (flat)</a></li>
<li data-filtertext="listview collapsible list indented"><a href="../listview-collapsible-item-indented/" data-ajax="false">Listview collapsible list items (indented)</a></li>
<li data-filtertext="grid listview responsive grids responsive listviews lists ul"><a href="../listview-grid/" data-ajax="false">Listview responsive grid</a></li>
</ul>
</li>
<li data-filtertext="loader widget page loading navigation overlay spinner"><a href="../loader/" data-ajax="false">Loader widget</a></li>
<li data-filtertext="navbar widget navmenu toolbars header footer"><a href="../navbar/" data-ajax="false">Navbar widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Navigation</h3>
<ul>
<li data-filtertext="ajax navigation navigate widget history event method"><a href="../navigation/" data-ajax="false">Navigation</a></li>
<li data-filtertext="linking pages page links navigation ajax prefetch cache"><a href="../navigation-linking-pages/" data-ajax="false">Linking pages</a></li>
<li data-filtertext="php redirect server redirection server-side navigation"><a href="../navigation-php-redirect/" data-ajax="false">PHP redirect demo</a></li>
<li data-filtertext="navigation redirection hash query"><a href="../navigation-hash-processing/" data-ajax="false">Hash processing demo</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Pages</h3>
<ul>
<li data-filtertext="pages page widget ajax navigation"><a href="../pages/" data-ajax="false">Pages</a></li>
<li data-filtertext="single page"><a href="../pages-single-page/" data-ajax="false">Single page</a></li>
<li data-filtertext="multipage multi-page page"><a href="../pages-multi-page/" data-ajax="false">Multi-page template</a></li>
<li data-filtertext="dialog page widget modal popup"><a href="../pages-dialog/" data-ajax="false">Dialog page</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Panel widget</h3>
<ul>
<li data-filtertext="panel widget sliding panels reveal push overlay responsive"><a href="../panel/" data-ajax="false">Panel</a></li>
<li data-filtertext=""><a href="../panel-external/" data-ajax="false">External panels</a></li>
<li data-filtertext="panel "><a href="../panel-fixed/" data-ajax="false">Fixed panels</a></li>
<li data-filtertext="panel slide panels sliding panels shadow rwd responsive breakpoint"><a href="../panel-responsive/" data-ajax="false">Panels responsive</a></li>
<li data-filtertext="panel custom style custom panel width reveal shadow listview panel styling page background wrapper"><a href="../panel-styling/" data-ajax="false">Custom panel style</a></li>
<li data-filtertext="panel open on swipe"><a href="../panel-swipe-open/" data-ajax="false">Panel open on swipe</a></li>
<li data-filtertext="panels outside page internal external toolbars"><a href="../panel-external-internal/" data-ajax="false">Panel external and internal</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Popup widget</h3>
<ul>
<li data-filtertext="popup widget popups dialog modal transition tooltip lightbox form overlay screen flip pop fade transition"><a href="../popup/" data-ajax="false">Popup</a></li>
<li data-filtertext="popup alignment position"><a href="../popup-alignment/" data-ajax="false">Popup alignment</a></li>
<li data-filtertext="popup arrow size popups popover"><a href="../popup-arrow-size/" data-ajax="false">Popup arrow size</a></li>
<li data-filtertext="dynamic popups popup images lightbox"><a href="../popup-dynamic/" data-ajax="false">Dynamic popups</a></li>
<li data-filtertext="popups with iframes scaling"><a href="../popup-iframe/" data-ajax="false">Popups with iframes</a></li>
<li data-filtertext="popup image scaling"><a href="../popup-image-scaling/" data-ajax="false">Popup image scaling</a></li>
<li data-filtertext="external popup outside multi-page"><a href="../popup-outside-multipage" data-ajax="false">Popup outside multi-page</a></li>
</ul>
</li>
<li data-filtertext="form rangeslider widget dual sliders dual handle sliders range input"><a href="../rangeslider/" data-ajax="false">Rangeslider widget</a></li>
<li data-filtertext="responsive web design rwd adaptive progressive enhancement PE accessible mobile breakpoints media query media queries"><a href="../rwd/" data-ajax="false">Responsive Web Design</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Selectmenu widget</h3>
<ul>
<li data-filtertext="form selectmenu widget select input custom select menu selects"><a href="../selectmenu/" data-ajax="false">Selectmenu</a></li>
<li data-filtertext="form custom select menu selectmenu widget custom menu option optgroup multiple selects"><a href="../selectmenu-custom/" data-ajax="false">Custom select menu</a></li>
<li data-filtertext="filterable select filter popup dialog"><a href="../selectmenu-custom-filter/" data-ajax="false">Custom select menu with filter</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Slider widget</h3>
<ul>
<li data-filtertext="form slider widget range input single sliders"><a href="../slider/" data-ajax="false">Slider</a></li>
<li data-filtertext="form slider widget flipswitch slider binary select flip toggle switch"><a href="../slider-flipswitch/" data-ajax="false">Slider flip toggle switch</a></li>
<li data-filtertext="form slider tooltip handle value input range sliders"><a href="../slider-tooltip/" data-ajax="false">Slider tooltip</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Table widget</h3>
<ul>
<li data-filtertext="table widget reflow column toggle th td responsive tables rwd hide show tabular"><a href="../table-column-toggle/" data-ajax="false">Table Column Toggle</a></li>
<li data-filtertext="table column toggle phone comparison demo"><a href="../table-column-toggle-example/" data-ajax="false">Table Column Toggle demo</a></li>
<li data-filtertext="responsive tables table column toggle heading groups rwd breakpoint"><a href="../table-column-toggle-heading-groups/" data-ajax="false">Table Column Toggle heading groups</a></li>
<li data-filtertext="responsive tables table column toggle hide rwd breakpoint customization options"><a href="../table-column-toggle-options/" data-ajax="false">Table Column Toggle options</a></li>
<li data-filtertext="table reflow th td responsive rwd columns tabular"><a href="../table-reflow/" data-ajax="false">Table Reflow</a></li>
<li data-filtertext="responsive tables table reflow heading groups rwd breakpoint"><a href="../table-reflow-heading-groups/" data-ajax="false">Table Reflow heading groups</a></li>
<li data-filtertext="responsive tables table reflow stripes strokes table style"><a href="../table-reflow-stripes-strokes/" data-ajax="false">Table Reflow stripes and strokes</a></li>
<li data-filtertext="responsive tables table reflow stack custom styles"><a href="../table-reflow-styling/" data-ajax="false">Table Reflow custom styles</a></li>
</ul>
</li>
<li data-filtertext="ui tabs widget"><a href="../tabs/" data-ajax="false">Tabs widget</a></li>
<li data-filtertext="form textinput widget text input textarea number date time tel email file color password"><a href="../textinput/" data-ajax="false">Textinput widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Theming</h3>
<ul>
<li data-filtertext="default theme swatches theming style css"><a href="../theme-default/" data-ajax="false">Default theme</a></li>
<li data-filtertext="classic theme old theme swatches theming style css"><a href="../theme-classic/" data-ajax="false">Classic theme</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Toolbar widget</h3>
<ul>
<li data-filtertext="toolbar widget header footer toolbars fixed fullscreen external sections"><a href="../toolbar/" data-ajax="false">Toolbar</a></li>
<li data-filtertext="dynamic toolbars dynamically add toolbar header footer"><a href="../toolbar-dynamic/" data-ajax="false">Dynamic toolbars</a></li>
<li data-filtertext="external toolbars header footer"><a href="../toolbar-external/" data-ajax="false">External toolbars</a></li>
<li data-filtertext="fixed toolbars header footer"><a href="../toolbar-fixed/" data-ajax="false">Fixed toolbars</a></li>
<li data-filtertext="fixed fullscreen toolbars header footer"><a href="../toolbar-fixed-fullscreen/" data-ajax="false">Fullscreen toolbars</a></li>
<li data-filtertext="external fixed toolbars header footer"><a href="../toolbar-fixed-external/" data-ajax="false">Fixed external toolbars</a></li>
<li data-filtertext="external persistent toolbars header footer navbar navmenu"><a href="../toolbar-fixed-persistent/" data-ajax="false">Persistent toolbars</a></li>
<li data-filtertext="external ajax optimized toolbars persistent toolbars header footer navbar"><a href="../toolbar-fixed-persistent-optimized/" data-ajax="false">Ajax optimized toolbars</a></li>
<li data-filtertext="form in toolbars header footer"><a href="../toolbar-fixed-forms/" data-ajax="false">Form in toolbar</a></li>
</ul>
</li>
<li data-filtertext="page transitions animated pages popup navigation flip slide fade pop"><a href="../transitions/" data-ajax="false">Transitions</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>3rd party API demos</h3>
<ul>
<li data-filtertext="backbone requirejs navigation router"><a href="../backbone-requirejs/" data-ajax="false">Backbone RequireJS</a></li>
<li data-filtertext="google maps geolocation demo"><a href="../map-geolocation/" data-ajax="false">Google Maps geolocation</a></li>
<li data-filtertext="google maps hybrid"><a href="../map-list-toggle/" data-ajax="false">Google Maps list toggle</a></li>
</ul>
</li>
</ul>
</div><!-- /panel -->
<div data-role="footer" data-position="fixed" data-tap-toggle="false" class="jqm-footer">
<p>jQuery Mobile Demos version <span class="jqm-version"></span></p>
<p>Copyright 2014 The jQuery Foundation</p>
</div><!-- /footer -->
<!-- TODO: This should become an external panel so we can add input to markup (unique ID) -->
<div data-role="panel" class="jqm-search-panel" data-position="right" data-display="overlay" data-theme="a">
<div class="jqm-search">
<ul class="jqm-list" data-filter-placeholder="Search demos..." data-filter-reveal="true">
<li data-filtertext="demos homepage" data-icon="home"><a href=".././">Home</a></li>
<li data-filtertext="introduction overview getting started"><a href="../intro/" data-ajax="false">Introduction</a></li>
<li data-filtertext="buttons button markup buttonmarkup method anchor link button element"><a href="../button-markup/" data-ajax="false">Buttons</a></li>
<li data-filtertext="form button widget input button submit reset"><a href="../button/" data-ajax="false">Button widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Checkboxradio widget</h3>
<ul>
<li data-filtertext="form checkboxradio widget checkbox input checkboxes controlgroups"><a href="../checkboxradio-checkbox/" data-ajax="false">Checkboxes</a></li>
<li data-filtertext="form checkboxradio widget radio input radio buttons controlgroups"><a href="../checkboxradio-radio/" data-ajax="false">Radio buttons</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Collapsible (set) widget</h3>
<ul>
<li data-filtertext="collapsibles content formatting"><a href="../collapsible/" data-ajax="false">Collapsible</a></li>
<li data-filtertext="dynamic collapsible set accordion append expand"><a href="../collapsible-dynamic/" data-ajax="false">Dynamic collapsibles</a></li>
<li data-filtertext="accordions collapsible set widget content formatting grouped collapsibles"><a href="../collapsibleset/" data-ajax="false">Collapsible set</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Controlgroup widget</h3>
<ul>
<li data-filtertext="controlgroups selectmenu checkboxradio input grouped buttons horizontal vertical"><a href="../controlgroup/" data-ajax="false">Controlgroup</a></li>
<li data-filtertext="dynamic controlgroup dynamically add buttons"><a href="../controlgroup-dynamic/" data-ajax="false">Dynamic controlgroups</a></li>
</ul>
</li>
<li data-filtertext="form datepicker widget date input"><a href="../datepicker/" data-ajax="false">Datepicker</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Events</h3>
<ul>
<li data-filtertext="swipe to delete list items listviews swipe events"><a href="../swipe-list/" data-ajax="false">Swipe list items</a></li>
<li data-filtertext="swipe to navigate swipe page navigation swipe events"><a href="../swipe-page/" data-ajax="false">Swipe page navigation</a></li>
</ul>
</li>
<li data-filtertext="filterable filter elements sorting searching listview table"><a href="../filterable/" data-ajax="false">Filterable widget</a></li>
<li data-filtertext="form flipswitch widget flip toggle switch binary select checkbox input"><a href="../flipswitch/" data-ajax="false">Flipswitch widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Forms</h3>
<ul>
<li data-filtertext="forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms/" data-ajax="false">Forms</a></li>
<li data-filtertext="form hide labels hidden accessible ui-hidden-accessible forms"><a href="../forms-label-hidden-accessible/" data-ajax="false">Hide labels</a></li>
<li data-filtertext="form field containers fieldcontain ui-field-contain forms"><a href="../forms-field-contain/" data-ajax="false">Field containers</a></li>
<li data-filtertext="forms disabled form elements"><a href="../forms-disabled/" data-ajax="false">Forms disabled</a></li>
<li data-filtertext="forms gallery examples overview forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms-gallery/" data-ajax="false">Forms gallery</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Grids</h3>
<ul>
<li data-filtertext="grids columns blocks content formatting rwd responsive css framework"><a href="../grids/" data-ajax="false">Grids</a></li>
<li data-filtertext="buttons in grids css framework"><a href="../grids-buttons/" data-ajax="false">Buttons in grids</a></li>
<li data-filtertext="custom responsive grids rwd css framework"><a href="../grids-custom-responsive/" data-ajax="false">Custom responsive grids</a></li>
</ul>
</li>
<li data-filtertext="blocks content formatting sections heading"><a href="../body-bar-classes/" data-ajax="false">Grouping and dividing content</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Icons</h3>
<ul>
<li data-filtertext="button icons svg disc alt custom icon position"><a href="../icons/" data-ajax="false">Icons</a></li>
<li data-filtertext=""><a href="../icons-grunticon/" data-ajax="false">Grunticon loader</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Listview widget</h3>
<ul>
<li data-filtertext="listview widget thumbnails icons nested split button collapsible ul ol"><a href="../listview/" data-ajax="false">Listview</a></li>
<li data-filtertext="autocomplete filterable reveal listview filtertextbeforefilter placeholder"><a href="../listview-autocomplete/" data-ajax="false">Listview autocomplete</a></li>
<li data-filtertext="autocomplete filterable reveal listview remote data filtertextbeforefilter placeholder"><a href="../listview-autocomplete-remote/" data-ajax="false">Listview autocomplete remote data</a></li>
<li data-filtertext="autodividers anchor jump scroll linkbars listview lists ul ol"><a href="../listview-autodividers-linkbar/" data-ajax="false">Listview autodividers linkbar</a></li>
<li data-filtertext="listview autodividers selector autodividersselector lists ul ol"><a href="../listview-autodividers-selector/" data-ajax="false">Listview autodividers selector</a></li>
<li data-filtertext="listview nested list items"><a href="../listview-nested-lists/" data-ajax="false">Listview Nested Listviews</a></li>
<li data-filtertext="listview collapsible list items flat"><a href="../listview-collapsible-item-flat/" data-ajax="false">Listview collapsible list items (flat)</a></li>
<li data-filtertext="listview collapsible list indented"><a href="../listview-collapsible-item-indented/" data-ajax="false">Listview collapsible list items (indented)</a></li>
<li data-filtertext="grid listview responsive grids responsive listviews lists ul"><a href="../listview-grid/" data-ajax="false">Listview responsive grid</a></li>
</ul>
</li>
<li data-filtertext="loader widget page loading navigation overlay spinner"><a href="../loader/" data-ajax="false">Loader widget</a></li>
<li data-filtertext="navbar widget navmenu toolbars header footer"><a href="../navbar/" data-ajax="false">Navbar widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Navigation</h3>
<ul>
<li data-filtertext="ajax navigation navigate widget history event method"><a href="../navigation/" data-ajax="false">Navigation</a></li>
<li data-filtertext="linking pages page links navigation ajax prefetch cache"><a href="../navigation-linking-pages/" data-ajax="false">Linking pages</a></li>
<li data-filtertext="php redirect server redirection server-side navigation"><a href="../navigation-php-redirect/" data-ajax="false">PHP redirect demo</a></li>
<li data-filtertext="navigation redirection hash query"><a href="../navigation-hash-processing/" data-ajax="false">Hash processing demo</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Pages</h3>
<ul>
<li data-filtertext="pages page widget ajax navigation"><a href="../pages/" data-ajax="false">Pages</a></li>
<li data-filtertext="single page"><a href="../pages-single-page/" data-ajax="false">Single page</a></li>
<li data-filtertext="multipage multi-page page"><a href="../pages-multi-page/" data-ajax="false">Multi-page template</a></li>
<li data-filtertext="dialog page widget modal popup"><a href="../pages-dialog/" data-ajax="false">Dialog page</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Panel widget</h3>
<ul>
<li data-filtertext="panel widget sliding panels reveal push overlay responsive"><a href="../panel/" data-ajax="false">Panel</a></li>
<li data-filtertext=""><a href="../panel-external/" data-ajax="false">External panels</a></li>
<li data-filtertext="panel "><a href="../panel-fixed/" data-ajax="false">Fixed panels</a></li>
<li data-filtertext="panel slide panels sliding panels shadow rwd responsive breakpoint"><a href="../panel-responsive/" data-ajax="false">Panels responsive</a></li>
<li data-filtertext="panel custom style custom panel width reveal shadow listview panel styling page background wrapper"><a href="../panel-styling/" data-ajax="false">Custom panel style</a></li>
<li data-filtertext="panel open on swipe"><a href="../panel-swipe-open/" data-ajax="false">Panel open on swipe</a></li>
<li data-filtertext="panels outside page internal external toolbars"><a href="../panel-external-internal/" data-ajax="false">Panel external and internal</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Popup widget</h3>
<ul>
<li data-filtertext="popup widget popups dialog modal transition tooltip lightbox form overlay screen flip pop fade transition"><a href="../popup/" data-ajax="false">Popup</a></li>
<li data-filtertext="popup alignment position"><a href="../popup-alignment/" data-ajax="false">Popup alignment</a></li>
<li data-filtertext="popup arrow size popups popover"><a href="../popup-arrow-size/" data-ajax="false">Popup arrow size</a></li>
<li data-filtertext="dynamic popups popup images lightbox"><a href="../popup-dynamic/" data-ajax="false">Dynamic popups</a></li>
<li data-filtertext="popups with iframes scaling"><a href="../popup-iframe/" data-ajax="false">Popups with iframes</a></li>
<li data-filtertext="popup image scaling"><a href="../popup-image-scaling/" data-ajax="false">Popup image scaling</a></li>
<li data-filtertext="external popup outside multi-page"><a href="../popup-outside-multipage" data-ajax="false">Popup outside multi-page</a></li>
</ul>
</li>
<li data-filtertext="form rangeslider widget dual sliders dual handle sliders range input"><a href="../rangeslider/" data-ajax="false">Rangeslider widget</a></li>
<li data-filtertext="responsive web design rwd adaptive progressive enhancement PE accessible mobile breakpoints media query media queries"><a href="../rwd/" data-ajax="false">Responsive Web Design</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Selectmenu widget</h3>
<ul>
<li data-filtertext="form selectmenu widget select input custom select menu selects"><a href="../selectmenu/" data-ajax="false">Selectmenu</a></li>
<li data-filtertext="form custom select menu selectmenu widget custom menu option optgroup multiple selects"><a href="../selectmenu-custom/" data-ajax="false">Custom select menu</a></li>
<li data-filtertext="filterable select filter popup dialog"><a href="../selectmenu-custom-filter/" data-ajax="false">Custom select menu with filter</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Slider widget</h3>
<ul>
<li data-filtertext="form slider widget range input single sliders"><a href="../slider/" data-ajax="false">Slider</a></li>
<li data-filtertext="form slider widget flipswitch slider binary select flip toggle switch"><a href="../slider-flipswitch/" data-ajax="false">Slider flip toggle switch</a></li>
<li data-filtertext="form slider tooltip handle value input range sliders"><a href="../slider-tooltip/" data-ajax="false">Slider tooltip</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Table widget</h3>
<ul>
<li data-filtertext="table widget reflow column toggle th td responsive tables rwd hide show tabular"><a href="../table-column-toggle/" data-ajax="false">Table Column Toggle</a></li>
<li data-filtertext="table column toggle phone comparison demo"><a href="../table-column-toggle-example/" data-ajax="false">Table Column Toggle demo</a></li>
<li data-filtertext="responsive tables table column toggle heading groups rwd breakpoint"><a href="../table-column-toggle-heading-groups/" data-ajax="false">Table Column Toggle heading groups</a></li>
<li data-filtertext="responsive tables table column toggle hide rwd breakpoint customization options"><a href="../table-column-toggle-options/" data-ajax="false">Table Column Toggle options</a></li>
<li data-filtertext="table reflow th td responsive rwd columns tabular"><a href="../table-reflow/" data-ajax="false">Table Reflow</a></li>
<li data-filtertext="responsive tables table reflow heading groups rwd breakpoint"><a href="../table-reflow-heading-groups/" data-ajax="false">Table Reflow heading groups</a></li>
<li data-filtertext="responsive tables table reflow stripes strokes table style"><a href="../table-reflow-stripes-strokes/" data-ajax="false">Table Reflow stripes and strokes</a></li>
<li data-filtertext="responsive tables table reflow stack custom styles"><a href="../table-reflow-styling/" data-ajax="false">Table Reflow custom styles</a></li>
</ul>
</li>
<li data-filtertext="ui tabs widget"><a href="../tabs/" data-ajax="false">Tabs widget</a></li>
<li data-filtertext="form textinput widget text input textarea number date time tel email file color password"><a href="../textinput/" data-ajax="false">Textinput widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Theming</h3>
<ul>
<li data-filtertext="default theme swatches theming style css"><a href="../theme-default/" data-ajax="false">Default theme</a></li>
<li data-filtertext="classic theme old theme swatches theming style css"><a href="../theme-classic/" data-ajax="false">Classic theme</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Toolbar widget</h3>
<ul>
<li data-filtertext="toolbar widget header footer toolbars fixed fullscreen external sections"><a href="../toolbar/" data-ajax="false">Toolbar</a></li>
<li data-filtertext="dynamic toolbars dynamically add toolbar header footer"><a href="../toolbar-dynamic/" data-ajax="false">Dynamic toolbars</a></li>
<li data-filtertext="external toolbars header footer"><a href="../toolbar-external/" data-ajax="false">External toolbars</a></li>
<li data-filtertext="fixed toolbars header footer"><a href="../toolbar-fixed/" data-ajax="false">Fixed toolbars</a></li>
<li data-filtertext="fixed fullscreen toolbars header footer"><a href="../toolbar-fixed-fullscreen/" data-ajax="false">Fullscreen toolbars</a></li>
<li data-filtertext="external fixed toolbars header footer"><a href="../toolbar-fixed-external/" data-ajax="false">Fixed external toolbars</a></li>
<li data-filtertext="external persistent toolbars header footer navbar navmenu"><a href="../toolbar-fixed-persistent/" data-ajax="false">Persistent toolbars</a></li>
<li data-filtertext="external ajax optimized toolbars persistent toolbars header footer navbar"><a href="../toolbar-fixed-persistent-optimized/" data-ajax="false">Ajax optimized toolbars</a></li>
<li data-filtertext="form in toolbars header footer"><a href="../toolbar-fixed-forms/" data-ajax="false">Form in toolbar</a></li>
</ul>
</li>
<li data-filtertext="page transitions animated pages popup navigation flip slide fade pop"><a href="../transitions/" data-ajax="false">Transitions</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>3rd party API demos</h3>
<ul>
<li data-filtertext="backbone requirejs navigation router"><a href="../backbone-requirejs/" data-ajax="false">Backbone RequireJS</a></li>
<li data-filtertext="google maps geolocation demo"><a href="../map-geolocation/" data-ajax="false">Google Maps geolocation</a></li>
<li data-filtertext="google maps hybrid"><a href="../map-list-toggle/" data-ajax="false">Google Maps list toggle</a></li>
</ul>
</li>
</ul>
</div>
</div><!-- /panel -->
</div><!-- /page -->
</body>
</html>

View File

@ -0,0 +1,83 @@
<!doctype html>
<html class="no-js ui-mobile-rendering" lang="en">
<head>
<title>Backbone.js, Require.js, and jQuery Mobile</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../css/themes/default/jquery.mobile-1.4.2.min.css">
<script src="//rawgithub.com/jrburke/requirejs/2.1.8/require.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div id="categories" data-role="page" data-title="Categories">
<div data-role="header">
<h1>Categories</h1>
</div><!-- /header -->
<div role="main" class="ui-content">
<h2>Select a Category Below:</h2>
<ul data-role="listview" data-inset="true">
<li><a href="#category?animals" class="animals">Animals</a></li>
<li><a href="#category?colors" class="colors">Colors</a></li>
<li><a href="#category?vehicles" class="vehicles">Vehicles</a></li>
</ul>
</div><!-- /content -->
</div>
<div id="animals" data-role="page" data-title="Animals">
<div data-role="header">
<h1>Animals</h1>
</div><!-- /header -->
<div role="main" class="ui-content">
<ul data-role="listview" data-inset="true">
</ul>
</div><!-- /content -->
</div>
<div id="colors" data-role="page" data-title="Colors">
<div data-role="header">
<h1>Colors</h1>
</div><!-- /header -->
<div role="main" class="ui-content">
<ul data-role="listview" data-inset="true">
</ul>
</div><!-- /content -->
</div>
<div id="vehicles" data-role="page" data-title="Vehicles">
<div data-role="header">
<h1>Vehicles</h1>
</div><!-- /header -->
<div role="main" class="ui-content">
<ul data-role="listview" data-inset="true">
</ul>
</div><!-- /content -->
</div>
<!-- Underscore Template that is used to display all of the Category Models -->
<script id="categoryItems" type="text/template">
<% _.each( collection.toJSON(), function( category, id ) { %>
<li class="ui-li-static">
<%= category.type %>
</li>
<% }); %>
</script>
</body>
</html>

View File

@ -0,0 +1,541 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile - Backbone.js and Require.js Apps</title>
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:300,400,700">
<link rel="stylesheet" href="../css/themes/default/jquery.mobile-1.4.2.min.css">
<link rel="stylesheet" href="../_assets/css/jqm-demos.css">
<script src="../js/jquery.js"></script>
<script src="../_assets/js/index.js"></script>
<script src="../js/jquery.mobile-1.4.2.min.js"></script>
</head>
<body>
<div data-role="page" class="jqm-demos" data-quicklinks="true">
<div data-role="header" class="jqm-header">
<h2><a href="../" title="jQuery Mobile Demos home"><img src="../_assets/img/jquery-logo.png" alt="jQuery Mobile"></a></h2>
<p><span class="jqm-version"></span> Demos</p>
<a href="#" class="jqm-navmenu-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-bars ui-nodisc-icon ui-alt-icon ui-btn-left">Menu</a>
<a href="#" class="jqm-search-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-search ui-nodisc-icon ui-alt-icon ui-btn-right">Search</a>
</div><!-- /header -->
<div role="main" class="ui-content jqm-content">
<h1>jQuery Mobile, Backbone.js and Require.js</h1>
<p>jQuery Mobile provides an <strong>HTML5-based user interface for all popular mobile device platforms</strong>, but it does not influence how you organize and structure your app's JavaScript. Many jQuery Mobile users turn to a variety of other popular third-party libraries, including MV* frameworks and dependency management tools, to help structure their code.
</p>
<h2>Backbone and Require.js</h2>
<p><strong>Backbone.js</strong> and <strong>Require.js</strong> are two of the most popular third-party libraries that are used with jQuery Mobile to provide a rich JavaScript tech stack for developers.
</p>
<p><strong>Backbone.js</strong> is a great client-side MV* JavaScript framework that provides structure to JavaScript applications by providing View, Model, Collection, Router, and Event class objects.
</p>
<p><strong>Require.js</strong> serves a few different purposes than Backbone.js. Require.js is an AMD (Asynchronous Module Definition) script loader that asynchronously loads your JavaScript to improve page load performance, while also helping with script dependency managagement and allowing you to organize your JavaScript into self contained modules (files).
</p>
<p>Although there is a high amount of developer interest with using jQuery Mobile, Backbone.js, and Require.js together, there is a high barrier of entry. Many users are confused about how to use the Backbone.js Router class object with the jQuery Mobile routing system.</p>
<a href="backbone-require.html" rel="external" class="ui-btn ui-btn-inline ui-corner-all ui-shadow ui-btn-icon-right ui-icon-carat-r">View example page</a>
<h2>jQuery Mobile configuration</h2>
<p>The technique used in this <a href="backbone-require.html" rel="external">example page</a> is by no means the only technique available, but it is one of the most elegant. The Backbone.js router is used exclusively to handle all hashchange events, and the jQuery Mobile <code>$.mobile.changePage()</code> method is used to programmatically change the page.</p>
<p>Below are two internal jQuery Mobile properties that are turned off to allow this to happen:</p>
<ul>
<li><code>$.mobile.linkBindingEnabled</code>
<ul>
<li>jQuery Mobile will automatically bind the clicks on anchor tags in your document. Setting this option to false will prevent all anchor click handling including the addition of active button state and alternate link blurring. This should only be used when attempting to delegate the click management to another library or custom code.</li>
</ul>
</li>
<li><code>$.mobile.hashListeningEnabled</code>
<ul>
<li>jQuery Mobile will automatically listen and handle changes to the location.hash. Disabling this will prevent jQuery Mobile from handling hash changes, which allows you to handle them yourself or use simple deep-links within a document that scroll to a particular id.</li>
</ul>
</li>
</ul>
</p>
<h2>Example page code</h2>
<p>To illustrate how the above internal jQuery Mobile properties are turned off, let's examine our example page code.</p>
<p>Inside of the <em>head</em> section of our <strong>index.html</strong> page, we first include the Require.js JavaScript library and set the <strong>data-main</strong> attribute of our script tag to the JavaScript file that we want Require.js to include on the page first (this file will contain all of our Require.js configurations). In this example, we are telling Require.js to look inside of the js folder and then load <strong>mobile.js</strong>.
</p>
<code>
&lt;head&gt;
&lt;script src=&quot;js/libs/require.js&quot; data-main=&quot;js/mobile&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
</code>
<p>If we look inside of <strong>mobile.js</strong>, we will find that the <code>$.mobile.linkBindingEnabled</code> and <code>$.mobile.hashListeningEnabled</code> jQuery Mobile attributes are set to false.
</p>
<pre>
<code>
// Sets the require.js configuration for your application.
require.config( {
// 3rd party script alias names
paths: {
// Core Libraries
"jquery": "../../../js/jquery",
"jquerymobile": "libs/jquerymobile",
"underscore": "libs/lodash",
"backbone": "libs/backbone"
},
// Sets the configuration for your third party scripts that are not AMD compatible
shim: {
"backbone": {
"deps": [ "underscore", "jquery" ],
"exports": "Backbone" //attaches "Backbone" to the window object
}
} // end Shim Configuration
} );
// Includes File Dependencies
require([ "jquery","backbone","routers/mobileRouter","jquerymobile" ], function( $, Backbone, Mobile ) {
// Prevents all anchor click handling
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
// Instantiates a new Backbone.js Mobile Router
this.router = new Mobile();
} );
</code>
</pre>
<p>Next, inside of the Backbone.js Router class object, we can respond to haschange events and manually call the jQuery Mobile <code>changePage()</code> method. Below is a small snippet of <strong>mobileRouter.js</strong>.</p>
<pre>
<code>
// Backbone.js Routes
routes: {
// When there is no hash bang on the url, the home method is called
"": "home",
// When #category? is on the url, the category method is called
"category?:type": "category"
},
// Home method
home: function() {
// Programatically changes to the categories page
$.mobile.changePage( "#categories" , { reverse: false, changeHash: false } );
}
</code>
</pre>
<p>The <a href="backbone-require.html" rel="external">example page</a> illustrates how to render a jQuery Mobile ListView that is populated with dynamic JSON data asynchronously. Feel free to take a deeper look into the source code to see how Require.js and Backbone.js are used.</p>
</div><!-- /content -->
<div data-role="panel" class="jqm-navmenu-panel" data-position="left" data-display="overlay" data-theme="a">
<ul class="jqm-list ui-alt-icon ui-nodisc-icon">
<li data-filtertext="demos homepage" data-icon="home"><a href=".././">Home</a></li>
<li data-filtertext="introduction overview getting started"><a href="../intro/" data-ajax="false">Introduction</a></li>
<li data-filtertext="buttons button markup buttonmarkup method anchor link button element"><a href="../button-markup/" data-ajax="false">Buttons</a></li>
<li data-filtertext="form button widget input button submit reset"><a href="../button/" data-ajax="false">Button widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Checkboxradio widget</h3>
<ul>
<li data-filtertext="form checkboxradio widget checkbox input checkboxes controlgroups"><a href="../checkboxradio-checkbox/" data-ajax="false">Checkboxes</a></li>
<li data-filtertext="form checkboxradio widget radio input radio buttons controlgroups"><a href="../checkboxradio-radio/" data-ajax="false">Radio buttons</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Collapsible (set) widget</h3>
<ul>
<li data-filtertext="collapsibles content formatting"><a href="../collapsible/" data-ajax="false">Collapsible</a></li>
<li data-filtertext="dynamic collapsible set accordion append expand"><a href="../collapsible-dynamic/" data-ajax="false">Dynamic collapsibles</a></li>
<li data-filtertext="accordions collapsible set widget content formatting grouped collapsibles"><a href="../collapsibleset/" data-ajax="false">Collapsible set</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Controlgroup widget</h3>
<ul>
<li data-filtertext="controlgroups selectmenu checkboxradio input grouped buttons horizontal vertical"><a href="../controlgroup/" data-ajax="false">Controlgroup</a></li>
<li data-filtertext="dynamic controlgroup dynamically add buttons"><a href="../controlgroup-dynamic/" data-ajax="false">Dynamic controlgroups</a></li>
</ul>
</li>
<li data-filtertext="form datepicker widget date input"><a href="../datepicker/" data-ajax="false">Datepicker</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Events</h3>
<ul>
<li data-filtertext="swipe to delete list items listviews swipe events"><a href="../swipe-list/" data-ajax="false">Swipe list items</a></li>
<li data-filtertext="swipe to navigate swipe page navigation swipe events"><a href="../swipe-page/" data-ajax="false">Swipe page navigation</a></li>
</ul>
</li>
<li data-filtertext="filterable filter elements sorting searching listview table"><a href="../filterable/" data-ajax="false">Filterable widget</a></li>
<li data-filtertext="form flipswitch widget flip toggle switch binary select checkbox input"><a href="../flipswitch/" data-ajax="false">Flipswitch widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Forms</h3>
<ul>
<li data-filtertext="forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms/" data-ajax="false">Forms</a></li>
<li data-filtertext="form hide labels hidden accessible ui-hidden-accessible forms"><a href="../forms-label-hidden-accessible/" data-ajax="false">Hide labels</a></li>
<li data-filtertext="form field containers fieldcontain ui-field-contain forms"><a href="../forms-field-contain/" data-ajax="false">Field containers</a></li>
<li data-filtertext="forms disabled form elements"><a href="../forms-disabled/" data-ajax="false">Forms disabled</a></li>
<li data-filtertext="forms gallery examples overview forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms-gallery/" data-ajax="false">Forms gallery</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Grids</h3>
<ul>
<li data-filtertext="grids columns blocks content formatting rwd responsive css framework"><a href="../grids/" data-ajax="false">Grids</a></li>
<li data-filtertext="buttons in grids css framework"><a href="../grids-buttons/" data-ajax="false">Buttons in grids</a></li>
<li data-filtertext="custom responsive grids rwd css framework"><a href="../grids-custom-responsive/" data-ajax="false">Custom responsive grids</a></li>
</ul>
</li>
<li data-filtertext="blocks content formatting sections heading"><a href="../body-bar-classes/" data-ajax="false">Grouping and dividing content</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Icons</h3>
<ul>
<li data-filtertext="button icons svg disc alt custom icon position"><a href="../icons/" data-ajax="false">Icons</a></li>
<li data-filtertext=""><a href="../icons-grunticon/" data-ajax="false">Grunticon loader</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Listview widget</h3>
<ul>
<li data-filtertext="listview widget thumbnails icons nested split button collapsible ul ol"><a href="../listview/" data-ajax="false">Listview</a></li>
<li data-filtertext="autocomplete filterable reveal listview filtertextbeforefilter placeholder"><a href="../listview-autocomplete/" data-ajax="false">Listview autocomplete</a></li>
<li data-filtertext="autocomplete filterable reveal listview remote data filtertextbeforefilter placeholder"><a href="../listview-autocomplete-remote/" data-ajax="false">Listview autocomplete remote data</a></li>
<li data-filtertext="autodividers anchor jump scroll linkbars listview lists ul ol"><a href="../listview-autodividers-linkbar/" data-ajax="false">Listview autodividers linkbar</a></li>
<li data-filtertext="listview autodividers selector autodividersselector lists ul ol"><a href="../listview-autodividers-selector/" data-ajax="false">Listview autodividers selector</a></li>
<li data-filtertext="listview nested list items"><a href="../listview-nested-lists/" data-ajax="false">Listview Nested Listviews</a></li>
<li data-filtertext="listview collapsible list items flat"><a href="../listview-collapsible-item-flat/" data-ajax="false">Listview collapsible list items (flat)</a></li>
<li data-filtertext="listview collapsible list indented"><a href="../listview-collapsible-item-indented/" data-ajax="false">Listview collapsible list items (indented)</a></li>
<li data-filtertext="grid listview responsive grids responsive listviews lists ul"><a href="../listview-grid/" data-ajax="false">Listview responsive grid</a></li>
</ul>
</li>
<li data-filtertext="loader widget page loading navigation overlay spinner"><a href="../loader/" data-ajax="false">Loader widget</a></li>
<li data-filtertext="navbar widget navmenu toolbars header footer"><a href="../navbar/" data-ajax="false">Navbar widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Navigation</h3>
<ul>
<li data-filtertext="ajax navigation navigate widget history event method"><a href="../navigation/" data-ajax="false">Navigation</a></li>
<li data-filtertext="linking pages page links navigation ajax prefetch cache"><a href="../navigation-linking-pages/" data-ajax="false">Linking pages</a></li>
<li data-filtertext="php redirect server redirection server-side navigation"><a href="../navigation-php-redirect/" data-ajax="false">PHP redirect demo</a></li>
<li data-filtertext="navigation redirection hash query"><a href="../navigation-hash-processing/" data-ajax="false">Hash processing demo</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Pages</h3>
<ul>
<li data-filtertext="pages page widget ajax navigation"><a href="../pages/" data-ajax="false">Pages</a></li>
<li data-filtertext="single page"><a href="../pages-single-page/" data-ajax="false">Single page</a></li>
<li data-filtertext="multipage multi-page page"><a href="../pages-multi-page/" data-ajax="false">Multi-page template</a></li>
<li data-filtertext="dialog page widget modal popup"><a href="../pages-dialog/" data-ajax="false">Dialog page</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Panel widget</h3>
<ul>
<li data-filtertext="panel widget sliding panels reveal push overlay responsive"><a href="../panel/" data-ajax="false">Panel</a></li>
<li data-filtertext=""><a href="../panel-external/" data-ajax="false">External panels</a></li>
<li data-filtertext="panel "><a href="../panel-fixed/" data-ajax="false">Fixed panels</a></li>
<li data-filtertext="panel slide panels sliding panels shadow rwd responsive breakpoint"><a href="../panel-responsive/" data-ajax="false">Panels responsive</a></li>
<li data-filtertext="panel custom style custom panel width reveal shadow listview panel styling page background wrapper"><a href="../panel-styling/" data-ajax="false">Custom panel style</a></li>
<li data-filtertext="panel open on swipe"><a href="../panel-swipe-open/" data-ajax="false">Panel open on swipe</a></li>
<li data-filtertext="panels outside page internal external toolbars"><a href="../panel-external-internal/" data-ajax="false">Panel external and internal</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Popup widget</h3>
<ul>
<li data-filtertext="popup widget popups dialog modal transition tooltip lightbox form overlay screen flip pop fade transition"><a href="../popup/" data-ajax="false">Popup</a></li>
<li data-filtertext="popup alignment position"><a href="../popup-alignment/" data-ajax="false">Popup alignment</a></li>
<li data-filtertext="popup arrow size popups popover"><a href="../popup-arrow-size/" data-ajax="false">Popup arrow size</a></li>
<li data-filtertext="dynamic popups popup images lightbox"><a href="../popup-dynamic/" data-ajax="false">Dynamic popups</a></li>
<li data-filtertext="popups with iframes scaling"><a href="../popup-iframe/" data-ajax="false">Popups with iframes</a></li>
<li data-filtertext="popup image scaling"><a href="../popup-image-scaling/" data-ajax="false">Popup image scaling</a></li>
<li data-filtertext="external popup outside multi-page"><a href="../popup-outside-multipage" data-ajax="false">Popup outside multi-page</a></li>
</ul>
</li>
<li data-filtertext="form rangeslider widget dual sliders dual handle sliders range input"><a href="../rangeslider/" data-ajax="false">Rangeslider widget</a></li>
<li data-filtertext="responsive web design rwd adaptive progressive enhancement PE accessible mobile breakpoints media query media queries"><a href="../rwd/" data-ajax="false">Responsive Web Design</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Selectmenu widget</h3>
<ul>
<li data-filtertext="form selectmenu widget select input custom select menu selects"><a href="../selectmenu/" data-ajax="false">Selectmenu</a></li>
<li data-filtertext="form custom select menu selectmenu widget custom menu option optgroup multiple selects"><a href="../selectmenu-custom/" data-ajax="false">Custom select menu</a></li>
<li data-filtertext="filterable select filter popup dialog"><a href="../selectmenu-custom-filter/" data-ajax="false">Custom select menu with filter</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Slider widget</h3>
<ul>
<li data-filtertext="form slider widget range input single sliders"><a href="../slider/" data-ajax="false">Slider</a></li>
<li data-filtertext="form slider widget flipswitch slider binary select flip toggle switch"><a href="../slider-flipswitch/" data-ajax="false">Slider flip toggle switch</a></li>
<li data-filtertext="form slider tooltip handle value input range sliders"><a href="../slider-tooltip/" data-ajax="false">Slider tooltip</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Table widget</h3>
<ul>
<li data-filtertext="table widget reflow column toggle th td responsive tables rwd hide show tabular"><a href="../table-column-toggle/" data-ajax="false">Table Column Toggle</a></li>
<li data-filtertext="table column toggle phone comparison demo"><a href="../table-column-toggle-example/" data-ajax="false">Table Column Toggle demo</a></li>
<li data-filtertext="responsive tables table column toggle heading groups rwd breakpoint"><a href="../table-column-toggle-heading-groups/" data-ajax="false">Table Column Toggle heading groups</a></li>
<li data-filtertext="responsive tables table column toggle hide rwd breakpoint customization options"><a href="../table-column-toggle-options/" data-ajax="false">Table Column Toggle options</a></li>
<li data-filtertext="table reflow th td responsive rwd columns tabular"><a href="../table-reflow/" data-ajax="false">Table Reflow</a></li>
<li data-filtertext="responsive tables table reflow heading groups rwd breakpoint"><a href="../table-reflow-heading-groups/" data-ajax="false">Table Reflow heading groups</a></li>
<li data-filtertext="responsive tables table reflow stripes strokes table style"><a href="../table-reflow-stripes-strokes/" data-ajax="false">Table Reflow stripes and strokes</a></li>
<li data-filtertext="responsive tables table reflow stack custom styles"><a href="../table-reflow-styling/" data-ajax="false">Table Reflow custom styles</a></li>
</ul>
</li>
<li data-filtertext="ui tabs widget"><a href="../tabs/" data-ajax="false">Tabs widget</a></li>
<li data-filtertext="form textinput widget text input textarea number date time tel email file color password"><a href="../textinput/" data-ajax="false">Textinput widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Theming</h3>
<ul>
<li data-filtertext="default theme swatches theming style css"><a href="../theme-default/" data-ajax="false">Default theme</a></li>
<li data-filtertext="classic theme old theme swatches theming style css"><a href="../theme-classic/" data-ajax="false">Classic theme</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Toolbar widget</h3>
<ul>
<li data-filtertext="toolbar widget header footer toolbars fixed fullscreen external sections"><a href="../toolbar/" data-ajax="false">Toolbar</a></li>
<li data-filtertext="dynamic toolbars dynamically add toolbar header footer"><a href="../toolbar-dynamic/" data-ajax="false">Dynamic toolbars</a></li>
<li data-filtertext="external toolbars header footer"><a href="../toolbar-external/" data-ajax="false">External toolbars</a></li>
<li data-filtertext="fixed toolbars header footer"><a href="../toolbar-fixed/" data-ajax="false">Fixed toolbars</a></li>
<li data-filtertext="fixed fullscreen toolbars header footer"><a href="../toolbar-fixed-fullscreen/" data-ajax="false">Fullscreen toolbars</a></li>
<li data-filtertext="external fixed toolbars header footer"><a href="../toolbar-fixed-external/" data-ajax="false">Fixed external toolbars</a></li>
<li data-filtertext="external persistent toolbars header footer navbar navmenu"><a href="../toolbar-fixed-persistent/" data-ajax="false">Persistent toolbars</a></li>
<li data-filtertext="external ajax optimized toolbars persistent toolbars header footer navbar"><a href="../toolbar-fixed-persistent-optimized/" data-ajax="false">Ajax optimized toolbars</a></li>
<li data-filtertext="form in toolbars header footer"><a href="../toolbar-fixed-forms/" data-ajax="false">Form in toolbar</a></li>
</ul>
</li>
<li data-filtertext="page transitions animated pages popup navigation flip slide fade pop"><a href="../transitions/" data-ajax="false">Transitions</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>3rd party API demos</h3>
<ul>
<li data-filtertext="backbone requirejs navigation router"><a href="../backbone-requirejs/" data-ajax="false">Backbone RequireJS</a></li>
<li data-filtertext="google maps geolocation demo"><a href="../map-geolocation/" data-ajax="false">Google Maps geolocation</a></li>
<li data-filtertext="google maps hybrid"><a href="../map-list-toggle/" data-ajax="false">Google Maps list toggle</a></li>
</ul>
</li>
</ul>
</div><!-- /panel -->
<div data-role="footer" data-position="fixed" data-tap-toggle="false" class="jqm-footer">
<p>jQuery Mobile Demos version <span class="jqm-version"></span></p>
<p>Copyright 2014 The jQuery Foundation</p>
</div><!-- /footer -->
<!-- TODO: This should become an external panel so we can add input to markup (unique ID) -->
<div data-role="panel" class="jqm-search-panel" data-position="right" data-display="overlay" data-theme="a">
<div class="jqm-search">
<ul class="jqm-list" data-filter-placeholder="Search demos..." data-filter-reveal="true">
<li data-filtertext="demos homepage" data-icon="home"><a href=".././">Home</a></li>
<li data-filtertext="introduction overview getting started"><a href="../intro/" data-ajax="false">Introduction</a></li>
<li data-filtertext="buttons button markup buttonmarkup method anchor link button element"><a href="../button-markup/" data-ajax="false">Buttons</a></li>
<li data-filtertext="form button widget input button submit reset"><a href="../button/" data-ajax="false">Button widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Checkboxradio widget</h3>
<ul>
<li data-filtertext="form checkboxradio widget checkbox input checkboxes controlgroups"><a href="../checkboxradio-checkbox/" data-ajax="false">Checkboxes</a></li>
<li data-filtertext="form checkboxradio widget radio input radio buttons controlgroups"><a href="../checkboxradio-radio/" data-ajax="false">Radio buttons</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Collapsible (set) widget</h3>
<ul>
<li data-filtertext="collapsibles content formatting"><a href="../collapsible/" data-ajax="false">Collapsible</a></li>
<li data-filtertext="dynamic collapsible set accordion append expand"><a href="../collapsible-dynamic/" data-ajax="false">Dynamic collapsibles</a></li>
<li data-filtertext="accordions collapsible set widget content formatting grouped collapsibles"><a href="../collapsibleset/" data-ajax="false">Collapsible set</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Controlgroup widget</h3>
<ul>
<li data-filtertext="controlgroups selectmenu checkboxradio input grouped buttons horizontal vertical"><a href="../controlgroup/" data-ajax="false">Controlgroup</a></li>
<li data-filtertext="dynamic controlgroup dynamically add buttons"><a href="../controlgroup-dynamic/" data-ajax="false">Dynamic controlgroups</a></li>
</ul>
</li>
<li data-filtertext="form datepicker widget date input"><a href="../datepicker/" data-ajax="false">Datepicker</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Events</h3>
<ul>
<li data-filtertext="swipe to delete list items listviews swipe events"><a href="../swipe-list/" data-ajax="false">Swipe list items</a></li>
<li data-filtertext="swipe to navigate swipe page navigation swipe events"><a href="../swipe-page/" data-ajax="false">Swipe page navigation</a></li>
</ul>
</li>
<li data-filtertext="filterable filter elements sorting searching listview table"><a href="../filterable/" data-ajax="false">Filterable widget</a></li>
<li data-filtertext="form flipswitch widget flip toggle switch binary select checkbox input"><a href="../flipswitch/" data-ajax="false">Flipswitch widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Forms</h3>
<ul>
<li data-filtertext="forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms/" data-ajax="false">Forms</a></li>
<li data-filtertext="form hide labels hidden accessible ui-hidden-accessible forms"><a href="../forms-label-hidden-accessible/" data-ajax="false">Hide labels</a></li>
<li data-filtertext="form field containers fieldcontain ui-field-contain forms"><a href="../forms-field-contain/" data-ajax="false">Field containers</a></li>
<li data-filtertext="forms disabled form elements"><a href="../forms-disabled/" data-ajax="false">Forms disabled</a></li>
<li data-filtertext="forms gallery examples overview forms text checkbox radio range button submit reset inputs selects textarea slider flipswitch label form elements"><a href="../forms-gallery/" data-ajax="false">Forms gallery</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Grids</h3>
<ul>
<li data-filtertext="grids columns blocks content formatting rwd responsive css framework"><a href="../grids/" data-ajax="false">Grids</a></li>
<li data-filtertext="buttons in grids css framework"><a href="../grids-buttons/" data-ajax="false">Buttons in grids</a></li>
<li data-filtertext="custom responsive grids rwd css framework"><a href="../grids-custom-responsive/" data-ajax="false">Custom responsive grids</a></li>
</ul>
</li>
<li data-filtertext="blocks content formatting sections heading"><a href="../body-bar-classes/" data-ajax="false">Grouping and dividing content</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Icons</h3>
<ul>
<li data-filtertext="button icons svg disc alt custom icon position"><a href="../icons/" data-ajax="false">Icons</a></li>
<li data-filtertext=""><a href="../icons-grunticon/" data-ajax="false">Grunticon loader</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Listview widget</h3>
<ul>
<li data-filtertext="listview widget thumbnails icons nested split button collapsible ul ol"><a href="../listview/" data-ajax="false">Listview</a></li>
<li data-filtertext="autocomplete filterable reveal listview filtertextbeforefilter placeholder"><a href="../listview-autocomplete/" data-ajax="false">Listview autocomplete</a></li>
<li data-filtertext="autocomplete filterable reveal listview remote data filtertextbeforefilter placeholder"><a href="../listview-autocomplete-remote/" data-ajax="false">Listview autocomplete remote data</a></li>
<li data-filtertext="autodividers anchor jump scroll linkbars listview lists ul ol"><a href="../listview-autodividers-linkbar/" data-ajax="false">Listview autodividers linkbar</a></li>
<li data-filtertext="listview autodividers selector autodividersselector lists ul ol"><a href="../listview-autodividers-selector/" data-ajax="false">Listview autodividers selector</a></li>
<li data-filtertext="listview nested list items"><a href="../listview-nested-lists/" data-ajax="false">Listview Nested Listviews</a></li>
<li data-filtertext="listview collapsible list items flat"><a href="../listview-collapsible-item-flat/" data-ajax="false">Listview collapsible list items (flat)</a></li>
<li data-filtertext="listview collapsible list indented"><a href="../listview-collapsible-item-indented/" data-ajax="false">Listview collapsible list items (indented)</a></li>
<li data-filtertext="grid listview responsive grids responsive listviews lists ul"><a href="../listview-grid/" data-ajax="false">Listview responsive grid</a></li>
</ul>
</li>
<li data-filtertext="loader widget page loading navigation overlay spinner"><a href="../loader/" data-ajax="false">Loader widget</a></li>
<li data-filtertext="navbar widget navmenu toolbars header footer"><a href="../navbar/" data-ajax="false">Navbar widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Navigation</h3>
<ul>
<li data-filtertext="ajax navigation navigate widget history event method"><a href="../navigation/" data-ajax="false">Navigation</a></li>
<li data-filtertext="linking pages page links navigation ajax prefetch cache"><a href="../navigation-linking-pages/" data-ajax="false">Linking pages</a></li>
<li data-filtertext="php redirect server redirection server-side navigation"><a href="../navigation-php-redirect/" data-ajax="false">PHP redirect demo</a></li>
<li data-filtertext="navigation redirection hash query"><a href="../navigation-hash-processing/" data-ajax="false">Hash processing demo</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Pages</h3>
<ul>
<li data-filtertext="pages page widget ajax navigation"><a href="../pages/" data-ajax="false">Pages</a></li>
<li data-filtertext="single page"><a href="../pages-single-page/" data-ajax="false">Single page</a></li>
<li data-filtertext="multipage multi-page page"><a href="../pages-multi-page/" data-ajax="false">Multi-page template</a></li>
<li data-filtertext="dialog page widget modal popup"><a href="../pages-dialog/" data-ajax="false">Dialog page</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Panel widget</h3>
<ul>
<li data-filtertext="panel widget sliding panels reveal push overlay responsive"><a href="../panel/" data-ajax="false">Panel</a></li>
<li data-filtertext=""><a href="../panel-external/" data-ajax="false">External panels</a></li>
<li data-filtertext="panel "><a href="../panel-fixed/" data-ajax="false">Fixed panels</a></li>
<li data-filtertext="panel slide panels sliding panels shadow rwd responsive breakpoint"><a href="../panel-responsive/" data-ajax="false">Panels responsive</a></li>
<li data-filtertext="panel custom style custom panel width reveal shadow listview panel styling page background wrapper"><a href="../panel-styling/" data-ajax="false">Custom panel style</a></li>
<li data-filtertext="panel open on swipe"><a href="../panel-swipe-open/" data-ajax="false">Panel open on swipe</a></li>
<li data-filtertext="panels outside page internal external toolbars"><a href="../panel-external-internal/" data-ajax="false">Panel external and internal</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Popup widget</h3>
<ul>
<li data-filtertext="popup widget popups dialog modal transition tooltip lightbox form overlay screen flip pop fade transition"><a href="../popup/" data-ajax="false">Popup</a></li>
<li data-filtertext="popup alignment position"><a href="../popup-alignment/" data-ajax="false">Popup alignment</a></li>
<li data-filtertext="popup arrow size popups popover"><a href="../popup-arrow-size/" data-ajax="false">Popup arrow size</a></li>
<li data-filtertext="dynamic popups popup images lightbox"><a href="../popup-dynamic/" data-ajax="false">Dynamic popups</a></li>
<li data-filtertext="popups with iframes scaling"><a href="../popup-iframe/" data-ajax="false">Popups with iframes</a></li>
<li data-filtertext="popup image scaling"><a href="../popup-image-scaling/" data-ajax="false">Popup image scaling</a></li>
<li data-filtertext="external popup outside multi-page"><a href="../popup-outside-multipage" data-ajax="false">Popup outside multi-page</a></li>
</ul>
</li>
<li data-filtertext="form rangeslider widget dual sliders dual handle sliders range input"><a href="../rangeslider/" data-ajax="false">Rangeslider widget</a></li>
<li data-filtertext="responsive web design rwd adaptive progressive enhancement PE accessible mobile breakpoints media query media queries"><a href="../rwd/" data-ajax="false">Responsive Web Design</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Selectmenu widget</h3>
<ul>
<li data-filtertext="form selectmenu widget select input custom select menu selects"><a href="../selectmenu/" data-ajax="false">Selectmenu</a></li>
<li data-filtertext="form custom select menu selectmenu widget custom menu option optgroup multiple selects"><a href="../selectmenu-custom/" data-ajax="false">Custom select menu</a></li>
<li data-filtertext="filterable select filter popup dialog"><a href="../selectmenu-custom-filter/" data-ajax="false">Custom select menu with filter</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Slider widget</h3>
<ul>
<li data-filtertext="form slider widget range input single sliders"><a href="../slider/" data-ajax="false">Slider</a></li>
<li data-filtertext="form slider widget flipswitch slider binary select flip toggle switch"><a href="../slider-flipswitch/" data-ajax="false">Slider flip toggle switch</a></li>
<li data-filtertext="form slider tooltip handle value input range sliders"><a href="../slider-tooltip/" data-ajax="false">Slider tooltip</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Table widget</h3>
<ul>
<li data-filtertext="table widget reflow column toggle th td responsive tables rwd hide show tabular"><a href="../table-column-toggle/" data-ajax="false">Table Column Toggle</a></li>
<li data-filtertext="table column toggle phone comparison demo"><a href="../table-column-toggle-example/" data-ajax="false">Table Column Toggle demo</a></li>
<li data-filtertext="responsive tables table column toggle heading groups rwd breakpoint"><a href="../table-column-toggle-heading-groups/" data-ajax="false">Table Column Toggle heading groups</a></li>
<li data-filtertext="responsive tables table column toggle hide rwd breakpoint customization options"><a href="../table-column-toggle-options/" data-ajax="false">Table Column Toggle options</a></li>
<li data-filtertext="table reflow th td responsive rwd columns tabular"><a href="../table-reflow/" data-ajax="false">Table Reflow</a></li>
<li data-filtertext="responsive tables table reflow heading groups rwd breakpoint"><a href="../table-reflow-heading-groups/" data-ajax="false">Table Reflow heading groups</a></li>
<li data-filtertext="responsive tables table reflow stripes strokes table style"><a href="../table-reflow-stripes-strokes/" data-ajax="false">Table Reflow stripes and strokes</a></li>
<li data-filtertext="responsive tables table reflow stack custom styles"><a href="../table-reflow-styling/" data-ajax="false">Table Reflow custom styles</a></li>
</ul>
</li>
<li data-filtertext="ui tabs widget"><a href="../tabs/" data-ajax="false">Tabs widget</a></li>
<li data-filtertext="form textinput widget text input textarea number date time tel email file color password"><a href="../textinput/" data-ajax="false">Textinput widget</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Theming</h3>
<ul>
<li data-filtertext="default theme swatches theming style css"><a href="../theme-default/" data-ajax="false">Default theme</a></li>
<li data-filtertext="classic theme old theme swatches theming style css"><a href="../theme-classic/" data-ajax="false">Classic theme</a></li>
</ul>
</li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>Toolbar widget</h3>
<ul>
<li data-filtertext="toolbar widget header footer toolbars fixed fullscreen external sections"><a href="../toolbar/" data-ajax="false">Toolbar</a></li>
<li data-filtertext="dynamic toolbars dynamically add toolbar header footer"><a href="../toolbar-dynamic/" data-ajax="false">Dynamic toolbars</a></li>
<li data-filtertext="external toolbars header footer"><a href="../toolbar-external/" data-ajax="false">External toolbars</a></li>
<li data-filtertext="fixed toolbars header footer"><a href="../toolbar-fixed/" data-ajax="false">Fixed toolbars</a></li>
<li data-filtertext="fixed fullscreen toolbars header footer"><a href="../toolbar-fixed-fullscreen/" data-ajax="false">Fullscreen toolbars</a></li>
<li data-filtertext="external fixed toolbars header footer"><a href="../toolbar-fixed-external/" data-ajax="false">Fixed external toolbars</a></li>
<li data-filtertext="external persistent toolbars header footer navbar navmenu"><a href="../toolbar-fixed-persistent/" data-ajax="false">Persistent toolbars</a></li>
<li data-filtertext="external ajax optimized toolbars persistent toolbars header footer navbar"><a href="../toolbar-fixed-persistent-optimized/" data-ajax="false">Ajax optimized toolbars</a></li>
<li data-filtertext="form in toolbars header footer"><a href="../toolbar-fixed-forms/" data-ajax="false">Form in toolbar</a></li>
</ul>
</li>
<li data-filtertext="page transitions animated pages popup navigation flip slide fade pop"><a href="../transitions/" data-ajax="false">Transitions</a></li>
<li data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" data-iconpos="right" data-inset="false">
<h3>3rd party API demos</h3>
<ul>
<li data-filtertext="backbone requirejs navigation router"><a href="../backbone-requirejs/" data-ajax="false">Backbone RequireJS</a></li>
<li data-filtertext="google maps geolocation demo"><a href="../map-geolocation/" data-ajax="false">Google Maps geolocation</a></li>
<li data-filtertext="google maps hybrid"><a href="../map-list-toggle/" data-ajax="false">Google Maps list toggle</a></li>
</ul>
</li>
</ul>
</div>
</div><!-- /panel -->
</div><!-- /page -->
</body>
</html>

View File

@ -0,0 +1,160 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile - Backbone.js and Require.js Apps</title>
<link rel="shortcut icon" href="../favicon.ico">
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:300,400,700">
<link rel="stylesheet" href="../../css/themes/default/jquery.mobile.css">
<link rel="stylesheet" href="../_assets/css/jqm-demos.css">
<script src="../../external/jquery/jquery.js"></script>
<script src="../_assets/js/"></script>
<script src="../../js/"></script>
</head>
<body>
<div data-role="page" class="jqm-demos" data-quicklinks="true">
<div data-role="header" class="jqm-header">
<h2><a href="../" title="jQuery Mobile Demos home"><img src="../_assets/img/jquery-logo.png" alt="jQuery Mobile"></a></h2>
<p><span class="jqm-version"></span> Demos</p>
<a href="#" class="jqm-navmenu-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-bars ui-nodisc-icon ui-alt-icon ui-btn-left">Menu</a>
<a href="#" class="jqm-search-link ui-btn ui-btn-icon-notext ui-corner-all ui-icon-search ui-nodisc-icon ui-alt-icon ui-btn-right">Search</a>
</div><!-- /header -->
<div role="main" class="ui-content jqm-content">
<h1>jQuery Mobile, Backbone.js and Require.js</h1>
<p>jQuery Mobile provides an <strong>HTML5-based user interface for all popular mobile device platforms</strong>, but it does not influence how you organize and structure your app's JavaScript. Many jQuery Mobile users turn to a variety of other popular third-party libraries, including MV* frameworks and dependency management tools, to help structure their code.
</p>
<h2>Backbone and Require.js</h2>
<p><strong>Backbone.js</strong> and <strong>Require.js</strong> are two of the most popular third-party libraries that are used with jQuery Mobile to provide a rich JavaScript tech stack for developers.
</p>
<p><strong>Backbone.js</strong> is a great client-side MV* JavaScript framework that provides structure to JavaScript applications by providing View, Model, Collection, Router, and Event class objects.
</p>
<p><strong>Require.js</strong> serves a few different purposes than Backbone.js. Require.js is an AMD (Asynchronous Module Definition) script loader that asynchronously loads your JavaScript to improve page load performance, while also helping with script dependency managagement and allowing you to organize your JavaScript into self contained modules (files).
</p>
<p>Although there is a high amount of developer interest with using jQuery Mobile, Backbone.js, and Require.js together, there is a high barrier of entry. Many users are confused about how to use the Backbone.js Router class object with the jQuery Mobile routing system.</p>
<a href="backbone-require.html" rel="external" class="ui-btn ui-btn-inline ui-corner-all ui-shadow ui-btn-icon-right ui-icon-carat-r">View example page</a>
<h2>jQuery Mobile configuration</h2>
<p>The technique used in this <a href="backbone-require.html" rel="external">example page</a> is by no means the only technique available, but it is one of the most elegant. The Backbone.js router is used exclusively to handle all hashchange events, and the jQuery Mobile <code>$.mobile.changePage()</code> method is used to programmatically change the page.</p>
<p>Below are two internal jQuery Mobile properties that are turned off to allow this to happen:</p>
<ul>
<li><code>$.mobile.linkBindingEnabled</code>
<ul>
<li>jQuery Mobile will automatically bind the clicks on anchor tags in your document. Setting this option to false will prevent all anchor click handling including the addition of active button state and alternate link blurring. This should only be used when attempting to delegate the click management to another library or custom code.</li>
</ul>
</li>
<li><code>$.mobile.hashListeningEnabled</code>
<ul>
<li>jQuery Mobile will automatically listen and handle changes to the location.hash. Disabling this will prevent jQuery Mobile from handling hash changes, which allows you to handle them yourself or use simple deep-links within a document that scroll to a particular id.</li>
</ul>
</li>
</ul>
</p>
<h2>Example page code</h2>
<p>To illustrate how the above internal jQuery Mobile properties are turned off, let's examine our example page code.</p>
<p>Inside of the <em>head</em> section of our <strong>index.html</strong> page, we first include the Require.js JavaScript library and set the <strong>data-main</strong> attribute of our script tag to the JavaScript file that we want Require.js to include on the page first (this file will contain all of our Require.js configurations). In this example, we are telling Require.js to look inside of the js folder and then load <strong>mobile.js</strong>.
</p>
<code>
&lt;head&gt;
&lt;script src=&quot;js/libs/require.js&quot; data-main=&quot;js/mobile&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
</code>
<p>If we look inside of <strong>mobile.js</strong>, we will find that the <code>$.mobile.linkBindingEnabled</code> and <code>$.mobile.hashListeningEnabled</code> jQuery Mobile attributes are set to false.
</p>
<pre>
<code>
// Sets the require.js configuration for your application.
require.config( {
// 3rd party script alias names
paths: {
// Core Libraries
"jquery": "../../../js/jquery",
"jquerymobile": "libs/jquerymobile",
"underscore": "libs/lodash",
"backbone": "libs/backbone"
},
// Sets the configuration for your third party scripts that are not AMD compatible
shim: {
"backbone": {
"deps": [ "underscore", "jquery" ],
"exports": "Backbone" //attaches "Backbone" to the window object
}
} // end Shim Configuration
} );
// Includes File Dependencies
require([ "jquery","backbone","routers/mobileRouter","jquerymobile" ], function( $, Backbone, Mobile ) {
// Prevents all anchor click handling
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
// Instantiates a new Backbone.js Mobile Router
this.router = new Mobile();
} );
</code>
</pre>
<p>Next, inside of the Backbone.js Router class object, we can respond to haschange events and manually call the jQuery Mobile <code>changePage()</code> method. Below is a small snippet of <strong>mobileRouter.js</strong>.</p>
<pre>
<code>
// Backbone.js Routes
routes: {
// When there is no hash bang on the url, the home method is called
"": "home",
// When #category? is on the url, the category method is called
"category?:type": "category"
},
// Home method
home: function() {
// Programatically changes to the categories page
$.mobile.changePage( "#categories" , { reverse: false, changeHash: false } );
}
</code>
</pre>
<p>The <a href="backbone-require.html" rel="external">example page</a> illustrates how to render a jQuery Mobile ListView that is populated with dynamic JSON data asynchronously. Feel free to take a deeper look into the source code to see how Require.js and Backbone.js are used.</p>
</div><!-- /content -->
<?php include( '../jqm-navmenu.php' ); ?>
<div data-role="footer" data-position="fixed" data-tap-toggle="false" class="jqm-footer">
<p>jQuery Mobile Demos version <span class="jqm-version"></span></p>
<p>Copyright 2014 The jQuery Foundation</p>
</div><!-- /footer -->
<?php include( '../jqm-search.php' ); ?>
</div><!-- /page -->
</body>
</html>

View File

@ -0,0 +1,101 @@
// Category Collection
// ===================
// Includes file dependencies
define([
"jquery",
"backbone",
"../models/CategoryModel" ], function( $, Backbone, CategoryModel ) {
// Extends Backbone.Router
var Collection = Backbone.Collection.extend( {
// The Collection constructor
initialize: function( models, options ) {
// Sets the type instance property (ie. animals)
this.type = options.type;
},
// Sets the Collection model property to be a Category Model
model: CategoryModel,
// Sample JSON data that in a real app will most likely come from a REST web service
jsonArray: [
{ "category": "animals", "type": "Pets" },
{ "category": "animals", "type": "Farm Animals" },
{ "category": "animals", "type": "Wild Animals" },
{ "category": "colors", "type": "Blue" },
{ "category": "colors", "type": "Green" },
{ "category": "colors", "type": "Orange" },
{ "category": "colors", "type": "Purple" },
{ "category": "colors", "type": "Red" },
{ "category": "colors", "type": "Yellow" },
{ "category": "colors", "type": "Violet" },
{ "category": "vehicles", "type": "Cars" },
{ "category": "vehicles", "type": "Planes" },
{ "category": "vehicles", "type": "Construction" }
],
// Overriding the Backbone.sync method (the Backbone.fetch method calls the sync method when trying to fetch data)
sync: function( method, model, options ) {
// Local Variables
// ===============
// Instantiates an empty array
var categories = [],
// Stores the this context in the self variable
self = this,
// Creates a jQuery Deferred Object
deferred = $.Deferred();
// Uses a setTimeout to mimic a real world application that retrieves data asynchronously
setTimeout( function() {
// Filters the above sample JSON data to return an array of only the correct category type
categories = _.filter( self.jsonArray, function( row ) {
return row.category === self.type;
} );
// Calls the options.success method and passes an array of objects (Internally saves these objects as models to the current collection)
options.success( categories );
// Triggers the custom `added` method (which the Category View listens for)
self.trigger( "added" );
// Resolves the deferred object (this triggers the changePage method inside of the Category Router)
deferred.resolve();
}, 1000);
// Returns the deferred object
return deferred;
}
} );
// Returns the Model class
return Collection;
} );

View File

@ -0,0 +1,55 @@
// Sets the require.js configuration for your application.
require.config( {
baseUrl: "../js",
// 3rd party script alias names
paths: {
// Core Libraries
"jquery": "jquery",
"jquerymobile": "jquery.mobile-1.4.2",
"underscore": "//rawgithub.com/lodash/lodash/2.4.1/dist/lodash",
"backbone": "//rawgithub.com/jashkenas/backbone/0.9.2/backbone",
"backbone-requirejs-demos": "../backbone-requirejs/js"
},
// Sets the configuration for your third party scripts that are not AMD compatible
shim: {
"backbone": {
"deps": [ "underscore", "jquery" ],
"exports": "Backbone"
}
}
});
// Includes File Dependencies
require([
"jquery",
"backbone",
"backbone-requirejs-demos/routers/mobileRouter"
], function ( $, Backbone, Mobile ) {
$( document ).on( "mobileinit",
// Set up the "mobileinit" handler before requiring jQuery Mobile's module
function () {
// Prevents all anchor click handling including the addition of active button state and alternate link bluring.
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
}
)
require( [ "jquerymobile" ], function () {
// Instantiates a new Backbone.js Mobile Router
this.router = new Mobile();
});
});

View File

@ -0,0 +1,18 @@
// Category Model
// ==============
// Includes file dependencies
define([
"jquery",
"backbone"
], function( $, Backbone ) {
// The Model constructor
var Model = Backbone.Model.extend( {
} );
// Returns the Model class
return Model;
} );

View File

@ -0,0 +1,89 @@
// Mobile Router
// =============
// Includes file dependencies
define([
"jquery",
"backbone",
"../models/CategoryModel",
"../collections/CategoriesCollection",
"../views/CategoryView"
], function( $, Backbone, CategoryModel, CategoriesCollection, CategoryView ) {
// Extends Backbone.Router
var CategoryRouter = Backbone.Router.extend( {
// The Router constructor
initialize: function() {
// Instantiates a new Animal Category View
this.animalsView = new CategoryView( { el: "#animals", collection: new CategoriesCollection( [] , { type: "animals" } ) } );
// Instantiates a new Colors Category View
this.colorsView = new CategoryView( { el: "#colors", collection: new CategoriesCollection( [] , { type: "colors" } ) } );
// Instantiates a new Vehicles Category View
this.vehiclesView = new CategoryView( { el: "#vehicles", collection: new CategoriesCollection( [] , { type: "vehicles" } ) } );
// Tells Backbone to start watching for hashchange events
Backbone.history.start();
},
// Backbone.js Routes
routes: {
// When there is no hash bang on the url, the home method is called
"": "home",
// When #category? is on the url, the category method is called
"category?:type": "category"
},
// Home method
home: function() {
// Programatically changes to the categories page
$.mobile.changePage( "#categories" , { reverse: false, changeHash: false } );
},
// Category method that passes in the type that is appended to the url hash
category: function(type) {
// Stores the current Category View inside of the currentView variable
var currentView = this[ type + "View" ];
// If there are no collections in the current Category View
if(!currentView.collection.length) {
// Show's the jQuery Mobile loading icon
$.mobile.loading( "show" );
// Fetches the Collection of Category Models for the current Category View
currentView.collection.fetch().done( function() {
// Programatically changes to the current categories page
$.mobile.changePage( "#" + type, { reverse: false, changeHash: false } );
} );
}
// If there already collections in the current Category View
else {
// Programatically changes to the current categories page
$.mobile.changePage( "#" + type, { reverse: false, changeHash: false } );
}
}
} );
// Returns the Router class
return CategoryRouter;
} );

View File

@ -0,0 +1,41 @@
// Category View
// =============
// Includes file dependencies
define([
"jquery",
"backbone",
"../models/CategoryModel"
], function( $, Backbone, CategoryModel ) {
// Extends Backbone.View
var CategoryView = Backbone.View.extend( {
// The View Constructor
initialize: function() {
// The render method is called when Category Models are added to the Collection
this.collection.on( "added", this.render, this );
},
// Renders all of the Category models on the UI
render: function() {
// Sets the view's template property
this.template = _.template( $( "script#categoryItems" ).html(), { "collection": this.collection } );
// Renders the view's template inside of the current listview element
this.$el.find("ul").html(this.template);
// Maintains chainability
return this;
}
} );
// Returns the View class
return CategoryView;
} );

Some files were not shown because too many files have changed in this diff Show More