<commit_before>Tickets = function(self){
  this.calendar = function(month, year, data) {
    if ( typeof(month) === 'object' ) {
      data = month;
      month = null;
    }
    this.current_date = new Date();
    this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
    this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
    this.draw = function(ele){
        // get dates
        var startingDay = new Date(this.year, this.month, 1).getDay(),
        endingDate = new Date(this.year, this.month + 1, 0),
        monthLength = endingDate.getDate(),
        inLastRow = 6 - endingDate.getDay();
        if (this.month > 11) {
          this.month -= 12;
          this.year += 1;
        } else if (this.month < 0) {
          this.month += 12;
          this.year -= 1;
        }

        // generate header
        this.table = document.createElement('table');
        this.head = document.createElement('thead');
        this.prev = document.createElement('th');
        this.next = document.createElement('th');
        this.title = document.createElement('th');
        this.days = document.createElement('tr');
        this.body = document.createElement('tbody');
        this.cells = '';
        this.table.setAttribute('class', 'calendar');
        this.table.appendChild(this.head);
        this.head.appendChild(this.prev);
        this.prev.innerHTML = "«";
        this.prev.id = 'prev';
        this.head.appendChild(this.title);
        this.head.appendChild(this.next);
        this.next.innerHTML = "»";
        this.next.id = 'next';
        this.table.appendChild(this.days);
        this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
        this.title.setAttribute('colspan', '5');
        this.days.setAttribute('class', 'header');
        for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
        this.days.innerHTML = this.cells;

        //generate calendar
        var html = '
';
        if ( startingDay ) html += '	';
        for (var day = 1; day <= monthLength; day++) {
        html += '
' + day + '
';
        //if data argument present, append key value for current day
        if (data) {
          var today = (this.month+1)+'/'+day+'/'+this.year;
          if (data[today]) {
            html += '
'+Object.keys(data[today]).length+' '+data.type+'
';
            html += '
<button class="btn btn-primary" onclick="db.Tickets.showTickets(db.Tickets.sortTickets()[\''+today+'\']);">Show Tickets</button>
';
          }
        }
        html += '	';
        if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
        }
        if ( inLastRow ) html += '	';
        html += '
';
        this.table.innerHTML += html;
        if (ele) {
          ele.innerHTML = this.table.outerHTML;
        } else {
          return this.table.outerHTML;
        }
        // save reference to dom node in object
        this.node = ele;
        // save reference to calendar object for enclosure scope
        var cal = this;
            (function(){
          // save calendar object reference for listeners
          var self = this;
          self.prev.addEventListener('click', function(){
            cal.month--;
            cal.draw(cal.node);
          });
          self.next.addEventListener('click', function(){
            cal.month++;
            cal.draw(cal.node);
          });
          document.onkeydown = function(e) {
            e = e || window.event;
              if (e.keyCode == '37') {
                // left arrow
                cal.month--;
                cal.draw(cal.node);
              } else if (e.keyCode == '39') {
                // right arrow
                cal.month++;
                cal.draw(cal.node);
              }
          };
        })();
      };
  };
  this.getTickets = function() {
    var lp = ko.dataFor(app);
    //get tickets
    if (lp.contentViewModel() !== undefined){
      if (typeof(lp.contentViewModel().myTickets) === "function"){
        self.Tickets.ticketArray = lp.contentViewModel().myTickets();
      }
    } else if (localStorage.getItem('ticketCache') !== null){
      self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
    }
    //return results
    if (self.Tickets.ticketArray) {
      localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
      return self.Tickets.ticketArray;
    } else {
      alert('Unable to access tickets at this time!');
      return [];
    }
  };
  this.getCritical = function() {
    var tickets = this.getTickets(),
    critical = [];
    for (var i = 0; i < tickets.length; i++) {
      if (tickets[i].ScheduledEndDate < new Date()) {
        critical.push(tickets[i]);
      }
    }
    if (tickets.length > 0){
      return critical;
    } else {
      return false;
    }
  };
  this.countCritical = function() {
    var criticals = self.Tickets.getCritical();
    if (criticals) {
      return 'Critical Tickets: ' + criticals.length + '';
    } else {
      return 'Error loading tickets!';
    }
  };
  this.sortTickets = function(tickets){
    if (! tickets){
      tickets = this.getTickets();
    }
    var data = {type: 'Tickets'};
    for (var i=0;i<tickets.length;i++){
      var ticket = tickets[i],
      date = new Date(ticket.ScheduledEndDate),
      day = (date.getMonth()+1)+'/'+date.getDate()+'/'+date.getFullYear();
      if (! data[day]){ data[day] = [];}
      data[day].push(ticket);
    }
    return data;
  };
  this.listTickets = function(tickets){
    var list = document.createElement('table'),
    head = list.appendChild(document.createElement('tr'));
    head.innerHTML = 'Business Name	Ticket Type	Due Date	';
    list.className = 'sortable';
    for (var i=0;i<tickets.length;i++){
      var ticket = tickets[i],
      listItem = document.createElement('tr'),
      content = ''+ticket.CompanyName+'	'+ticket.TicketTypeName+'	';
      content += ''+(ticket.ScheduledEndDate.getMonth()+1);
      content += '/'+ticket.ScheduledEndDate.getDate()+'/';
      content += ticket.ScheduledEndDate.getFullYear()+'	';
      listItem.innerHTML = content;
      listItem.setAttribute('data-client', ticket.CustomerId);
      listItem.onclick = function(){
        self.Tools.openClient(this.dataset.client);
        var modals = document.getElementsByClassName('bootbox-close-button');
        for (var i=0;i<modals.length;i++){modals[i].click();}
      };
      list.appendChild(listItem);
    }
    return list;
  };
  this.showTickets = function(tickets){
    bootbox.dialog({
      message: self.Tickets.listTickets(tickets),
      title: "Tickets (click row to open client)",
      className: "ticket-list",
      buttons: {},
    });
  };
  this.tryCache = function(){
    try {
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
      }
    } catch(err) {
      setTimeout(function(){self.Tickets.tryCache();}, 1000);
    }
  };
};
<commit_msg>Update tickets.js<commit_after>Tickets = function(self){
  this.calendar = function(month, year, data) {
    if ( typeof(month) === 'object' ) {
      data = month;
      month = null;
    }
    this.current_date = new Date();
    this.day_labels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    this.month_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    this.month = (isNaN(month) || month === null) ? this.current_date.getMonth() : month;
    this.year = (isNaN(year) || year === null) ? this.current_date.getFullYear() : year;
    this.draw = function(ele){
        // get dates
        var startingDay = new Date(this.year, this.month, 1).getDay(),
        endingDate = new Date(this.year, this.month + 1, 0),
        monthLength = endingDate.getDate(),
        inLastRow = 6 - endingDate.getDay();
        if (this.month > 11) {
          this.month -= 12;
          this.year += 1;
        } else if (this.month < 0) {
          this.month += 12;
          this.year -= 1;
        }

        // generate header
        this.table = document.createElement('table');
        this.head = document.createElement('thead');
        this.prev = document.createElement('th');
        this.next = document.createElement('th');
        this.title = document.createElement('th');
        this.days = document.createElement('tr');
        this.body = document.createElement('tbody');
        this.cells = '';
        this.table.setAttribute('class', 'calendar');
        this.table.appendChild(this.head);
        this.head.appendChild(this.prev);
        this.prev.innerHTML = "«";
        this.prev.id = 'prev';
        this.head.appendChild(this.title);
        this.head.appendChild(this.next);
        this.next.innerHTML = "»";
        this.next.id = 'next';
        this.table.appendChild(this.days);
        this.title.innerHTML = this.month_labels[this.month] + " " + this.year;
        this.title.setAttribute('colspan', '5');
        this.days.setAttribute('class', 'header');
        for (var i = 0; i <= 6; i++ ) this.cells += '' + this.day_labels[i] + '	';
        this.days.innerHTML = this.cells;

        //generate calendar
        var html = '
';
        if ( startingDay ) html += '	';
        for (var day = 1; day <= monthLength; day++) {
        html += '
' + day + '
';
        //if data argument present, append key value for current day
        if (data) {
          var today = (this.month+1)+'/'+day+'/'+this.year;
          if (data[today]) {
            html += '
'+Object.keys(data[today]).length+' '+data.type+'
';
            html += '
<button class="btn btn-primary" onclick="db.Tickets.showTickets(db.Tickets.sortTickets()[\''+today+'\']);">Show Tickets</button>
';
          }
        }
        html += '	';
        if ( (day + startingDay) % 7 === 0 && day != monthLength ) html += '

';
        }
        if ( inLastRow ) html += '	';
        html += '
';
        this.table.innerHTML += html;
        if (ele) {
          ele.innerHTML = this.table.outerHTML;
        } else {
          return this.table.outerHTML;
        }
        // save reference to dom node in object
        this.node = ele;
        // save reference to calendar object for enclosure scope
        var cal = this;
            (function(){
          // save calendar object reference for listeners
          var self = this;
          self.prev.addEventListener('click', function(){
            cal.month--;
            cal.draw(cal.node);
          });
          self.next.addEventListener('click', function(){
            cal.month++;
            cal.draw(cal.node);
          });
          document.onkeydown = function(e) {
            e = e || window.event;
              if (e.keyCode == '37') {
                // left arrow
                cal.month--;
                cal.draw(cal.node);
              } else if (e.keyCode == '39') {
                // right arrow
                cal.month++;
                cal.draw(cal.node);
              }
          };
        })();
      };
  };
  this.getTickets = function() {
    var lp = ko.dataFor(app);
    //get tickets
    if (lp.contentViewModel() !== undefined){
      if (typeof(lp.contentViewModel().myTickets) === "function"){
        self.Tickets.ticketArray = lp.contentViewModel().myTickets();
      }
    } else if (localStorage.getItem('ticketCache') !== null){
      self.Tickets.ticketArray = JSON.parse(localStorage.getItem('ticketCache'));
    }
    //return results
    if (self.Tickets.ticketArray) {
      localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
      return self.Tickets.ticketArray;
    } else {
      alert('Unable to access tickets at this time!');
      return [];
    }
  };
  this.getCritical = function() {
    var tickets = this.getTickets(),
    critical = [];
    for (var i = 0; i < tickets.length; i++) {
      if (tickets[i].ScheduledEndDate < new Date()) {
        critical.push(tickets[i]);
      }
    }
    if (tickets.length > 0){
      return critical;
    } else {
      return false;
    }
  };
  this.countCritical = function() {
    var criticals = self.Tickets.getCritical();
    if (criticals) {
      return 'Critical Tickets: ' + criticals.length + '';
    } else {
      return 'Error loading tickets!';
    }
  };
  this.sortTickets = function(tickets){
    if (! tickets){
      tickets = this.getTickets();
    }
    var data = {type: 'Tickets'};
    for (var i=0;i<tickets.length;i++){
      var ticket = tickets[i],
      date = new Date(ticket.ScheduledEndDate),
      day = (date.getMonth()+1)+'/'+date.getDate()+'/'+date.getFullYear();
      if (! data[day]){ data[day] = [];}
      data[day].push(ticket);
    }
    return data;
  };
  this.listTickets = function(tickets){
    var list = document.createElement('table'),
    head = list.appendChild(document.createElement('thead')),
    body = list.appendChild(document.createElement('tbody'));
    head.innerHTML = '
Business Name	Ticket Type	Due Date
';
    sorttable.makeSortable(list);
    for (var i=0;i<tickets.length;i++){
      var ticket = tickets[i],
      listItem = document.createElement('tr'),
      content = ''+ticket.CompanyName+'	'+ticket.TicketTypeName+'	';
      content += ''+(ticket.ScheduledEndDate.getMonth()+1);
      content += '/'+ticket.ScheduledEndDate.getDate()+'/';
      content += ticket.ScheduledEndDate.getFullYear()+'	';
      listItem.innerHTML = content;
      listItem.setAttribute('data-client', ticket.CustomerId);
      listItem.onclick = function(){
        self.Tools.openClient(this.dataset.client);
        var modals = document.getElementsByClassName('bootbox-close-button');
        for (var i=0;i<modals.length;i++){modals[i].click();}
      };
      body.appendChild(listItem);
    }
    return list;
  };
  this.showTickets = function(tickets){
    bootbox.dialog({
      message: self.Tickets.listTickets(tickets),
      title: "Tickets (click row to open client)",
      className: "ticket-list",
      buttons: {},
    });
  };
  this.tryCache = function(){
    try {
      if (self.Tickets.ticketArray) {
        localStorage.setItem('ticketCache', JSON.stringify(self.Tickets.ticketArray));
      }
    } catch(err) {
      setTimeout(function(){self.Tickets.tryCache();}, 1000);
    }
  };
};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    <%# expression %>: dynamic (auto-updating) expression is output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *    $$feature(<whitespace>|<): output the View or Action for the current Value
 */

