jquery-seat-charts使用-座席番号のカスタマイズとデータの再ロード

27914 ワード

一.座席番号のカスタマイズ(データ・ソースの再ロード)

1.カスタムデータ
var data1 = [['aa1','aa2','aa3','aa4','aa5','aa6'],['bb1','bb2','bb3','bb4','bb5','bb6'],['cc1','cc2','cc3','cc4','cc5','cc6']];

2.html転送データ
			naming: {//       
				top: false, //        ( ) 
				// rows: ['3', '2', '1'],
				// columns: ['A', 'B', 'C', 'G', 'D', 'F'],
				getLabel: function(character, row, column) { //       
					return column;
				},
				getData:function(dataList){
					console.log(dataList)
					return dataList;
				},
				data:data1
			},

3.ソースコードの修正は400行程度、ケーブルの修正
							seats[id] = new seat({
								id        : id,
								label     : naming.data[row][column] ,

								// label     : overrideLabel ?	overrideLabel : naming.getLabel(character, naming.rows[row], naming.columns[column]),
								row       : row,
								column    : column,
								character : character
							});

4.ソースコード修正、25行程度でdataパラメータを入れる
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;
					},
					data:[]
				},

二.データの再リフレッシュ
ソースコードの開始位置の変更
	if (this.data('seatCharts')) {
			// console.log(this.data('seatCharts'))
			// return this.data('seatCharts');

			// console.log(setup)
			// console.log(setup.legend.items)
			// console.log(this.data('seatCharts'))
			var ary = setup.legend.items;
			ary.splice(0,ary.length); 
			this.empty();
		}
フル・インスタンス
html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>test</title>
<link rel="stylesheet" type="text/css" href="css/roomchartcommon.css" />
<script type="text/javascript" src="js/jquery-1.11.2.js"></script>
<script type="text/javascript" src="js/jquery.seat-charts.js"></script>
<script type="text/javascript">
	var price = 100; //   
	var beforeroom;
			var $cart = $('#rooms_selected'), //   
			$rooms_num = $('#rooms_num'), //   
			$total_price = $('#rooms_price'); //   
			$roomNo = $('#roomNo');//   
			$roomMsg = $('#roomMsg');//    
			var sc ;
	var data1 = [['aa1','aa2','aa3','aa4','aa5','aa6'],['bb1','bb2','bb3','bb4','bb5','bb6'],
					  ['cc1','cc2','cc3','cc4','cc5','cc6']];
	var data2 = [['dd1','dd2','dd3','dd4','dd5','dd6'],['ee1','ee2','ee3','ee4','ee5','ee6'],
					  ['ff1','ff2','ff3','ff4','ff5','ff6']];					  
	$(document).ready(function() {
		initchart(data1);
	});
	function initchart(dataList){
		sc = $('#room_area').seatCharts({
			map: [//      f      ;e      ;     "_"     
				'ffffff',
				'eeeeee',
				'ffeeee'
			],
			seats: {//             
				f: {
					price: 125,
					classes: 'first-class',
					category: '   '
				},
				e: {
					price: 70,
					classes: 'economy-class',
					category: '   '
				}
			},
			naming: {//       
				top: false, //        ( ) 
				// rows: ['3', '2', '1'],
				// columns: ['A', 'B', 'C', 'G', 'D', 'F'],
				getLabel: function(character, row, column) { //       
					return column;
				},
				getData:function(dataList){
					console.log(dataList)
					return dataList;
				},
				data:dataList
			},
			legend: {//    
				node: $('#roomlegend'),
				items: [
					['f', 'available', '   '],
					['e', 'available', '   '],
					['f', 'unavailable', '   ']
				]
			},
			click: function() {
				if (this.status() == 'available') { //      ,      
					var roomNoText = $('<li>' + this.settings.label + ' </li>')
							.attr('id', 'cart-item-' + this.settings.id)
							.data('seatId', this.settings.id).text();
					$roomNo.text(roomNoText);
					var roomMsgHtml = '<span>      </span><br><input type="button" class="roominbtn" value="  "/>';
					$roomMsg.html(roomMsgHtml);
					return 'selected';
					$('<li>' + (this.settings.row + 1) + this.settings.label + ' </li>')
							.attr('id', 'cart-item-' + this.settings.id)
							.data('seatId', this.settings.id)
							.appendTo($cart);

					$rooms_num.text(sc.find('selected').length + 1); //      
					$total_price.text(getTotalPrice(sc) + price);//       

					return 'selected';
				} else if (this.status() == 'selected') { //      

					$rooms_num.text(sc.find('selected').length - 1);//     
					$total_price.text(getTotalPrice(sc) - price);//       
					$('#cart-item-' + this.settings.id).remove();//       

					return 'available';
				} else if (this.status() == 'unavailable') { //      
					var roomNoText = $('<li>' + this.settings.label + ' </li>')
							.attr('id', 'cart-item-' + this.settings.id)
							.data('seatId', this.settings.id).text();
							console.log(roomNoText);
					$roomNo.text(roomNoText);
					var roomMsgText = "  、  、  、  ";
					$roomMsg.text(roomMsgText);
					return 'unavailable';
				} else {
					return this.style();
				}
			}
		});
		//        
		sc.get(['3_03', '2_05']).status('unavailable');
	}
	function refresh(){
		// console.log(sc);
		// sc.dataReload(data2)
		initchart(data2)
	}
</script>
</head>
<body>
	<button style="float:right;width:150px;height:30px;" onclick="refresh()">    </button>
	<div class="roomcontent">
		<div id="room_area">
		</div>
		<div id="roomlegend" class='of'></div>
		<div id="roomdetail">
			<h3>      </h3>
			<div id="roomNo">
			</div>
			<div id="roomMsg">
			</div>
		</div>
	</div>


</body>
</html>


ソースコード
/*
 * jQuery-Seat-Charts v1.1.0
*/
(function($) {
	$.fn.seatCharts = function (setup) {

		//if there's seatCharts object associated with the current element, return it
		if (this.data('seatCharts')) {
			// console.log(this.data('seatCharts'))
			// return this.data('seatCharts');

			// console.log(setup)
			// console.log(setup.legend.items)
			// console.log(this.data('seatCharts'))
			var ary = setup.legend.items;
			ary.splice(0,ary.length); 
			this.empty();
		}
		
		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;
					},
					data:[]
				},
				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;
								}
								
								//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("0"+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) {
						//console.log(naming);
						//so users don't have to specify empty objects
						// console.log(naming);
						// console.log("character"+naming.getLabel(character, naming.rows[row], naming.columns[column]));
						// console.log("row"+row);
						// console.log(column);
						// console.log(naming.data)
						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     : naming.data[row][column] ,

								// 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();
			
				//user searches just for a particual character
				return query.length == 1 ? (function(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;
					})();
			},
			dataReload : function(data){
				// console.log(this)
				// console.log(data);
			}
		});		
		return fn.data('seatCharts');
	}
})(jQuery);