<commit_before>import React, {Component} from 'react'
import NavLink from './navlink'
import Logo from '../Logo'
import {browserHistory} from 'react-router'
import Search from '../Search'

export default class AppHeader extends Component {
  constructor(props) {
    super(props)
    if (this.props.params.query) new Search().query(this.props.params.query)
  }

  render() {
    return <header>
      <NavLink to="/"><Logo {...this.props}/></NavLink>
      <nav id="primary">
        <NavLink to="/collections">Collections</NavLink>
	<NavLink to="/about">About</NavLink>
      	<NavLink to="/policy/ethical-use">Ethical Use</NavLink>
      </nav>
      <input
        name="q" type="search" placeholder="Search Query"
        onFocus={this.query} onChange={this.query}
        value={this.props.params.query} />
    </header>
  }

  query(e) {
    // Preserve any collection prefixes that might be present, e.g. /collections/ied/
    let prefix = /(^\/collections\/\w+)[\/.]*/.exec(location.pathname) || ''

    browserHistory.push(`${prefix}/search/${e.target.value}`)
    new Search().query(e.target.value)
  }
}

<commit_msg>Refactor.  Shorten search initialization.<commit_after>import React, {Component} from 'react'
import NavLink from './navlink'
import Logo from '../Logo'
import {browserHistory} from 'react-router'
import Search from '../Search'

export default class AppHeader extends Component {
  constructor(props) {
    super(props)
    new Search().query(this.props.params.query || '')
  }

  render() {
    return <header>
      <NavLink to="/"><Logo {...this.props}/></NavLink>
      <nav id="primary">
        <NavLink to="/collections">Collections</NavLink>
	<NavLink to="/about">About</NavLink>
      	<NavLink to="/policy/ethical-use">Ethical Use</NavLink>
      </nav>
      <input
        name="q" type="search" placeholder="Search Query"
        onFocus={this.query} onChange={this.query}
        value={this.props.params.query} />
    </header>
  }

  query(e) {
    // Preserve any collection prefixes that might be present, e.g. /collections/ied/
    let prefix = /(^\/collections\/\w+)[\/.]*/.exec(location.pathname) || ''

    browserHistory.push(`${prefix}/search/${e.target.value}`)
    new Search().query(e.target.value)
  }
}

<|endoftext|>


<commit_before>Ext.namespace('Talho.Rollcall');
Ext.namespace('Talho.Rollcall.ux');

Talho.Rollcall.init_store = null;

Talho.Rollcall.ADST = Ext.extend(Ext.Panel, {
  constructor: function(config)
  {
    Ext.apply(config, {
      title:      config.title,
      id:         config.id,
      itemdId:    config.id,
      closable:   true,
      autoScroll: true,
      layout:     'border',
      defaults: {
        collapsible: true,
        split:       true,
        cmargins:    '5 5 0 0',
        margins:     '5 0 0 0'
      },
      items: [{
        title:    'Saved Queries',
        region:   'south',
        height:   150,
        minSize:  75,
        maxSize:  250,
        bodyStyle:   'padding:15px',
        items:    new Talho.Rollcall.SavedQueriesPanel({})
      },{
        title:       'Reports',
        region:      'east',
        width:       200,
        minSize:     175,
        maxSize:     400,
        bodyStyle:   'padding:0px',
        layout:      'fit',
        autoScroll:  true,
        items:       new Talho.Rollcall.ReportsPanel({})
      },{
        title: 'Alarms',
        region:'west',
        width: 200,
        minSize: 175,
        maxSize: 400,
        bodyStyle: 'padding:0px',
        items: new Talho.Rollcall.AlarmsPanel({})
      },{
        listeners:   { scope: this},
        title:       'ADST',
        itemId:      'ADST_panel',
        id:          'ADST_panel',
        collapsible: false,
        region:      'center',
        autoScroll:  true,
        listeners: {
          render: function(this_comp){
            new Ext.LoadMask(this_comp.getEl(), {msg:"Please wait...", store: Talho.Rollcall.init_store});
          }
        },
        items:[{
          xtype:  'container',
          itemId: 'query_container',
          layout: 'column',
          hidden: true,
          items:[{
            xtype: 'form',
            itemId: 'ADSTFormPanel',
            columnWidth: 1,
            labelAlign: 'top',
            id: "ADSTFormPanel",
            url:'/rollcall/adst',
            buttonAlign: 'left',
            buttons: [{
              text: "Submit",
              scope: this,
              handler: function(buttonEl, eventObj){
                Ext.getCmp('ADSTFormPanel').getForm().submit({
                  scope: this,
                  waitMsg: "Please wait...",
                  waitTitle: "Loading",
                  success: function(form, action)
                  {
                    Ext.getCmp('ADSTResultPanel').show();
                    Ext.getCmp('ADSTResultPanel').processQuery(action.result);
                  },
                  failure: function(form, action)
                  {

                  }
                });
              },
              formBind: true
            },{
              text: "Cancel",
              handler: this.clearForm
            }],
            initComponent: function() {
              Talho.Rollcall.init_store = new Ext.data.JsonStore({
                autoLoad: true,
                root:   'options',
                fields: ['absenteeism', 'age', 'data_functions', 'gender', 'grade', 'school_type',   'schools', 'symptons', 'temperature', 'zipcode'],
                url:    '/rollcall/query_options',
                listeners:{
                  scope: this,
                  load: function(this_store, record){
                    var simple_config = {};
                    var adv_config = {};
                    for(var i =0; i < record.length; i++){
                      if(record[i].data.schools != ""){
                        simple_config.schools = adv_config.schools = new Array();
                        for(var s = 0; s < record[i].data.schools.length; s++){
                          simple_config.schools[s] = adv_config.schools[s] = [
                            record[i].data.schools[s].id, record[i].data.schools[s].display_name
                          ]
                        }
                      }else{
                        string_eval = "simple_config."+this_store.fields.items[i].name+" = adv_config."+this_store.fields.items[i].name+" = new Array();"+
                        "for(var a = 0; a "+"<"+" record[i].data."+this_store.fields.items[i].name+".length; a++){"+
                            "simple_config."+this_store.fields.items[i].name+"[a] = adv_config."+this_store.fields.items[i].name+"[a] = ["+
                              "record[i].data."+this_store.fields.items[i].name+"[a].id, record[i].data."+this_store.fields.items[i].name+"[a].value"+
                            "];"+
                         "}"
                        eval(string_eval);
                      }
                    }
                    this.findParentByType('container').show();
                    this.add(new Talho.Rollcall.SimpleADSTContainer(simple_config));
                    this.add(new Talho.Rollcall.AdvancedADSTContainer(adv_config));
                    this.doLayout();
                  }
                }
              });

              this.__proto__.initComponent.apply(this);
            }
          }]
        }, new Talho.Rollcall.ADSTResultPanel({}) ]
      }]
    });
    Talho.Rollcall.ADST.superclass.constructor.call(this, config);
  }
});

Talho.Rollcall.ADST.initialize = function(config)
{
  return new Talho.Rollcall.ADST(config);
}

Talho.ScriptManager.reg('Talho.Rollcall.ADST', Talho.Rollcall.ADST, Talho.Rollcall.ADST.initialize);
<commit_msg>Finished cleaning up scope.<commit_after>Ext.namespace('Talho.Rollcall');
Ext.namespace('Talho.Rollcall.ux');

Talho.Rollcall.ADST = Ext.extend(Ext.Panel, {
  constructor: function(config)
  {
    var resultPanel = new Talho.Rollcall.ADSTResultPanel({});

    Ext.apply(config, {
      init_store: null,
      closable:   true,
      autoScroll: true,
      layout:     'border',
      defaults: {
        collapsible: true,
        split:       true,
        cmargins:    '5 5 0 0',
        margins:     '5 0 0 0'
      },
      items: [{
        title:    'Saved Queries',
        region:   'south',
        height:   150,
        minSize:  75,
        maxSize:  250,
        bodyStyle:   'padding:15px',
        items:    new Talho.Rollcall.SavedQueriesPanel({})
      },{
        title:       'Reports',
        region:      'east',
        width:       200,
        minSize:     175,
        maxSize:     400,
        bodyStyle:   'padding:0px',
        layout:      'fit',
        autoScroll:  true,
        items:       new Talho.Rollcall.ReportsPanel({})
      },{
        title: 'Alarms',
        region:'west',
        width: 200,
        minSize: 175,
        maxSize: 400,
        bodyStyle: 'padding:0px',
        items: new Talho.Rollcall.AlarmsPanel({})
      },{
        listeners:   { scope: this},
        title:       'ADST',
        itemId:      'ADST_panel',
        id:          'ADST_panel',
        collapsible: false,
        region:      'center',
        autoScroll:  true,
        listeners: {
          render: function(this_comp){
            new Ext.LoadMask(this_comp.getEl(), {msg:"Please wait...", store: this.ownerCt.init_store});
          }
        },
        resultPanel: resultPanel,
        items:[{
          xtype:  'container',
          itemId: 'query_container',
          layout: 'column',
          hidden: true,
          items:[{
            xtype: 'form',
            itemId: 'ADSTFormPanel',
            columnWidth: 1,
            labelAlign: 'top',
            id: "ADSTFormPanel",
            url:'/rollcall/adst',
            buttonAlign: 'left',
            buttons: [{
              text: "Submit",
              scope: this,
              handler: function(buttonEl, eventObj){
                this.submit({
                  scope: this,
                  waitMsg: "Please wait...",
                  waitTitle: "Loading",
                  success: function(form, action)
                  {
                    this.ownerCt.ownerCt.resultPanel.show();
                    this.ownerCt.ownerCt.resultPanel.processQuery(action.result);
                  },
                  failure: function(form, action)
                  {

                  }
                });
              },
              formBind: true
            },{
              text: "Cancel",
              handler: this.clearForm
            }],
            initComponent: function() {
              this.ownerCt.ownerCt.ownerCt.init_store = new Ext.data.JsonStore({
                autoLoad: true,
                root:   'options',
                fields: ['absenteeism', 'age', 'data_functions', 'gender', 'grade', 'school_type',   'schools', 'symptons', 'temperature', 'zipcode'],
                url:    '/rollcall/query_options',
                listeners:{
                  scope: this,
                  load: function(this_store, record){
                    var simple_config = {};
                    var adv_config = {};
                    for(var i =0; i < record.length; i++){
                      if(record[i].data.schools != ""){
                        simple_config.schools = adv_config.schools = new Array();
                        for(var s = 0; s < record[i].data.schools.length; s++){
                          simple_config.schools[s] = adv_config.schools[s] = [
                            record[i].data.schools[s].id, record[i].data.schools[s].display_name
                          ]
                        }
                      }else{
                        string_eval = "simple_config."+this_store.fields.items[i].name+" = adv_config."+this_store.fields.items[i].name+" = new Array();"+
                        "for(var a = 0; a "+"<"+" record[i].data."+this_store.fields.items[i].name+".length; a++){"+
                            "simple_config."+this_store.fields.items[i].name+"[a] = adv_config."+this_store.fields.items[i].name+"[a] = ["+
                              "record[i].data."+this_store.fields.items[i].name+"[a].id, record[i].data."+this_store.fields.items[i].name+"[a].value"+
                            "];"+
                         "}"
                        eval(string_eval);
                      }
                    }
                    this.ownerCt.show();
                    this.add(new Talho.Rollcall.SimpleADSTContainer(simple_config));
                    this.add(new Talho.Rollcall.AdvancedADSTContainer(adv_config));
                    this.doLayout();
                  }
                }
              });

              this.__proto__.initComponent.apply(this);
            }
          }]
        }, resultPanel ]
      }]
    });
    Talho.Rollcall.ADST.superclass.constructor.call(this, config);
  }
});