var TemplateParser = {
  __proto__: grammar,

  START: sym('markup'),

  markup: repeat0(alt(
    sym('tag'),
    sym('create child'),
    sym('simple value'),
    sym('live value tag'),
    sym('raw values tag'),
    sym('values tag'),
    sym('code tag'),
    sym('ignored newline'),
    sym('newline'),
    sym('single quote'),
    sym('text')
  )),

  'create child': seq('$$', repeat(notChars(' $\n<{')),
                      optional(JSONParser.export('objAsString'))),

  'simple value': seq('%%', repeat(notChars(' "\n<'))),

  'live value tag': seq('<%#', repeat(not('%>', anyChar)), '%>'),

  'raw values tag': alt(
    seq('<%=', repeat(not('%>', anyChar)), '%>'),
    seq('{{{', repeat(not('}}}', anyChar)), '}}}')
  ),

  'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

  'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
  'ignored newline': literal('\\\n'),
  newline: literal('\n'),
  'single quote': literal("'"),
  text: anyChar
};

var TemplateOutput = {
  /**
   * obj - Parent object.  If objects are output and have an initHTML() method, then they
   * are added to the parent by calling obj.addChild().
   **/
  // TODO(kgr): redesign, I think this is actually broken.  If we call appendHTML() of
  // a sub-view then it will be added to the wrong parent.
  create: function(obj) {
    var buf = '';
    var f = function(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        if ( o && o.toView_ ) o = o.toView_();
        if ( ! ( o === null || o === undefined ) ) {
          if ( o.appendHTML ) {
            o.appendHTML(this);
          } else if ( o.toHTML ) {
            buf += o.toHTML();
          } else {
            buf += o;
          }
          if ( o.initHTML && obj.addChild ) obj.addChild(o);
        }
      }
    };

    f.toString = function() { return buf; };

    return f;
  }
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  push: function() { this.out.push.apply(this.out, arguments); },

  header: 'var self = this; var X = this.X; var escapeHTML = View.getPrototype().strToHTML; var out = opt_out ? opt_out : TemplateOutput.create(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
   markup: function (v) {
     var ret = this.header + this.out.join('') + this.footer;
     this.out = [];
     return ret;
   },
   'create child': function(v) {
     var name = v[1].join('').constantize();
     this.push("', self.createTemplateView('", name, "'",
               v[2] ? ', ' + v[2] : '',
               "),\n'");
   },
   'simple value': function(v) { this.push("',\n self.", v[1].join(''), ",\n'"); },
   'raw values tag': function (v) { this.push("',\n", v[1].join(''), ",\n'"); },
   'values tag': function (v) { this.push("',\nescapeHTML(", v[1].join(''), "),\n'"); },
   'live value tag': function (v) { this.push("',\nself.dynamicTag('span', function() { return ", v[1].join(''), "; }.bind(this)),\n'"); },
   'code tag': function (v) { this.push("');\n", v[1].join(''), ";out('"); },
   'single quote': function () { this.push("\\'"); },
   newline: function () { this.push("\\n"); },
   text: function(v) { this.push(v); }
});

var TemplateUtil = {

   /** Create a method which only compiles the template when first used. **/
   lazyCompile: function(t) {
     var delegate;

     return function() {
       if ( ! delegate ) {
         if ( ! t.template )
           throw 'Must arequire() template model before use for ' + this.name_ + '.' + t.name;
         delegate = TemplateUtil.compile(Template.isInstance(t) ? t : Template.create(t));
       }

       return delegate.apply(this, arguments);
     };
   },

   compile: window.chrome && window.chrome.app && window.chrome.app.runtime ?
     function() {
       return function() {
         return "Models must be arequired()'ed for Templates to be compiled in Packaged Apps.";
       };
     } :
     function(t) {
       var code = TemplateCompiler.parseString(t.template);

       try {
         var args = ['opt_out'];
         for ( var i = 0 ; i < t.args.length ; i++ ) {
           args.push(t.args[i].name);
         }
         args.push(code);
         return Function.apply(null, args);
       } catch (err) {
         console.log('Template Error: ', err);
         console.log(code);
         return function() {};
       }
     },

   /**
    * Combinator which takes a template which expects an output parameter and
    * converts it into a function which returns a string.
    */
   stringifyTemplate: function (template) {
      return function() {
         var buf = [];

         this.output(buf.push.bind(buf), obj);

         return buf.join('');
      };
   },

   // TODO: add docs to explain what this method does.
   templateMemberExpander: function(t, opt_X) {
     // Load templates from an external file
     // if their 'template' property isn't set
     var i = 0;
     var X = opt_X? opt_X : window.X;
     if ( typeof t === 'function' ) {
       t = docTemplate = X.Template.create({
         name: t.name,
         // ignore first argument, which should be 'opt_out'
         args: t.toString().match(/\((.*)\)/)[1].split(',').slice(1).filter(function(a) {
           return X.Arg.create({name: a});
         }),
         template: multiline(t)});
     } else if ( typeof t === 'string' ) {
       t = docTemplate = X.Template.create({
         name: 'body',
         template: t
       });
     } else if ( ! t.template ) {
       // console.log('loading: '+ this.name + ' ' + t.name);

       var future = afuture();
       var path = this.sourcePath;

       t.futureTemplate = future.get;
       path = path.substring(0, path.lastIndexOf('/')+1);
       path += this.name + '_' + t.name + '.ft';

       var xhr = new XMLHttpRequest();
       xhr.open("GET", path);
       xhr.asend(function(data) {
         t.template = data;
         future.set(X.Template.create(t));
         t.futureTemplate = undefined;
       });
     } else if ( typeof t.template === 'function' ) {
       t.template = multiline(t.template);
     }
     // TODO: do we need the case where you specify a Template def. with
     // .template = 'string'? Unify this with modelExpandTemplates.
     return t;
   },

   modelExpandTemplates: function(self, templates) {
     // Load templates from an external file
     // if their 'template' property isn't set
     var i = 0;
     templates.forEach(function(t) {
       if ( typeof t === 'function' ) {
         t = templates[i] = Template.create({
           name: t.name,
           // ignore first argument, which should be 'opt_out'
           args: t.toString().match(/\((.*?)\)/)[1].split(',').slice(1).map(function(a) {
             return Arg.create({name: a.trim()});
           }),
           template: multiline(t)});
       } else if ( ! t.template ) {
         // console.log('loading: '+ self.name + ' ' + t.name);

         var future = afuture();
         var path = this.sourcePath;

         t.futureTemplate = future.get;
         path = path.substring(0, path.lastIndexOf('/')+1);
         path += self.name + '_' + t.name + '.ft';

         var xhr = new XMLHttpRequest();
         xhr.open("GET", path);
         xhr.asend(function(data) {
           t.template = data;
           future.set(Template.create(t));
           t.futureTemplate = undefined;
         });
       } else if ( typeof t.template === 'function' ) {
         t.template = multiline(t.template);
       } else if (!t.template$) {
         // we haven't FOAMalized the template, and there's no crazy multiline functions.
         // Note that Model and boostrappy models must use this case, as Template is not
         // yet defined at bootstrap time. Use a Template object definition with a bare
         // string template body in those cases.
         if (typeof Template != "undefined")
           t = templates[i] = JSONUtil.mapToObj(self.X, t, Template);
         else
           t = templates[i] = JSONUtil.mapToObj(self.X, t); // safe for bootstrap, but won't do anything in that case.
       }
       i++;
     }.bind(self))
  }
};

