added jquery lib files natively
This commit is contained in:
20
libs/jQuery-Seat-Charts/LICENSE
Normal file
20
libs/jQuery-Seat-Charts/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013, 2016 Mateusz Markowski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
528
libs/jQuery-Seat-Charts/README.md
Normal file
528
libs/jQuery-Seat-Charts/README.md
Normal file
@@ -0,0 +1,528 @@
|
||||
# jQuery Seat Charts
|
||||
|
||||
### jQuery Seat Charts (JSC) is a full-blown seat map library. It will generate an accessible map, legend, handle mouse & keyboard events and finally give you powerful selectors to control your map.
|
||||
|
||||
[Simple demo map](http://jsc.mm-lamp.com/)
|
||||
|
||||
## Example:
|
||||
|
||||
Basic setup:
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
var sc = $('#seat-map').seatCharts({
|
||||
map: [
|
||||
'aaaaaaaaaaaa',
|
||||
'aaaaaaaaaaaa',
|
||||
'bbbbbbbbbb__',
|
||||
'bbbbbbbbbb__',
|
||||
'bbbbbbbbbbbb',
|
||||
'cccccccccccc'
|
||||
],
|
||||
seats: {
|
||||
a: {
|
||||
price : 99.99,
|
||||
classes : 'front-seat' //your custom CSS class
|
||||
}
|
||||
|
||||
},
|
||||
click: function () {
|
||||
if (this.status() == 'available') {
|
||||
//do some stuff, i.e. add to the cart
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
//seat has been vacated
|
||||
return 'available';
|
||||
} else if (this.status() == 'unavailable') {
|
||||
//seat has been already booked
|
||||
return 'unavailable';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Make all available 'c' seats unavailable
|
||||
sc.find('c.available').status('unavailable');
|
||||
|
||||
/*
|
||||
Get seats with ids 2_6, 1_7 (more on ids later on),
|
||||
put them in a jQuery set and change some css
|
||||
*/
|
||||
sc.get(['2_6', '1_7']).node().css({
|
||||
color: '#ffcfcf'
|
||||
});
|
||||
|
||||
console.log('Seat 1_2 costs ' + sc.get('1_2').data().price + ' and is currently ' + sc.status('1_2'));
|
||||
|
||||
});
|
||||
|
||||
|
||||
## Basics:
|
||||
|
||||
Building maps is fairly easy with jQuery Seat Charts, you can literally pass an array of strings which represents succeeding rows. Let's take a look at a theatre example:
|
||||
|
||||
//Seat map definition
|
||||
[
|
||||
'aaaaaa__DDDDD',
|
||||
'aaaaaa__aaaaa',
|
||||
'aaaaaa__aaaaa',
|
||||
'bbbbbb__bbbbb',
|
||||
'bbbbbb__bbbbb',
|
||||
'bbbbbb__bbbbb',
|
||||
'ccccccccccccc'
|
||||
]
|
||||
|
||||
Each single character represents a different type of seat and you have a freedom of choosing anyone but underscore **_**. Underscore is used to indicate that there shouldn't be any seat at a certain place. In our example I chose **a** seats to be the closest to the screen, **D** meant for disabled and **b** and **c** as just plain seats. I also built a corridor in the middle of our theatre, so people can conviniently reach their seats.
|
||||
|
||||
Your chosen characters can carry a hash of data which is a great way to pass crucial seat details such as price or a description that you want to show on hover.
|
||||
|
||||
seats: {
|
||||
a: {
|
||||
price : 24.55,
|
||||
description : 'Fair priced seat!'
|
||||
}
|
||||
}
|
||||
|
||||
Once you build your map and define seats, you can start implementing the booking magic.
|
||||
|
||||
## Booking Magic
|
||||
|
||||
JSC combines keyboard and mouse events to offer a unified API. There're three types of events which JSC can produce:
|
||||
|
||||
* **click**: click or spacebar
|
||||
* **focus**: mouse or arrows
|
||||
* **blur**: mouse or arrows
|
||||
|
||||
|
||||
All three events have their default handlers but you're more than likely to overwrite at least one of them. JSC flexible API let you choose where you want to specify your handlers. You can define global click handlers like in the *Basic setup* example at the very beginning or you can implement separate handlers for each *character*:
|
||||
|
||||
|
||||
a: {
|
||||
click : function () {
|
||||
//This will only be applied to a seats
|
||||
},
|
||||
price : 34.99,
|
||||
category : 'VIP Seats'
|
||||
}
|
||||
|
||||
Each event handler is fired in *seat* context which gives you an easy access (using *this* variable) to its properties, DOM node and data which you may have specified during the setup:
|
||||
|
||||
click: function () {
|
||||
if (this.status() == 'available') {
|
||||
//seat's available and can be taken!
|
||||
|
||||
//let's retrieve the data, so we can add the seat to our cart
|
||||
var price = this.data().price,
|
||||
category = this.data().category;
|
||||
|
||||
//jQuery element access example
|
||||
this.node().css({
|
||||
'font-size' : '25px'
|
||||
});
|
||||
|
||||
//return new seat status
|
||||
return 'selected';
|
||||
}
|
||||
//…
|
||||
}
|
||||
|
||||
**Please note**: event handler should return new status of a seat depending on what happended. If user clicks on a seat and the seat's *available*, *selected* status should be returned. If user clicks on a *selected* seat, it most likely should become *available* again. Full status reference:
|
||||
|
||||
* **available**: seat which can be taken
|
||||
* **unavailable**: seat which cannot be taken
|
||||
* **selected**: seat which has been taken by current user
|
||||
|
||||
Since JSC also works with *focus/blur* events, it features a special status called *focused* which actually doesn't apply to seat status but rather to the way it's displayed. If you use *.status* method on a focused seat, you will get its real status. To get an idea of this, please take a look at how events are handled by default:
|
||||
|
||||
click : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
return 'available';
|
||||
} else {
|
||||
/*
|
||||
If we don't want to change the status (i.e. seat's unavailable) we ought to return this.style(). this.style() is a reference to seat's special status which means that it can be focused as well. You shouldn't return this.status() here
|
||||
*/
|
||||
return this.style();
|
||||
}
|
||||
|
||||
},
|
||||
focus : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
//if seat's available, it can be focused
|
||||
return 'focused';
|
||||
} else {
|
||||
//otherwise nothing changes
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
blur : function() {
|
||||
//The only place where you should return actual seat status
|
||||
return this.status();
|
||||
},
|
||||
|
||||
***
|
||||
|
||||
Your site's popular and people fight for your tickets? Don't forget to update your map with new bookings live!
|
||||
|
||||
//sc will contain a reference to the map
|
||||
var sc = $('#sc-container').seatCharts({
|
||||
//...
|
||||
});
|
||||
|
||||
setInterval(function() {
|
||||
$.ajax({
|
||||
type : 'get',
|
||||
url : '/bookings/get/100',
|
||||
dataType : 'json',
|
||||
success : function(response) {
|
||||
//iterate through all bookings for our event
|
||||
$.each(response.bookings, function(index, booking) {
|
||||
//find seat by id and set its status to unavailable
|
||||
sc.status(booking.seat_id, 'unavailable');
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 10000); //every 10 seconds
|
||||
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
Required params are marked with *
|
||||
|
||||
### animate
|
||||
|
||||
Bool, enables animated status switches.
|
||||
|
||||
**Please note**: *animate* uses *switchClass* method of [jQuery UI](http://jqueryui.com/), so if you want to use *animate*, you need to include jQuery UI in the page.
|
||||
|
||||
### blur
|
||||
|
||||
Blur handler. Fired when seat loses focus due to mouse move or arrow hit. You most likely don't want to overwrite this one.
|
||||
|
||||
//default handler
|
||||
blur : function() {
|
||||
return this.status();
|
||||
},
|
||||
|
||||
### click
|
||||
|
||||
Click handler. Fired when user clicks on a seat or hits spacebar on a focused seat. You're most likely to overwrite this one based off this example:
|
||||
|
||||
click : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
//do some custom stuff
|
||||
console.log(this.data());
|
||||
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
//do some custom stuff
|
||||
|
||||
return 'available';
|
||||
} else {
|
||||
//i.e. alert that the seat's not available
|
||||
|
||||
return this.style();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
### focus
|
||||
|
||||
Focus handler. Fired when seat receives focus. You most likely don't want to overwrite this one.
|
||||
|
||||
//default handler
|
||||
focus : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'focused';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
|
||||
### legend
|
||||
|
||||
JSC is able to create an UL element with a map legend based on your seat types and custom CSS. If you want JSC to generate a legend for you, you will just need to pass some basic information:
|
||||
|
||||
##### node
|
||||
jQuery reference to a DIV element where legend should be rendered. If it's missing, JSC will create a DIV container itself.
|
||||
|
||||
node : $('#my-legend-container')
|
||||
|
||||
##### items
|
||||
|
||||
An array of legend item details. Each array element should be a three-element array: [ *character, status, description* ]
|
||||
|
||||
legend : {
|
||||
node : $('#my-legend-container'),
|
||||
items : [
|
||||
[ v, 'available', 'VIP seats!' ],
|
||||
[ e, 'available', 'Economy seats'],
|
||||
[ e, 'unavailable', 'Unavailable economy seats' ]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
### map*
|
||||
An array of strings that represents your map:
|
||||
|
||||
[
|
||||
'aaa___aaa',
|
||||
'aaaa_aaaa',
|
||||
'aaaa_aaaa'
|
||||
]
|
||||
|
||||
Underscore is used as a spacer between seats.
|
||||
|
||||
**Please note**: number of columns must be equal in each row.
|
||||
|
||||
**New**: You can now override label and ID per character. This is optional and can be applied to any number of seats:
|
||||
|
||||
|
||||
[
|
||||
'a[ID,LABEL]a[ID2,LABEL2]a___a[JUST_ID1]aa',
|
||||
'aaaa_aaaa[,JUST_LABEL1]',
|
||||
'aaaa_aaaa'
|
||||
]
|
||||
|
||||
ID and/or label should be specified after the letter and enclosed in square brackets. ID should go first, optionally followed by custom label. If you just want to specify label without overriding ID, leave ID empty: a[,Just Label]
|
||||
|
||||
ID may contain letters, numbers and underscores. Label can contain the same groups of characters as well as spaces.
|
||||
|
||||
|
||||
### naming
|
||||
|
||||
You can specify your own column and row labels as well as functions for generating seat ids and labels.
|
||||
|
||||
**columns**
|
||||
|
||||
An array of column names, *columns.length* must equal the actual number of columns:
|
||||
|
||||
columns: ['A', 'B', 'C', 'D', 'E']
|
||||
|
||||
If you don't define your own columns, succeeding numbers starting from 1 will be used.
|
||||
|
||||
**getId**
|
||||
|
||||
Callback which may accept the following parameters: *character*, *row*, *column*, where *row* and *column* are names either specified by you using *columns* and *rows* arrays or by default JSC settings. This function should return an id based off passed arguments. Default getId function:
|
||||
|
||||
getId : function(character, row, column) {
|
||||
return row + '_' + column;
|
||||
}
|
||||
|
||||
Returned id is not only used as an internal identifier but also as a DOM id.
|
||||
|
||||
**getLabel**
|
||||
|
||||
Callback which may accept the following parameters: *character*, *row*, *column*, where *row* and *column* are names either specified by you using *columns* and *rows* arrays or by default JSC settings. This function should return a seat label based off passed arguments. Default getLabel function:
|
||||
|
||||
getLabel : function (character, row, column) {
|
||||
return column;
|
||||
}
|
||||
|
||||
Labels will be displayed over seats, so if you don't want any labels, just return an empty string.
|
||||
|
||||
Sometimes it can be really hard to generate labels you want with getLabel, so now it's possible to specify custom labels per each seat. Please take a look at the map section.
|
||||
|
||||
|
||||
**left**
|
||||
|
||||
Bool, defaults to true. If true, JSC will display an additional column on the left of the map with row names as specified by you using *rows* array or by default JSC settings
|
||||
|
||||
**rows**
|
||||
|
||||
An array of row names, *rows* length must equal the actual number of rows:
|
||||
|
||||
rows: ['I', 'II', 'III', 'IV', 'V']
|
||||
|
||||
If you don't define your own rows, succeeding numbers starting from 1 will be used.
|
||||
|
||||
**top**
|
||||
|
||||
Bool, defaults to true. If true, JSC will display an additional row on the top of the map with column names as specified by you using *columns* array or by default JSC settings
|
||||
|
||||
### seats
|
||||
|
||||
A hash of seat options, seat *characters* should be used as keys. You can pass the following params:
|
||||
|
||||
**blur**
|
||||
|
||||
Blur event which should be applied only to seats of a particular *character*.
|
||||
|
||||
**classes**
|
||||
|
||||
Custom CSS classes which should be applied to seats. Either an array or a string, JSC doesn't care:
|
||||
|
||||
classes : 'seat-red seat-big'
|
||||
//equals
|
||||
classes : ['seat-red', 'seat-big']
|
||||
|
||||
**click**
|
||||
|
||||
Custom click handler.
|
||||
|
||||
**focus**
|
||||
|
||||
Custom focus handler.
|
||||
|
||||
|
||||
|
||||
## Selectors
|
||||
|
||||
JSC offers you two flexible selector methods that are chainable and return *set* of seats:
|
||||
|
||||
### .get( ids )
|
||||
|
||||
You can pass either one id or an array of ids:
|
||||
|
||||
sc.get('2_3'); //get 2_3 seat
|
||||
sc.get(['2_3', '2_4']); //get 2_3 and 2_4 seats
|
||||
|
||||
### .find( mixed )
|
||||
|
||||
Find method lets you search using *character*, seat status, combination of both (separated with a dot) or a regexp:
|
||||
|
||||
sc.find('a'); //find all a seats
|
||||
sc.find('unavailable'); //find all unavailable seats
|
||||
sc.find('a.available'); //find all available a seats
|
||||
sc.find(/^1_[0-9]+/); //find all seats in the first row
|
||||
|
||||
|
||||
#### .get and .find chained together:
|
||||
|
||||
sc.get(['1_2', '1_3', '1_4']).find('available'); //find available seats within specified seat ids
|
||||
|
||||
Both methods return either one seat or a set of seats which share similiar methods:
|
||||
|
||||
## Set Methods
|
||||
|
||||
### .status( ids, status )
|
||||
|
||||
Update status for a seat set with given ids. *ids* variable may contain a single id or a an array of ids.
|
||||
|
||||
sc.status('2_15', 'unvailable'); //set status for one seat
|
||||
sc.status(['2_15', '2_10'], 'unvailable'); //set status for two seats
|
||||
|
||||
### .status( status )
|
||||
|
||||
Update status for all seats in the current set.
|
||||
|
||||
sc.find('unavailable').status('available'); //make all unvailable seats available
|
||||
|
||||
### .node( )
|
||||
|
||||
Returns a jQuery set of seat node references.
|
||||
|
||||
sc.find('unavailable').node().fadeOut('fast'); //make all unavailable seats disappear
|
||||
|
||||
### .each( callback )
|
||||
|
||||
Iterates through a seat set, callback will be fired in the context of each element. Callback may accept seat id as an argument.
|
||||
|
||||
sc.find('a.unavailable').each(function(seatId) {
|
||||
console.log(this.data()); //display seat data
|
||||
});
|
||||
|
||||
You can break the loop returning *false*.
|
||||
|
||||
## Seat Methods
|
||||
|
||||
### .status( [status] )
|
||||
If *status* argument is set, it will be used as a new seat status, otherwise current status will be returned.
|
||||
|
||||
### .node( )
|
||||
Returns a reference to jQuery element.
|
||||
|
||||
### .data( )
|
||||
Returns a reference to seat data.
|
||||
|
||||
### .char( )
|
||||
Returns seat *character*.
|
||||
|
||||
|
||||
## Styling
|
||||
|
||||
JSC uses a few CSS classes that are pretty self explanatory:
|
||||
|
||||
### .seatCharts-container
|
||||
DIV container where seat chart's rendered.
|
||||
|
||||
### .seatCharts-row
|
||||
DIV element which serves as a row. You're most likely to edit its height.
|
||||
|
||||
### .seatCharts-cell
|
||||
This class is applied to both seats and spacers ( _ ).
|
||||
|
||||
### .seatCharts-seat
|
||||
Applied to all seats regardless of character.
|
||||
|
||||
### .seatCharts-space
|
||||
Applied to spacers.
|
||||
|
||||
### .seatCharts-seat.selected
|
||||
*Selected* seats.
|
||||
|
||||
### .seatCharts-seat.focused
|
||||
*Focused* seats.
|
||||
|
||||
### .seatCharts-seat.available
|
||||
*Available* seats.
|
||||
|
||||
### .seatCharts-seat.unavailable
|
||||
*Unavailable* seats.
|
||||
|
||||
**Please note:** if you need each of your seat type (indicated by character) look differently, this is the easiest way:
|
||||
|
||||
CSS:
|
||||
.seatCharts-seat.selected.vip {
|
||||
background-color: #ff4fff;
|
||||
}
|
||||
|
||||
.seatCharts-seat.focused.vip {
|
||||
background-color: #ccffcc;
|
||||
}
|
||||
|
||||
//…
|
||||
|
||||
.seatCharts-seat.selected.economy {
|
||||
background-color: #000fff;
|
||||
}
|
||||
|
||||
//…
|
||||
|
||||
JavaScript:
|
||||
|
||||
var sc = $.seatCharts({
|
||||
seats: {
|
||||
v: {
|
||||
classes: 'vip',
|
||||
price : 300
|
||||
},
|
||||
e: {
|
||||
classes: 'economy',
|
||||
price : 50
|
||||
}
|
||||
}
|
||||
//…
|
||||
});
|
||||
|
||||
|
||||
### .seatCharts-legendList
|
||||
UL element which holds the legend.
|
||||
|
||||
### .seatCharts-legendItem
|
||||
LI element of the legend.
|
||||
|
||||
## FAQ
|
||||
|
||||
#### What licence is jQuery Seat Charts released under?
|
||||
jQuery Seat Charts is released under [MIT license](http://choosealicense.com/licenses/mit/).
|
||||
|
||||
#### How is JSC accessible?
|
||||
JSC implements [WAI-ARIA](www.w3.org/WAI/intro/aria) standard meaning that people using solely keyboards will share the same experience as mouse-users. You can easily check it yourself navigating with arrows and hitting spacebar instead of mouse click.
|
||||
7
libs/jQuery-Seat-Charts/TODO.md
Normal file
7
libs/jQuery-Seat-Charts/TODO.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# TODO
|
||||
|
||||
* Extend the .get selector so it's possible to pass each seat id as a separate argument. Let's keep the array method for backward compatibility,
|
||||
* Add some way for rebuilding the map
|
||||
* Aria tests
|
||||
* Seat SeatSet functions instead of plain Objects
|
||||
|
||||
68
libs/jQuery-Seat-Charts/jquery.seat-charts.css
Normal file
68
libs/jQuery-Seat-Charts/jquery.seat-charts.css
Normal file
@@ -0,0 +1,68 @@
|
||||
div.seatCharts-container {
|
||||
/*min-width: 700px;*/
|
||||
}
|
||||
div.seatCharts-cell {
|
||||
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: 3px;
|
||||
float: left;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
font-size: 13px;
|
||||
line-height:16px;
|
||||
color: blue;
|
||||
|
||||
}
|
||||
div.seatCharts-seat {
|
||||
background-color: green;
|
||||
color: white;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
cursor: default;
|
||||
}
|
||||
div.seatCharts-seat:focus {
|
||||
border: none;
|
||||
}
|
||||
/*
|
||||
.seatCharts-seat:focus {
|
||||
outline: none;
|
||||
}
|
||||
*/
|
||||
|
||||
div.seatCharts-space {
|
||||
background-color: white;
|
||||
}
|
||||
div.seatCharts-row {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
div.seatCharts-row:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.seatCharts-seat.selected {
|
||||
background-color: aqua;
|
||||
}
|
||||
|
||||
div.seatCharts-seat.focused {
|
||||
background-color: #6db131;
|
||||
}
|
||||
|
||||
div.seatCharts-seat.available {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
div.seatCharts-seat.unavailable {
|
||||
background-color: red;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
ul.seatCharts-legendList {
|
||||
list-style: none;
|
||||
}
|
||||
li.seatCharts-legendItem {
|
||||
margin-top: 10px;
|
||||
line-height: 2;
|
||||
}
|
||||
627
libs/jQuery-Seat-Charts/jquery.seat-charts.js
Normal file
627
libs/jQuery-Seat-Charts/jquery.seat-charts.js
Normal file
@@ -0,0 +1,627 @@
|
||||
/*!
|
||||
* jQuery-Seat-Charts v1.1.5
|
||||
* https://github.com/mateuszmarkowski/jQuery-Seat-Charts
|
||||
*
|
||||
* Copyright 2013, 2016 Mateusz Markowski
|
||||
* Released under the MIT license
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
//'use strict';
|
||||
|
||||
$.fn.seatCharts = function (setup) {
|
||||
|
||||
//if there's seatCharts object associated with the current element, return it
|
||||
if (this.data('seatCharts')) {
|
||||
return this.data('seatCharts');
|
||||
}
|
||||
|
||||
var fn = this,
|
||||
seats = {},
|
||||
seatIds = [],
|
||||
legend,
|
||||
settings = {
|
||||
animate : false, //requires jQuery UI
|
||||
naming : {
|
||||
top : true,
|
||||
left : true,
|
||||
getId : function(character, row, column) {
|
||||
return row + '_' + column;
|
||||
},
|
||||
getLabel : function (character, row, column) {
|
||||
return column;
|
||||
}
|
||||
|
||||
},
|
||||
legend : {
|
||||
node : null,
|
||||
items : []
|
||||
},
|
||||
click : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
return 'available';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
|
||||
},
|
||||
focus : function() {
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'focused';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
blur : function() {
|
||||
return this.status();
|
||||
},
|
||||
seats : {}
|
||||
|
||||
},
|
||||
//seat will be basically a seat object which we'll when generating the map
|
||||
seat = (function(seatCharts, seatChartsSettings) {
|
||||
return function (setup) {
|
||||
var fn = this;
|
||||
|
||||
fn.settings = $.extend({
|
||||
status : 'available', //available, unavailable, selected
|
||||
style : 'available',
|
||||
//make sure there's an empty hash if user doesn't pass anything
|
||||
data : seatChartsSettings.seats[setup.character] || {}
|
||||
//anything goes here?
|
||||
}, setup);
|
||||
|
||||
fn.settings.$node = $('<div></div>');
|
||||
|
||||
fn.settings.$node
|
||||
.attr({
|
||||
id : fn.settings.id,
|
||||
role : 'checkbox',
|
||||
'aria-checked' : false,
|
||||
focusable : true,
|
||||
tabIndex : -1 //manual focus
|
||||
})
|
||||
.text(fn.settings.label)
|
||||
.addClass(['seatCharts-seat', 'seatCharts-cell', 'available'].concat(
|
||||
//let's merge custom user defined classes with standard JSC ones
|
||||
fn.settings.classes,
|
||||
typeof seatChartsSettings.seats[fn.settings.character] == "undefined" ?
|
||||
[] : seatChartsSettings.seats[fn.settings.character].classes
|
||||
).join(' '));
|
||||
|
||||
//basically a wrapper function
|
||||
fn.data = function() {
|
||||
return fn.settings.data;
|
||||
};
|
||||
|
||||
fn.char = function() {
|
||||
return fn.settings.character;
|
||||
};
|
||||
|
||||
fn.node = function() {
|
||||
return fn.settings.$node;
|
||||
};
|
||||
|
||||
/*
|
||||
* Can either set or return status depending on arguments.
|
||||
*
|
||||
* If there's no argument, it will return the current style.
|
||||
*
|
||||
* If you pass an argument, it will update seat's style
|
||||
*/
|
||||
fn.style = function() {
|
||||
|
||||
return arguments.length == 1 ?
|
||||
(function(newStyle) {
|
||||
var oldStyle = fn.settings.style;
|
||||
|
||||
//if nothing changes, do nothing
|
||||
if (newStyle == oldStyle) {
|
||||
return oldStyle;
|
||||
}
|
||||
|
||||
//focused is a special style which is not associated with status
|
||||
fn.settings.status = newStyle != 'focused' ? newStyle : fn.settings.status;
|
||||
fn.settings.$node
|
||||
.attr('aria-checked', newStyle == 'selected');
|
||||
|
||||
//if user wants to animate status changes, let him do this
|
||||
seatChartsSettings.animate ?
|
||||
fn.settings.$node.switchClass(oldStyle, newStyle, 200) :
|
||||
fn.settings.$node.removeClass(oldStyle).addClass(newStyle);
|
||||
|
||||
return fn.settings.style = newStyle;
|
||||
})(arguments[0]) : fn.settings.style;
|
||||
};
|
||||
|
||||
//either set or retrieve
|
||||
fn.status = function() {
|
||||
|
||||
return fn.settings.status = arguments.length == 1 ?
|
||||
fn.style(arguments[0]) : fn.settings.status;
|
||||
};
|
||||
|
||||
//using immediate function to convienietly get shortcut variables
|
||||
(function(seatSettings, character, seat) {
|
||||
//attach event handlers
|
||||
$.each(['click', 'focus', 'blur'], function(index, callback) {
|
||||
|
||||
//we want to be able to call the functions for each seat object
|
||||
fn[callback] = function() {
|
||||
if (callback == 'focus') {
|
||||
//if there's already a focused element, we have to remove focus from it first
|
||||
if (seatCharts.attr('aria-activedescendant') !== undefined) {
|
||||
seats[seatCharts.attr('aria-activedescendant')].blur();
|
||||
}
|
||||
seatCharts.attr('aria-activedescendant', seat.settings.id);
|
||||
seat.node().focus();
|
||||
}
|
||||
|
||||
/*
|
||||
* User can pass his own callback function, so we have to first check if it exists
|
||||
* and if not, use our default callback.
|
||||
*
|
||||
* Each callback function is executed in the current seat context.
|
||||
*/
|
||||
return fn.style(typeof seatSettings[character][callback] === 'function' ?
|
||||
seatSettings[character][callback].apply(seat) : seatChartsSettings[callback].apply(seat));
|
||||
};
|
||||
|
||||
});
|
||||
//the below will become seatSettings, character, seat thanks to the immediate function
|
||||
})(seatChartsSettings.seats, fn.settings.character, fn);
|
||||
|
||||
fn.node()
|
||||
//the first three mouse events are simple
|
||||
.on('click', fn.click)
|
||||
.on('mouseenter', fn.focus)
|
||||
.on('mouseleave', fn.blur)
|
||||
|
||||
//keydown requires quite a lot of logic, because we have to know where to move the focus
|
||||
.on('keydown', (function(seat, $seat) {
|
||||
|
||||
return function (e) {
|
||||
|
||||
var $newSeat;
|
||||
|
||||
//everything depends on the pressed key
|
||||
switch (e.which) {
|
||||
//spacebar will just trigger the same event mouse click does
|
||||
case 32:
|
||||
e.preventDefault();
|
||||
seat.click();
|
||||
break;
|
||||
//UP & DOWN
|
||||
case 40:
|
||||
case 38:
|
||||
e.preventDefault();
|
||||
|
||||
/*
|
||||
* This is a recursive, immediate function which searches for the first "focusable" row.
|
||||
*
|
||||
* We're using immediate function because we want a convenient access to some DOM elements
|
||||
* We're using recursion because sometimes we may hit an empty space rather than a seat.
|
||||
*
|
||||
*/
|
||||
$newSeat = (function findAvailable($rows, $seats, $currentRow) {
|
||||
var $newRow;
|
||||
|
||||
//let's determine which row should we move to
|
||||
|
||||
if (!$rows.index($currentRow) && e.which == 38) {
|
||||
//if this is the first row and user has pressed up arrow, move to the last row
|
||||
$newRow = $rows.last();
|
||||
} else if ($rows.index($currentRow) == $rows.length-1 && e.which == 40) {
|
||||
//if this is the last row and user has pressed down arrow, move to the first row
|
||||
$newRow = $rows.first();
|
||||
} else {
|
||||
//using eq to get an element at the desired index position
|
||||
$newRow = $rows.eq(
|
||||
//if up arrow, then decrement the index, if down increment it
|
||||
$rows.index($currentRow) + (e.which == 38 ? (-1) : (+1))
|
||||
);
|
||||
}
|
||||
|
||||
//now that we know the row, let's get the seat using the current column position
|
||||
$newSeat = $newRow.find('.seatCharts-seat,.seatCharts-space').eq($seats.index($seat));
|
||||
|
||||
//if the seat we found is a space, keep looking further
|
||||
return $newSeat.hasClass('seatCharts-space') ?
|
||||
findAvailable($rows, $seats, $newRow) : $newSeat;
|
||||
|
||||
})($seat
|
||||
//get a reference to the parent container and then select all rows but the header
|
||||
.parents('.seatCharts-container')
|
||||
.find('.seatCharts-row:not(.seatCharts-header)'),
|
||||
$seat
|
||||
//get a reference to the parent row and then find all seat cells (both seats & spaces)
|
||||
.parents('.seatCharts-row:first')
|
||||
.find('.seatCharts-seat,.seatCharts-space'),
|
||||
//get a reference to the current row
|
||||
$seat.parents('.seatCharts-row:not(.seatCharts-header)')
|
||||
);
|
||||
|
||||
//we couldn't determine the new seat, so we better give up
|
||||
if (!$newSeat.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
//remove focus from the old seat and put it on the new one
|
||||
seat.blur();
|
||||
seats[$newSeat.attr('id')].focus();
|
||||
$newSeat.focus();
|
||||
|
||||
//update our "aria" reference with the new seat id
|
||||
seatCharts.attr('aria-activedescendant', $newSeat.attr('id'));
|
||||
|
||||
break;
|
||||
//LEFT & RIGHT
|
||||
case 37:
|
||||
case 39:
|
||||
e.preventDefault();
|
||||
/*
|
||||
* The logic here is slightly different from the one for up/down arrows.
|
||||
* User will be able to browse the whole map using just left/right arrow, because
|
||||
* it will move to the next row when we reach the right/left-most seat.
|
||||
*/
|
||||
$newSeat = (function($seats) {
|
||||
|
||||
if (!$seats.index($seat) && e.which == 37) {
|
||||
//user has pressed left arrow and we're currently on the left-most seat
|
||||
return $seats.last();
|
||||
} else if ($seats.index($seat) == $seats.length -1 && e.which == 39) {
|
||||
//user has pressed right arrow and we're currently on the right-most seat
|
||||
return $seats.first();
|
||||
} else {
|
||||
//simply move one seat left or right depending on the key
|
||||
return $seats.eq($seats.index($seat) + (e.which == 37 ? (-1) : (+1)));
|
||||
}
|
||||
|
||||
})($seat
|
||||
.parents('.seatCharts-container:first')
|
||||
.find('.seatCharts-seat:not(.seatCharts-space)'));
|
||||
|
||||
if (!$newSeat.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
//handle focus
|
||||
seat.blur();
|
||||
seats[$newSeat.attr('id')].focus();
|
||||
$newSeat.focus();
|
||||
|
||||
//update our "aria" reference with the new seat id
|
||||
seatCharts.attr('aria-activedescendant', $newSeat.attr('id'));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
})(fn, fn.node()));
|
||||
//.appendTo(seatCharts.find('.' + row));
|
||||
|
||||
}
|
||||
})(fn, settings);
|
||||
|
||||
fn.addClass('seatCharts-container');
|
||||
|
||||
//true -> deep copy!
|
||||
$.extend(true, settings, setup);
|
||||
|
||||
//Generate default row ids unless user passed his own
|
||||
settings.naming.rows = settings.naming.rows || (function(length) {
|
||||
var rows = [];
|
||||
for (var i = 1; i <= length; i++) {
|
||||
rows.push(i);
|
||||
}
|
||||
return rows;
|
||||
})(settings.map.length);
|
||||
|
||||
//Generate default column ids unless user passed his own
|
||||
settings.naming.columns = settings.naming.columns || (function(length) {
|
||||
var columns = [];
|
||||
for (var i = 1; i <= length; i++) {
|
||||
columns.push(i);
|
||||
}
|
||||
return columns;
|
||||
})(settings.map[0].split('').length);
|
||||
|
||||
if (settings.naming.top) {
|
||||
var $headerRow = $('<div></div>')
|
||||
.addClass('seatCharts-row seatCharts-header');
|
||||
|
||||
if (settings.naming.left) {
|
||||
$headerRow.append($('<div></div>').addClass('seatCharts-cell'));
|
||||
}
|
||||
|
||||
|
||||
$.each(settings.naming.columns, function(index, value) {
|
||||
$headerRow.append(
|
||||
$('<div></div>')
|
||||
.addClass('seatCharts-cell')
|
||||
.text(value)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn.append($headerRow);
|
||||
|
||||
//do this for each map row
|
||||
$.each(settings.map, function(row, characters) {
|
||||
|
||||
var $row = $('<div></div>').addClass('seatCharts-row');
|
||||
|
||||
if (settings.naming.left) {
|
||||
$row.append(
|
||||
$('<div></div>')
|
||||
.addClass('seatCharts-cell seatCharts-space')
|
||||
.text(settings.naming.rows[row])
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do this for each seat (letter)
|
||||
*
|
||||
* Now users will be able to pass custom ID and label which overwrite the one that seat would be assigned by getId and
|
||||
* getLabel
|
||||
*
|
||||
* New format is like this:
|
||||
* a[ID,label]a[ID]aaaaa
|
||||
*
|
||||
* So you can overwrite the ID or label (or both) even for just one seat.
|
||||
* Basically ID should be first, so if you want to overwrite just label write it as follows:
|
||||
* a[,LABEL]
|
||||
*
|
||||
* Allowed characters in IDs areL 0-9, a-z, A-Z, _
|
||||
* Allowed characters in labels are: 0-9, a-z, A-Z, _, ' ' (space)
|
||||
*
|
||||
*/
|
||||
|
||||
$.each(characters.match(/[a-z_]{1}(\[[0-9a-z_]{0,}(,[0-9a-z_ ]+)?\])?/gi), function (column, characterParams) {
|
||||
var matches = characterParams.match(/([a-z_]{1})(\[([0-9a-z_ ,]+)\])?/i),
|
||||
//no matter if user specifies [] params, the character should be in the second element
|
||||
character = matches[1],
|
||||
//check if user has passed some additional params to override id or label
|
||||
params = typeof matches[3] !== 'undefined' ? matches[3].split(',') : [],
|
||||
//id param should be first
|
||||
overrideId = params.length ? params[0] : null,
|
||||
//label param should be second
|
||||
overrideLabel = params.length === 2 ? params[1] : null;
|
||||
|
||||
$row.append(character != '_' ?
|
||||
//if the character is not an underscore (empty space)
|
||||
(function(naming) {
|
||||
|
||||
//so users don't have to specify empty objects
|
||||
settings.seats[character] = character in settings.seats ? settings.seats[character] : {};
|
||||
|
||||
var id = overrideId ? overrideId : naming.getId(character, naming.rows[row], naming.columns[column]);
|
||||
seats[id] = new seat({
|
||||
id : id,
|
||||
label : overrideLabel ?
|
||||
overrideLabel : naming.getLabel(character, naming.rows[row], naming.columns[column]),
|
||||
row : row,
|
||||
column : column,
|
||||
character : character
|
||||
});
|
||||
|
||||
seatIds.push(id);
|
||||
return seats[id].node();
|
||||
|
||||
})(settings.naming) :
|
||||
//this is just an empty space (_)
|
||||
$('<div></div>').addClass('seatCharts-cell seatCharts-space')
|
||||
);
|
||||
});
|
||||
|
||||
fn.append($row);
|
||||
});
|
||||
|
||||
//if there're any legend items to be rendered
|
||||
settings.legend.items.length ? (function(legend) {
|
||||
//either use user-defined container or create our own and insert it right after the seat chart div
|
||||
var $container = (legend.node || $('<div></div>').insertAfter(fn))
|
||||
.addClass('seatCharts-legend');
|
||||
|
||||
var $ul = $('<ul></ul>')
|
||||
.addClass('seatCharts-legendList')
|
||||
.appendTo($container);
|
||||
|
||||
$.each(legend.items, function(index, item) {
|
||||
$ul.append(
|
||||
$('<li></li>')
|
||||
.addClass('seatCharts-legendItem')
|
||||
.append(
|
||||
$('<div></div>')
|
||||
//merge user defined classes with our standard ones
|
||||
.addClass(['seatCharts-seat', 'seatCharts-cell', item[1]].concat(
|
||||
settings.classes,
|
||||
typeof settings.seats[item[0]] == "undefined" ? [] : settings.seats[item[0]].classes).join(' ')
|
||||
)
|
||||
)
|
||||
.append(
|
||||
$('<span></span>')
|
||||
.addClass('seatCharts-legendDescription')
|
||||
.text(item[2])
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return $container;
|
||||
})(settings.legend) : null;
|
||||
|
||||
fn.attr({
|
||||
tabIndex : 0
|
||||
});
|
||||
|
||||
|
||||
//when container's focused, move focus to the first seat
|
||||
fn.focus(function() {
|
||||
if (fn.attr('aria-activedescendant')) {
|
||||
seats[fn.attr('aria-activedescendant')].blur();
|
||||
}
|
||||
|
||||
fn.find('.seatCharts-seat:not(.seatCharts-space):first').focus();
|
||||
seats[seatIds[0]].focus();
|
||||
|
||||
});
|
||||
|
||||
//public methods of seatCharts
|
||||
fn.data('seatCharts', {
|
||||
seats : seats,
|
||||
seatIds : seatIds,
|
||||
//set for one, set for many, get for one
|
||||
status: function() {
|
||||
var fn = this;
|
||||
|
||||
return arguments.length == 1 ? fn.seats[arguments[0]].status() : (function(seatsIds, newStatus) {
|
||||
|
||||
return typeof seatsIds == 'string' ? fn.seats[seatsIds].status(newStatus) : (function() {
|
||||
$.each(seatsIds, function(index, seatId) {
|
||||
fn.seats[seatId].status(newStatus);
|
||||
});
|
||||
})();
|
||||
})(arguments[0], arguments[1]);
|
||||
},
|
||||
each : function(callback) {
|
||||
var fn = this;
|
||||
|
||||
for (var seatId in fn.seats) {
|
||||
if (false === callback.call(fn.seats[seatId], seatId)) {
|
||||
return seatId;//return last checked
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
node : function() {
|
||||
var fn = this;
|
||||
//basically create a CSS query to get all seats by their DOM ids
|
||||
return $('#' + fn.seatIds.join(',#'));
|
||||
},
|
||||
|
||||
find : function(query) {//D, a.available, unavailable
|
||||
var fn = this;
|
||||
|
||||
var seatSet = fn.set();
|
||||
|
||||
//is RegExp
|
||||
return query instanceof RegExp ?
|
||||
(function () {
|
||||
fn.each(function (id) {
|
||||
if (id.match(query)) {
|
||||
seatSet.push(id, this);
|
||||
}
|
||||
});
|
||||
return seatSet;
|
||||
})() :
|
||||
(query.length == 1 ?
|
||||
(function (character) {
|
||||
//user searches just for a particual character
|
||||
fn.each(function () {
|
||||
if (this.char() == character) {
|
||||
seatSet.push(this.settings.id, this);
|
||||
}
|
||||
});
|
||||
|
||||
return seatSet;
|
||||
})(query) :
|
||||
(function () {
|
||||
//user runs a more sophisticated query, so let's see if there's a dot
|
||||
return query.indexOf('.') > -1 ?
|
||||
(function () {
|
||||
//there's a dot which separates character and the status
|
||||
var parts = query.split('.');
|
||||
|
||||
fn.each(function (seatId) {
|
||||
if (this.char() == parts[0] && this.status() == parts[1]) {
|
||||
seatSet.push(this.settings.id, this);
|
||||
}
|
||||
});
|
||||
|
||||
return seatSet;
|
||||
})() :
|
||||
(function () {
|
||||
fn.each(function () {
|
||||
if (this.status() == query) {
|
||||
seatSet.push(this.settings.id, this);
|
||||
}
|
||||
});
|
||||
return seatSet;
|
||||
})();
|
||||
})()
|
||||
);
|
||||
|
||||
},
|
||||
set : function set() {//inherits some methods
|
||||
var fn = this;
|
||||
|
||||
return {
|
||||
seats : [],
|
||||
seatIds : [],
|
||||
length : 0,
|
||||
status : function() {
|
||||
var args = arguments,
|
||||
that = this;
|
||||
//if there's just one seat in the set and user didn't pass any params, return current status
|
||||
return this.length == 1 && args.length == 0 ? this.seats[0].status() : (function() {
|
||||
//otherwise call status function for each of the seats in the set
|
||||
$.each(that.seats, function() {
|
||||
this.status.apply(this, args);
|
||||
});
|
||||
})();
|
||||
},
|
||||
node : function() {
|
||||
return fn.node.call(this);
|
||||
},
|
||||
each : function() {
|
||||
return fn.each.call(this, arguments[0]);
|
||||
},
|
||||
get : function() {
|
||||
return fn.get.call(this, arguments[0]);
|
||||
},
|
||||
find : function() {
|
||||
return fn.find.call(this, arguments[0]);
|
||||
},
|
||||
set : function() {
|
||||
return set.call(fn);
|
||||
},
|
||||
push : function(id, seat) {
|
||||
this.seats.push(seat);
|
||||
this.seatIds.push(id);
|
||||
++this.length;
|
||||
}
|
||||
};
|
||||
},
|
||||
//get one object or a set of objects
|
||||
get : function(seatsIds) {
|
||||
var fn = this;
|
||||
|
||||
return typeof seatsIds == 'string' ?
|
||||
fn.seats[seatsIds] : (function() {
|
||||
|
||||
var seatSet = fn.set();
|
||||
|
||||
$.each(seatsIds, function(index, seatId) {
|
||||
if (typeof fn.seats[seatId] === 'object') {
|
||||
seatSet.push(seatId, fn.seats[seatId]);
|
||||
}
|
||||
});
|
||||
|
||||
return seatSet;
|
||||
})();
|
||||
}
|
||||
});
|
||||
|
||||
return fn.data('seatCharts');
|
||||
}
|
||||
|
||||
|
||||
})(jQuery);
|
||||
9
libs/jQuery-Seat-Charts/jquery.seat-charts.min.js
vendored
Normal file
9
libs/jQuery-Seat-Charts/jquery.seat-charts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
509
libs/jQuery-Seat-Charts/test/general.js
Normal file
509
libs/jQuery-Seat-Charts/test/general.js
Normal file
@@ -0,0 +1,509 @@
|
||||
(function ($) {
|
||||
|
||||
module('general');
|
||||
|
||||
//Creates a very simple map and returns map's container.
|
||||
function simpleMapSetup(params) {
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$div = $('<div id="seat-map">');
|
||||
|
||||
$fixture.append($div);
|
||||
|
||||
$div.seatCharts(
|
||||
$.extend(true, {}, {
|
||||
map: [
|
||||
'aa_aa',
|
||||
'bbbbb',
|
||||
'bbbbb'
|
||||
],
|
||||
seats: {
|
||||
a: {
|
||||
classes : 'a1-seat-class a2-seat-class'
|
||||
},
|
||||
b: {
|
||||
classes : ['b1-seat-class', 'b2-seat-class']
|
||||
}
|
||||
|
||||
}
|
||||
}, params)
|
||||
);
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
function Counter() {
|
||||
this.click = 0;
|
||||
this.focus = 0;
|
||||
this.blur = 0;
|
||||
|
||||
this.reset = function () {
|
||||
this.click = this.focus = this.blur = 0;
|
||||
};
|
||||
}
|
||||
|
||||
test('Testing general structure of a simple map.', function () {
|
||||
expect(5);
|
||||
|
||||
var $seatCharts = simpleMapSetup(),
|
||||
$space = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-cell:eq(3)');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row').length, 4, 'Number of rows.');
|
||||
|
||||
ok($space.hasClass('seatCharts-space') && !$space.hasClass('seatCharts-seat'), 'There should be a spacer cell in the first row.')
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat').length, 4, 'Number of columns in row 1.');
|
||||
|
||||
for (var i = 2; i <= 3; i += 1) {
|
||||
equal($seatCharts.find('.seatCharts-row:eq('+(i)+') .seatCharts-seat').length, 5, 'Number of columns in row '+i+'.');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('Testing seat classes', function () {
|
||||
expect(6);
|
||||
|
||||
var $seatCharts = simpleMapSetup(),
|
||||
$aSeat = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(0)'),
|
||||
$bSeat = $seatCharts.find('.seatCharts-row:eq(2) .seatCharts-seat:eq(3)');
|
||||
|
||||
ok($aSeat.hasClass('a1-seat-class'), 'Seat a has its a1-seat-class assigned using a string.');
|
||||
|
||||
ok($aSeat.hasClass('a2-seat-class'), 'Seat a has its a2-seat-class assigned using a string.');
|
||||
|
||||
ok($bSeat.hasClass('b1-seat-class'), 'Seat b has its b1-seat-class assigned using an array.');
|
||||
|
||||
ok($bSeat.hasClass('b2-seat-class'), 'Seat b has its b2-seat-class assigned using an array.');
|
||||
|
||||
ok(!($aSeat.hasClass('b1-seat-class') || $aSeat.hasClass('b2-seat-class')), 'Seat a does not have any b seat classes.');
|
||||
|
||||
ok(!($bSeat.hasClass('a1-seat-class') || $bSeat.hasClass('a2-seat-class')), 'Seat b does not have any a seat classes.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing default column & row labels', function () {
|
||||
expect(9);
|
||||
|
||||
var $seatCharts = simpleMapSetup();
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(0) .seatCharts-cell:eq(0)').text(), '', 'Top leftmost cell should be empty.');
|
||||
|
||||
for (var i = 1; i <= 5; i += 1) {
|
||||
equal($seatCharts.find('.seatCharts-row:eq(0) .seatCharts-cell:eq('+i+')').text(), i, 'Column header '+i+' has correct label.');
|
||||
}
|
||||
|
||||
for (var i = 1; i <= 3; i += 1) {
|
||||
equal($seatCharts.find('.seatCharts-row:eq('+i+') .seatCharts-cell:eq(0)').text(), i, 'Row header '+i+' has correct label.');
|
||||
}
|
||||
});
|
||||
|
||||
test('Testing custom column & row labels', function () {
|
||||
expect(3);
|
||||
|
||||
var $seatCharts = simpleMapSetup({
|
||||
naming : {
|
||||
columns : ['I', 'II', 'III', 'IV', 'V'],
|
||||
rows : ['a', 'b', 'c']
|
||||
}
|
||||
});
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(0) .seatCharts-cell:eq(0)').text(), '', 'Top leftmost cell should be empty.');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(0) .seatCharts-cell:eq(3)').text(), 'III', '3rd column header has correct label.');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(2) .seatCharts-cell:eq(0)').text(), 'b', '2nd row header has correct label.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing default seat labels and IDs', function () {
|
||||
expect(4);
|
||||
|
||||
var $seatCharts = simpleMapSetup();
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(0)').text(), '1', 'First seat in the first row label.');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(2)').text(), '4', 'Third seat in the first row label.');
|
||||
|
||||
equal($seatCharts.find('#3_5').length, 1, 'Seat with id 3_5 exists.');
|
||||
|
||||
equal($seatCharts.find('#3_6').length, 0, 'And it is the last seat id.');
|
||||
});
|
||||
|
||||
test('Testing custom seat labels and IDs', function () {
|
||||
expect(4);
|
||||
|
||||
var getIdExecutions = 0,
|
||||
getLabelExecutions = 0,
|
||||
$seatCharts = simpleMapSetup({
|
||||
naming : {
|
||||
getId : function (character, row, column) {
|
||||
getIdExecutions += 1
|
||||
//return all arguments separated with -
|
||||
return [].slice.call(arguments).join('-');
|
||||
},
|
||||
getLabel : function (character, row, column) {
|
||||
getLabelExecutions += 1;
|
||||
//return all arguments separated with +
|
||||
return [].slice.call(arguments).join('+');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
equal(getIdExecutions, 14, 'getId has been called for each seat.');
|
||||
equal(getLabelExecutions, 14, 'getLabel has been called for each seat.');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(2)').text(), 'a+1+4', 'Correct label assigned.');
|
||||
|
||||
equal($seatCharts.find('.seatCharts-row:eq(3) .seatCharts-seat:eq(4)').attr('id'), 'b-3-5', 'Correct id assigned.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing overriding labels and IDs', function () {
|
||||
expect(10);
|
||||
|
||||
var $seatCharts = simpleMapSetup({
|
||||
map: [
|
||||
'a[1_A1,A1]a[1_A2,A2]_aa',
|
||||
'bbbbb',
|
||||
'bb[3_B2]bbb[,B5]'
|
||||
]
|
||||
}),
|
||||
//a[1_A1,A1]
|
||||
$seat1 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(0)'),
|
||||
//a[1_A2,A2]
|
||||
$seat2 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(1)'),
|
||||
//a
|
||||
$seat3 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(2)'),
|
||||
//b[3_B2]
|
||||
$seat4 = $seatCharts.find('.seatCharts-row:eq(3) .seatCharts-seat:eq(1)'),
|
||||
//b[,B5]
|
||||
$seat5 = $seatCharts.find('.seatCharts-row:eq(3) .seatCharts-seat:eq(4)');
|
||||
|
||||
equal($seat1.text(), 'A1', 'Seat 1 has correct label assigned.');
|
||||
equal($seat1.attr('id'), '1_A1', 'Seat 1 has correct id assigned.');
|
||||
|
||||
equal($seat2.text(), 'A2', 'Seat 2 has correct label assigned.');
|
||||
equal($seat2.attr('id'), '1_A2', 'Seat 2 has correct id assigned.');
|
||||
|
||||
equal($seat3.text(), '4', 'Seat 3 has correct label assigned.');
|
||||
equal($seat3.attr('id'), '1_4', 'Seat 3 has correct id assigned.');
|
||||
|
||||
equal($seat4.text(), '2', 'Seat 4 has correct label assigned.');
|
||||
equal($seat4.attr('id'), '3_B2', 'Seat 4 has correct id assigned.');
|
||||
|
||||
equal($seat5.text(), 'B5', 'Seat 5 has correct label assigned.');
|
||||
equal($seat5.attr('id'), '3_5', 'Seat 5 has correct id assigned.');
|
||||
});
|
||||
|
||||
test('Testing overriding+custom labels and IDs', function () {
|
||||
expect(12);
|
||||
|
||||
var getIdExecutions = 0,
|
||||
getLabelExecutions = 0,
|
||||
$seatCharts = simpleMapSetup({
|
||||
naming : {
|
||||
getId : function (character, row, column) {
|
||||
getIdExecutions += 1
|
||||
//return all arguments separated with -
|
||||
return [].slice.call(arguments).join('-');
|
||||
},
|
||||
getLabel : function (character, row, column) {
|
||||
getLabelExecutions += 1;
|
||||
//return all arguments separated with +
|
||||
return [].slice.call(arguments).join('+');
|
||||
}
|
||||
},
|
||||
map: [
|
||||
'a[1_A1,A1]a[1_A2,A2]_aa',
|
||||
'bbbbb',
|
||||
'bb[3_B2]bbb[,B5]'
|
||||
]
|
||||
}),
|
||||
//a[1_A1,A1]
|
||||
$seat1 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(0)'),
|
||||
//a[1_A2,A2]
|
||||
$seat2 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(1)'),
|
||||
//a
|
||||
$seat3 = $seatCharts.find('.seatCharts-row:eq(1) .seatCharts-seat:eq(2)'),
|
||||
//b[3_B2]
|
||||
$seat4 = $seatCharts.find('.seatCharts-row:eq(3) .seatCharts-seat:eq(1)'),
|
||||
//b[,B5]
|
||||
$seat5 = $seatCharts.find('.seatCharts-row:eq(3) .seatCharts-seat:eq(4)');
|
||||
|
||||
equal(getIdExecutions, 11, 'getId has been called for each seat.');
|
||||
equal(getLabelExecutions, 11, 'getLabel has been called for each seat.');
|
||||
|
||||
equal($seat1.text(), 'A1', 'Seat 1 has correct label assigned.');
|
||||
equal($seat1.attr('id'), '1_A1', 'Seat 1 has correct id assigned.');
|
||||
|
||||
equal($seat2.text(), 'A2', 'Seat 2 has correct label assigned.');
|
||||
equal($seat2.attr('id'), '1_A2', 'Seat 2 has correct id assigned.');
|
||||
|
||||
equal($seat3.text(), 'a+1+4', 'Seat 3 has correct label assigned.');
|
||||
equal($seat3.attr('id'), 'a-1-4', 'Seat 3 has correct id assigned.');
|
||||
|
||||
equal($seat4.text(), 'b+3+2', 'Seat 4 has correct label assigned.');
|
||||
equal($seat4.attr('id'), '3_B2', 'Seat 4 has correct id assigned.');
|
||||
|
||||
equal($seat5.text(), 'B5', 'Seat 5 has correct label assigned.');
|
||||
equal($seat5.attr('id'), 'b-3-5', 'Seat 5 has correct id assigned.');
|
||||
});
|
||||
|
||||
test('Testing disabled left & top containers for labels', function () {
|
||||
var $seatCharts = simpleMapSetup({
|
||||
naming : {
|
||||
top: false,
|
||||
left: false
|
||||
}
|
||||
});
|
||||
|
||||
ok($seatCharts.find('.seatCharts-row:eq(0) .seatCharts-cell:eq(0)').hasClass('seatCharts-seat'), 'Top leftmost cell should contain a seat.');
|
||||
})
|
||||
|
||||
test('Testing legend with container specified', function () {
|
||||
expect(4);
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$legend = $('<div>').appendTo($fixture),
|
||||
$seatCharts = simpleMapSetup({
|
||||
legend : {
|
||||
node : $legend,
|
||||
items : [
|
||||
['a', 'available', 'A seat when available'],
|
||||
['b', 'available', 'B seat when available'],
|
||||
['a', 'unavailable', 'A seat when unavailable'],
|
||||
['b', 'unavailable', 'B seat when unavailable']
|
||||
]
|
||||
}
|
||||
}),
|
||||
$item,
|
||||
$seat;
|
||||
|
||||
ok($legend.hasClass('seatCharts-legend'), 'Legend class has been assigned to the container');
|
||||
|
||||
equal($legend.find('ul.seatCharts-legendList li.seatCharts-legendItem').length, 4, 'There is a list of 4 legend items.');
|
||||
|
||||
$item = $legend.find('.seatCharts-legendItem:eq(0)');
|
||||
$seat = $item.find('div:first');
|
||||
|
||||
ok($seat.hasClass('seatCharts-seat') && $seat.hasClass('seatCharts-cell') && $seat.hasClass('available') && $seat.hasClass('a1-seat-class') && $seat.hasClass('a2-seat-class'), 'The first legend item has correct classes assigned.');
|
||||
|
||||
equal($item.find('.seatCharts-legendDescription').text(), 'A seat when available', 'The first item has correct label assigned.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing legend without container specified', function () {
|
||||
expect(4);
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$seatCharts = simpleMapSetup({
|
||||
legend : {
|
||||
items : [
|
||||
['a', 'available', 'A seat when available'],
|
||||
['b', 'available', 'B seat when available'],
|
||||
['a', 'unavailable', 'A seat when unavailable'],
|
||||
['b', 'unavailable', 'B seat when unavailable']
|
||||
]
|
||||
}
|
||||
}),
|
||||
$legend,
|
||||
$item,
|
||||
$seat;
|
||||
|
||||
equal($('div.seatCharts-legend').length, 1, 'Legend div has been created.');
|
||||
|
||||
$legend = $('div.seatCharts-legend:eq(0)');
|
||||
|
||||
equal($legend.find('ul.seatCharts-legendList li.seatCharts-legendItem').length, 4, 'There is a list of 4 legend items.');
|
||||
|
||||
$item = $legend.find('.seatCharts-legendItem:eq(0)');
|
||||
$seat = $item.find('div:first');
|
||||
|
||||
ok($seat.hasClass('seatCharts-seat') && $seat.hasClass('seatCharts-cell') && $seat.hasClass('available') && $seat.hasClass('a1-seat-class') && $seat.hasClass('a2-seat-class'), 'The first legend item has correct classes assigned.');
|
||||
|
||||
equal($item.find('.seatCharts-legendDescription').text(), 'A seat when available', 'The first item has correct label assigned.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing map-level callbacks', function () {
|
||||
var $seatCharts = simpleMapSetup({
|
||||
click : function () {
|
||||
executions.click += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
return 'available';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
focus : function() {
|
||||
executions.focus += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'focused';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
blur : function() {
|
||||
executions.blur += 1;
|
||||
|
||||
return this.status();
|
||||
}
|
||||
}),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
//simple counter object
|
||||
executions = new Counter,
|
||||
clickEvent = $.Event('click'),
|
||||
mouseenterEvent = $.Event('mouseenter'),
|
||||
mouseleaveEvent = $.Event('mouseleave'),
|
||||
focusEvent = $.Event('focus'),
|
||||
keyEvent = $.Event('keydown');
|
||||
|
||||
seatCharts.get('2_3').status('unavailable');
|
||||
|
||||
seatCharts.get('2_1').node().trigger(mouseenterEvent);
|
||||
seatCharts.get('2_1').node().trigger(mouseleaveEvent);
|
||||
seatCharts.get('2_2').node().trigger(mouseenterEvent);
|
||||
seatCharts.get('2_2').node().trigger(mouseleaveEvent);
|
||||
seatCharts.get('2_3').node().trigger(mouseenterEvent);
|
||||
|
||||
propEqual(executions, {
|
||||
click : 0,
|
||||
focus : 3,
|
||||
blur : 4,
|
||||
reset : function () {}
|
||||
}, 'Blur and focus are correctly triggered.');
|
||||
|
||||
//start over
|
||||
executions.reset();
|
||||
|
||||
seatCharts.get('3_1').node().trigger(mouseenterEvent);
|
||||
|
||||
//arrow down
|
||||
keyEvent.which = 38;
|
||||
seatCharts.get('3_1').node().trigger(keyEvent);
|
||||
|
||||
//spacebar
|
||||
keyEvent.which = 32;
|
||||
|
||||
seatCharts.get('2_1').node().trigger(keyEvent);
|
||||
|
||||
propEqual(executions, {
|
||||
click : 1,
|
||||
focus : 2,
|
||||
blur : 3,
|
||||
reset : function () {}
|
||||
}, 'Blur, focus and click are correctly triggered.');
|
||||
});
|
||||
|
||||
test('Testing seat-level callbacks', function () {
|
||||
var $seatCharts = simpleMapSetup({
|
||||
seats : {
|
||||
a : {
|
||||
click : function () {
|
||||
executionsA.click += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
return 'available';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
focus : function() {
|
||||
executionsA.focus += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'focused';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
blur : function() {
|
||||
executionsA.blur += 1;
|
||||
|
||||
return this.status();
|
||||
}
|
||||
},
|
||||
b : {
|
||||
click : function () {
|
||||
executionsB.click += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'selected';
|
||||
} else if (this.status() == 'selected') {
|
||||
return 'available';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
focus : function() {
|
||||
executionsB.focus += 1;
|
||||
|
||||
if (this.status() == 'available') {
|
||||
return 'focused';
|
||||
} else {
|
||||
return this.style();
|
||||
}
|
||||
},
|
||||
blur : function() {
|
||||
executionsB.blur += 1;
|
||||
|
||||
return this.status();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
//each seat type has its own callbacks and hence different counters
|
||||
executionsA = new Counter,
|
||||
executionsB = new Counter,
|
||||
clickEvent = $.Event('click'),
|
||||
mouseenterEvent = $.Event('mouseenter'),
|
||||
mouseleaveEvent = $.Event('mouseleave'),
|
||||
focusEvent = $.Event('focus'),
|
||||
keyEvent = $.Event('keydown');
|
||||
|
||||
seatCharts.get('2_3').status('unavailable');
|
||||
|
||||
seatCharts.get('2_1').node().trigger(mouseenterEvent);
|
||||
seatCharts.get('2_1').node().trigger(mouseleaveEvent);
|
||||
seatCharts.get('2_2').node().trigger(mouseenterEvent);
|
||||
seatCharts.get('2_2').node().trigger(mouseleaveEvent);
|
||||
seatCharts.get('2_3').node().trigger(mouseenterEvent);
|
||||
|
||||
propEqual(executionsB, {
|
||||
click : 0,
|
||||
focus : 3,
|
||||
blur : 4,
|
||||
reset : function () {}
|
||||
}, 'Blur, focus and click are correctly triggered for B seats.');
|
||||
|
||||
seatCharts.get('1_1').node().trigger(mouseenterEvent);
|
||||
|
||||
//arrow right
|
||||
keyEvent.which = 39;
|
||||
seatCharts.get('1_1').node().trigger(keyEvent);
|
||||
seatCharts.get('1_2').node().trigger(keyEvent);
|
||||
|
||||
//spacebar
|
||||
keyEvent.which = 32;
|
||||
|
||||
seatCharts.get('1_4').node().trigger(keyEvent);
|
||||
|
||||
propEqual(executionsA, {
|
||||
click : 1,
|
||||
focus : 3,
|
||||
blur : 4,
|
||||
reset : function () {}
|
||||
}, 'Blur, focus and click are correctly triggered for A seats.');
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
24
libs/jQuery-Seat-Charts/test/index.html
Normal file
24
libs/jQuery-Seat-Charts/test/index.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>JSC Test Suite</title>
|
||||
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.14.0.css">
|
||||
<link rel="stylesheet" href="../jquery.seat-charts.css">
|
||||
<script src="http://code.jquery.com/qunit/qunit-1.14.0.js"></script>
|
||||
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
|
||||
<script type="text/javascript" src="../jquery.seat-charts.min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="general.js"></script>
|
||||
<script type="text/javascript" src="methods.js"></script>
|
||||
<script type="text/javascript" src="interactions.js"></script>
|
||||
<script type="text/javascript" src="multiple.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">JSC Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
</body>
|
||||
</html>
|
||||
283
libs/jQuery-Seat-Charts/test/interactions.js
Normal file
283
libs/jQuery-Seat-Charts/test/interactions.js
Normal file
@@ -0,0 +1,283 @@
|
||||
(function ($) {
|
||||
|
||||
module('interactions');
|
||||
|
||||
//Creates a very simple map and returns map's container.
|
||||
function interactionsMapSetup(params) {
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$div = $('<div id="seat-map">');
|
||||
|
||||
$fixture.append($div);
|
||||
|
||||
$div.seatCharts(
|
||||
$.extend(true, {}, {
|
||||
map: [
|
||||
'aa_aa',
|
||||
'aaaaa',
|
||||
'bbbbb',
|
||||
'bbbbb',
|
||||
'ccccc',
|
||||
'_____',
|
||||
'cc_cc',
|
||||
'_____',
|
||||
'cc___'
|
||||
],
|
||||
seats: {
|
||||
a: {
|
||||
classes : 'a1-seat-class a2-seat-class',
|
||||
price : 45,
|
||||
anObject : {
|
||||
aProperty: 'testing'
|
||||
}
|
||||
},
|
||||
b: {
|
||||
classes : ['b1-seat-class', 'b2-seat-class'],
|
||||
price : 25,
|
||||
anObject2: {
|
||||
aProperty2: 23
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}, params)
|
||||
);
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
test('Testing focus/blur with mouse', function () {
|
||||
expect(8);
|
||||
|
||||
var $seatCharts = interactionsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
seat1 = seatCharts.get('3_4'),
|
||||
seat2 = seatCharts.get('4_1'),
|
||||
mouseenterEvent,
|
||||
focusEvent;
|
||||
|
||||
//focus the first seat
|
||||
mouseenterEvent = $.Event('mouseenter');
|
||||
|
||||
seat1.node().trigger(mouseenterEvent);
|
||||
|
||||
equal(seat1.style(), 'focused', 'Test if focused using .style function.');
|
||||
|
||||
equal(seat1.node()[0], document.activeElement, 'Test if focused using document.activeElement');
|
||||
|
||||
equal($seatCharts.attr('aria-activedescendant'), seat1.node().attr('id'), 'Test if aria-activedescendant has been populated with the correct id.');
|
||||
|
||||
//move focus to some other seat
|
||||
seat2.node().trigger(mouseenterEvent);
|
||||
|
||||
equal(seat1.style(), 'available', 'Test if previous seat lost focus using .style function.');
|
||||
|
||||
equal(seat2.style(), 'focused', 'Test if focused using .style function.');
|
||||
|
||||
equal(seat2.node()[0], document.activeElement, 'Test if focused using document.activeElement');
|
||||
|
||||
equal($seatCharts.attr('aria-activedescendant'), '4_1', 'Test if aria-activedescendant has been populated with the correct id.');
|
||||
|
||||
focusEvent = $.Event('focus');
|
||||
$seatCharts.trigger(focusEvent);
|
||||
|
||||
equal(document.getElementById('1_1'), document.activeElement, 'First seat should be focused by default');
|
||||
|
||||
});
|
||||
|
||||
|
||||
test('Testing focus/blur with keyboard', function () {
|
||||
expect(14);
|
||||
|
||||
var $seatCharts = interactionsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
focusEvent,
|
||||
leftEvent,
|
||||
rightEvent,
|
||||
upEvent,
|
||||
downEvent;
|
||||
|
||||
focusEvent = $.Event('focus');
|
||||
$seatCharts.trigger(focusEvent);
|
||||
|
||||
leftEvent = $.Event('keydown');
|
||||
leftEvent.which = 37;
|
||||
|
||||
rightEvent = $.Event('keydown');
|
||||
rightEvent.which = 39;
|
||||
|
||||
downEvent = $.Event('keydown');
|
||||
downEvent.which = 40;
|
||||
|
||||
upEvent = $.Event('keydown');
|
||||
upEvent.which = 38;
|
||||
|
||||
seatCharts.get('1_1').node().trigger(rightEvent);
|
||||
|
||||
//right arrow
|
||||
|
||||
equal(document.activeElement, document.getElementById('1_2'), 'Right arrow moves focus to the right seat.');
|
||||
|
||||
equal($seatCharts.attr('aria-activedescendant'), seatCharts.get('1_2').node().attr('id'), 'Test if aria-activedescendant has been populated with the correct id.');
|
||||
|
||||
seatCharts.get('1_2').node().trigger(rightEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('1_4'), 'Right arrow moves focus to the right seat skipping the empty space.');
|
||||
|
||||
seatCharts.get('1_4').node().trigger(rightEvent);
|
||||
seatCharts.get('1_5').node().trigger(rightEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('2_1'), 'Right arrow moves focus to the first seat of the next row when it reaches the end of the current row.');
|
||||
|
||||
seatCharts.get('5_5').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('5_5').node().trigger(rightEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('7_1'), 'Right arrow moves focus to the first seat skipping empty spaces.');
|
||||
|
||||
seatCharts.get('9_1').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('9_1').node().trigger(rightEvent);
|
||||
|
||||
seatCharts.get('9_2').node().trigger(rightEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('1_1'), 'Right arrow moves focus to the first seat skipping empty spaces and starting over when the last seat is reached.');
|
||||
|
||||
//left arrow
|
||||
|
||||
seatCharts.get('2_3').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('2_3').node().trigger(leftEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('2_2'), 'Left arrow moves focus to the left seat.');
|
||||
|
||||
seatCharts.get('2_2').node().trigger(leftEvent);
|
||||
|
||||
seatCharts.get('2_1').node().trigger(leftEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('1_5'), 'Left arrow moves focus to the last seat of the previous row when the beginning of the current row is reached.');
|
||||
|
||||
seatCharts.get('9_1').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('9_1').node().trigger(leftEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('7_5'), 'Left arrow moves focus to the last seat of the previous row when the beginning of the current row is reached skipping empty spaces.');
|
||||
|
||||
seatCharts.get('1_1').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('1_1').node().trigger(leftEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('9_2'), 'Left arrow moves focus to the last seat when pressed on the first seat skipping empty spaces.');
|
||||
|
||||
//down
|
||||
|
||||
seatCharts.get('2_2').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('2_2').node().trigger(downEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('3_2'), 'Down arrow moves focus to the seat below.');
|
||||
|
||||
seatCharts.get('5_3').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('5_3').node().trigger(downEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('2_3'), 'Down arrow moves focus to the seat below skipping empty spaces.');
|
||||
|
||||
//up
|
||||
|
||||
seatCharts.get('4_4').node().trigger(focusEvent);
|
||||
|
||||
seatCharts.get('4_4').node().trigger(upEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('3_4'), 'Up arrow moves focus to the seat above.');
|
||||
|
||||
$(document.activeElement).trigger(upEvent);
|
||||
$(document.activeElement).trigger(upEvent);
|
||||
$(document.activeElement).trigger(upEvent);
|
||||
$(document.activeElement).trigger(upEvent);
|
||||
|
||||
equal(document.activeElement, document.getElementById('5_4'), 'Up arrow moves focus to the seat above skipping empty spaces.');
|
||||
});
|
||||
|
||||
test('Testing default click callback with mouse', function () {
|
||||
expect(7);
|
||||
|
||||
var $seatCharts = interactionsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
clickEvent,
|
||||
focusEvent;
|
||||
|
||||
//disable some seats
|
||||
seatCharts.get(['1_4', '4_2']).status('unavailable');
|
||||
|
||||
clickEvent = $.Event('click');
|
||||
|
||||
focusEvent = $.Event('focus');
|
||||
|
||||
$('#5_2').trigger(clickEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '1', 'Clicking on an available seat should change its status to selected.');
|
||||
|
||||
equal(seatCharts.get('5_2').style(), 'selected', 'Selected seat should return selected style.');
|
||||
|
||||
equal(seatCharts.get('5_2').status(), 'selected', 'Selected seat should return selected status.');
|
||||
|
||||
ok(seatCharts.get('5_2').node().hasClass('selected'), 'Selected seat should have selected class.');
|
||||
|
||||
$('#1_4').trigger(clickEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '1', 'You can not select an unavailable seat.');
|
||||
|
||||
$('#5_2').trigger(clickEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '0', 'Clicking on a selected seat should change its status to available.');
|
||||
|
||||
$('#3_3').trigger(focusEvent);
|
||||
|
||||
$('#3_3').trigger(clickEvent);
|
||||
|
||||
equal(seatCharts.get('3_3').status(), 'selected', 'Clicking on a focused seat should change its status to selected.');
|
||||
});
|
||||
|
||||
test('Testing default click callback with keyboard', function () {
|
||||
expect(7);
|
||||
|
||||
var $seatCharts = interactionsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
spacebarEvent,
|
||||
focusEvent;
|
||||
|
||||
//disable some seats
|
||||
seatCharts.find('c').status('unavailable');
|
||||
|
||||
spacebarEvent = $.Event('keydown');
|
||||
spacebarEvent.which = 32;
|
||||
|
||||
focusEvent = $.Event('focus');
|
||||
|
||||
$('#1_1').trigger(spacebarEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '1', 'Pressing spacebar on an available seat should change its status to selected.');
|
||||
|
||||
equal(seatCharts.get('1_1').style(), 'selected', 'Selected seat should return selected style.');
|
||||
|
||||
equal(seatCharts.get('1_1').status(), 'selected', 'Selected seat should return selected status.');
|
||||
|
||||
ok(seatCharts.get('1_1').node().hasClass('selected'), 'Selected seat should have selected class.');
|
||||
|
||||
$('#7_2').trigger(spacebarEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '1', 'You can not select an unavailable seat.');
|
||||
|
||||
$('#1_1').trigger(spacebarEvent);
|
||||
|
||||
equal(seatCharts.find('selected').length, '0', 'Pressing spacebar on a selected seat should change its status to available.');
|
||||
|
||||
$('#2_5').trigger(focusEvent);
|
||||
|
||||
$('#2_5').trigger(spacebarEvent);
|
||||
|
||||
equal(seatCharts.get('2_5').status(), 'selected', 'Pressing spacebar on a focused seat should change its status to selected.');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
294
libs/jQuery-Seat-Charts/test/methods.js
Normal file
294
libs/jQuery-Seat-Charts/test/methods.js
Normal file
@@ -0,0 +1,294 @@
|
||||
(function ($) {
|
||||
|
||||
module('methods');
|
||||
|
||||
//Creates a very simple map and returns map's container.
|
||||
function methodsMapSetup(params) {
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$div = $('<div id="seat-map">');
|
||||
|
||||
$fixture.append($div);
|
||||
|
||||
$div.seatCharts(
|
||||
$.extend(true, {}, {
|
||||
map: [
|
||||
'aa_aa',
|
||||
'aaaaa',
|
||||
'bbbbb',
|
||||
'bbbbb',
|
||||
'ccccc',
|
||||
],
|
||||
seats: {
|
||||
a: {
|
||||
classes : 'a1-seat-class a2-seat-class',
|
||||
price : 45,
|
||||
anObject : {
|
||||
aProperty: 'testing'
|
||||
}
|
||||
},
|
||||
b: {
|
||||
classes : ['b1-seat-class', 'b2-seat-class'],
|
||||
price : 25,
|
||||
anObject2: {
|
||||
aProperty2: 23
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}, params)
|
||||
);
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
test('Testing Seat methods & properties', function () {
|
||||
expect(9);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
seat = seatCharts.get('1_2');
|
||||
|
||||
equal(typeof seat.blur, 'function', '.blur method present.');
|
||||
equal(typeof seat.char, 'function', '.char method present.');
|
||||
equal(typeof seat.click, 'function', '.click method present.');
|
||||
equal(typeof seat.data, 'function', '.data method present.');
|
||||
equal(typeof seat.focus, 'function', '.focus method present.');
|
||||
equal(typeof seat.node, 'function', '.node method present.');
|
||||
equal(typeof seat.settings, 'object', '.settings property present.');
|
||||
equal(typeof seat.status, 'function', '.status method present.');
|
||||
equal(typeof seat.style, 'function', '.style method present.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing Seat Set methods & properties', function () {
|
||||
expect(11);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
seat = seatCharts.get(['1_2', '4_3']);
|
||||
|
||||
equal(typeof seat.each, 'function', '.each method present.');
|
||||
equal(typeof seat.find, 'function', '.find method present.');
|
||||
equal(typeof seat.get, 'function', '.get method present.');
|
||||
equal(typeof seat.length, 'number', '.length property present.');
|
||||
equal(typeof seat.node, 'function', '.node method present.');
|
||||
equal(typeof seat.push, 'function', '.push method present.');
|
||||
equal(typeof seat.seatIds, 'object', '.seatIds property present.');
|
||||
equal(seat.seatIds.length, 2, '.seatIds property correct.');
|
||||
equal(typeof seat.seats, 'object', '.seats property present.');
|
||||
equal(typeof seat.set, 'function', '.set method present.');
|
||||
equal(typeof seat.status, 'function', '.status method present.');
|
||||
});
|
||||
|
||||
test('Testing .get selector', function () {
|
||||
expect(7);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts();
|
||||
|
||||
equal(typeof seatCharts.get('1_1'), 'object', '.get for one id should return an object.');
|
||||
|
||||
equal(typeof seatCharts.get('1_1').length, 'undefined', '.get for one id should return an object without length property.');
|
||||
|
||||
equal(typeof seatCharts.get(['1_1', '3_3']), 'object', '.get for two ids should return an object.');
|
||||
|
||||
equal(seatCharts.get(['1_1', '3_3', '2_4']).length, 3, '.get for three ids should have a property length with value 3.');
|
||||
|
||||
equal(typeof seatCharts.get('99_99'), 'undefined', '.get for invalid id should return undefined.');
|
||||
|
||||
equal(typeof seatCharts.get(['99_99', '2_3']), 'object', '.get for invalid and valid id and should return an object.');
|
||||
|
||||
equal(seatCharts.get(['99_99', '2_3']).length, 1, 'With 1 as length.');
|
||||
|
||||
});
|
||||
|
||||
test('Testing .status method', function () {
|
||||
expect(10);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
seat1,
|
||||
seatsSet;
|
||||
|
||||
seat1 = seatCharts.get('2_3');
|
||||
|
||||
equal(seat1.status(), 'available', 'Default status is available.');
|
||||
|
||||
seat1.status('unavailable');
|
||||
|
||||
equal(seat1.status(), 'unavailable', 'Status has been changed.');
|
||||
|
||||
seat1.status('selected');
|
||||
|
||||
equal(seat1.status(), 'selected', 'Status has been changed again.');
|
||||
|
||||
seatsSet = seatCharts.get(['2_2', '2_4']);
|
||||
|
||||
seatsSet.status('selected');
|
||||
|
||||
equal(seatCharts.get('2_2').status(), 'selected', 'Setting status for the whole set 1.');
|
||||
equal(seatCharts.get('2_4').status(), 'selected', 'Setting status for the whole set 2.');
|
||||
|
||||
seatCharts.status('3_2', 'unavailable');
|
||||
|
||||
equal(seatCharts.get('3_2').status(), 'unavailable', 'Alternative .status usage.');
|
||||
|
||||
seatCharts.status(['4_4', '5_2', '5_1'], 'unavailable');
|
||||
|
||||
equal(seatCharts.get('4_4').status(), 'unavailable', 'Alternative .status usage for the whole set 1.');
|
||||
equal(seatCharts.get('5_2').status(), 'unavailable', 'Alternative .status usage for the whole set 2.');
|
||||
equal(seatCharts.get('5_1').status(), 'unavailable', 'Alternative .status usage for the whole set 3.');
|
||||
|
||||
//Issue #8 - Very odd behaviour when using sc.status();
|
||||
seatCharts.get(['1_1', '1_2']).status('unavailable');
|
||||
|
||||
//settings the same status twice
|
||||
seatCharts.get(['1_1', '1_2']).status('unavailable');
|
||||
|
||||
equal(seatCharts.get('1_1').status(), 'unavailable', 'Status remains correct after setting the same status again');
|
||||
});
|
||||
|
||||
test('Testing .find selector', function () {
|
||||
expect(16);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts();
|
||||
|
||||
seatCharts.get(['4_1', '1_5', '2_3']).status('unavailable');
|
||||
|
||||
seatCharts.get(['5_2', '1_4']).status('selected');
|
||||
|
||||
equal(seatCharts.find('available').length, 19, 'Finding by status alone.');
|
||||
|
||||
equal(seatCharts.find('avble').length, 0, 'Finding by invalid status alone.');
|
||||
|
||||
equal(seatCharts.get(['4_1', '4_2']).find('unavailable').length, 1, 'Finding in set by status alone.');
|
||||
|
||||
equal(seatCharts.find('c').length, 5, 'Finding by character alone.');
|
||||
|
||||
equal(seatCharts.find('O').length, 0, 'Finding by invalid character.');
|
||||
|
||||
equal(seatCharts.get(['2_1', '3_2', '5_5', '5_3', '4_2']).find('b').length, 2, 'Finding in set by character alone.');
|
||||
|
||||
equal(seatCharts.get(['2_1', '3_2', '5_5', '5_3', '4_2']).find('_').length, 0, 'Finding in set by invalid character.');
|
||||
|
||||
equal(seatCharts.find('c.available').length, 4, 'Finding by character and status.');
|
||||
|
||||
equal(seatCharts.find('c.able').length, 0, 'Finding by character and invalid status.');
|
||||
|
||||
equal(seatCharts.find('P.availble').length, 0, 'Finding by invalid character and status.');
|
||||
|
||||
equal(seatCharts.get(['2_1', '3_2', '5_5', '5_3', '4_2', '2_3']).find('b.available').length, 2, 'Finding in set by character and status.');
|
||||
|
||||
equal(seatCharts.get(['2_1', '3_2', '5_5', '5_3', '4_2', '2_3']).find('X.available').length, 0, 'Finding in set by invalid character and status.');
|
||||
|
||||
equal(seatCharts.get(['2_1', '3_2', '5_5', '5_3', '4_2', '2_3']).find('c.invalid-status').length, 0, 'Finding in set by character and invalid status.');
|
||||
|
||||
equal(seatCharts.get(['9_12', '', '4_53']).find('b').length, 0, 'Finding in empty set.');
|
||||
|
||||
equal(seatCharts.find(/^1_.*/).length, 4, 'Finding first row seats using a regexp.');
|
||||
|
||||
equal(seatCharts.find(/^[0-9]+_3/).length, 4, 'Finding third column seats using a regexp.');
|
||||
});
|
||||
|
||||
test('Testing .node method', function () {
|
||||
expect(6);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts();
|
||||
|
||||
seatCharts.get(['2_2', '5_4']).status('unavailable');
|
||||
|
||||
ok(seatCharts.get('1_4').node() instanceof jQuery, '.node returns a jQuery object.');
|
||||
|
||||
equal(seatCharts.get('2_3').node().length, 1, '.node for one seat returns set with 1 element.');
|
||||
|
||||
equal(seatCharts.get(['2_3', '4_2']).node().length, 2, '.node for two seats returns set with 2 elements.');
|
||||
|
||||
equal(seatCharts.find('c.available').node().length, 4, '.node returns jQuery set with all objects matching .find query.');
|
||||
|
||||
equal(seatCharts.get('1_4').node()[0], $('#1_4')[0], 'The same node returned by .get and jQuery selector.');
|
||||
|
||||
equal(seatCharts.get(['2_2', '3_5']).node()[1], $('#3_5')[0], 'The same nodes returned by .get and jQuery selector.');
|
||||
});
|
||||
|
||||
test('Testing .each method', function () {
|
||||
expect(4);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts(),
|
||||
executions1 = 0,
|
||||
executions2 = 0,
|
||||
executions3 = 0;
|
||||
|
||||
seatCharts.get(['5_2', '5_1']).status('selected');
|
||||
|
||||
seatCharts.find('c.available').each(function () {
|
||||
executions1 += 1;
|
||||
});
|
||||
|
||||
equal(executions1, 3, '.each callback should be called for each element of the set.');
|
||||
|
||||
seatCharts.find('c').each(function () {
|
||||
executions2 += 1;
|
||||
|
||||
return false; //break
|
||||
});
|
||||
|
||||
equal(executions2, 1, 'Returning false should break .each loop.');
|
||||
|
||||
seatCharts.find('Z').each(function() {
|
||||
executions3 += 1;
|
||||
});
|
||||
|
||||
equal(executions3, 0, '.each should not be called when the set is empty.');
|
||||
|
||||
seatCharts.find('a').each(function () {
|
||||
equal(typeof this.data, 'function', 'Seat is used as the context.');
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
test('Testing .data method', function () {
|
||||
expect(4);
|
||||
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts();
|
||||
|
||||
propEqual(seatCharts.get('1_2').data(), {
|
||||
classes : 'a1-seat-class a2-seat-class',
|
||||
price : 45,
|
||||
anObject : {
|
||||
aProperty: 'testing'
|
||||
}
|
||||
}, 'a seat has correct properties.');
|
||||
|
||||
propEqual(seatCharts.get('3_4').data(), {
|
||||
classes : ['b1-seat-class', 'b2-seat-class'],
|
||||
price : 25,
|
||||
anObject2: {
|
||||
aProperty2: 23
|
||||
}
|
||||
}, 'b seat has correct properties.');
|
||||
|
||||
propEqual(seatCharts.get('5_2').data(), {}, 'c seat has correct properties.');
|
||||
|
||||
seatCharts.get('1_2').data().price = '75';
|
||||
|
||||
equal(seatCharts.get('1_1').data().price, '75', 'All seat of the same character share the reference to the same object');
|
||||
|
||||
});
|
||||
|
||||
test('Testing .char method', function () {
|
||||
var $seatCharts = methodsMapSetup(),
|
||||
seatCharts = $seatCharts.seatCharts();
|
||||
|
||||
equal(seatCharts.get('5_5').char(), 'c', 'Correct character returned 1.');
|
||||
|
||||
equal(seatCharts.get('2_3').char(), 'a', 'Correct character returned 2.');
|
||||
|
||||
equal(seatCharts.get('4_4').char(), 'b', 'Correct character returned 3.');
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
57
libs/jQuery-Seat-Charts/test/multiple.js
Normal file
57
libs/jQuery-Seat-Charts/test/multiple.js
Normal file
@@ -0,0 +1,57 @@
|
||||
(function ($) {
|
||||
|
||||
module('multiple');
|
||||
|
||||
//testing multiple maps on page to ensure there are no conflicts
|
||||
function multipleMapSetup(params) {
|
||||
|
||||
multipleMapSetup.counter = multipleMapSetup.counter || 1;
|
||||
|
||||
var $fixture = $('#qunit-fixture'),
|
||||
$div = $('<div id="seat-map-'+(multipleMapSetup.counter++)+'">');
|
||||
|
||||
$fixture.append($div);
|
||||
|
||||
$div.seatCharts(
|
||||
$.extend(true, {}, {
|
||||
map: [
|
||||
'aa_aa',
|
||||
'bbbbb',
|
||||
'bbbbb'
|
||||
],
|
||||
seats: {
|
||||
a: {
|
||||
classes : 'a1-seat-class a2-seat-class'
|
||||
},
|
||||
b: {
|
||||
classes : ['b1-seat-class', 'b2-seat-class']
|
||||
}
|
||||
|
||||
}
|
||||
}, params)
|
||||
);
|
||||
|
||||
return $div;
|
||||
}
|
||||
|
||||
test('Testing selectors for multi maps', function () {
|
||||
var $seatCharts1 = multipleMapSetup(),
|
||||
seatCharts1 = $seatCharts1.seatCharts(),
|
||||
$seatCharts2 = multipleMapSetup({
|
||||
map: [
|
||||
'eeeeeeeee',
|
||||
'baaabaaaa',
|
||||
'bbbbb____'
|
||||
],
|
||||
}),
|
||||
seatCharts2 = $seatCharts2.seatCharts();
|
||||
|
||||
seatCharts1.find('a.available').status('unavailable');
|
||||
|
||||
equal(seatCharts1.find('unavailable').length, 4, 'Status has been changed correctly');
|
||||
|
||||
equal(seatCharts2.find('unavailable').length, 0, 'Status has not been changed for the other map.');
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user