Talho.Rollcall.ADST.initialize = function(config)
{
  return new Talho.Rollcall.ADST(config);
}

Talho.ScriptManager.reg('Talho.Rollcall.ADST', Talho.Rollcall.ADST, Talho.Rollcall.ADST.initialize);
<|endoftext|>


<commit_before>Ext.namespace('Talho.Rollcall');
Ext.namespace('Talho.Rollcall.ux');

Talho.Rollcall.ADST = Ext.extend(Ext.Panel, {
  constructor: function(config)
  {
    this.providers      = new Array();
    var resultPanel     = new Talho.Rollcall.ADSTResultPanel({});
    this.getResultPanel = function()
    {
      return resultPanel;
    };

    Ext.apply(this, config);
    Ext.apply(this,
    {
      layout:   'fit',
      closable: true,
      scope:    this,
      items:[{
        id:         'adst_container',
        layout:     'border',
        autoScroll: true,
        scope:      this,
        defaults: {
          collapsible: true,
          split:       true//,
          //cmargins:    '5 0 0 0',
          //margins:     '5 0 0 0'
        },
        items: [{
          title:      'Alarm Queries',
          itemId:     'alarm_queries',
          id:         'alarm_queries',
          region:     'south',
          height:     140,
          minSize:    100,
          maxSize:    140,
          autoScroll: true,
          layout:     'fit',
          items:      new Talho.Rollcall.AlarmQueriesPanel({adst_panel: this})
        },/*{
          title:       'Reports',
          id:          'reports_panel',
          itemId:      'reports_panel',
          region:      'east',
          bodyStyle:   'padding:0px',
          layout:      'fit',
          width:       175,
          minSize:     150,
          maxSize:     175,
          autoScroll:  true,
          hideBorders: true,
          items:       new Talho.Rollcall.ReportsPanel({}),
          bbar:[{
            text:    'Create',
            iconCls: 'documents-add-icon',
            id:      'create_report_button',
            itemId:  'create_report_button',
            disabled: true,
            handler: function(btn,event)
            {
              this.ownerCt.ownerCt.getComponent('reports_grid').load_report_window();
            }
          }]
        },*/{
          title:     'Alarms',
          region:    'west',
          layout:    'fit',
          bodyStyle: 'padding:0px',
          width:     175,
          minSize:   150,
          maxSize:   175,
          hideBorders: true,
          items:     new Talho.Rollcall.AlarmsPanel({}),
          bbar:[{
            text:    'Refresh',
            iconCls: 'x-tbar-loading',
            handler: function(btn,event)
            {
              this.ownerCt.ownerCt.getComponent('alarm_panel').alarms_store.load();
            }
          },'->',{
            text:     'GIS',
            id:       'gis_button',
            itemId:   'gis_button',
            iconCls:  'x-tbar-gis',
            disabled: true,
            handler:  function()
            {
              this.ownerCt.ownerCt.getComponent('alarm_panel').load_alarm_gmap_window();
            }
          }]
        },{
          title:       'ADST',
          itemId:      'ADST_panel',
          id:          'ADST_panel',
          collapsible: false,
          region:      'center',
          autoScroll:  true,
          scope:       this,
          items:[{
            xtype:  'container',
            itemId: 'query_container',
            layout: 'column',
            scope:  this,
            hideBorders: true,
            items:[{
              xtype:       'form',
              itemId:      'ADSTFormPanel',
              labelAlign:  'top',
              id:          "ADSTFormPanel",
              url:         '/rollcall/adst',
              buttonAlign: 'left',
              columnWidth: 1,
              scope:       this,
              buttons: [{
                text:     "Submit",
                scope:    this,
                hidden:   true,
                handler:  this.submitQuery,
                formBind: true
              },{
                text:    "Reset Form",
                scope:   this,
                hidden:  true,
                handler: this.resetForm
              },{
                text:    "Export Result Set",
                hidden:  true,
                scope:   this,
                handler: this.exportResultSet
              },{
                text:    "Map Result Set",
                hidden:  true,
                scope:   this,
                handler: this.mapResultSet
              },{
                text:    "Create Alarm from Result Set",
                hidden:  true,
                scope:   this,
                handler: this.saveResultSet
              }],
              listeners:{
                scope:        this,
                beforerender: this.initFormComponent
              }
            }]
          }, resultPanel ],
          bbar: new Ext.PagingToolbar({
            scope:          this,
            displayInfo:    true,
            prependButtons: true,
            pageSize:       6,
            listeners:{
              'beforechange': this.setNextPage
            }
          })
        }]
      }]
    });
    Talho.Rollcall.ADST.superclass.constructor.call(this, config);
    this.addListener("deactivate", function(w){
      if(Ext.getCmp('gmap_alarm_window')) Ext.getCmp('gmap_alarm_window').close();
      this.get(0).get(1).getComponent('alarm_panel').close_alarm_tip();
    });
    this.addListener("close", function(w){
      if(Ext.getCmp('gmap_alarm_window')) Ext.getCmp('gmap_alarm_window').close();
      this.get(0).get(1).getComponent('alarm_panel').close_alarm_tip();
    });
  },
  renderGraphs: function(id, image, obj, class_name)
  {
    provider = new Ext.direct.PollingProvider({
      id:        'image' + id + '-provider',
      type:      'polling',
      url:       image,
      listeners: {
        scope: obj,
        data: function(provider, e)
        {
          if(e.xhr.status == 200) {
            var element_id = Ext.id();
            (function(provider)
            {
              this.update('
' +
                          '' +
                          '
');
              this.doLayout();
            }).defer(50,this,[provider]);
            (function(provider)
            {
              this.update('
' +
                          '' +
                          '
');
              this.doLayout();
            }).defer(1000,this,[provider]);
            provider.disconnect();
            return true;
          } else {
            return false;
          }
        }
      }
    });
    this.providers.push(provider);
    Ext.Direct.addProvider(provider);
  },
  buildParams: function(form_values)
  {
    var params = new Object;
    params['authenticity_token'] = FORM_AUTH_TOKEN;
    for (key in form_values)
      if (Ext.getCmp('advanced_query_select').isVisible()){
        if(key.indexOf('_adv') != -1)
          params[key.replace(/_adv/,'')] = form_values[key];
      }else{
        if(key.indexOf('_simple') != -1)
          params[key.replace(/_simple/,'')] = form_values[key];
      }
    return params;
  },
  saveResultSet: function(buttonEl, eventObj)
  {
    this.getResultPanel().showAlarmQueryConsole(null);
    return true;
  },
  mapResultSet: function(buttonEl, eventObj)
  {
    var form_values = buttonEl.findParentByType('form').getForm().getValues();
    var params      = this.buildParams(form_values);
    params["limit"] = this.getResultPanel().getResultStore().getTotalCount();
    Ext.Ajax.request({
      url:      '/rollcall/schools',
      method:   'GET',
      params:   params,
      scope:    this,
      callback: function(options, success, response){
        var gmapPanel = new Ext.ux.GMapPanel({zoomLevel: 9});
        var win       = new Ext.Window({
          title:      "Google Map of Schools",
          layout:     'fit',
          labelAlign: 'top',
          padding:    '5',
          width:      510,
          height:     450,
          items:      [gmapPanel]
        });
        win.schools = Ext.decode(response.responseText).results;
        win.addButton({xtype: 'button', text: 'Dismiss', handler: function(){ win.close(); }, scope: this, width:'auto'});
        win.addListener("afterrender", function(w){
          var center = new google.maps.LatLng(w.schools[0].gmap_lat, w.schools[0].gmap_lng);
          gmapPanel.gmap.setCenter(center);
          for(var i = 0; i < w.schools.length; i++) {
            var loc           = new google.maps.LatLng(w.schools[i].gmap_lat, w.schools[i].gmap_lng);
            var marker        = gmapPanel.addMarker(loc, w.schools[i].display_name, {});
            var addr_elems    = w.schools[i].gmap_addr.split(",");
            marker.info       = "" + w.schools[i].display_name + "
";
            marker.info      += addr_elems[0] + "
" + addr_elems[1] + "
" + addr_elems.slice(2).join(",");
            marker.info_popup = null;
            google.maps.event.addListener(marker, 'click', function(){
              if (this.info_popup) {
                this.info_popup.close(gmapPanel.gmap, this);
                this.info_popup = null;
              } else {
                this.info_popup = new google.maps.InfoWindow({content: this.info});
                this.info_popup.open(gmapPanel.gmap, this);
              }
            });
          }
        });
        win.show();
      },
      failure: function(){}
    });
  },
  exportResultSet: function(buttonEl, eventObj)
  {
    Ext.Ajax.request({
      url:    '/rollcall/export',
      method: 'GET',
      params: this.buildParams(buttonEl.findParentByType("form").getForm().getValues()),
      scope:  this,
      callback: function(options, success, response){
        Ext.MessageBox.show({
          title: 'Creating CSV Export File',
          msg: 'Your CSV file will be placed in your documents folders when the system '+
          'is done generating it. Please check your documents folder in a few minutes.',
          buttons: Ext.MessageBox.OK,
          icon: Ext.MessageBox.INFO
        });
      },
      failure: function(){
      }
    });
  },
  resetForm: function(buttonEl, eventObj)
  {
    buttonEl.findParentByType("form").getForm().reset();
  },
  submitQuery: function(buttonEl, eventObj)
  {
    this.getResultPanel().clearProviders();
    var form_panel   = this.find('id', 'ADSTFormPanel')[0];
    var form_values  = form_panel.getForm().getValues();
    var result_store = this.getResultPanel().getResultStore();
    form_panel.findParentByType('panel').getBottomToolbar().bindStore(result_store);
    result_store.baseParams = {}; // clear previous search values
    var params              = this.buildParams(form_values);
    for(key in params)
      result_store.setBaseParam(key, params[key]);
    form_panel.buttons[2].show();
    form_panel.buttons[3].show();
    form_panel.buttons[4].show();
    var panel_mask = new Ext.LoadMask(this.getComponent('adst_container').getComponent('ADST_panel').getEl(), {msg:"Please wait..."});
    panel_mask.show();
    result_store.on('load', function(){ panel_mask.hide(); });
    result_store.load({params: this.buildParams(form_values)});
    return true;
  },
  setNextPage: function(this_toolbar, params)
  {
    var result_store   = this_toolbar.ownerCt.ownerCt.ownerCt.getResultPanel().getResultStore();
    var container_mask = new Ext.LoadMask(this_toolbar.ownerCt.ownerCt.ownerCt.getResultPanel().getEl(), {msg:"Please wait..."});
    params['page']     = Math.floor(params.start /  params.limit) + 1;
    container_mask.show();
    result_store.on('load', function(){ container_mask.hide(); });
    return true;
  },
  loadInitMask: function()
  {
    new Ext.LoadMask(this.getComponent('adst_container').getComponent('ADST_panel').getEl(),    {msg:"Please wait...", store: this.init_store});
  },
  initFormComponent: function(form_panel)
  {
    this.init_store = new Ext.data.JsonStore({
      root:     'options',
      fields:   ['absenteeism', 'age', 'data_functions', 'data_functions_adv', 'gender', 'grade', 'school_type', 'schools', 'symptoms', 'zipcode'],
      url:      '/rollcall/query_options',
      autoLoad: false,
      listeners:{
        scope: form_panel,
        load:  function(this_store, records){
          this.ownerCt.show();
          this.add(new Talho.Rollcall.SimpleADSTContainer({options: records[0].data}));
          this.add(new Talho.Rollcall.AdvancedADSTContainer({options: records[0].data}));
          this.buttons[0].show();
          this.buttons[1].show();
          //this.ownerCt.ownerCt.ownerCt.getComponent('reports_panel').getBottomToolbar().findById('create_report_button').enable();
          this.doLayout();
        }
      }
    });
    this.loadInitMask();
    this.init_store.load();
  },
  init_store: null
});

Talho.Rollcall.ADST.initialize = function(config)
{
  return new Talho.Rollcall.ADST(config);
}

Talho.ScriptManager.reg('Talho.Rollcall.ADST', Talho.Rollcall.ADST, Talho.Rollcall.ADST.initialize);
<commit_msg>Fixed map center calculation.<commit_after>Ext.namespace('Talho.Rollcall');
Ext.namespace('Talho.Rollcall.ux');

Talho.Rollcall.ADST = Ext.extend(Ext.Panel, {
  constructor: function(config)
  {
    this.providers      = new Array();
    var resultPanel     = new Talho.Rollcall.ADSTResultPanel({});
    this.getResultPanel = function()
    {
      return resultPanel;
    };

    Ext.apply(this, config);
    Ext.apply(this,
    {
      layout:   'fit',
      closable: true,
      scope:    this,
      items:[{
        id:         'adst_container',
        layout:     'border',
        autoScroll: true,
        scope:      this,
        defaults: {
          collapsible: true,
          split:       true//,
          //cmargins:    '5 0 0 0',
          //margins:     '5 0 0 0'
        },
        items: [{
          title:      'Alarm Queries',
          itemId:     'alarm_queries',
          id:         'alarm_queries',
          region:     'south',
          height:     140,
          minSize:    100,
          maxSize:    140,
          autoScroll: true,
          layout:     'fit',
          items:      new Talho.Rollcall.AlarmQueriesPanel({adst_panel: this})
        },/*{
          title:       'Reports',
          id:          'reports_panel',
          itemId:      'reports_panel',
          region:      'east',
          bodyStyle:   'padding:0px',
          layout:      'fit',
          width:       175,
          minSize:     150,
          maxSize:     175,
          autoScroll:  true,
          hideBorders: true,
          items:       new Talho.Rollcall.ReportsPanel({}),
          bbar:[{
            text:    'Create',
            iconCls: 'documents-add-icon',
            id:      'create_report_button',
            itemId:  'create_report_button',
            disabled: true,
            handler: function(btn,event)
            {
              this.ownerCt.ownerCt.getComponent('reports_grid').load_report_window();
            }
          }]
        },*/{
          title:     'Alarms',
          region:    'west',
          layout:    'fit',
          bodyStyle: 'padding:0px',
          width:     175,
          minSize:   150,
          maxSize:   175,
          hideBorders: true,
          items:     new Talho.Rollcall.AlarmsPanel({}),
          bbar:[{
            text:    'Refresh',
            iconCls: 'x-tbar-loading',
            handler: function(btn,event)
            {
              this.ownerCt.ownerCt.getComponent('alarm_panel').alarms_store.load();
            }
          },'->',{
            text:     'GIS',
            id:       'gis_button',
            itemId:   'gis_button',
            iconCls:  'x-tbar-gis',
            disabled: true,
            handler:  function()
            {
              this.ownerCt.ownerCt.getComponent('alarm_panel').load_alarm_gmap_window();
            }
          }]
        },{
          title:       'ADST',
          itemId:      'ADST_panel',
          id:          'ADST_panel',
          collapsible: false,
          region:      'center',
          autoScroll:  true,
          scope:       this,
          items:[{
            xtype:  'container',
            itemId: 'query_container',
            layout: 'column',
            scope:  this,
            hideBorders: true,
            items:[{
              xtype:       'form',
              itemId:      'ADSTFormPanel',
              labelAlign:  'top',
              id:          "ADSTFormPanel",
              url:         '/rollcall/adst',
              buttonAlign: 'left',
              columnWidth: 1,
              scope:       this,
              buttons: [{
                text:     "Submit",
                scope:    this,
                hidden:   true,
                handler:  this.submitQuery,
                formBind: true
              },{
                text:    "Reset Form",
                scope:   this,
                hidden:  true,
                handler: this.resetForm
              },{
                text:    "Export Result Set",
                hidden:  true,
                scope:   this,
                handler: this.exportResultSet
              },{
                text:    "Map Result Set",
                hidden:  true,
                scope:   this,
                handler: this.mapResultSet
              },{
                text:    "Create Alarm from Result Set",
                hidden:  true,
                scope:   this,
                handler: this.saveResultSet
              }],
              listeners:{
                scope:        this,
                beforerender: this.initFormComponent
              }
            }]
          }, resultPanel ],
          bbar: new Ext.PagingToolbar({
            scope:          this,
            displayInfo:    true,
            prependButtons: true,
            pageSize:       6,
            listeners:{
              'beforechange': this.setNextPage
            }
          })
        }]
      }]
    });
    Talho.Rollcall.ADST.superclass.constructor.call(this, config);
    this.addListener("deactivate", function(w){
      if(Ext.getCmp('gmap_alarm_window')) Ext.getCmp('gmap_alarm_window').close();
      this.get(0).get(1).getComponent('alarm_panel').close_alarm_tip();
    });
    this.addListener("close", function(w){
      if(Ext.getCmp('gmap_alarm_window')) Ext.getCmp('gmap_alarm_window').close();
      this.get(0).get(1).getComponent('alarm_panel').close_alarm_tip();
    });
  },
  renderGraphs: function(id, image, obj, class_name)
  {
    provider = new Ext.direct.PollingProvider({
      id:        'image' + id + '-provider',
      type:      'polling',
      url:       image,
      listeners: {
        scope: obj,
        data: function(provider, e)
        {
          if(e.xhr.status == 200) {
            var element_id = Ext.id();
            (function(provider)
            {
              this.update('
' +
                          '' +
                          '
');
              this.doLayout();
            }).defer(50,this,[provider]);
            (function(provider)
            {
              this.update('
' +
                          '' +
                          '
');
              this.doLayout();
            }).defer(1000,this,[provider]);
            provider.disconnect();
            return true;
          } else {
            return false;
          }
        }
      }
    });
    this.providers.push(provider);
    Ext.Direct.addProvider(provider);
  },
  buildParams: function(form_values)
  {
    var params = new Object;
    params['authenticity_token'] = FORM_AUTH_TOKEN;
    for (key in form_values)
      if (Ext.getCmp('advanced_query_select').isVisible()){
        if(key.indexOf('_adv') != -1)
          params[key.replace(/_adv/,'')] = form_values[key];
      }else{
        if(key.indexOf('_simple') != -1)
          params[key.replace(/_simple/,'')] = form_values[key];
      }
    return params;
  },
  saveResultSet: function(buttonEl, eventObj)
  {
    this.getResultPanel().showAlarmQueryConsole(null);
    return true;
  },
  mapResultSet: function(buttonEl, eventObj)
  {
    var form_values = buttonEl.findParentByType('form').getForm().getValues();
    var params      = this.buildParams(form_values);
    params["limit"] = this.getResultPanel().getResultStore().getTotalCount();
    Ext.Ajax.request({
      url:      '/rollcall/schools',
      method:   'GET',
      params:   params,
      scope:    this,
      callback: function(options, success, response){
        var gmapPanel = new Ext.ux.GMapPanel({zoomLevel: 9});
        var win       = new Ext.Window({
          title:      "Google Map of Schools",
          layout:     'fit',
          labelAlign: 'top',
          padding:    '5',
          width:      510,
          height:     450,
          items:      [gmapPanel]
        });
        win.schools = Ext.decode(response.responseText).results;
        win.addButton({xtype: 'button', text: 'Dismiss', handler: function(){ win.close(); }, scope: this, width:'auto'});
        gmapPanel.addListener("mapready", function(obj){
          min_lat = Ext.min(win.schools, function(a,b){ return (a.gmap_latb.gmap_lat) ? 1 : 0; });
          max_lat = Ext.max(win.schools, function(a,b){ return (a.gmap_latb.gmap_lat) ? 1 : 0; });
          min_lng = Ext.min(win.schools, function(a,b){ return (a.gmap_lngb.gmap_lng) ? 1 : 0; });
          max_lng = Ext.max(win.schools, function(a,b){ return (a.gmap_lngb.gmap_lng) ? 1 : 0; });
          var center = new google.maps.LatLng((max_lat.gmap_lat+min_lat.gmap_lat)/2, (max_lng.gmap_lng+min_lng.gmap_lng)/2);
          gmapPanel.gmap.setCenter(center);
          for(var i = 0; i < win.schools.length; i++) {
            var loc           = new google.maps.LatLng(win.schools[i].gmap_lat, win.schools[i].gmap_lng);
            var marker        = gmapPanel.addMarker(loc, win.schools[i].display_name, {});
            var addr_elems    = win.schools[i].gmap_addr.split(",");
            marker.info       = "" + win.schools[i].display_name + "
";
            marker.info      += addr_elems[0] + "
" + addr_elems[1] + "
" + addr_elems.slice(2).join(",");
            marker.info_popup = null;
            google.maps.event.addListener(marker, 'click', function(){
              if (this.info_popup) {
                this.info_popup.close(gmapPanel.gmap, this);
                this.info_popup = null;
              } else {
                this.info_popup = new google.maps.InfoWindow({content: this.info});
                this.info_popup.open(gmapPanel.gmap, this);
              }
            });
          }
        });
        win.show();
      },
      failure: function(){}
    });
  },
  exportResultSet: function(buttonEl, eventObj)
  {
    Ext.Ajax.request({
      url:    '/rollcall/export',
      method: 'GET',
      params: this.buildParams(buttonEl.findParentByType("form").getForm().getValues()),
      scope:  this,
      callback: function(options, success, response){
        Ext.MessageBox.show({
          title: 'Creating CSV Export File',
          msg: 'Your CSV file will be placed in your documents folders when the system '+
          'is done generating it. Please check your documents folder in a few minutes.',
          buttons: Ext.MessageBox.OK,
          icon: Ext.MessageBox.INFO
        });
      },
      failure: function(){
      }
    });
  },
  resetForm: function(buttonEl, eventObj)
  {
    buttonEl.findParentByType("form").getForm().reset();
  },
  submitQuery: function(buttonEl, eventObj)
  {
    this.getResultPanel().clearProviders();
    var form_panel   = this.find('id', 'ADSTFormPanel')[0];
    var form_values  = form_panel.getForm().getValues();
    var result_store = this.getResultPanel().getResultStore();
    form_panel.findParentByType('panel').getBottomToolbar().bindStore(result_store);
    result_store.baseParams = {}; // clear previous search values
    var params              = this.buildParams(form_values);
    for(key in params)
      result_store.setBaseParam(key, params[key]);
    form_panel.buttons[2].show();
    form_panel.buttons[3].show();
    form_panel.buttons[4].show();
    var panel_mask = new Ext.LoadMask(this.getComponent('adst_container').getComponent('ADST_panel').getEl(), {msg:"Please wait..."});
    panel_mask.show();
    result_store.on('load', function(){ panel_mask.hide(); });
    result_store.load({params: this.buildParams(form_values)});
    return true;
  },
  setNextPage: function(this_toolbar, params)
  {
    var result_store   = this_toolbar.ownerCt.ownerCt.ownerCt.getResultPanel().getResultStore();
    var container_mask = new Ext.LoadMask(this_toolbar.ownerCt.ownerCt.ownerCt.getResultPanel().getEl(), {msg:"Please wait..."});
    params['page']     = Math.floor(params.start /  params.limit) + 1;
    container_mask.show();
    result_store.on('load', function(){ container_mask.hide(); });
    return true;
  },
  loadInitMask: function()
  {
    new Ext.LoadMask(this.getComponent('adst_container').getComponent('ADST_panel').getEl(),    {msg:"Please wait...", store: this.init_store});
  },
  initFormComponent: function(form_panel)
  {
    this.init_store = new Ext.data.JsonStore({
      root:     'options',
      fields:   ['absenteeism', 'age', 'data_functions', 'data_functions_adv', 'gender', 'grade', 'school_type', 'schools', 'symptoms', 'zipcode'],
      url:      '/rollcall/query_options',
      autoLoad: false,
      listeners:{
        scope: form_panel,
        load:  function(this_store, records){
          this.ownerCt.show();
          this.add(new Talho.Rollcall.SimpleADSTContainer({options: records[0].data}));
          this.add(new Talho.Rollcall.AdvancedADSTContainer({options: records[0].data}));
          this.buttons[0].show();
          this.buttons[1].show();
          //this.ownerCt.ownerCt.ownerCt.getComponent('reports_panel').getBottomToolbar().findById('create_report_button').enable();
          this.doLayout();
        }
      }
    });
    this.loadInitMask();
    this.init_store.load();
  },
  init_store: null
});

Talho.Rollcall.ADST.initialize = function(config)
{
  return new Talho.Rollcall.ADST(config);
}

Talho.ScriptManager.reg('Talho.Rollcall.ADST', Talho.Rollcall.ADST, Talho.Rollcall.ADST.initialize);
<|endoftext|>


<commit_before>(function () {
  'use strict';

  // --------------------------------------------------- variable initialisation
  /*
   * HACK: we are passing a parameter to this scripts through a script tag in
   *       test.pug. pageId is a global variable.
   */
  var isExam = 'exam' == pageId;

  var questionId,
      score    = 0,
      counter  = 0,
      answered = true; // used in changeQuestion, to see if used has answered

  // JQuery quick access to important nodes
  var $domain       = $('#domain'),
      $question     = $('#question'),
      $answers      = $('#answers'),
      $nextQuestion = $('#next-question'),
      $dashboard    = $('#dashboard'),
      $score        = $('#score'),
      $droptarget   = $('#droptarget');

  // Session storage use
  if (isExam && getSession('preferences') !== null) {
    var numberOfQuestions = getSession('preferences').numberOfQuestions || 10,
        domains           = getSession('preferences').domains || "";
  } else {
    var numberOfQuestions = 10, domains = "";
  }

  // ---------------------------------------------------- main logic (functions)
  /**
   * Change DOM elements relative to a question :
   *  - question
   *  - domain
   *  - answers
   *  - score count (through dragndrop function)
   *
   * The question is randomly retrieved from the database. If the global
   * parameter isExam is set, then the question can be only in domains
   * contained in sessionStorage.domains; and it also increment the counter.
   * If the counter is greater than sessionStorage.numberOfQuestions, then exam
   * is over and window is redirected to /result.
   * @return undefined
   */
  function changeQuestion() {
    if (!answered) {
      $droptarget.addClass('blink');
      return;
    }
    answered = false;
    ++counter;
    var url;
    if (isExam) {
      if (counter == numberOfQuestions)
        $nextQuestion.find('span').html('Fin de l’examen');
      else if (counter > numberOfQuestions) {
        setLocal(
          "result",
          (getLocal("result") || []).concat({
            timestamp: Date.now(),
            goodAnswers: score,
            totalAnswers: counter,
            surrender: false
          })
        );
        go('result');
        return;
      }
      url = "/api/ask/rand/" + domains;
    } else {
      url = "/api/ask/rand/";
    }
    $.get(url)
      .done(function(data) {
        questionId = data.id;
        $domain.html(data.domain);
        $question.html(data.question);
        // clean everything except first answer (bones)
        $answers.find('.answer:not(:first)').remove()
        for (var answer of data.answers) {
          $answers
            // clone body of an answer
            .find('.answer:first')
            .clone()
            // append current answer elements to the clone
            .find('label')
              .html(answer)
            .end()
            // append the clone to DOM (#answer)
            .appendTo($answers)
            // show the clone
            .show();
        }

        dragndrop();
      })
      .fail(function (data) {
        console.log(data);
      });

  }

  function dragndrop(){
    var draggable = document.querySelectorAll(".answer");
    var droptarget = document.getElementById("droptarget");
    //draggable[0].classList.remove("right");

    droptarget.innerHTML = "Glisser la réponse !";
    droptarget.classList.remove("false");
    droptarget.classList.remove("right");
    droptarget.classList.add("free");

    for(var i = 1; i < draggable.length; i++){
      (function(i){
        draggable[i].classList.add("draggable");
        draggable[i].setAttribute("draggable", "true");
        draggable[i].addEventListener('dragstart', dragStart, false);  //the user starts dragging the element
        draggable[i].addEventListener('dragend'  , dragEnd  , false);
      })(i)
    }

    // Fired when the user drags the draggable onto the drop target (only fires
    // when the draggable element changes from being outside to being over)
    droptarget.addEventListener('dragenter', dragEnter, false);
    // Fired once the draggable element is over the drop target and keeps
    // firing for as long as the draggable element is being dragged over the
    // drop target.
    droptarget.addEventListener('dragover' , dragOver , false);
    // If the user drags the draggable object out of the drop target again,
    // the dragleave event is fired.
    droptarget.addEventListener('dragleave', dragLeave, false);
    // If the user drops the draggable object on the drop target, the drop
    // event is fired.
    droptarget.addEventListener('drop'     , drop     , false);

    /* Draggable event handlers */
    function dragStart(event) {
        var dataToSet = event.target.getElementsByTagName('label')[0].innerHTML;
        event.dataTransfer.setData("text", dataToSet); //data that is transfered to the drop target when the element is dropped. (MIME, data)
        event.dataTransfer.effectsAllowed = "copy";

        for(var i = 1; i < draggable.length; i++){
          (function(i){
            if(document.getElementsByTagName('label')[i].innerHTML == event.target.getElementsByTagName('label')[0].innerHTML){
              draggable[i].classList.add("dragged");
            }
          })(i)
        }
    }

    function dragEnd(event) {
      for(var i = 1; i < draggable.length; i++){
        (function(i){
          if(document.getElementsByTagName('label')[i].innerHTML == event.target.getElementsByTagName('label')[0].innerHTML){
            draggable[i].classList.remove("dragged");
          }
        })(i)
      }
    }

    /* Drop target event handlers */
    function dragEnter(event) {
      droptarget.classList.remove("free");
      droptarget.classList.add("enter");
    }

    function dragOver(event) {

        event.preventDefault();
        return false; //Necessary to avoid default browsers behaviours
    }

    function dragLeave(event) {
      droptarget.classList.remove("enter");
      droptarget.classList.add("free");
    }

    function drop(event) {
        var data = event.dataTransfer.getData('text'); //reads the data set in dragStart()
        var url = "/api/ans/" + questionId + "/";
        var isGoodAnswer = 0;
        var indexAnswer = 0;
        var choice = 0;

        droptarget.classList.remove("enter");

        for(var i = 1; i < draggable.length; i++){
          (function(i){
            if(document.getElementsByTagName('label')[i].innerHTML == data){
              url += i-1;
              choice = draggable[i];
              choice.classList.add("hidden");
              event.target.innerHTML = data;
            }
          })(i)
        }

        $.get(url)
          .done(function(data) {
            isGoodAnswer = data.isGoodAnswer;
            indexAnswer = data.goodAnswerIndex;
            if(isGoodAnswer){
              ++score;
              droptarget.classList.add("right");
              //We indicate that the choosen answer is the good one
            }else{
              droptarget.classList.add("false");
              draggable[indexAnswer+1].classList.add("right");
              //We indicate that the the choosen answer is not the good one and we show the good one
            }
            answered = true;
            // update stats in localstorage
            updateQuestionStats($domain.html(), isGoodAnswer, isExam);
            // update score in DOM
            $score.html(score + " / " + counter);

            //When an element is dropped, we need to remove draggable class and attribute on other items in order to avoid multiple d&d
            for(var j = 1; j < draggable.length; j++ ){
              if(draggable[j] != undefined){
                (function(j){
                  draggable[j].removeEventListener("dragstart", dragStart);
                  draggable[j].removeEventListener("dragend", dragEnd);
                  draggable[j].setAttribute("draggable", "false");
                  draggable[j].classList.remove("draggable");
                })(j)
              }
            }

            droptarget.removeEventListener("dragenter", dragEnter);
            droptarget.removeEventListener("dragover", dragOver);
            droptarget.removeEventListener("dragleave", dragLeave);
            droptarget.removeEventListener("drop", drop);

          });

          event.preventDefault();
          event.stopPropagation();
    }
  }

  /**
   * Update statistics for a question only.
   *
   * @return undefined
   */
  function updateQuestionStats(domain, isGood, isExam) {
    var stats = getLocal("questionStatistics");
    stats = stats || {
      "answers"         : 0,
      "examAnswers"     : 0,
      "goodAnswers"     : 0,
      "goodExamAnswers" : 0,
      "domains"         : {}
    };
    stats.domains[domain] = stats.domains[domain] || {
      "answers"         : 0,
      "examAnswers"     : 0,
      "goodAnswers"     : 0,
      "goodExamAnswers" : 0
    };
    stats.domains[domain].answers++;
    stats.answers++;
    if (isExam) {
      stats.domains[domain].examAnswers++;
      stats.examAnswers++;
      if (isGood) {
        stats.domains[domain].goodExamAnswers++;
        stats.goodExamAnswers++;
      }
    }
    if (isGood) {
      stats.domains[domain].goodAnswers++;
      stats.goodAnswers++;
    }
    setLocal("questionStatistics",stats);
  }

  // ------------------------------------------------------------- DOM binding
  $nextQuestion.click(changeQuestion);
  $droptarget.on('animationend', function(event) {
    $(this).removeClass('blink');
  });

  if (isExam) {
    $('#dashboard').click(function (event) {
      event.preventDefault();
      setLocal(
        "result",
        (getLocal("result") || []).concat({
          timestamp: Date.now(),
          goodAnswers: 0,
          totalAnswers: counter,
          surrender: true
        })
      );
      go('result');
    })
  }

  // ---------------------------------------------------------- Initialisation
  changeQuestion();
})();
<commit_msg>change result for results, and counter for number of questions<commit_after>(function () {
  'use strict';

  // --------------------------------------------------- variable initialisation
  /*
   * HACK: we are passing a parameter to this scripts through a script tag in
   *       test.pug. pageId is a global variable.
   */
  var isExam = 'exam' == pageId;

  var questionId,
      score    = 0,
      counter  = 0,
      answered = true; // used in changeQuestion, to see if used has answered

  // JQuery quick access to important nodes
  var $domain       = $('#domain'),
      $question     = $('#question'),
      $answers      = $('#answers'),
      $nextQuestion = $('#next-question'),
      $dashboard    = $('#dashboard'),
      $score        = $('#score'),
      $droptarget   = $('#droptarget');

  // Session storage use
  if (isExam && getSession('preferences') !== null) {
    var numberOfQuestions = getSession('preferences').numberOfQuestions || 10,
        domains           = getSession('preferences').domains || "";
  } else {
    var numberOfQuestions = 10, domains = "";
  }

  // ---------------------------------------------------- main logic (functions)
  /**
   * Change DOM elements relative to a question :
   *  - question
   *  - domain
   *  - answers
   *  - score count (through dragndrop function)
   *
   * The question is randomly retrieved from the database. If the global
   * parameter isExam is set, then the question can be only in domains
   * contained in sessionStorage.domains; and it also increment the counter.
   * If the counter is greater than sessionStorage.numberOfQuestions, then exam
   * is over and window is redirected to /result.
   * @return undefined
   */
  function changeQuestion() {
    if (!answered) {
      $droptarget.addClass('blink');
      return;
    }
    answered = false;
    ++counter;
    var url;
    if (isExam) {
      if (counter == numberOfQuestions)
        $nextQuestion.find('span').html('Fin de l’examen');
      else if (counter > numberOfQuestions) {
        setLocal(
          "results",
          (getLocal("results") || []).concat({
            timestamp: Date.now(),
            goodAnswers: score,
            totalAnswers: numberOfQuestions,
            surrender: false
          })
        );
        go('result');
        return;
      }
      url = "/api/ask/rand/" + domains;
    } else {
      url = "/api/ask/rand/";
    }
    $.get(url)
      .done(function(data) {
        questionId = data.id;
        $domain.html(data.domain);
        $question.html(data.question);
        // clean everything except first answer (bones)
        $answers.find('.answer:not(:first)').remove()
        for (var answer of data.answers) {
          $answers
            // clone body of an answer
            .find('.answer:first')
            .clone()
            // append current answer elements to the clone
            .find('label')
              .html(answer)
            .end()
            // append the clone to DOM (#answer)
            .appendTo($answers)
            // show the clone
            .show();
        }

        dragndrop();
      })
      .fail(function (data) {
        console.log(data);
      });

  }

  function dragndrop(){
    var draggable = document.querySelectorAll(".answer");
    var droptarget = document.getElementById("droptarget");
    //draggable[0].classList.remove("right");

    droptarget.innerHTML = "Glisser la réponse !";
    droptarget.classList.remove("false");
    droptarget.classList.remove("right");
    droptarget.classList.add("free");

    for(var i = 1; i < draggable.length; i++){
      (function(i){
        draggable[i].classList.add("draggable");
        draggable[i].setAttribute("draggable", "true");
        draggable[i].addEventListener('dragstart', dragStart, false);  //the user starts dragging the element
        draggable[i].addEventListener('dragend'  , dragEnd  , false);
      })(i)
    }

    // Fired when the user drags the draggable onto the drop target (only fires
    // when the draggable element changes from being outside to being over)
    droptarget.addEventListener('dragenter', dragEnter, false);
    // Fired once the draggable element is over the drop target and keeps
    // firing for as long as the draggable element is being dragged over the
    // drop target.
    droptarget.addEventListener('dragover' , dragOver , false);
    // If the user drags the draggable object out of the drop target again,
    // the dragleave event is fired.
    droptarget.addEventListener('dragleave', dragLeave, false);
    // If the user drops the draggable object on the drop target, the drop
    // event is fired.
    droptarget.addEventListener('drop'     , drop     , false);

    /* Draggable event handlers */
    function dragStart(event) {
        var dataToSet = event.target.getElementsByTagName('label')[0].innerHTML;
        event.dataTransfer.setData("text", dataToSet); //data that is transfered to the drop target when the element is dropped. (MIME, data)
        event.dataTransfer.effectsAllowed = "copy";

        for(var i = 1; i < draggable.length; i++){
          (function(i){
            if(document.getElementsByTagName('label')[i].innerHTML == event.target.getElementsByTagName('label')[0].innerHTML){
              draggable[i].classList.add("dragged");
            }
          })(i)
        }
    }

    function dragEnd(event) {
      for(var i = 1; i < draggable.length; i++){
        (function(i){
          if(document.getElementsByTagName('label')[i].innerHTML == event.target.getElementsByTagName('label')[0].innerHTML){
            draggable[i].classList.remove("dragged");
          }
        })(i)
      }
    }

    /* Drop target event handlers */
    function dragEnter(event) {
      droptarget.classList.remove("free");
      droptarget.classList.add("enter");
    }

    function dragOver(event) {

        event.preventDefault();
        return false; //Necessary to avoid default browsers behaviours
    }

    function dragLeave(event) {
      droptarget.classList.remove("enter");
      droptarget.classList.add("free");
    }

    function drop(event) {
        var data = event.dataTransfer.getData('text'); //reads the data set in dragStart()
        var url = "/api/ans/" + questionId + "/";
        var isGoodAnswer = 0;
        var indexAnswer = 0;
        var choice = 0;

        droptarget.classList.remove("enter");

        for(var i = 1; i < draggable.length; i++){
          (function(i){
            if(document.getElementsByTagName('label')[i].innerHTML == data){
              url += i-1;
              choice = draggable[i];
              choice.classList.add("hidden");
              event.target.innerHTML = data;
            }
          })(i)
        }

        $.get(url)
          .done(function(data) {
            isGoodAnswer = data.isGoodAnswer;
            indexAnswer = data.goodAnswerIndex;
            if(isGoodAnswer){
              ++score;
              droptarget.classList.add("right");
              //We indicate that the choosen answer is the good one
            }else{
              droptarget.classList.add("false");
              draggable[indexAnswer+1].classList.add("right");
              //We indicate that the the choosen answer is not the good one and we show the good one
            }
            answered = true;
            // update stats in localstorage
            updateQuestionStats($domain.html(), isGoodAnswer, isExam);
            // update score in DOM
            $score.html(score + " / " + counter);

            //When an element is dropped, we need to remove draggable class and attribute on other items in order to avoid multiple d&d
            for(var j = 1; j < draggable.length; j++ ){
              if(draggable[j] != undefined){
                (function(j){
                  draggable[j].removeEventListener("dragstart", dragStart);
                  draggable[j].removeEventListener("dragend", dragEnd);
                  draggable[j].setAttribute("draggable", "false");
                  draggable[j].classList.remove("draggable");
                })(j)
              }
            }

            droptarget.removeEventListener("dragenter", dragEnter);
            droptarget.removeEventListener("dragover", dragOver);
            droptarget.removeEventListener("dragleave", dragLeave);
            droptarget.removeEventListener("drop", drop);

          });

          event.preventDefault();
          event.stopPropagation();
    }
  }

  /**
   * Update statistics for a question only.
   *
   * @return undefined
   */
  function updateQuestionStats(domain, isGood, isExam) {
    var stats = getLocal("questionStatistics");
    stats = stats || {
      "answers"         : 0,
      "examAnswers"     : 0,
      "goodAnswers"     : 0,
      "goodExamAnswers" : 0,
      "domains"         : {}
    };
    stats.domains[domain] = stats.domains[domain] || {
      "answers"         : 0,
      "examAnswers"     : 0,
      "goodAnswers"     : 0,
      "goodExamAnswers" : 0
    };
    stats.domains[domain].answers++;
    stats.answers++;
    if (isExam) {
      stats.domains[domain].examAnswers++;
      stats.examAnswers++;
      if (isGood) {
        stats.domains[domain].goodExamAnswers++;
        stats.goodExamAnswers++;
      }
    }
    if (isGood) {
      stats.domains[domain].goodAnswers++;
      stats.goodAnswers++;
    }
    setLocal("questionStatistics",stats);
  }

  // ------------------------------------------------------------- DOM binding
  $nextQuestion.click(changeQuestion);
  $droptarget.on('animationend', function(event) {
    $(this).removeClass('blink');
  });

  if (isExam) {
    $('#dashboard').click(function (event) {
      event.preventDefault();
      setLocal(
        "results",
        (getLocal("results") || []).concat({
          timestamp: Date.now(),
          goodAnswers: 0,
          totalAnswers: numberOfQuestions,
          surrender: true
        })
      );
      go('result');
    })
  }

  // ---------------------------------------------------------- Initialisation
  changeQuestion();
})();
<|endoftext|>


<commit_before>var w;
(function( $ ){

  var buttons = {
    'bb-b': {
      name: 'bb-b',
      title: 'Bold',
      icon: 'fa fa-bold',
      callback: function(e) {
        var tag = 'b';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-i': {
      name: 'bb-i',
      title: 'Italic',
      icon: 'fa fa-italic',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[i][/i]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[i]' + selected.text + '[/i]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-u': {
      name: 'bb-u',
      title: 'Underline',
      icon: 'fa fa-underline',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[u][/u]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[u]' + selected.text + '[/u]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-s': {
      name: 'bb-s',
      title: 'Strike-through',
      icon: 'fa fa-strikethrough',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[s][/s]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[s]' + selected.text + '[/s]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-url': {
      name: 'bb-url',
      title: 'URL',
      icon: 'fa fa-chain',
      callback: function(e) {
        var tag = 'url';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-img': {
      name: 'bb-img',
      title: 'Image',
      icon: 'fa fa-image',
      callback: function(e) {
        var tag = 'img';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-quote': {
      name: 'bb-quote',
      title: 'Quote',
      icon: 'fa fa-quote-left',
      callback: function(e) {
        var tag = 'quote';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-hider': {
      name: 'bb-hider',
      title: 'Hider',
      icon: 'fa fa-eye-slash',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('\n[hider=My Hider]\n\n[/hider]\n');
          var newPos = selected.end + 18;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '\n[hider=My Hider]\n' + selected.text + '\n[/hider]\n';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          // cursor+1 so that the initial \n is not selected
          e.setSelection(cursor+1, cursor+chunk.length);
        }
      }
    },
    'bb-tabs': {
      name: 'bb-tabs',
      title: 'Tabs',
      icon: 'fa fa-folder',
      callback: function(e) {
        var selected = e.getSelection();
        var cursor = selected.start;
        e.setSelection(cursor, cursor);
        var markup = '\n[tabs]\n[tab=Hello]\n:)\n[/tab]\n[tab=Goodbye]\n:(\n[/tab]\n[/tabs]\n';
        e.replaceSelection(markup);
        e.setSelection(cursor+1, cursor+markup.length);
      }
    },
    'bb-color': {
      name: 'bb-color',
      title: 'Font Color',
      icon: 'fa fa-eyedropper',
      toggle: true,
      callback: function(e) {
        console.log('Clicked');
      }
    },
    'bb-preview': {
      name: 'bb-preview',
      toggle: true,
      title: 'Preview2',
      icon: 'fa fa-search',
      btnClass: 'btn btn-primary btn-sm',
      btnText: 'Preview',
      callback: function(e) {
        console.log('cb');
        if (e.$isPreview === false) {
          e.showPreview();
          e.enableButtons('bb-preview');
        } else {
          e.hidePreview();
          e.$editor.find('.bbcode-errors ul').html('');
          e.$editor.find('.bbcode-errors p').html('Click "Preview" to check for errors');
        }
      }
    }
  };

  $.fn.bbcode = function(opts) {
    var $this = $(this);

    // The Markdown editor instance will be stored in $M so I can access
    // its state easily from anywhere in this module.
    // I assign it in the editor's "show" event when it loads which seems to
    // always happen before everything else. Probably not seeing a simpler
    // more obvious strategy to fetch the edit instance.
    // Note: $M is the same object that markdown-bootstrap exposes
    // with the arg it passes to its callbacks like onPreview and onSave.
    // console.dir($M) it for more info. For example, $M.$editor gets
    // the entire editor container. $M.$element gets the textarea.
    // And there's all sorts of props/fns available on this object.
    // More info: http://www.codingdrama.com/bootstrap-markdown/
    var $M;

    // `opts` arg will be merged into this
    var defaults = {
      resize: 'vertical',
      height: 350,
      iconlibrary: 'fa',
      onShow: function(e) {
        console.log('show');
        $M = e;
      },
      onPreview: function(e) {
        // if (!e.isDirty())
        //   return e.getContent();

        var result = XBBCODE.process({
          text: e.getContent(),
          addInLineBreaks: true
        });

        // Display errs in editor footer if there are any
        e.$editor.find('.bbcode-errors p').html('Errors: ');

        if (result.error) {
          var html = '';
          html = html + result.errorQueue.map(function(msg) {
            return '
' + msg + '
';
          }).join('');
          e.$editor.find('.bbcode-errors ul').html(html);
        } else {
          e.$editor.find('.bbcode-errors ul').html('');
          e.$editor.find('.bbcode-errors p').append(' None');
        }

        return result.html;
      },
      hiddenButtons: ['cmdBold', 'cmdItalic', 'cmdHeading',
                      'cmdUrl', 'cmdImage', 'cmdPreview',
                      'cmdList', 'cmdList0', 'cmdCode', 'cmdQuote'],
      additionalButtons: [
        [
          {name: 'bbcode1',
           data: [buttons['bb-b'], buttons['bb-i'], buttons['bb-u'],
                  buttons['bb-s'], buttons['bb-color']]},
          {name: 'bbcode2',
           data: [buttons['bb-url'], buttons['bb-img']]},
          {name: 'bbcode3',
           data: [buttons['bb-quote'], buttons['bb-hider'], buttons['bb-tabs']]},
          {name: 'bbcode4',
           data: [buttons['bb-preview']]}
        ]
      ],
      footer: '
'+
              '
Click the "Preview" button to check for errors
'+
              '

'+
              '
'
    };

    opts = $.extend(defaults, opts);

    $this.markdown(opts);

    // Hook up color button
    var colors = [
      // Pastel
      ['f7976a', 'f9ad81', 'fdc68a', 'fff79a',
       'c4df9b', 'a2d39c', '82ca9d', '7bcdc8',
       '6ecff6', '7ea7d8', '8493ca', '8882be',
       'a187be', 'bc8dbf', 'f49ac2', 'f6989d'],
      // Full
      ['ed1c24', 'f26522', 'f7941d', 'fff200',
       '8dc73f', '39b54a', '00a651', '00a99d',
       '00aeef', '0072bc', '0054a6', '2e3192',
       '662d91', '92278f', 'ec008c', 'ed145b'],
      // Dark
      ['9e0b0f', 'a0410d', 'a36209', 'aba000',
       '598527', '1a7b30', '007236', '00746b',
       '0076a3', '004b80', '003471', '1b1464',
       '440e62', '630460', '9e005d', '9e0039']
    ];
    var content = '
';
    content = content + colors.map(function(row) {
      var html = '
';
      html = html + row.map(function(hex) {
        return ''
      }).join('');
      return html + '
';
    }).join('');
    content = content + '
';

    $M.$editor.find('button[title="Font Color"]').popover({
      placement: 'auto bottom',
      content: content,
      html: true
    }).on('shown.bs.popover', function() {
      var self = this;
      var id = $(this).attr('aria-describedby');
      var $popover = $('#' + id);
      $popover.find('.bb-color-swatch').on('click', function(e) {
        e.preventDefault();
        var hex = $(this).attr('data-hex');

        var selected = $M.getSelection();
        if (selected.length === 0) {
          $M.replaceSelection('[color='+hex+'][/color]');
          var newPos = selected.start + 14;
          $M.setSelection(newPos, newPos);
        } else {
          var chunk = '[color='+hex+']' + selected.text + '[/color]';
          var cursor;
          $M.replaceSelection(chunk);
          cursor = selected.start;
          $M.setSelection(cursor, cursor+chunk.length);
        }
        // Get rid of popover once color is selected
        // $(self).popover('hide');
      });
    });

    // Expose $M for debugging
    window.$M = $M;

    return this;
  };
})( jQuery );
<commit_msg>Add indication when user is in preview mode<commit_after>var w;
(function( $ ){

  var buttons = {
    'bb-b': {
      name: 'bb-b',
      title: 'Bold',
      icon: 'fa fa-bold',
      callback: function(e) {
        var tag = 'b';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-i': {
      name: 'bb-i',
      title: 'Italic',
      icon: 'fa fa-italic',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[i][/i]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[i]' + selected.text + '[/i]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-u': {
      name: 'bb-u',
      title: 'Underline',
      icon: 'fa fa-underline',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[u][/u]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[u]' + selected.text + '[/u]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-s': {
      name: 'bb-s',
      title: 'Strike-through',
      icon: 'fa fa-strikethrough',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('[s][/s]');
          e.setSelection(selected.end + 3, selected.end + 3);
        } else {
          var chunk = '[s]' + selected.text + '[/s]';
          var cursor;
          e.replaceSelection(chunk);
          cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-url': {
      name: 'bb-url',
      title: 'URL',
      icon: 'fa fa-chain',
      callback: function(e) {
        var tag = 'url';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-img': {
      name: 'bb-img',
      title: 'Image',
      icon: 'fa fa-image',
      callback: function(e) {
        var tag = 'img';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-quote': {
      name: 'bb-quote',
      title: 'Quote',
      icon: 'fa fa-quote-left',
      callback: function(e) {
        var tag = 'quote';
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('['+tag+'][/'+tag+']');
          var newPos = selected.end + tag.length + 2;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '['+tag+']' + selected.text + '[/'+tag+']';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          e.setSelection(cursor, cursor+chunk.length);
        }
      }
    },
    'bb-hider': {
      name: 'bb-hider',
      title: 'Hider',
      icon: 'fa fa-eye-slash',
      callback: function(e) {
        var selected = e.getSelection();
        if (selected.length === 0) {
          e.replaceSelection('\n[hider=My Hider]\n\n[/hider]\n');
          var newPos = selected.end + 18;
          e.setSelection(newPos, newPos);
        } else {
          var chunk = '\n[hider=My Hider]\n' + selected.text + '\n[/hider]\n';
          e.replaceSelection(chunk);
          var cursor = selected.start;
          // cursor+1 so that the initial \n is not selected
          e.setSelection(cursor+1, cursor+chunk.length);
        }
      }
    },
    'bb-tabs': {
      name: 'bb-tabs',
      title: 'Tabs',
      icon: 'fa fa-folder',
      callback: function(e) {
        var selected = e.getSelection();
        var cursor = selected.start;
        e.setSelection(cursor, cursor);
        var markup = '\n[tabs]\n[tab=Hello]\n:)\n[/tab]\n[tab=Goodbye]\n:(\n[/tab]\n[/tabs]\n';
        e.replaceSelection(markup);
        e.setSelection(cursor+1, cursor+markup.length);
      }
    },
    'bb-color': {
      name: 'bb-color',
      title: 'Font Color',
      icon: 'fa fa-eyedropper',
      toggle: true,
      callback: function(e) {
        console.log('Clicked');
      }
    },
    'bb-preview': {
      name: 'bb-preview',
      toggle: true,
      title: 'Preview2',
      icon: 'fa fa-search',
      btnClass: 'btn btn-primary btn-sm',
      btnText: 'Preview',
      callback: function(e) {
        if (e.$isPreview === false) {
          e.showPreview();
          e.enableButtons('bb-preview');
          e.$editor.find('.bbcode-editor-mode').css('display', 'inline-block');
        } else {
          e.hidePreview();
          e.$editor.find('.bbcode-errors ul').html('');
          e.$editor.find('.bbcode-errors p').html('Click "Preview" to check for errors');
          e.$editor.find('.bbcode-editor-mode').hide();
        }
      }
    }
  };

  $.fn.bbcode = function(opts) {
    var $this = $(this);

    // The Markdown editor instance will be stored in $M so I can access
    // its state easily from anywhere in this module.
    // I assign it in the editor's "show" event when it loads which seems to
    // always happen before everything else. Probably not seeing a simpler
    // more obvious strategy to fetch the edit instance.
    // Note: $M is the same object that markdown-bootstrap exposes
    // with the arg it passes to its callbacks like onPreview and onSave.
    // console.dir($M) it for more info. For example, $M.$editor gets
    // the entire editor container. $M.$element gets the textarea.
    // And there's all sorts of props/fns available on this object.
    // More info: http://www.codingdrama.com/bootstrap-markdown/
    var $M;

    // `opts` arg will be merged into this
    var defaults = {
      resize: 'vertical',
      height: 350,
      iconlibrary: 'fa',
      onShow: function(e) {
        console.log('show');
        $M = e;
      },
      onPreview: function(e) {
        // if (!e.isDirty())
        //   return e.getContent();

        var result = XBBCODE.process({
          text: e.getContent(),
          addInLineBreaks: true
        });

        // Display errs in editor footer if there are any
        e.$editor.find('.bbcode-errors p').html('Errors: ');

        if (result.error) {
          var html = '';
          html = html + result.errorQueue.map(function(msg) {
            return '
' + msg + '
';
          }).join('');
          e.$editor.find('.bbcode-errors ul').html(html);
        } else {
          e.$editor.find('.bbcode-errors ul').html('');
          e.$editor.find('.bbcode-errors p').append(' None');
        }

        return result.html;
      },
      hiddenButtons: ['cmdBold', 'cmdItalic', 'cmdHeading',
                      'cmdUrl', 'cmdImage', 'cmdPreview',
                      'cmdList', 'cmdList0', 'cmdCode', 'cmdQuote'],
      additionalButtons: [
        [
          {name: 'bbcode1',
           data: [buttons['bb-b'], buttons['bb-i'], buttons['bb-u'],
                  buttons['bb-s'], buttons['bb-color']]},
          {name: 'bbcode2',
           data: [buttons['bb-url'], buttons['bb-img']]},
          {name: 'bbcode3',
           data: [buttons['bb-quote'], buttons['bb-hider'], buttons['bb-tabs']]},
          {name: 'bbcode4',
           data: [buttons['bb-preview']]}
        ]
      ],
      footer: '
You are in Preview Mode
'+
              '
'+
              '
Click the "Preview" button to check for errors
'+
              '

'+
              '
'
    };

    opts = $.extend(defaults, opts);

    // Activate the editor
    $this.markdown(opts);

    // Hook up color button
    var colors = [
      // Pastel
      ['f7976a', 'f9ad81', 'fdc68a', 'fff79a',
       'c4df9b', 'a2d39c', '82ca9d', '7bcdc8',
       '6ecff6', '7ea7d8', '8493ca', '8882be',
       'a187be', 'bc8dbf', 'f49ac2', 'f6989d'],
      // Full
      ['ed1c24', 'f26522', 'f7941d', 'fff200',
       '8dc73f', '39b54a', '00a651', '00a99d',
       '00aeef', '0072bc', '0054a6', '2e3192',
       '662d91', '92278f', 'ec008c', 'ed145b'],
      // Dark
      ['9e0b0f', 'a0410d', 'a36209', 'aba000',
       '598527', '1a7b30', '007236', '00746b',
       '0076a3', '004b80', '003471', '1b1464',
       '440e62', '630460', '9e005d', '9e0039']
    ];
    var content = '
';
    content = content + colors.map(function(row) {
      var html = '
';
      html = html + row.map(function(hex) {
        return ''
      }).join('');
      return html + '
';
    }).join('');
    content = content + '
';

    $M.$editor.find('button[title="Font Color"]').popover({
      placement: 'auto bottom',
      content: content,
      html: true
    }).on('shown.bs.popover', function() {
      var self = this;
      var id = $(this).attr('aria-describedby');
      var $popover = $('#' + id);
      $popover.find('.bb-color-swatch').on('click', function(e) {
        e.preventDefault();
        var hex = $(this).attr('data-hex');

        var selected = $M.getSelection();
        if (selected.length === 0) {
          $M.replaceSelection('[color='+hex+'][/color]');
          var newPos = selected.start + 14;
          $M.setSelection(newPos, newPos);
        } else {
          var chunk = '[color='+hex+']' + selected.text + '[/color]';
          var cursor;
          $M.replaceSelection(chunk);
          cursor = selected.start;
          $M.setSelection(cursor, cursor+chunk.length);
        }
        // Get rid of popover once color is selected
        // $(self).popover('hide');
      });
    });

    // Expose $M for debugging
    window.$M = $M;

    return this;
  };
})( jQuery );
<|endoftext|>


<commit_before>/* global cdnDomain, devDomain */
(function (doc) {

"use strict";

var REGEX_GIST_URL = /^(https?):\/\/gist\.github\.com\/(.+?)\/([^\/]+)/i;
var REGEX_RAW_URL  = /^(https?):\/\/(?:gist|raw)\.github(?:usercontent)?\.com\/([^\/]+\/[^\/]+\/[^\/]+|[0-9A-Za-z-]+\/[0-9a-f]+\/raw)\/(.+)/i;
var REGEX_REPO_URL = /^(https?):\/\/github\.com\/(.+?)\/(.+?)\/(?:(?:blob|raw)\/)?(.+?\/.+)/i;

var devEl  = doc.getElementById('url-dev');
var prodEl = doc.getElementById('url-prod');
var urlEl  = doc.getElementById('url');

urlEl.addEventListener('input', function () {
    var url = decodeURIComponent(urlEl.value.trim());

    if (REGEX_RAW_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = encodeURI(url.replace(REGEX_RAW_URL, '$1://' + devDomain + '/$2/$3'));
        prodEl.value = encodeURI(url.replace(REGEX_RAW_URL, '$1://' + cdnDomain + '/$2/$3'));

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else if (REGEX_REPO_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = encodeURI(url.replace(REGEX_REPO_URL, '$1://' + devDomain + '/$2/$3/$4'));
        prodEl.value = encodeURI(url.replace(REGEX_REPO_URL, '$1://' + cdnDomain + '/$2/$3/$4'));

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else if (REGEX_GIST_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = encodeURI(url.replace(REGEX_GIST_URL, '$1://' + devDomain + '/$2/$3/raw/'));
        prodEl.value = encodeURI(url.replace(REGEX_GIST_URL, '$1://' + cdnDomain + '/$2/$3/raw/'));

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else {
        urlEl.classList.remove('valid');

        if (url.length) {
            urlEl.classList.add('invalid');
        } else {
            urlEl.classList.remove('invalid');
        }

        devEl.value  = '';
        prodEl.value = '';

        devEl.classList.remove('valid');
        prodEl.classList.remove('valid');
    }
}, false);

devEl.addEventListener('focus', onFocus);
prodEl.addEventListener('focus', onFocus);

function onFocus(e) {
    setTimeout(function () {
        e.target.select();
    }, 1);
}

}(document));
<commit_msg>Just don’t bother decoding or encoding URLs.<commit_after>/* global cdnDomain, devDomain */
(function (doc) {

"use strict";

var REGEX_GIST_URL = /^(https?):\/\/gist\.github\.com\/(.+?)\/([^\/]+)/i;
var REGEX_RAW_URL  = /^(https?):\/\/(?:gist|raw)\.github(?:usercontent)?\.com\/([^\/]+\/[^\/]+\/[^\/]+|[0-9A-Za-z-]+\/[0-9a-f]+\/raw)\/(.+)/i;
var REGEX_REPO_URL = /^(https?):\/\/github\.com\/(.+?)\/(.+?)\/(?:(?:blob|raw)\/)?(.+?\/.+)/i;

var devEl  = doc.getElementById('url-dev');
var prodEl = doc.getElementById('url-prod');
var urlEl  = doc.getElementById('url');

urlEl.addEventListener('input', function () {
    var url = urlEl.value.trim();

    if (REGEX_RAW_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = url.replace(REGEX_RAW_URL, '$1://' + devDomain + '/$2/$3');
        prodEl.value = url.replace(REGEX_RAW_URL, '$1://' + cdnDomain + '/$2/$3');

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else if (REGEX_REPO_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = url.replace(REGEX_REPO_URL, '$1://' + devDomain + '/$2/$3/$4');
        prodEl.value = url.replace(REGEX_REPO_URL, '$1://' + cdnDomain + '/$2/$3/$4');

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else if (REGEX_GIST_URL.test(url)) {
        urlEl.classList.remove('invalid');
        urlEl.classList.add('valid');

        devEl.value  = url.replace(REGEX_GIST_URL, '$1://' + devDomain + '/$2/$3/raw/');
        prodEl.value = url.replace(REGEX_GIST_URL, '$1://' + cdnDomain + '/$2/$3/raw/');

        devEl.classList.add('valid');
        prodEl.classList.add('valid');
    } else {
        urlEl.classList.remove('valid');

        if (url.length) {
            urlEl.classList.add('invalid');
        } else {
            urlEl.classList.remove('invalid');
        }

        devEl.value  = '';
        prodEl.value = '';

        devEl.classList.remove('valid');
        prodEl.classList.remove('valid');
    }
}, false);

devEl.addEventListener('focus', onFocus);
prodEl.addEventListener('focus', onFocus);

function onFocus(e) {
    setTimeout(function () {
        e.target.select();
    }, 1);
}

}(document));
<|endoftext|>


<commit_before>(()=>{"use strict";// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
	const newGameUrl = document.currentScript.dataset.newgame;
	const $main = document.querySelector('main');
	loginPromise.then(login => {
		$main.appendChild(buildDom({'':'section#status', c:[
			{'':'h1', c:login.user},
			{c:{'':'ul.stat', c:[
				{'':'li', c:["Ranking: ", {'':'span.figure', c: '1234'}]},
				{'':'li', c:["Punkte: ", {'':'span.figure', c: '123'}]}
			]}},
			{'':'a.start-game', href: newGameUrl, c: "Neues Spiel"}
		]}));
		makeXHR('GET', login.player_||login.player[''], {Accept: 'application/json', Authorization: login.token}, xhr => xhr.status >= 200 && xhr.status < 300 && xhr.getResponseHeader('Content-Type') === 'application/json' ? buildDom([
			{'':'section#open-games', c:[{'':'h1', c:"Spiele gegen …"}, {'':'ul', c:JSON.parse(xhr.responseText).activegames_.map(showGame(login))}]},
			{'':'section#waiting-games', c:[{'':'h1', c:"Warten auf …"}]},
		]).forEach(x => $main.appendChild(x)) : console.error(xhr)).send();
	});
})();
<commit_msg>/: show correct score<commit_after>(()=>{"use strict";// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
	const newGameUrl = document.currentScript.dataset.newgame;
	const $main = document.querySelector('main');
	loginPromise.then(login => makeXHR('GET', login.player_||login.player[''], {Accept: 'application/json', Authorization: login.token}, xhr => {
		if (xhr.status < 200 || xhr.status >= 300 || xhr.getResponseHeader('Content-Type') !== 'application/json') {return}
		const json = JSON.parse(xhr.responseText);
		$main.appendChild(buildDom({'':'section#status', c:[
			{'':'h1', c:login.user},
			{c:{'':'ul.stat', c:[
				{'':'li', c:["Ranking: ", {'':'span.figure', c: '1234'}]},
				{'':'li', c:["Punkte: ", {'':'span.figure', c: ''+json.score}]}
			]}},
			{'':'a.start-game', href: newGameUrl, c: "Neues Spiel"}
		]}));
		buildDom([
			{'':'section#open-games', c:[{'':'h1', c:"Spiele gegen …"}, {'':'ul', c:json.activegames_.map(showGame(login))}]},
			{'':'section#waiting-games', c:[{'':'h1', c:"Warten auf …"}]},
		]).forEach(x => $main.appendChild(x));
	}).send());
})();
<|endoftext|>