/** Is actually synchronous but is replaced in ChromeApp with an async version. **/
var aeval = function(src) {
  return aconstant(eval('(' + src + ')'));
};

var aevalTemplate = function(t) {
  if ( t.template ) {
    return aeval('function (opt_out) {' + TemplateCompiler.parseString(t.template) + '}');
  }

  return aseq(
    t.futureTemplate,
    function(ret, t) {
      aeval('function (opt_out) {' + TemplateCompiler.parseString(t.template) + '}')(ret);
    });
};

<commit_msg>Start of TemplateUtil FOAM tag support.<commit_after>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    <%# expression %>: dynamic (auto-updating) expression is output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *    $$feature(<whitespace>|<): output the View or Action for the current Value
 */

var FOAMTagParser = {
  __proto__: XMLParser,

  START: sym('tag'),

  tag: seq(
    literal_ic('<foam'),
    sym('whitespace'),
    repeat(sym('attribute'), sym('whitespace')),
    sym('whitespace'),
    alt(sym('closed'), sym('matching'))
  ),

  closed: literal('/>'),

  matching: seq1(1,
    '>',
    str(repeat(alt(
      sym('tag'),
      sym('text'))
    )),
    literal_ic('</foam>')
  ),

  label: str(plus(notChars(' =/\t\r\n<>\'"'))),

  text: str(plus(not(literal_ic('</foam')))),

  value: str(seq1(1, '"', repeat(notChar('"')), '"')),

  whitespace: repeat(alt(' ', '\t', '\r', '\n'))

}.addActions({
  tag: function(xs) {
    var obj = {
      attrs: {},
      children: xs[4] || [],
      toString: function() {
        var out = '<foam ';
        for ( key in this.attrs ) { out += key + '="' + this.attrs[key] + '" '; }
        if ( this.children.length ) {
          out += this.children.join();
          out += '</foam>';
        } else {
          out += '/>';
        }
        return out;
      }
    };
    xs[2].forEach(function(attr) { obj.attrs[attr[0]] = attr[2]; });
    debugger;
    return obj;
  }
});

var TemplateParser = {
  __proto__: grammar,

  START: sym('markup'),

  markup: repeat0(alt(
//    sym('foamTag'),
    sym('create child'),
    sym('simple value'),
    sym('live value tag'),
    sym('raw values tag'),
    sym('values tag'),
    sym('code tag'),
    sym('ignored newline'),
    sym('newline'),
    sym('single quote'),
    sym('text')
  )),

  'foamTag': FOAMTagParser.export('tag'),

  'create child': seq('$$', repeat(notChars(' $\n<{')),
                      optional(JSONParser.export('objAsString'))),

  'simple value': seq('%%', repeat(notChars(' "\n<'))),

  'live value tag': seq('<%#', repeat(not('%>', anyChar)), '%>'),

  'raw values tag': alt(
    seq('<%=', repeat(not('%>', anyChar)), '%>'),
    seq('{{{', repeat(not('}}}', anyChar)), '}}}')
  ),

  'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

  'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
  'ignored newline': literal('\\\n'),
  newline: literal('\n'),
  'single quote': literal("'"),
  text: anyChar
};

var TemplateOutput = {
  /**
   * obj - Parent object.  If objects are output and have an initHTML() method, then they
   * are added to the parent by calling obj.addChild().
   **/
  // TODO(kgr): redesign, I think this is actually broken.  If we call appendHTML() of
  // a sub-view then it will be added to the wrong parent.
  create: function(obj) {
    var buf = '';
    var f = function(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        if ( o && o.toView_ ) o = o.toView_();
        if ( ! ( o === null || o === undefined ) ) {
          if ( o.appendHTML ) {
            o.appendHTML(this);
          } else if ( o.toHTML ) {
            buf += o.toHTML();
          } else {
            buf += o;
          }
          if ( o.initHTML && obj.addChild ) obj.addChild(o);
        }
      }
    };

    f.toString = function() { return buf; };

    return f;
  }
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  push: function() { this.out.push.apply(this.out, arguments); },

  header: 'var self = this; var X = this.X; var escapeHTML = View.getPrototype().strToHTML; var out = opt_out ? opt_out : TemplateOutput.create(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
  markup: function (v) {
    var ret = this.header + this.out.join('') + this.footer;
    this.out = [];
    return ret;
  },
  'create child': function(v) {
    var name = v[1].join('').constantize();
    this.push("', self.createTemplateView('", name, "'",
              v[2] ? ', ' + v[2] : '',
              "),\n'");
  },
  foamTag: function(v) {
    return this.push(v.toString());
  },
  'simple value': function(v) { this.push("',\n self.", v[1].join(''), ",\n'"); },
  'raw values tag': function (v) { this.push("',\n", v[1].join(''), ",\n'"); },
  'values tag': function (v) { this.push("',\nescapeHTML(", v[1].join(''), "),\n'"); },
  'live value tag': function (v) { this.push("',\nself.dynamicTag('span', function() { return ", v[1].join(''), "; }.bind(this)),\n'"); },
  'code tag': function (v) { this.push("');\n", v[1].join(''), ";out('"); },
  'single quote': function () { this.push("\\'"); },
  newline: function () { this.push("\\n"); },
  text: function(v) { this.push(v); }
});

