2017-10-13 136 views
0

我正在使用Jquery Seat Chart作为订票系统。一切工作正常,但是当我打电话给返回已经预订的座位的功能时,座位的状态不会改变为'已经预订'。jquery.seat-charts.js未捕获的TypeError:无法读取未定义的属性“状态”

我得到'jquery.seat-charts.js未捕获TypeError:无法读取未定义'错误的属性'状态'。

这里是我的代码:

function getBookedSeats() { 
     jQuery(document).ready(function ($) { 
      $.ajax({ 
       type  : 'get', 
       url  : 'bookings/getSelectedSeats', 
       data  : 'show_id=<?php echo $show_id ?>', 
       success : function(response) { 
        response1 = JSON.parse(response); 
        $.each(response1.bookings, function (index, booking) { 
         sc.status(booking.seat_id, 'unavailable'); 
        }); 

       } 
      }); 
     }); 
    } 

和错误IAM越来越是jquery.seat-chart.js之线486

jquery.seat-chart.js之

(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 = $('<div class="row"></div>') 
      .addClass('seatCharts-legendList') 
      .appendTo($container); 

     $.each(legend.items, function(index, item) { 
      $ul.append(
       $('<div class="col-md-2 col-xs-2"></div>') 
        .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);

+0

Ajax调用内部的'sc'变量是不确定的,你不能得到一个属性(在此case'status')未定义的变量。 –

回答

0

由于sc.status(par1,par2)期望第一个par1的格式为'Row_Col',第二个par2不可用。我不得不到座位号转换成PAR1格式:

$.each(response1.bookings, function (index, booking) { 
var seat_n = convertSeat(booking.seat_id); 
sc.get(seat_n).status('unavailable'); 
}); 

convertSeat()

function convertSeat(seat_number) { 
     if(seat_number <= 29){ 
      var seat_node = 'A_'+seat_number; 
      return seat_node; 
     } 
     else if(seat_number <= 58){ 
      var seat = seat_number - 29; 
      var seat_node = 'B_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 87){ 
      var seat = seat_number - 58; 
      var seat_node = 'C_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 116){ 
      var seat = seat_number - 87; 
      var seat_node = 'D_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 145){ 
      var seat = seat_number - 116; 
      var seat_node = 'E_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 174){ 
      var seat = seat_number - 145; 
      var seat_node = 'F_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 203){ 
      var seat = seat_number - 174; 
      var seat_node = 'G_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 232){ 
      var seat = seat_number - 203; 
      var seat_node = 'H_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 261){ 
      var seat = seat_number - 232; 
      var seat_node = 'I_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 290){ 
      var seat = seat_number - 261; 
      var seat_node = 'J_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 319){ 
      var seat = seat_number - 290; 
      var seat_node = 'K_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 348){ 
      var seat = seat_number - 319; 
      var seat_node = 'L_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 377){ 
      var seat = seat_number - 348; 
      var seat_node = 'M_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 406){ 
      var seat = seat_number - 377; 
      var seat_node = 'N_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 435){ 
      var seat = seat_number - 406; 
      var seat_node = 'O_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 464){ 
      var seat = seat_number - 435; 
      var seat_node = 'P_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 493){ 
      var seat = seat_number - 464; 
      var seat_node = 'Q_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 522){ 
      var seat = seat_number - 493; 
      var seat_node = 'R_'+seat; 
      return seat_node; 
     } 
     else if(seat_number <= 551){ 
      var seat = seat_number - 522; 
      var seat_node = 'S_'+seat; 
      return seat_node; 
     } 
    } 
相关问题