var TemplateUtil = {

   /** Create a method which only compiles the template when first used. **/
   lazyCompile: function(t) {
     var delegate;

     return function() {
       if ( ! delegate ) {
         if ( ! t.template )
           throw 'Must arequire() template model before use for ' + this.name_ + '.' + t.name;
         delegate = TemplateUtil.compile(Template.isInstance(t) ? t : Template.create(t));
       }

       return delegate.apply(this, arguments);
     };
   },

   compile: window.chrome && window.chrome.app && window.chrome.app.runtime ?
     function() {
       return function() {
         return "Models must be arequired()'ed for Templates to be compiled in Packaged Apps.";
       };
     } :
     function(t) {
       var code = TemplateCompiler.parseString(t.template);

       try {
         var args = ['opt_out'];
         for ( var i = 0 ; i < t.args.length ; i++ ) {
           args.push(t.args[i].name);
         }
         args.push(code);
         return Function.apply(null, args);
       } catch (err) {
         console.log('Template Error: ', err);
         console.log(code);
         return function() {};
       }
     },

   /**
    * Combinator which takes a template which expects an output parameter and
    * converts it into a function which returns a string.
    */
   stringifyTemplate: function (template) {
      return function() {
         var buf = [];

         this.output(buf.push.bind(buf), obj);

         return buf.join('');
      };
   },

   // TODO: add docs to explain what this method does.
   templateMemberExpander: function(t, opt_X) {
     // Load templates from an external file
     // if their 'template' property isn't set
     var i = 0;
     var X = opt_X? opt_X : window.X;
     if ( typeof t === 'function' ) {
       t = docTemplate = X.Template.create({
         name: t.name,
         // ignore first argument, which should be 'opt_out'
         args: t.toString().match(/\((.*)\)/)[1].split(',').slice(1).filter(function(a) {
           return X.Arg.create({name: a});
         }),
         template: multiline(t)});
     } else if ( typeof t === 'string' ) {
       t = docTemplate = X.Template.create({
         name: 'body',
         template: t
       });
     } else if ( ! t.template ) {
       // console.log('loading: '+ this.name + ' ' + t.name);

       var future = afuture();
       var path = this.sourcePath;

       t.futureTemplate = future.get;
       path = path.substring(0, path.lastIndexOf('/')+1);
       path += this.name + '_' + t.name + '.ft';

       var xhr = new XMLHttpRequest();
       xhr.open("GET", path);
       xhr.asend(function(data) {
         t.template = data;
         future.set(X.Template.create(t));
         t.futureTemplate = undefined;
       });
     } else if ( typeof t.template === 'function' ) {
       t.template = multiline(t.template);
     }
     // TODO: do we need the case where you specify a Template def. with
     // .template = 'string'? Unify this with modelExpandTemplates.
     return t;
   },

   modelExpandTemplates: function(self, templates) {
     // Load templates from an external file
     // if their 'template' property isn't set
     var i = 0;
     templates.forEach(function(t) {
       if ( typeof t === 'function' ) {
         t = templates[i] = Template.create({
           name: t.name,
           // ignore first argument, which should be 'opt_out'
           args: t.toString().match(/\((.*?)\)/)[1].split(',').slice(1).map(function(a) {
             return Arg.create({name: a.trim()});
           }),
           template: multiline(t)});
       } else if ( ! t.template ) {
         // console.log('loading: '+ self.name + ' ' + t.name);

         var future = afuture();
         var path = this.sourcePath;

         t.futureTemplate = future.get;
         path = path.substring(0, path.lastIndexOf('/')+1);
         path += self.name + '_' + t.name + '.ft';

         var xhr = new XMLHttpRequest();
         xhr.open("GET", path);
         xhr.asend(function(data) {
           t.template = data;
           future.set(Template.create(t));
           t.futureTemplate = undefined;
         });
       } else if ( typeof t.template === 'function' ) {
         t.template = multiline(t.template);
       } else if (!t.template$) {
         // we haven't FOAMalized the template, and there's no crazy multiline functions.
         // Note that Model and boostrappy models must use this case, as Template is not
         // yet defined at bootstrap time. Use a Template object definition with a bare
         // string template body in those cases.
         if (typeof Template != "undefined")
           t = templates[i] = JSONUtil.mapToObj(self.X, t, Template);
         else
           t = templates[i] = JSONUtil.mapToObj(self.X, t); // safe for bootstrap, but won't do anything in that case.
       }
       i++;
     }.bind(self))
  }
};

/** Is actually synchronous but is replaced in ChromeApp with an async version. **/
var aeval = function(src) {
  return aconstant(eval('(' + src + ')'));
};

var aevalTemplate = function(t) {
  if ( t.template ) {
    return aeval('function (opt_out) {' + TemplateCompiler.parseString(t.template) + '}');
  }

  return aseq(
    t.futureTemplate,
    function(ret, t) {
      aeval('function (opt_out) {' + TemplateCompiler.parseString(t.template) + '}')(ret);
    });
};

<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *
 * TODO: add support for arguments
 */

var TemplateParser = {
  __proto__: grammar,

  START: sym('markup'),

  markup: repeat0(alt(
    sym('create child'),
    sym('simple value'),
    sym('raw values tag'),
    sym('values tag'),
    sym('code tag'),
    sym('ignored newline'),
    sym('newline'),
    sym('single quote'),
    sym('text')
  )),

  'create child': seq('$$', repeat(not(alt(' ','\n','<'), anyChar))),

  'simple value': seq('%%', repeat(not(alt(' ','\n','<'), anyChar))),

  'raw values tag': alt(
    seq('<%=', repeat(not('%>', anyChar)), '%>'),
    seq('{{{', repeat(not('}}}', anyChar)), '}}}')
  ),

  'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

  'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
  'ignored newline': literal('\\\n'),
  newline: literal('\n'),
  'single quote': literal("'"),
  text: anyChar
};

var TemplateOutput = {
  create: function(obj) {
    var buf = '';
    var f = function(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        buf += o.toHTML ? o.toHTML() : o;
        if ( o.initHTML && obj.addChild ) obj.addChild(o);
      }
    };

    f.toString = function() { return buf; };

    return f;
  }
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  push: function() { this.out.push.apply(this.out, arguments); },

  header: 'var out = opt_out ? opt_out : TemplateOutput.create(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
   markup: function (v) {
     var ret = this.header + this.out.join('') + this.footer;
     this.out = [];
     return ret;
   },
   'create child': function(v) { this.push("', this.createView(this.model.", v[1].join(''), "), '"); },
   'simple value': function(v) { this.push("', this.", v[1].join(''), ",'"); },
   'raw values tag': function (v) { this.push("',", v[1].join(''), ",'"); },
   'values tag': function (v) { this.push("',", AbstractView.getPrototype().strToHTML(v[1].join('')), ",'"); },
   'code tag': function (v) { this.push("');", v[1].join(''), "out('"); },
   'single quote': function () { this.push("\\'"); },
   newline: function () { this.push("\\n"); },
   text: function(v) { this.push(v); }
});

var TemplateUtil = {

   /** Create a method which only compiles the template when first used. **/
   lazyCompile: function(t) {
     var delegate;

     return function() {
       if ( ! delegate ) {
         delegate = TemplateUtil.compile(t.template);
       }

       return delegate.apply(this, arguments);
     };
   },

   compile: window.chrome && window.chrome.app && window.chrome.app.runtime ?
     function() {
       return function() {
         return "Models must be arequired()'ed for Templates to be compiled in Packaged Apps.";
       };
     } :
     function(str) {
       var code = TemplateCompiler.parseString(str);

       try {
         return new Function("opt_out", code);
       } catch (err) {
         console.log("Template Error: ", err);
         console.log(code);
         return function() {};
       }
     },

   /**
    * Combinator which takes a template which expects an output parameter and
    * converts it into a function which returns a string.
    */
   stringifyTemplate: function (template) {
      return function() {
         var buf = [];

         this.output(buf.push.bind(buf), obj);

         return buf.join('');
      };
   }
};
<commit_msg>Improved %% template syntax.<commit_after>/**
 * @license
 * Copyright 2013 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *
 * TODO: add support for arguments
 */

var TemplateParser = {
  __proto__: grammar,

  START: sym('markup'),

  markup: repeat0(alt(
    sym('create child'),
    sym('simple value'),
    sym('raw values tag'),
    sym('values tag'),
    sym('code tag'),
    sym('ignored newline'),
    sym('newline'),
    sym('single quote'),
    sym('text')
  )),

  'create child': seq('$$', repeat(not(alt(' ','\n','<'), anyChar))),

  'simple value': seq('%%', repeat(not(alt(' ','\n','<','"'), anyChar))),

  'raw values tag': alt(
    seq('<%=', repeat(not('%>', anyChar)), '%>'),
    seq('{{{', repeat(not('}}}', anyChar)), '}}}')
  ),

  'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

  'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
  'ignored newline': literal('\\\n'),
  newline: literal('\n'),
  'single quote': literal("'"),
  text: anyChar
};

var TemplateOutput = {
  create: function(obj) {
    var buf = '';
    var f = function(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        buf += o.toHTML ? o.toHTML() : o;
        if ( o.initHTML && obj.addChild ) obj.addChild(o);
      }
    };

    f.toString = function() { return buf; };

    return f;
  }
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  push: function() { this.out.push.apply(this.out, arguments); },

  header: 'var out = opt_out ? opt_out : TemplateOutput.create(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
   markup: function (v) {
     var ret = this.header + this.out.join('') + this.footer;
     this.out = [];
     return ret;
   },
   'create child': function(v) { this.push("', this.createView(this.model.", v[1].join(''), "), '"); },
   'simple value': function(v) { this.push("', this.", v[1].join(''), ",'"); },
   'raw values tag': function (v) { this.push("',", v[1].join(''), ",'"); },
   'values tag': function (v) { this.push("',", AbstractView.getPrototype().strToHTML(v[1].join('')), ",'"); },
   'code tag': function (v) { this.push("');", v[1].join(''), "out('"); },
   'single quote': function () { this.push("\\'"); },
   newline: function () { this.push("\\n"); },
   text: function(v) { this.push(v); }
});

var TemplateUtil = {

   /** Create a method which only compiles the template when first used. **/
   lazyCompile: function(t) {
     var delegate;

     return function() {
       if ( ! delegate ) {
         delegate = TemplateUtil.compile(t.template);
       }

       return delegate.apply(this, arguments);
     };
   },

   compile: window.chrome && window.chrome.app && window.chrome.app.runtime ?
     function() {
       return function() {
         return "Models must be arequired()'ed for Templates to be compiled in Packaged Apps.";
       };
     } :
     function(str) {
       var code = TemplateCompiler.parseString(str);

       try {
         return new Function("opt_out", code);
       } catch (err) {
         console.log("Template Error: ", err);
         console.log(code);
         return function() {};
       }
     },

   /**
    * Combinator which takes a template which expects an output parameter and
    * converts it into a function which returns a string.
    */
   stringifyTemplate: function (template) {
      return function() {
         var buf = [];

         this.output(buf.push.bind(buf), obj);

         return buf.join('');
      };
   }
};
<|endoftext|>


<commit_before>export class AppError extends Error {
  constructor({ name, message, extra = {} }) {
    super(message);
    this.name = name;
    this.extra = extra;
  }
}

export class AxiosError extends AppError {
  constructor({ message, status = null, extra = {} }) {
    super({ name: 'AxiosError', message, extra });
    this.status = status;
  }
}

export class UnverifiedError extends AppError {
  constructor() {
    super({
      name: 'UnverifiedError',
      message: 'Unverified email address accessing protected route',
    });
  }
}

export class Auth0Error extends AppError {
  constructor({ message }) {
    super({
      name: 'Auth0Error',
      message,
    });
  }
}
<commit_msg>some formatting<commit_after>export class AppError extends Error {
  constructor({ name, message, extra = {} }) {
    super(message);
    this.name = name;
    this.extra = extra;
  }
}

export class AxiosError extends AppError {
  constructor({ message, status = null, extra = {} }) {
    super({ name: 'AxiosError', message, extra });
    this.status = status;
  }
}

export class UnverifiedError extends AppError {
  constructor() {
    super({
      name: 'UnverifiedError',
      message: 'Unverified email address accessing protected route',
    });
  }
}

export class Auth0Error extends AppError {
  constructor({ message }) {
    super({ name: 'Auth0Error', message });
  }
}
<|endoftext|>


<commit_before>

function robots (req, res){

    var isValidHost = ['absch.cbd.int'].includes(req.headers['hosts']);

    var text = isValidHost ? 'Allow: /' : 'Disallow: /';

    res.contentType('text/plain');
    res.end('User-agent: *\n' + text);
}

function sitemap(req, res){
    require('superagent')
            .get(`https://attachments.cbd.int/sitemap-${process.env.CLEARINGHOUSE.toLowerCase()}.xml`)
            .pipe(res);
}

function errorLogs(req, res){
    proxy.web(req, res, { target: `${apiUrl}/api/v2016/error-logs?type=client-app-errors&serverAppVersion=${encodeURIComponent(appVersion)}`,
                            secure:false, ignorePath:true, xfwd:true });
}

module.exports = {
    robots,
    sitemap
}
<commit_msg>move middlewares to root<commit_after><|endoftext|>


<commit_before>import { MenuItem, MenuItems } from '../../imports/api/menuItem.js';
import { Order, orderItem } from '../../imports/api/order.js';
import { ReactiveVar } from 'meteor/reactive-var'

let orderArray = [];
let rvOrderArray = new ReactiveVar([]);
let topDrinksArray = [];
let rvtopDrinksArray = new ReactiveVar([]);
let topAppsArray = [];
let rvtopAppsArray = new ReactiveVar([]);
let topEntreesArray = [];
let rvtopEntreesArray = new ReactiveVar([]);
let topDessertsArray = [];
let rvtopDessertsArray = new ReactiveVar([]);

/**
 * @function createOrderItem
 * @summary Creates an order item with the following parameters
 * @param mItemID
 * @param mPriority
 * @param mMenuItemID
 * @param mSpecialRequests
 */
function createOrderItem(mItemID, mPriority, mMenuItemID, mSpecialRequests) {
    return new orderItem({
        "itemID": mItemID,
        "priority": mPriority,
        "menuItemID": mMenuItemID,
        "specialRequests": mSpecialRequests,
		"actualCookTime": MenuItem.findOne({itemID: mMenuItemID}).cookTime,
		"isCompleted": false
    });
}
Template.waiter.events({
    /**
     * @function click .Appetizers
     * @summary Displays the appetizers menu and hides the rest along with the sidebar
     */
    'click .Appetizers' () {
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("appMenu").className = "displayAll";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .Entrees
     * @summary Displays the entrees menu and hides the rest along with the sidebar
     */
    'click .Entrees' () {
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayAll";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .FloorPlan
     * @summary Displays the floor plan and hides the rest along with the sidebar
     */
    'click .FloorPlan' () {
        document.getElementById("floorPlan").className = "displayAll";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .Desserts
     * @summary Displays the desserts menu and hides the rest along with the sidebar
     */
    'click .Desserts' () {
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayAll";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');

    },
    /**
     * @function click .placeOrder
     * @summary Displays the place order tab and hides the rest along with the sidebar
     */
    'click .placeOrder' () {
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayAll";
        $('.menu-active').removeClass('menu-active');
		Template.waiter.__helpers.get('selected')();
    },
    /**
     * @function click #placeOrder
     * @summary Takes all the Order items created by orderArray and fills in the rest of the fields of the order and places the order into the order collection
     */
    'click #placeOrder' () {
		var mOrderID = 1;
		if (!Order.find().count() == 0) { mOrderID = Order.findOne({}, { sort: {orderID: -1}}).orderID + 1; }
        new Order({
            orderID: mOrderID,
            waiterID: 69,
            orderItems: orderArray,
            timePlaced: new Date(),
			isCompleted: false
        }).placeOrder();
        orderArray = [];
        rvOrderArray.set(orderArray);
    },
    /**
     * @function click #cancelOrder
     * @summary Drops all the selected items for the order
     */
    'click #cancelOrder' () {
        orderArray = [];
		rvOrderArray.set(orderArray);
    },
    /**
     * @function click .drinkicon
     * @summary Opens the drinks modal showcasing all the menu items classified as drinks
     */
    'click .drinkicon' () {
        $('#drinksModal')
            .modal('show')
        ;
    },

});

Template.menuCards.events({
    /**
     * @function click #addItem
     * @summary Creates the order item for the selected item and pushes the order back into the orderArray
     */
    'click #addItem'() {
        orderArray.push(createOrderItem(orderArray.length + 1, 2, this.itemID, "NONE"));
		rvOrderArray.set(orderArray);
    },
});

Template.selectedCards.events({
    /**
     * @function click #removeItem
     * @summary Removes the respective item from the orderArray so it is not placed in the final order
     */
    'click #removeItem' (){
        for (i = 0; i < orderArray.length; i++)
        {
            if (orderArray[i].itemID == this.itemID) {
                orderArray.splice(i, 1);
                break;
            }
        }
		/** Update the itemIDs to fill in any potential gaps **/
		for (i = 0; i < orderArray.length; i++)
        {
			orderArray[i].itemID = i + 1;
			rvOrderArray.set(orderArray);
        }
    },

});

Template.waiter.helpers({
    /**
     * @function drinks
     * @summary returns all the objects from the database with the mealType of Enum 0, drinks.
     */
    drinks() {
        return MenuItems.find({mealType: 0});
    },
    /**
     * @function apps
     * @summary returns all the objects from the database with the mealType of Enum 1, appetizers.
     */
    apps() {
        return MenuItems.find({mealType: 1});
    },
    /**
     * @function entrees
     * @summary returns all the objects from the database with the mealType of Enum 2, entrees.
     */
    entrees() {
        return MenuItems.find({mealType: 2});
    },
    /**
     * @function desserts
     * @summary returns all the objects from the database with the mealType of Enum 3, desserts.
     */
    desserts() {
        return MenuItems.find({mealType: 3});

    },
    /**
     * @function selected
     * @summary returns all the objects from the selectedItems collection
     */
    selected() {
        return(rvOrderArray.get());
    },
    topThreeDrinks() {

        let i = 0;
        MenuItems.find({mealType: 0}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topDrinksArray[i] = element.itemID;
                i++;
            }
        });
        rvtopDrinksArray.set(topDrinksArray);
        i = 0;
        MenuItems.find({mealType: 1}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topAppsArray[i] = element.itemID;
                i++;
            }

        });
        rvtopAppsArray.set(topAppsArray);
        i = 0;
        MenuItems.find({mealType: 2}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topEntreesArray[i] = element.itemID;
                i++;
            }

        });
        rvtopEntreesArray.set(topEntreesArray);
        i = 0;
        MenuItems.find({mealType: 3}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topDessertsArray[i] = element.itemID;
                i++;
            }
        });
        rvtopDessertsArray.set(topDessertsArray);

    },

});

Template.selectedCards.helpers({
	itemName(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemName;
	},
	itemPrice(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemPrice;
	},
	itemDescription(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemDescription;
	},
	cookTime(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.cookTime;
	}
});

Template.menuCards.helpers({
    'isTopOne': function () {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[0] || this.itemID == topAppsArray[0] || this.itemID == topEntreesArray[0] || this.itemID == topDessertsArray[0])
        {
            return true;
        }
    },
    'isTopTwo': function() {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[1] || this.itemID == topAppsArray[1] || this.itemID == topEntreesArray[1] || this.itemID == topDessertsArray[1])
        {
            return true;
        }
    },
    'isTopThree': function() {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[2] || this.itemID == topAppsArray[2] || this.itemID == topEntreesArray[2] || this.itemID == topDessertsArray[2])
        {
            return true;
        }
    },
});
<commit_msg>Fixed remove item from waiter interface<commit_after>import { MenuItem, MenuItems } from '../../imports/api/menuItem.js';
import { Order, orderItem } from '../../imports/api/order.js';
import { ReactiveVar } from 'meteor/reactive-var'

let orderArray = [];
let rvOrderArray = new ReactiveVar([]);
let topDrinksArray = [];
let rvtopDrinksArray = new ReactiveVar([]);
let topAppsArray = [];
let rvtopAppsArray = new ReactiveVar([]);
let topEntreesArray = [];
let rvtopEntreesArray = new ReactiveVar([]);
let topDessertsArray = [];
let rvtopDessertsArray = new ReactiveVar([]);

/**
 * @function createOrderItem
 * @summary Creates an order item with the following parameters
 * @param mItemID
 * @param mPriority
 * @param mMenuItemID
 * @param mSpecialRequests
 */
function createOrderItem(mItemID, mPriority, mMenuItemID, mSpecialRequests) {
    return new orderItem({
        "itemID": mItemID,
        "priority": mPriority,
        "menuItemID": mMenuItemID,
        "specialRequests": mSpecialRequests,
		"actualCookTime": MenuItem.findOne({itemID: mMenuItemID}).cookTime,
		"isCompleted": false
    });
}
Template.waiter.events({
    /**
     * @function click .Appetizers
     * @summary Displays the appetizers menu and hides the rest along with the sidebar
     */
    'click .Appetizers' () {
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("appMenu").className = "displayAll";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .Entrees
     * @summary Displays the entrees menu and hides the rest along with the sidebar
     */
    'click .Entrees' () {
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayAll";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .FloorPlan
     * @summary Displays the floor plan and hides the rest along with the sidebar
     */
    'click .FloorPlan' () {
        document.getElementById("floorPlan").className = "displayAll";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');
    },
    /**
     * @function click .Desserts
     * @summary Displays the desserts menu and hides the rest along with the sidebar
     */
    'click .Desserts' () {
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayAll";
        document.getElementById("placeOrderMenu").className = "displayNone";
        $('.menu-active').removeClass('menu-active');

    },
    /**
     * @function click .placeOrder
     * @summary Displays the place order tab and hides the rest along with the sidebar
     */
    'click .placeOrder' () {
        document.getElementById("floorPlan").className = "displayNone";
        document.getElementById("entreeMenu").className = "displayNone";
        document.getElementById("appMenu").className = "displayNone";
        document.getElementById("dessertsMenu").className = "displayNone";
        document.getElementById("placeOrderMenu").className = "displayAll";
        $('.menu-active').removeClass('menu-active');
		Template.waiter.__helpers.get('selected')();
    },
    /**
     * @function click #placeOrder
     * @summary Takes all the Order items created by orderArray and fills in the rest of the fields of the order and places the order into the order collection
     */
    'click #placeOrder' () {
		var mOrderID = 1;
		if (!Order.find().count() == 0) { mOrderID = Order.findOne({}, { sort: {orderID: -1}}).orderID + 1; }
        new Order({
            orderID: mOrderID,
            waiterID: 69,
            orderItems: orderArray,
            timePlaced: new Date(),
			isCompleted: false
        }).placeOrder();
        orderArray = [];
        rvOrderArray.set(orderArray);
    },
    /**
     * @function click #cancelOrder
     * @summary Drops all the selected items for the order
     */
    'click #cancelOrder' () {
        orderArray = [];
		rvOrderArray.set(orderArray);
    },
    /**
     * @function click .drinkicon
     * @summary Opens the drinks modal showcasing all the menu items classified as drinks
     */
    'click .drinkicon' () {
        $('#drinksModal')
            .modal('show')
        ;
    },

});

Template.menuCards.events({
    /**
     * @function click #addItem
     * @summary Creates the order item for the selected item and pushes the order back into the orderArray
     */
    'click #addItem'() {
        orderArray.push(createOrderItem(orderArray.length + 1, 2, this.itemID, "NONE"));
		rvOrderArray.set(orderArray);
    },
});

Template.selectedCards.events({
    /**
     * @function click #removeItem
     * @summary Removes the respective item from the orderArray so it is not placed in the final order
     */
    'click #removeItem' (){
        for (i = 0; i < orderArray.length; i++)
        {
			if (i == 0) {
				orderArray.shift();
				break;
			}
            if (orderArray[i].itemID == this.itemID) {
                orderArray.splice(i, 1);
                break;
            }
        }
		/** Update the itemIDs to fill in any potential gaps **/
		for (i = 0; i < orderArray.length; i++)
        {
			orderArray[i].itemID = i + 1;
        }
		rvOrderArray.set(orderArray);
    },

});

Template.waiter.helpers({
    /**
     * @function drinks
     * @summary returns all the objects from the database with the mealType of Enum 0, drinks.
     */
    drinks() {
        return MenuItems.find({mealType: 0});
    },
    /**
     * @function apps
     * @summary returns all the objects from the database with the mealType of Enum 1, appetizers.
     */
    apps() {
        return MenuItems.find({mealType: 1});
    },
    /**
     * @function entrees
     * @summary returns all the objects from the database with the mealType of Enum 2, entrees.
     */
    entrees() {
        return MenuItems.find({mealType: 2});
    },
    /**
     * @function desserts
     * @summary returns all the objects from the database with the mealType of Enum 3, desserts.
     */
    desserts() {
        return MenuItems.find({mealType: 3});

    },
    /**
     * @function selected
     * @summary returns all the objects from the selectedItems collection
     */
    selected() {
        return(rvOrderArray.get());
    },
    topThreeDrinks() {

        let i = 0;
        MenuItems.find({mealType: 0}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topDrinksArray[i] = element.itemID;
                i++;
            }
        });
        rvtopDrinksArray.set(topDrinksArray);
        i = 0;
        MenuItems.find({mealType: 1}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topAppsArray[i] = element.itemID;
                i++;
            }

        });
        rvtopAppsArray.set(topAppsArray);
        i = 0;
        MenuItems.find({mealType: 2}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topEntreesArray[i] = element.itemID;
                i++;
            }

        });
        rvtopEntreesArray.set(topEntreesArray);
        i = 0;
        MenuItems.find({mealType: 3}, {sort: {timesOrdered: -1}}).forEach(function (element) {
            if (i < 3) {
                topDessertsArray[i] = element.itemID;
                i++;
            }
        });
        rvtopDessertsArray.set(topDessertsArray);

    },

});

Template.selectedCards.helpers({
	itemName(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemName;
	},
	itemPrice(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemPrice;
	},
	itemDescription(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.itemDescription;
	},
	cookTime(order) {
		let menuItem = MenuItems.findOne({itemID: order.menuItemID});
		return menuItem.cookTime;
	}
});

Template.menuCards.helpers({
    'isTopOne': function () {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[0] || this.itemID == topAppsArray[0] || this.itemID == topEntreesArray[0] || this.itemID == topDessertsArray[0])
        {
            return true;
        }
    },
    'isTopTwo': function() {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[1] || this.itemID == topAppsArray[1] || this.itemID == topEntreesArray[1] || this.itemID == topDessertsArray[1])
        {
            return true;
        }
    },
    'isTopThree': function() {
        topDrinksArray = rvtopDrinksArray.get();
        topAppsArray = rvtopAppsArray.get();
        topEntreesArray = rvtopEntreesArray.get();
        topDessertsArray = rvtopDessertsArray.get();
        if (this.itemID == topDrinksArray[2] || this.itemID == topAppsArray[2] || this.itemID == topEntreesArray[2] || this.itemID == topDessertsArray[2])
        {
            return true;
        }
    },
});
<|endoftext|>


<commit_before>var fs = require('fs');
var ast = require('./ast');

function generator() {
    var code = [];
    function write(src, eol) {
        code.push(src + (eol ? '\n' : ''));
    };

    function write_runtime(target) {
        if(target == 'no-runtime') {
            return;
        }

        var rt = fs.readFileSync('runtime.js', 'utf-8');
        write(rt, true);

        if(target != 'js-noeval') {
            rt = fs.readFileSync('runtime-eval.js', 'utf-8');
            write(rt, true);
        }
    }

    function create_generator() {
        return generator();
    }

    function link(node1, node2, tag) {
        node2.link = node1;
        node1.tag = tag;
    }

    function unlink(node) {
        node.link = null;
    }

    function has_hook(name) {
        return !!hooks[name];
    }

    function run_hook(name, node, parse) {
        hooks[name](node, parse);
    }

    function is_throw(node) {
        return node.type == ast.LIST &&
            node.children[0].data &&
            node.children[0].data.str == 'throw';
    }

    function parse_expr(parse, parent, node) {
        // Link these nodes for context (big hack)
        link(parent, node, 'expr');
        parse(node);
        unlink(node);
    }

    function write_boolean(node) {
        if(node.data === true) {
            write('true');
        }
        else {
            write('false');
        }
    }

    function transform_symbol(str) {
        str = str.replace(/-/g, '_dash_');
        str = str.replace(/\?/g, '_p_');
        str = str.replace(/\!/g, '_excl_');
        str = str.replace(/>/g, '_gt_');
        str = str.replace(/</g, '_lt_');
        str = str.replace(/%/g, '_per_');
        return str;
    }

    function write_number(node) {
        // NUMBER
        write(node.data);
    }

    function write_string(node) {
        // STRING
        var str = node.data;
        str = str.replace(/\\/g, '\\\\');
        str = str.replace(/\n/g, '\\n');
        str = str.replace(/\r/g, '\\r');
        str = str.replace(/\t/g, '\\t');
        str = str.replace(/"/g, '\\"');
        write('"' + str  + '"');
    }

    function write_term(node) {
        // TERM (variable, keyword, etc)
        write(transform_symbol(node.data.str));
    }

    function write_symbol(node) {
        // SYMBOL
        write('string_dash__gt_symbol("' + transform_symbol(node.data.str) + '")');
    }

    function write_set(node, parse) {
        // var TERM = EXPR;
        write('var ');
        write_set_excl(node, parse);
    }

    function write_set_excl(node, parse) {
        // TERM = EXPR;
        write_term(node.children[1]);
        write(' = ');
        parse(node.children[2]);
        write(';');
    }

    function write_lambda(node, parse) {
        // function(TERM1, TERM2, ...) { EXPR1; EXPR2; ...; return EXPRn; }
        var args_expr = node.children[1];

        if(args_expr.type == ast.LIST) {
            var capture_name;

            write('function(');

            for(var i=0, len=args_expr.children.length; i<len; i++) {
                var arg = args_expr.children[i];

                // support for dot-style rest arguments
                if(arg.data.str == '.') {
                    capture_name = args_expr.children[i+1];
                    break;
                }
                else {
                    if(i>0) {
                        write(',');
                    }

                    write_term(arg);
                }
            }

            write('){', true);

            if(capture_name) {
                write('var ');
                write_term(capture_name);
                write(' = vector_dash_to_dash_list(Array.prototype.slice.call(arguments, ' +
                      (args_expr.children.length - 2) + '));', true);
            }
        }
        else {
            write('function() {', true);
            write('var ' + args_expr.data.str +
                  ' = vector_dash_to_dash_list(Array.prototype.slice.call(arguments));', true);
        }

        for(var i=2, len=node.children.length; i<len; i++) {
            var child = node.children[i];

            if(i == node.children.length-1 &&
               !is_throw(child)) {
                write('return ');
            }
            parse(child);
        }

        write('}', true);
    }

    function write_op(op, node, parse) {
        // (EXPR1 <op> EXPR2 <op> ... <op> EXPRn),
        write('(');
        for(var i=1, len=node.children.length; i<len; i++) {
            if(i > 1) {
                write(op);
            }

            parse_expr(parse, node, node.children[i]);
        }

        write(')');
    }

    function write_func_call(node, parse) {
        if(node.children[0].type == ast.TERM) {
            write_term(node.children[0]);
        }
        else {
            write('(');
            parse_expr(parse, node, node.children[0]);
            write(')');
        }

        write('(');

        for(var i=1, len=node.children.length; i<len; i++) {
            if(i>1) {
                write(',');
            }

            parse_expr(parse, node, node.children[i]);
        }

        write(')');

        // var util = require('util');
        // util.puts(util.inspect(node, false, 4));

        // if the parent node is not a function call, we should end
        // the expression. this solves ambiguities with the next
        // statement which could be another function call in the form
        // (foo)(x, y, z) where it tries to call the result of this
        // function
        if(!node.link ||
           (node.link && node.link.tag != 'expr')) {
            write(';');
        }
    }

    function write_vector(node, parse, context) {
        write('unquote_splice_vec([');
        for(var i=0, len=node.children.length; i<len; i++) {
            if(i > 0) {
                write(',');
            }
            write_list_element(node, i, parse, context);
        }
        write('])');
    }

    function write_map(node, parse, context) {
        write('unquote_splice_map({');

        for(var i=0, len=node.children.length; i<len; i+=2) {
            if(i>0) {
                write(',');
            }

            var key = node.children[i];
            var val_index = i+1;

            var key_form = key.children[0];
            if(key.type == ast.LIST && key_form.data) {
                if(key_form.data.str == 'unquote-splicing') {
                    key = '__unquote_splicing';
                    val_index = i;
                }
                else if(key.children[0].data.str != 'quote') {
                    throw "Invalid key for dict: " + key;
                }
                else {
                    key = key.children[1].data.str;
                }
            }
            else {
                throw "Invalid key for dict: " + key;
            }

            write('"' + transform_symbol(key) + '": ');
            write_list_element(node, val_index, parse, context);
        }

        write('})');
    }

    function write_list(node, parse, context) {
        write('unquote_splice(');
        _write_list(node, 0, parse, context);
        write(')');
    }

    function _write_list(node, i, parse, context) {
        if(i < node.children.length) {
            write('make_dash_list([');
            write_list_element(node, i, parse, context);
            write(',');
            _write_list(node, i+1, parse, context);
            write('])');
        }
        else {
            write('_emptylst');
        }
    }

    function write_list_element(node, i, parse, context) {
        var n = node.children[i];

        if(context == 'quote' || context == 'quasi') {
            if(context == 'quasi') {
                if(n.children[0] && n.children[0].type == ast.TERM) {
                    // If it's a list with a term in the front, check if
                    // it's an unquote or unquote-splicing and handle
                    // it specially
                    var term = n.children[0];

                    if(term.data.str == 'unquote') {
                        parse_expr(parse, n, n.children[1]);
                        return;
                    }
                    else if(term.data.str == 'unquote-splicing') {
                        write('{ please_splice: true, data: ');
                        parse_expr(parse, n, n.children[1]);
                        write(' }');
                        return;
                    }
                }
            }

            if(n.type == ast.TERM) {
                write_symbol(n);
            }
            else if(n.type == ast.NUMBER) {
                write_number(n);
            }
            else if(n.type == ast.BOOLEAN) {
                write_boolean(n);
            }
            else if(n.type == ast.STRING) {
                write_string(n);
            }
            else if(n.type == ast.LIST) {
                write_list(n, parse, context);
            }
            else if(n.type == ast.VECTOR) {
                write_vector(n, parse, context);
            }
        }
        else {
            parse_expr(parse, node, n);
        }
    }

    var hooks = {
        '+': function(node, parse) {
            write_op('+', node, parse);
        },

        '-': function(node, parse) {
            write_op('-', node, parse);
        },

        '*': function(node, parse) {
            write_op('*', node, parse);
        },

        '/': function(node, parse) {
            write_op('/', node, parse);
        },

        '=': function(node, parse) {
            write_op('===', node, parse);
        },

        '>': function(node, parse) {
            write_op('>', node, parse);
        },

        '<': function(node, parse) {
            write_op('<', node, parse);
        },

        'if': function (node, parse) {
            // (function() { if(EXPR1) { return EXPR2; } else { return EXPR3; }})()
            write('(function() {');

            write('if(');
            parse_expr(parse, node, node.children[1]);
            write(') { ');

            if(!is_throw(node.children[2])) {
                write('return ');
            }

            parse(node.children[2]);
            write('}');

            if(node.children.length > 3) {
                write(' else { ');

                if(!is_throw(node.children[3])) {
                    write('return ');
                }

                parse(node.children[3]);
                write('}');
            }

            write('})()');

            if(!node.link ||
               (node.link && node.link.tag != 'expr')) {
                write(';');
            }

            write('\n');
        },

        'and': function(node, parse) {
            write_op('&&', node, parse);
        },

        'or': function(node, parse) {
            write_op('||', node, parse);
        },

        'require': function(node, parse) {
            for(var i=1, len=node.children.length; i<len; i++) {
                var expr = node.children[i];
                var name = expr.children[0];
                var path = expr.children[1];

                write('var ');
                write_term(name);
                write(' = require("' + path.data + '");', true);
            }
        },

        'string-append': function(node, parse) {
            write_op('+', node, parse);
        }
    };

    return {
        create_generator: create_generator,
        has_hook: has_hook,
        run_hook: run_hook,
        write_runtime: write_runtime,
        write_boolean: write_boolean,
        write_number: write_number,
        write_string: write_string,
        write_term: write_term,
        write_set: write_set,
        write_set_excl: write_set_excl,
        write_lambda: write_lambda,
        write_func_call: write_func_call,
        write_list: write_list,
        write_vector: write_vector,
        write_map: write_map,
        write_symbol: write_symbol,

        get_code: function() {
            return code.join('');
        }
    };
};

module.exports = generator;
<commit_msg>add mod to old compiler<commit_after>var fs = require('fs');
var ast = require('./ast');

function generator() {
    var code = [];
    function write(src, eol) {
        code.push(src + (eol ? '\n' : ''));
    };

    function write_runtime(target) {
        if(target == 'no-runtime') {
            return;
        }

        var rt = fs.readFileSync('runtime.js', 'utf-8');
        write(rt, true);

        if(target != 'js-noeval') {
            rt = fs.readFileSync('runtime-eval.js', 'utf-8');
            write(rt, true);
        }
    }

    function create_generator() {
        return generator();
    }

    function link(node1, node2, tag) {
        node2.link = node1;
        node1.tag = tag;
    }

    function unlink(node) {
        node.link = null;
    }

    function has_hook(name) {
        return !!hooks[name];
    }

    function run_hook(name, node, parse) {
        hooks[name](node, parse);
    }

    function is_throw(node) {
        return node.type == ast.LIST &&
            node.children[0].data &&
            node.children[0].data.str == 'throw';
    }

    function parse_expr(parse, parent, node) {
        // Link these nodes for context (big hack)
        link(parent, node, 'expr');
        parse(node);
        unlink(node);
    }

    function write_boolean(node) {
        if(node.data === true) {
            write('true');
        }
        else {
            write('false');
        }
    }

    function transform_symbol(str) {
        str = str.replace(/-/g, '_dash_');
        str = str.replace(/\?/g, '_p_');
        str = str.replace(/\!/g, '_excl_');
        str = str.replace(/>/g, '_gt_');
        str = str.replace(/</g, '_lt_');
        str = str.replace(/%/g, '_per_');
        return str;
    }

    function write_number(node) {
        // NUMBER
        write(node.data);
    }

    function write_string(node) {
        // STRING
        var str = node.data;
        str = str.replace(/\\/g, '\\\\');
        str = str.replace(/\n/g, '\\n');
        str = str.replace(/\r/g, '\\r');
        str = str.replace(/\t/g, '\\t');
        str = str.replace(/"/g, '\\"');
        write('"' + str  + '"');
    }

    function write_term(node) {
        // TERM (variable, keyword, etc)
        write(transform_symbol(node.data.str));
    }

    function write_symbol(node) {
        // SYMBOL
        write('string_dash__gt_symbol("' + transform_symbol(node.data.str) + '")');
    }

    function write_set(node, parse) {
        // var TERM = EXPR;
        write('var ');
        write_set_excl(node, parse);
    }

    function write_set_excl(node, parse) {
        // TERM = EXPR;
        write_term(node.children[1]);
        write(' = ');
        parse(node.children[2]);
        write(';');
    }

    function write_lambda(node, parse) {
        // function(TERM1, TERM2, ...) { EXPR1; EXPR2; ...; return EXPRn; }
        var args_expr = node.children[1];

        if(args_expr.type == ast.LIST) {
            var capture_name;

            write('function(');

            for(var i=0, len=args_expr.children.length; i<len; i++) {
                var arg = args_expr.children[i];

                // support for dot-style rest arguments
                if(arg.data.str == '.') {
                    capture_name = args_expr.children[i+1];
                    break;
                }
                else {
                    if(i>0) {
                        write(',');
                    }

                    write_term(arg);
                }
            }

            write('){', true);

            if(capture_name) {
                write('var ');
                write_term(capture_name);
                write(' = vector_dash_to_dash_list(Array.prototype.slice.call(arguments, ' +
                      (args_expr.children.length - 2) + '));', true);
            }
        }
        else {
            write('function() {', true);
            write('var ' + args_expr.data.str +
                  ' = vector_dash_to_dash_list(Array.prototype.slice.call(arguments));', true);
        }

        for(var i=2, len=node.children.length; i<len; i++) {
            var child = node.children[i];

            if(i == node.children.length-1 &&
               !is_throw(child)) {
                write('return ');
            }
            parse(child);
        }

        write('}', true);
    }

    function write_op(op, node, parse) {
        // (EXPR1 <op> EXPR2 <op> ... <op> EXPRn),
        write('(');
        for(var i=1, len=node.children.length; i<len; i++) {
            if(i > 1) {
                write(op);
            }

            parse_expr(parse, node, node.children[i]);
        }

        write(')');
    }

    function write_func_call(node, parse) {
        if(node.children[0].type == ast.TERM) {
            write_term(node.children[0]);
        }
        else {
            write('(');
            parse_expr(parse, node, node.children[0]);
            write(')');
        }

        write('(');

        for(var i=1, len=node.children.length; i<len; i++) {
            if(i>1) {
                write(',');
            }

            parse_expr(parse, node, node.children[i]);
        }

        write(')');

        // var util = require('util');
        // util.puts(util.inspect(node, false, 4));

        // if the parent node is not a function call, we should end
        // the expression. this solves ambiguities with the next
        // statement which could be another function call in the form
        // (foo)(x, y, z) where it tries to call the result of this
        // function
        if(!node.link ||
           (node.link && node.link.tag != 'expr')) {
            write(';');
        }
    }

    function write_vector(node, parse, context) {
        write('unquote_splice_vec([');
        for(var i=0, len=node.children.length; i<len; i++) {
            if(i > 0) {
                write(',');
            }
            write_list_element(node, i, parse, context);
        }
        write('])');
    }

    function write_map(node, parse, context) {
        write('unquote_splice_map({');

        for(var i=0, len=node.children.length; i<len; i+=2) {
            if(i>0) {
                write(',');
            }

            var key = node.children[i];
            var val_index = i+1;

            var key_form = key.children[0];
            if(key.type == ast.LIST && key_form.data) {
                if(key_form.data.str == 'unquote-splicing') {
                    key = '__unquote_splicing';
                    val_index = i;
                }
                else if(key.children[0].data.str != 'quote') {
                    throw "Invalid key for dict: " + key;
                }
                else {
                    key = key.children[1].data.str;
                }
            }
            else {
                throw "Invalid key for dict: " + key;
            }

            write('"' + transform_symbol(key) + '": ');
            write_list_element(node, val_index, parse, context);
        }

        write('})');
    }

    function write_list(node, parse, context) {
        write('unquote_splice(');
        _write_list(node, 0, parse, context);
        write(')');
    }

    function _write_list(node, i, parse, context) {
        if(i < node.children.length) {
            write('make_dash_list([');
            write_list_element(node, i, parse, context);
            write(',');
            _write_list(node, i+1, parse, context);
            write('])');
        }
        else {
            write('_emptylst');
        }
    }

    function write_list_element(node, i, parse, context) {
        var n = node.children[i];

        if(context == 'quote' || context == 'quasi') {
            if(context == 'quasi') {
                if(n.children[0] && n.children[0].type == ast.TERM) {
                    // If it's a list with a term in the front, check if
                    // it's an unquote or unquote-splicing and handle
                    // it specially
                    var term = n.children[0];

                    if(term.data.str == 'unquote') {
                        parse_expr(parse, n, n.children[1]);
                        return;
                    }
                    else if(term.data.str == 'unquote-splicing') {
                        write('{ please_splice: true, data: ');
                        parse_expr(parse, n, n.children[1]);
                        write(' }');
                        return;
                    }
                }
            }

            if(n.type == ast.TERM) {
                write_symbol(n);
            }
            else if(n.type == ast.NUMBER) {
                write_number(n);
            }
            else if(n.type == ast.BOOLEAN) {
                write_boolean(n);
            }
            else if(n.type == ast.STRING) {
                write_string(n);
            }
            else if(n.type == ast.LIST) {
                write_list(n, parse, context);
            }
            else if(n.type == ast.VECTOR) {
                write_vector(n, parse, context);
            }
        }
        else {
            parse_expr(parse, node, n);
        }
    }

    var hooks = {
        '+': function(node, parse) {
            write_op('+', node, parse);
        },

        '-': function(node, parse) {
            write_op('-', node, parse);
        },

        '*': function(node, parse) {
            write_op('*', node, parse);
        },

        '/': function(node, parse) {
            write_op('/', node, parse);
        },

        '=': function(node, parse) {
            write_op('===', node, parse);
        },

        '>': function(node, parse) {
            write_op('>', node, parse);
        },

        '<': function(node, parse) {
            write_op('<', node, parse);
        },

        '%': function(node, parse) {
            write_op('%', node, parse);
        },

        'if': function (node, parse) {
            // (function() { if(EXPR1) { return EXPR2; } else { return EXPR3; }})()
            write('(function() {');

            write('if(');
            parse_expr(parse, node, node.children[1]);
            write(') { ');

            if(!is_throw(node.children[2])) {
                write('return ');
            }

            parse(node.children[2]);
            write('}');

            if(node.children.length > 3) {
                write(' else { ');

                if(!is_throw(node.children[3])) {
                    write('return ');
                }

                parse(node.children[3]);
                write('}');
            }

            write('})()');

            if(!node.link ||
               (node.link && node.link.tag != 'expr')) {
                write(';');
            }

            write('\n');
        },

        'and': function(node, parse) {
            write_op('&&', node, parse);
        },

        'or': function(node, parse) {
            write_op('||', node, parse);
        },

        'require': function(node, parse) {
            for(var i=1, len=node.children.length; i<len; i++) {
                var expr = node.children[i];
                var name = expr.children[0];
                var path = expr.children[1];

                write('var ');
                write_term(name);
                write(' = require("' + path.data + '");', true);
            }
        },

        'string-append': function(node, parse) {
            write_op('+', node, parse);
        }
    };

    return {
        create_generator: create_generator,
        has_hook: has_hook,
        run_hook: run_hook,
        write_runtime: write_runtime,
        write_boolean: write_boolean,
        write_number: write_number,
        write_string: write_string,
        write_term: write_term,
        write_set: write_set,
        write_set_excl: write_set_excl,
        write_lambda: write_lambda,
        write_func_call: write_func_call,
        write_list: write_list,
        write_vector: write_vector,
        write_map: write_map,
        write_symbol: write_symbol,

        get_code: function() {
            return code.join('');
        }
    };
};

module.exports = generator;
<|endoftext|>


<commit_before><commit_msg>css classname typo<commit_after><|endoftext|>