<commit_before>'use strict';

// ノードが読み込まれたときに処理を実行する
document.addEventListener('DOMContentLoaded', function (e) {

  const btn = document.getElementById('send_message_btn');
  btn.addEventListener('click', function (e) {

    // 1. eventを止める
    e.preventDefault();

    // 2. formを取得
    const form = document.getElementsByTagName('form').form;

    // 3. メッセージを取得
    const message = form.getElementsByTagName('textarea').input_message.value;

    // 4. ajax通信
        const data = {
          message: message,
          date: new Date()
        };

    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {

      if (xhr.readyState == 4) {
        if (xhr.status == 200 || xhr.status == 304) {
          const data = xhr.responseText;
          console.log('成功！！：' + data);
          // success();
        } else {
          console.log('m9(^Д^)ﾌﾟｷﾞｬｰ：' + xhr.statusText);
          success();
        }
      }
    };

    xhr.open('POST', 'http://localhost:3000/comment', true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify(data));
    xhr.abort();

  });

  // textareaにフォーカスインする
  document.getElementById('input_message').focus();

});

// 通信成功時のコールバック
function success() {
  // 1. contentが下に動く
  const contents = document.getElementById('contents');
  contents.classList.add('contents_animation');

  // 2. textareaが上に動いて、メールの中へ入る
  const textarea = document.getElementById('textarea_wrap');
  textarea.classList.add('textarea_animation');

  // 3. mail_topが閉じるアニメーション
  const mail_top = document.getElementById('mail_top');
  mail_top.classList.add('mail_top_animation');

  // 4. 投稿ボタンを消す
  const send_btn = document.getElementById('send_message_btn');
  send_btn.style.visibility = 'hidden';

  // 5. おキャット様アイコンで手紙に封をする
  const cat_icon = document.getElementById('cat_icon');
  cat_icon.classList.add('cat_icon_animation');

  // 6. 手紙を送る
  const mail_form = document.getElementById('form');
  mail_form.classList.add('send_mail_animation');

  // 7. 送信結果表示
  const result = document.getElementById('result');
  result.classList.add('show_result_animation');

  // 8. アニメーションのコールバックを登録
  result.addEventListener('animationend', resultCallback);

  // 関数
  function resultCallback(e){
    console.log(`アニメーションの初期化`);
    // formを隠す
    mail_form.style.visibility = 'hidden';
    // アニメーションで使用したクラスを初期化
    contents.classList.remove('contents_animation');
    textarea.classList.remove('textarea_animation');
    mail_top.classList.remove('mail_top_animation');
    send_btn.style.visibility = '';
    cat_icon.classList.remove('cat_icon_animation');
    mail_form.classList.remove('send_mail_animation');
    result.classList.remove('show_result_animation');
    // formを出す
    const mail_back = document.getElementById('mail_back');
    mail_back.style.visibility = 'hidden';
    const mail_front = document.getElementById('mail_front');
    mail_front.style.visibility = 'hidden';
    mail_top.style.visibility = 'hidden';
    mail_form.style.visibility = '';

    // callbackを登録
    textarea.addEventListener('animationend',textareaCallback);
    // textarea出現アニメーション開始
    textarea.classList.add('show_textarea_animation');

    // イベントを解除
    result.removeEventListener('animationend', resultCallback);
  }

  function textareaCallback(e){
          //初期化
      textarea.classList.remove('show_textarea_animation');
      mail_back.style.visibility = '';
      mail_front.style.visibility = '';
      mail_top.style.visibility = '';
      // focusイン
      textarea.focus();

      // イベントを解除
      textarea.removeEventListener('animationend', textareaCallback);

  }

}
<commit_msg>テキストエリア送信後、入力内容を初期化<commit_after>'use strict';

// ノードが読み込まれたときに処理を実行する
document.addEventListener('DOMContentLoaded', function (e) {

  const btn = document.getElementById('send_message_btn');
  btn.addEventListener('click', function (e) {

    // 1. eventを止める
    e.preventDefault();

    // 2. formを取得
    const form = document.getElementsByTagName('form').form;

    // 3. メッセージを取得
    const message = form.getElementsByTagName('textarea').input_message.value;

    // 4. ajax通信
        const data = {
          message: message,
          date: new Date()
        };

    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function () {

      if (xhr.readyState == 4) {
        if (xhr.status == 200 || xhr.status == 304) {
          const data = xhr.responseText;
          console.log('成功！！：' + data);
          success();
          xhr.abort();
        } else {
          console.log('m9(^Д^)ﾌﾟｷﾞｬｰ：' + xhr.statusText);
        }
      }
    };

    xhr.open('POST', 'http://localhost:3000/comment', true);
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify(data));

  });

  // textareaにフォーカスインする
  document.getElementById('input_message').focus();

});

// 通信成功時のコールバック
function success() {
  // 1. contentが下に動く
  const contents = document.getElementById('contents');
  contents.classList.add('contents_animation');

  // 2. textareaが上に動いて、メールの中へ入る
  const textarea = document.getElementById('textarea_wrap');
  textarea.classList.add('textarea_animation');

  // 3. mail_topが閉じるアニメーション
  const mail_top = document.getElementById('mail_top');
  mail_top.classList.add('mail_top_animation');

  // 4. 投稿ボタンを消す
  const send_btn = document.getElementById('send_message_btn');
  send_btn.style.visibility = 'hidden';

  // 5. おキャット様アイコンで手紙に封をする
  const cat_icon = document.getElementById('cat_icon');
  cat_icon.classList.add('cat_icon_animation');

  // 6. 手紙を送る
  const mail_form = document.getElementById('form');
  mail_form.classList.add('send_mail_animation');

  // 7. 送信結果表示
  const result = document.getElementById('result');
  result.classList.add('show_result_animation');

  // 8. アニメーションのコールバックを登録
  result.addEventListener('animationend', resultCallback);

  // 関数
  function resultCallback(e){
    console.log(`アニメーションの初期化`);
    // formを隠す
    mail_form.style.visibility = 'hidden';
    // アニメーションで使用したクラスを初期化
    contents.classList.remove('contents_animation');
    textarea.classList.remove('textarea_animation');
    textarea.value = '';
    mail_top.classList.remove('mail_top_animation');
    send_btn.style.visibility = '';
    cat_icon.classList.remove('cat_icon_animation');
    mail_form.classList.remove('send_mail_animation');
    result.classList.remove('show_result_animation');

    // formを出す
    const mail_back = document.getElementById('mail_back');
    mail_back.style.visibility = 'hidden';
    const mail_front = document.getElementById('mail_front');
    mail_front.style.visibility = 'hidden';
    mail_top.style.visibility = 'hidden';
    mail_form.style.visibility = '';

    // callbackを登録
    textarea.addEventListener('animationend',textareaCallback);
    // textarea出現アニメーション開始
    textarea.classList.add('show_textarea_animation');

    // イベントを解除
    result.removeEventListener('animationend', resultCallback);
  }

  function textareaCallback(e){
          //初期化
      textarea.classList.remove('show_textarea_animation');
      mail_back.style.visibility = '';
      mail_front.style.visibility = '';
      mail_top.style.visibility = '';
      // focusイン
      textarea.focus();

      // イベントを解除
      textarea.removeEventListener('animationend', textareaCallback);

  }

}
<|endoftext|>


<commit_before>$(function(){

  var $todaysLunches = $("#todaysLunches");

  var todaysLunchesShown = false;
  function showTodaysLunches() {
    if (!todaysLunchesShown) {
      $todaysLunches.show().transition({ opacity: 1 }, "slow");
      todaysLunchesShown = true;
    }
  }

  jsRoutes.controllers.LunchInfo.todaysLunches().ajax({
    success: function(response, status, xhr) {
      $todaysLunches.html(response);
      showTodaysLunches();
    },
    error: function (xhr, status, errorThrown) {
      var msg = "Tyvärr uppstod ett fel: ";
      $todaysLunches.html("
Fel! " + msg + xhr.status + " " + xhr.statusText + "
");
    }
  });

  setTimeout(function() {
    showTodaysLunches();
  }, 250);
});
<commit_msg>Rename LunchInfo -> LunchInfoController<commit_after>$(function(){

  var $todaysLunches = $("#todaysLunches");

  var todaysLunchesShown = false;
  function showTodaysLunches() {
    if (!todaysLunchesShown) {
      $todaysLunches.show().transition({ opacity: 1 }, "slow");
      todaysLunchesShown = true;
    }
  }

  jsRoutes.controllers.LunchInfoController.todaysLunches().ajax({
    success: function(response, status, xhr) {
      $todaysLunches.html(response);
      showTodaysLunches();
    },
    error: function (xhr, status, errorThrown) {
      var msg = "Tyvärr uppstod ett fel: ";
      $todaysLunches.html("
Fel! " + msg + xhr.status + " " + xhr.statusText + "
");
    }
  });

  setTimeout(function() {
    showTodaysLunches();
  }, 250);
});
<|endoftext|>


<commit_before>$(function() {
  var formAoColumns = [selectColumn, formLinkColumn, titleColumn, createdOnColumn, updatedOnColumn, updatedByColumn, sharedWithColumn];
  fnAddFilterFoot('#form-table', formAoColumns);
  var formTable = $('#form-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: formAoColumns,
    aaSorting: [
      [3, 'desc'],
      [4, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(formTable, '/forms/json');

  $('#form-select-all').click(function(e) {
    fnSelectAll(formTable, 'row-selected', 'select-row', true);
  });

  $('#form-select-none').click(function(e) {
    fnDeselect(formTable, 'row-selected', 'select-row');
  });

  var sharedFormAoColumns = [formLinkColumn, titleColumn, createdByColumn, createdOnColumn, updatedOnColumn, updatedByColumn, sharedWithColumn];
  fnAddFilterFoot('#shared-form-table', sharedFormAoColumns);
  var sharedFormTable = $('#shared-form-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: sharedFormAoColumns,
    aaSorting: [
      [3, 'desc'],
      [5, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(sharedFormTable, '/sharedforms/json');

  var travelerAoColumns = [travelerConfigLinkColumn, travelerShareLinkColumn, travelerLinkColumn, titleColumn, statusColumn, deviceColumn, sharedWithColumn, createdOnColumn, updatedByColumn, updatedOnColumn];
  fnAddFilterFoot('#traveler-table', travelerAoColumns);
  var travelerTable = $('#traveler-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: travelerAoColumns,
    aaSorting: [
      [9, 'desc'],
      [7, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(travelerTable, '/travelers/json');

  var sharedTravelerAoColumns = [travelerLinkColumn, titleColumn, statusColumn, deviceColumn, sharedWithColumn, createdByColumn, createdOnColumn, updatedByColumn, updatedOnColumn];
  fnAddFilterFoot('#shared-traveler-table', sharedTravelerAoColumns);
  var sharedTravelerTable = $('#shared-traveler-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: sharedTravelerAoColumns,
    aaSorting: [
      [8, 'desc'],
      [6, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(sharedTravelerTable, '/sharedtravelers/json');

  $('#form-travel').click(function(e) {
    var selected = fnGetSelected(formTable, 'row-selected');
    if (selected.length == 0) {
      $('#modalLabel').html('Alert');
      $('#modal .modal-body').html('No form has been selected!');
      $('#modal .modal-footer').html('<button data-dismiss="modal" aria-hidden="true" class="btn">Return</button>');
      $('#modal').modal('show');
    } else if (selected.length > 1) {
      $('#modalLabel').html('Alert');
      $('#modal .modal-body').html('Only one selected form is allowed for this action!');
      $('#modal .modal-footer').html('<button data-dismiss="modal" aria-hidden="true" class="btn">Return</button>');
      $('#modal').modal('show');
    } else {
      $.ajax({
        url: '/travelers/',
        method: 'POST',
        contentType: 'application/json',
        dataType: 'json',
        data: JSON.stringify({
          form: formTable.fnGetData(selected[0])._id
        })
      }).done(function(json) {
        $('#message').append('
<button class="close" data-dismiss="alert">x</button>A new traveler is created at ' + json.location + '
');
        $(window).scrollTop($('#message div:last-child').offset().top - 40);
        // initTable();
      }).fail(function(jqXHR, status, error) {
        $('#message').append('
<button class="close" data-dismiss="alert">x</button>Cannot create new traveler
');
        $(window).scrollTop($('#message div:last-child').offset().top - 40);
      }).always();
    }
  });

  $('#reload').click(function(e) {
    initTable(formTable, '/forms/json');
    initTable(sharedFormTable, '/sharedforms/json');
    initTable(travelerTable, '/travelers/json');
    initTable(sharedTravelerTable, '/sharedtravelers/json');
  });

  // binding events
  selectEvent();
  filterEvent();
});

function initTable(oTable, url) {
  $.ajax({
    url: url,
    type: 'GET',
    dataType: 'json'
  }).done(function(json) {
    oTable.fnClearTable();
    oTable.fnAddData(json);
    oTable.fnDraw();
  }).fail(function(jqXHR, status, error) {
    $('#message').append('
<button class="close" data-dismiss="alert">x</button>Cannot reach the server for forms.
');
    $(window).scrollTop($('#message div:last-child').offset().top - 40);
  }).always();
}

// function travel<commit_msg>format and add global for jslint<commit_after>/*global clearInterval: false, clearTimeout: false, document: false, event: false, frames: false, history: false, Image: false, location: false, name: false, navigator: false, Option: false, parent: false, screen: false, setInterval: false, setTimeout: false, window: false, XMLHttpRequest: false, FormData: false */
/*global moment: false, Binder: false*/
/*global selectColumn: false, formLinkColumn: false, titleColumn: false, createdOnColumn: false, updatedOnColumn: false, updatedByColumn: false, sharedWithColumn: false, fnAddFilterFoot: false, sDom: false, oTableTools: false, fnSelectAll: false, fnDeselect: false, createdByColumn: false, createdOnColumn: false, travelerConfigLinkColumn: false, travelerShareLinkColumn: false, travelerLinkColumn: false, statusColumn: false, deviceColumn: false, fnGetSelected: false, selectEvent: false, filterEvent: false*/

function initTable(oTable, url) {
  $.ajax({
    url: url,
    type: 'GET',
    dataType: 'json'
  }).done(function (json) {
    oTable.fnClearTable();
    oTable.fnAddData(json);
    oTable.fnDraw();
  }).fail(function (jqXHR, status, error) {
    $('#message').append('
<button class="close" data-dismiss="alert">x</button>Cannot reach the server for forms.
');
    $(window).scrollTop($('#message div:last-child').offset().top - 40);
  }).always();
}

$(function () {
  var formAoColumns = [selectColumn, formLinkColumn, titleColumn, createdOnColumn, updatedOnColumn, updatedByColumn, sharedWithColumn];
  fnAddFilterFoot('#form-table', formAoColumns);
  var formTable = $('#form-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: formAoColumns,
    aaSorting: [
      [3, 'desc'],
      [4, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(formTable, '/forms/json');

  $('#form-select-all').click(function (e) {
    fnSelectAll(formTable, 'row-selected', 'select-row', true);
  });

  $('#form-select-none').click(function (e) {
    fnDeselect(formTable, 'row-selected', 'select-row');
  });

  var sharedFormAoColumns = [formLinkColumn, titleColumn, createdByColumn, createdOnColumn, updatedOnColumn, updatedByColumn, sharedWithColumn];
  fnAddFilterFoot('#shared-form-table', sharedFormAoColumns);
  var sharedFormTable = $('#shared-form-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: sharedFormAoColumns,
    aaSorting: [
      [3, 'desc'],
      [5, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(sharedFormTable, '/sharedforms/json');

  var travelerAoColumns = [travelerConfigLinkColumn, travelerShareLinkColumn, travelerLinkColumn, titleColumn, statusColumn, deviceColumn, sharedWithColumn, createdOnColumn, updatedByColumn, updatedOnColumn];
  fnAddFilterFoot('#traveler-table', travelerAoColumns);
  var travelerTable = $('#traveler-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: travelerAoColumns,
    aaSorting: [
      [9, 'desc'],
      [7, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(travelerTable, '/travelers/json');

  var sharedTravelerAoColumns = [travelerLinkColumn, titleColumn, statusColumn, deviceColumn, sharedWithColumn, createdByColumn, createdOnColumn, updatedByColumn, updatedOnColumn];
  fnAddFilterFoot('#shared-traveler-table', sharedTravelerAoColumns);
  var sharedTravelerTable = $('#shared-traveler-table').dataTable({
    aaData: [],
    // bAutoWidth: false,
    aoColumns: sharedTravelerAoColumns,
    aaSorting: [
      [8, 'desc'],
      [6, 'desc']
    ],
    sDom: sDom,
    oTableTools: oTableTools
  });
  initTable(sharedTravelerTable, '/sharedtravelers/json');

  if ($('#all-traveler-table').length) {
    var allTravelerAoColumns = [travelerLinkColumn, titleColumn, statusColumn, deviceColumn, sharedWithColumn, createdByColumn, createdOnColumn, updatedByColumn, updatedOnColumn];
    fnAddFilterFoot('#all-traveler-table', allTravelerAoColumns);
    var allTravelerTable = $('#all-traveler-table').dataTable({
      aaData: [],
      // bAutoWidth: false,
      aoColumns: allTravelerAoColumns,
      aaSorting: [
        [8, 'desc'],
        [6, 'desc']
      ],
      sDom: sDom,
      oTableTools: oTableTools
    });
    initTable(allTravelerTable, '/alltravelers/json');
  }

  $('#form-travel').click(function (e) {
    var selected = fnGetSelected(formTable, 'row-selected');
    if (selected.length === 0) {
      $('#modalLabel').html('Alert');
      $('#modal .modal-body').html('No form has been selected!');
      $('#modal .modal-footer').html('<button data-dismiss="modal" aria-hidden="true" class="btn">Return</button>');
      $('#modal').modal('show');
    } else if (selected.length > 1) {
      $('#modalLabel').html('Alert');
      $('#modal .modal-body').html('Only one selected form is allowed for this action!');
      $('#modal .modal-footer').html('<button data-dismiss="modal" aria-hidden="true" class="btn">Return</button>');
      $('#modal').modal('show');
    } else {
      $.ajax({
        url: '/travelers/',
        method: 'POST',
        contentType: 'application/json',
        dataType: 'json',
        data: JSON.stringify({
          form: formTable.fnGetData(selected[0])._id
        })
      }).done(function (json) {
        $('#message').append('
<button class="close" data-dismiss="alert">x</button>A new traveler is created at ' + json.location + '
');
        $(window).scrollTop($('#message div:last-child').offset().top - 40);
        // initTable();
      }).fail(function (jqXHR, status, error) {
        $('#message').append('
<button class="close" data-dismiss="alert">x</button>Cannot create new traveler
');
        $(window).scrollTop($('#message div:last-child').offset().top - 40);
      }).always();
    }
  });

  $('#reload').click(function (e) {
    initTable(formTable, '/forms/json');
    initTable(sharedFormTable, '/sharedforms/json');
    initTable(travelerTable, '/travelers/json');
    initTable(sharedTravelerTable, '/sharedtravelers/json');
  });

  // binding events
  selectEvent();
  filterEvent();
});

<|endoftext|>


<commit_before>angular.module('FortuitApp', [])
  .controller('MainCtrl', ['$scope', '$http', function($scope, $http) {
    $scope.probabilities = [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99];
    $scope.confidences = [50, 60, 70, 80, 90, 99];
    $scope.predictions = [];
    $scope.page = 0;

    $scope.setView = function(view) {
      // Do onload stuff
      if(view === 'home') {
        $http.get('/api/users/me/predictions?resolved=false')
          .success(function(data) {
            if(data.error) {
              $scope.predictions = [];
            } else {
              $scope.predictions = data;
              $scope.predictions.forEach(function(prediction) {
                prediction.percent = Math.round(prediction.confidence * 100);
              });
            }

            $scope.view = 'home';
          })
          .error(function(data) {
            console.log('Failed at getting data');
            $scope.view = 'home';
          });
      } else if(view === 'archive') {
        $scope.page = 0;
        $http.get('/api/users/me/predictions?resolved=true')
          .success(function(data) {
            if(data.error) {
              $scope.predictions = [];
            } else {
              $scope.predictions = data;
              $scope.predictions.forEach(function(prediction) {
                prediction.percent = Math.round(prediction.confidence * 100);
              });
            }
            $scope.view = 'archive';
          })
          .error(function(data) {
            console.log('Failed at getting data');
            $scope.view = 'archive';
          });
      } else {
        $scope.view = view;
      }
    };

    $scope.logout = function() {
      window.location = '/logout';
    }

    $scope.submit = function(confidence) {
      $http.post('/api/predictions/', {desc: $scope.new_prediction_desc, confidence: confidence/100}).
        success(function(prediction) {
          prediction.percent = Math.round(prediction.confidence * 100);
          $scope.predictions.unshift(prediction);
        });
    };

    $scope.setView('home');
  }]);
<commit_msg>Refactored a bit, added potential for pagination to archive.<commit_after>angular.module('FortuitApp', [])
  .controller('MainCtrl', ['$scope', '$http', function($scope, $http) {
    $scope.probabilities = [1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 99];
    $scope.confidences = [50, 60, 70, 80, 90, 99];
    $scope.predictions = [];
    $scope.page = 0;
    $scope.pageCount = 1;

    function getPredictions(options, cb) {
      var queryString = "/api/users/me/predictions";
      if(options.count)
        queryString += "/pages";
      if(options.resolved !== undefined)
        queryString += "?resolved=" + options.resolved;
      if(options.page !== undefined)
        queryString += "&page=" + options.page;
      $http.get(queryString)
        .success(function(data) {
          if(!data.error) {
            cb(data);
          }
        })
        .error(function(data) {
          console.log('Failed at getting data');

          cb(null);
        });
    }

    $scope.setView = function(view) {
      // Do onload stuff
      if(view === 'home') {
        $scope.predictions = [];
        getPredictions({resolved: false}, function(data) {
          if(data !== null) {
            $scope.predictions = data;
            $scope.predictions.forEach(function(prediction) {
              prediction.percent = Math.round(prediction.confidence * 100);
            });
          }
          $scope.view = 'home';
        });
      } else if(view === 'archive') {
        $scope.page = 0;
        $scope.predictions = [];

        getPredictions({count: true, resolved: true}, function(pageCount) {
          if(pageCount !== null) {
            $scope.pageCount = pageCount;
            getPredictions({resolved: true, page: 0}, function(data) {
              if(data !== null) {
                $scope.predictions = data;
                $scope.predictions.forEach(function(prediction) {
                  prediction.percent = Math.round(prediction.confidence * 100);
                });
              }
              $scope.view = 'archive';
            });
          } else {
            $scope.view = 'archive';
          }
        });
      } else {
        $scope.view = view;
      }
    };

    $scope.changePage = function(delta) {
      if($scope.view === 'archive') {
        if($scope.page + delta >= 0 && $scope.page + delta < $scope.pageCount) {
          $scope.page = delta;
          getPredictions({resolved: true, page: $scope.page}, function(data) {
            if(data !== null) {
              $scope.predictions = data;
              $scope.predictions.forEach(function(prediction) {
                prediction.percent = Math.round(prediction.confidence * 100);
              });
            }
          });
        }
      }
    };

    $scope.logout = function() {
      window.location = '/logout';
    };

    $scope.submit = function(confidence) {
      $http.post('/api/predictions/', {desc: $scope.new_prediction_desc, confidence: confidence/100}).
        success(function(prediction) {
          prediction.percent = Math.round(prediction.confidence * 100);
          $scope.predictions.unshift(prediction);
        });
    };

    $scope.setView('home');
  }]);
<|endoftext|>


<commit_before>$(function() {

  var setupAutocomplete = function() {
    var go = function(name) {
      location.href = '/@/' + name;
    }
    var $input = $(this);
    lichess.loadCss('/assets/stylesheets/autocomplete.css');
    lichess.loadScript('/assets/javascripts/vendor/typeahead.jquery.min.js').done(function() {
      $input.typeahead(null, {
        minLength: 2,
        hint: true,
        highlight: true,
        source: function(query, sync, async) {
          $.ajax({
            url: '/player/autocomplete?term=' + query,
            success: function(res) {
              // hack to fix typeahead limit bug
              if (res.length === 10) res.push(null);
              async(res);
            }
          });
        },
        limit: 10,
        templates: {
          empty: '
No player found
',
          pending: lichess.spinnerHtml,
          suggestion: function(a) {
            return '' + a + '';
          }
        }
      }).bind('typeahead:render', function() {
        $('body').trigger('lichess.content_loaded');
      }).bind('typeahead:select', function(ev, sel) {
        go(sel);
      }).keypress(function(e) {
        if (e.which == 10 || e.which == 13) go($(this).val());
      }).focus();
    });
  };

  $('input.user-autocomplete-jump').each(setupAutocomplete);

  $("div.user_show .mod_zone_toggle").each(function() {
    $(this).click(function() {
      var $zone = $("div.user_show .mod_zone");
      if ($zone.is(':visible')) $zone.hide();
      else $zone.html(lichess.spinnerHtml).show();
      $zone.load($(this).attr("href"), function() {
        $zone.find('form.fide_title select').on('change', function() {
          $(this).parent('form').submit();
        });
        $('body').trigger('lichess.content_loaded');
        var relatedUsers = +$('.reportCard thead th:last').text();
        if (relatedUsers > 100) {
          $zone.find('.others').css('display', 'none').before('Show ' + relatedUsers + ' related users');
          $zone.find('.others-show').click(function() {
            $(this).next().css('display', '');
            $(this).remove();
          });
        }
        $zone.find('li.ip').slice(0, 3).each(function() {
          var $li = $(this);
          $.ajax({
            url: '/mod/ip-intel?ip=' + $(this).find('.address').text(),
            success: function(res) {
              $li.append($('' + res + '% proxy'));
            }
          });
        });
      });
      return false;
    });
    if (location.search.indexOf('mod') === 1) $(this).click();
  });

  $("div.user_show .note_zone_toggle").each(function() {
    $(this).click(function() {
      $("div.user_show .note_zone").toggle();
    });
    if (location.search.indexOf('note') != -1) $(this).click();
  });

  $('form.autosubmit').each(function() {
    var $form = $(this);
    $form.find('input').change(function() {
      $.ajax({
        url: $form.attr('action'),
        method: $form.attr('method'),
        data: $form.serialize(),
        success: function() {
          $form.find('.saved').fadeIn();
        }
      });
    });
  });

  $("div.user_show .claim_title_zone").each(function() {
    var $zone = $(this);
    $zone.find('.actions a').click(function() {
      $.post($(this).attr('href'));
      $zone.remove();
      return false;
    });
  });

  if ($('#perfStat.correspondence .view_games').length &&
    lichess.once('user-correspondence-view-games')) lichess.hopscotch(function() {
    hopscotch.configure({
      i18n: {
        nextBtn: 'OK, got it'
      }
    }).startTour({
      id: 'correspondence-games',
      showPrevButton: true,
      isTourBubble: false,
      steps: [{
        title: "Recently finished games",
        content: "Would you like to display the list of your correspondence games, sorted by completion date?",
        target: $('#perfStat.correspondence .view_games')[0],
        placement: "bottom"
      }]
    });
  });
});
<commit_msg>hide parts of excess modlog<commit_after>$(function() {

  var setupAutocomplete = function() {
    var go = function(name) {
      location.href = '/@/' + name;
    }
    var $input = $(this);
    lichess.loadCss('/assets/stylesheets/autocomplete.css');
    lichess.loadScript('/assets/javascripts/vendor/typeahead.jquery.min.js').done(function() {
      $input.typeahead(null, {
        minLength: 2,
        hint: true,
        highlight: true,
        source: function(query, sync, async) {
          $.ajax({
            url: '/player/autocomplete?term=' + query,
            success: function(res) {
              // hack to fix typeahead limit bug
              if (res.length === 10) res.push(null);
              async(res);
            }
          });
        },
        limit: 10,
        templates: {
          empty: '
No player found
',
          pending: lichess.spinnerHtml,
          suggestion: function(a) {
            return '' + a + '';
          }
        }
      }).bind('typeahead:render', function() {
        $('body').trigger('lichess.content_loaded');
      }).bind('typeahead:select', function(ev, sel) {
        go(sel);
      }).keypress(function(e) {
        if (e.which == 10 || e.which == 13) go($(this).val());
      }).focus();
    });
  };

  $('input.user-autocomplete-jump').each(setupAutocomplete);

  $("div.user_show .mod_zone_toggle").each(function() {
    $(this).click(function() {
      var $zone = $("div.user_show .mod_zone");
      if ($zone.is(':visible')) $zone.hide();
      else $zone.html(lichess.spinnerHtml).show();
      $zone.load($(this).attr("href"), function() {
        $zone.find('form.fide_title select').on('change', function() {
          $(this).parent('form').submit();
        });
        $('body').trigger('lichess.content_loaded');
        var relatedUsers = +$zone.find('.reportCard thead th:last').text();
        if (relatedUsers > 100) {
          var others = $zone.find('.others').hide()
            .before('Show ' + relatedUsers + ' related users... (very large!)');
          $zone.find('#others-show').click(function() {
            others.show();
            $(this).remove();
          });
        }
        var $modLog = $zone.find('.mod_log ul').children();
        if ($modLog.length > 20) {
          var list = $modLog.slice(20);
          list.first().before('Show all ' + $modLog.length + ' mod log entries...');
          list.wrap('');
          $zone.find('#modlog-show').click(function() {
            $zone.find('.modlog-hidden').show();
            $(this).remove();
          });
        }
        $zone.find('li.ip').slice(0, 3).each(function() {
          var $li = $(this);
          $.ajax({
            url: '/mod/ip-intel?ip=' + $(this).find('.address').text(),
            success: function(res) {
              $li.append($('' + res + '% proxy'));
            }
          });
        });
      });
      return false;
    });
    if (location.search.indexOf('mod') === 1) $(this).click();
  });

  $("div.user_show .note_zone_toggle").each(function() {
    $(this).click(function() {
      $("div.user_show .note_zone").toggle();
    });
    if (location.search.indexOf('note') != -1) $(this).click();
  });

  $('form.autosubmit').each(function() {
    var $form = $(this);
    $form.find('input').change(function() {
      $.ajax({
        url: $form.attr('action'),
        method: $form.attr('method'),
        data: $form.serialize(),
        success: function() {
          $form.find('.saved').fadeIn();
        }
      });
    });
  });

  $("div.user_show .claim_title_zone").each(function() {
    var $zone = $(this);
    $zone.find('.actions a').click(function() {
      $.post($(this).attr('href'));
      $zone.remove();
      return false;
    });
  });

  if ($('#perfStat.correspondence .view_games').length &&
    lichess.once('user-correspondence-view-games')) lichess.hopscotch(function() {
    hopscotch.configure({
      i18n: {
        nextBtn: 'OK, got it'
      }
    }).startTour({
      id: 'correspondence-games',
      showPrevButton: true,
      isTourBubble: false,
      steps: [{
        title: "Recently finished games",
        content: "Would you like to display the list of your correspondence games, sorted by completion date?",
        target: $('#perfStat.correspondence .view_games')[0],
        placement: "bottom"
      }]
    });
  });
});
<|endoftext|>


<commit_before>/*   Copyright (c) 2010, Diaspora Inc.  This file is
*   licensed under the Affero General Public License version 3.  See
*   the COPYRIGHT file.
*/

$(document).ready(function(){

	$('#debug_info').click(function() {
		$('#debug_more').toggle('fast');
	});

  $("label").inFieldLabels();

  $('#flash_notice, #flash_error, #flash_alert').delay(2500).slideUp(130);

  $("div.image_cycle").cycle({
    fx: 'fade',
    random: 1,
    timeout: 2000,
    speed: 3000
  });

  //buttons//////
  $("#add_aspect_button").fancybox({ 'titleShow' : false });
  $("#add_request_button").fancybox({ 'titleShow': false });
  $(".add_request_button").fancybox({ 'titleShow': false });

  $("input[type='submit']").addClass("button");

  $(".image_cycle img").load( function() {
    $(this).fadeIn("slow");
  });

  $("#global_search").hover(
    function() {
      $(this).fadeTo('fast', '1');
    },
    function() {
      $(this).fadeTo('fast', '0.5');
    }
  );

});//end document ready

//Called with $(selector).clearForm()
$.fn.clearForm = function() {
  return this.each(function() {
  var type = this.type, tag = this.tagName.toLowerCase();
  if (tag == 'form')
    return $(':input',this).clearForm();
  if (type == 'text' || type == 'password' || tag == 'textarea')
    this.value = '';
  //else if (type == 'checkbox' || type == 'radio')
    //this.checked = false;
  else if (tag == 'select')
    this.selectedIndex = -1;
  $(this).blur();
  });
};

<commit_msg>DG IZ; shift+enter in publisher box submits contents<commit_after>/*   Copyright (c) 2010, Diaspora Inc.  This file is
*   licensed under the Affero General Public License version 3.  See
*   the COPYRIGHT file.
*/

$(document).ready(function(){

	$('#debug_info').click(function() {
		$('#debug_more').toggle('fast');
	});

  $("label").inFieldLabels();

  $('#flash_notice, #flash_error, #flash_alert').delay(2500).slideUp(130);

  $("div.image_cycle").cycle({
    fx: 'fade',
    random: 1,
    timeout: 2000,
    speed: 3000
  });

  //buttons//////
  $("#add_aspect_button").fancybox({ 'titleShow' : false });
  $("#add_request_button").fancybox({ 'titleShow': false });
  $(".add_request_button").fancybox({ 'titleShow': false });

  $("input[type='submit']").addClass("button");

  $(".image_cycle img").load( function() {
    $(this).fadeIn("slow");
  });

  $("#global_search").hover(
    function() {
      $(this).fadeTo('fast', '1');
    },
    function() {
      $(this).fadeTo('fast', '0.5');
    }
  );

  $("#publisher textarea").keydown( function(e) {
    if (e.shiftKey && e.keyCode == 13) {
      $("#publisher form").submit();
    }
  });

});//end document ready

//Called with $(selector).clearForm()
$.fn.clearForm = function() {
  return this.each(function() {
  var type = this.type, tag = this.tagName.toLowerCase();
  if (tag == 'form')
    return $(':input',this).clearForm();
  if (type == 'text' || type == 'password' || tag == 'textarea')
    this.value = '';
  //else if (type == 'checkbox' || type == 'radio')
    //this.checked = false;
  else if (tag == 'select')
    this.selectedIndex = -1;
  $(this).blur();
  });
};

<|endoftext|>


<commit_before>dojo.provide("paste.php");

dojo.require("dojox.highlight._base");

//
// PHP5 definition (c) Victor Karamzin <Victor.Karamzin@enterra-inc.com>
// released under BSD, submitted to the Dojo Foundation under CLA
//
(function(){

    var dh = dojox.highlight, dhc = dh.constants;

    var PHP5_KEYWORDS = {'and': 1, 'include_once': 1, 'list': 1, 'abstract': 1, 'global': 1,
        'private': 1, 'echo': 1, 'interface': 1, 'as': 1, 'static': 1,
        'endswitch': 1, 'array': 1, 'null': 1, 'if': 1, 'endwhile': 1, 'or': 1,
        'const': 1, 'for': 1, 'endforeach': 1, 'self': 1, 'var': 1, 'while': 1,
        'isset': 1, 'public': 1, 'protected': 1, 'exit': 1, 'foreach': 1,
        'throw': 1, 'elseif': 1, 'extends': 1, 'include': 1, '__FILE__': 1,
        'empty': 1, 'require_once': 1, 'function': 1, 'do': 1, 'xor': 1,
        'return': 1, 'implements': 1, 'parent': 1, 'clone': 1, 'use': 1,
        '__CLASS__': 1, '__LINE__': 1, 'else': 1, 'break': 1, 'print': 1,
        'eval': 1, 'new': 1, 'catch': 1, '__METHOD__': 1, 'class': 1, 'case': 1,
        'exception': 1, 'php_user_filter': 1, 'default': 1, 'die': 1, 'require': 1,
        '__FUNCTION__': 1, 'enddeclare': 1, 'final': 1, 'try': 1, 'this': 1,
        'switch': 1, 'continue': 1, 'endfor': 1, 'endif': 1, 'declare': 1,
        'unset': 1};
    var PHP_IDENTIFIER_RE = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';

    if (!dh['languages']) {
        dh.languages = {};
    }

    dh.languages.php = {
        // summary: PHP highlight definitions
        defaultMode: {
            lexems: [dhc.IDENT_RE],
            contains: ['comment', 'number', 'string', 'variable'],
            keywords: PHP5_KEYWORDS
        },
        case_insensitive: true,
        modes: [
            dhc.C_LINE_COMMENT_MODE,
            dhc.HASH_COMMENT_MODE,
            {
                className: 'comment',
                begin: '/\\*', end: '\\*/',
                contains: ['phpdoc']
            },
            {
                className: 'phpdoc',
                begin: '\\s@[A-Za-z]+', end: '^',
                relevance: 10
            },
            dhc.C_NUMBER_MODE,
            {
                className: 'string',
                begin: '\'', end: '\'',
                contains: ['escape'],
                relevance: 0
            },
            {
                className: 'string',
                begin: '"', end: '"',
                contains: ['escape'],
                relevance: 0
            },
            dhc.BACKSLASH_ESCAPE,
            {
                className: 'variable',
                begin: '\\$' + PHP_IDENTIFIER_RE, end: '^'
            }
        ]
    }
})();
<commit_msg>PHP highlight definition attribution<commit_after>dojo.provide("paste.php");

dojo.require("dojox.highlight._base");

// Adapted from dojox/highlight/languages/php.js from current Dojo trunk at the
// time of this writing.
//
// Original attribution:
// PHP5 definition (c) Victor Karamzin <Victor.Karamzin@enterra-inc.com>
// released under BSD, submitted to the Dojo Foundation under CLA
//
(function(){

    var dh = dojox.highlight, dhc = dh.constants;

    var PHP5_KEYWORDS = {'and': 1, 'include_once': 1, 'list': 1, 'abstract': 1, 'global': 1,
        'private': 1, 'echo': 1, 'interface': 1, 'as': 1, 'static': 1,
        'endswitch': 1, 'array': 1, 'null': 1, 'if': 1, 'endwhile': 1, 'or': 1,
        'const': 1, 'for': 1, 'endforeach': 1, 'self': 1, 'var': 1, 'while': 1,
        'isset': 1, 'public': 1, 'protected': 1, 'exit': 1, 'foreach': 1,
        'throw': 1, 'elseif': 1, 'extends': 1, 'include': 1, '__FILE__': 1,
        'empty': 1, 'require_once': 1, 'function': 1, 'do': 1, 'xor': 1,
        'return': 1, 'implements': 1, 'parent': 1, 'clone': 1, 'use': 1,
        '__CLASS__': 1, '__LINE__': 1, 'else': 1, 'break': 1, 'print': 1,
        'eval': 1, 'new': 1, 'catch': 1, '__METHOD__': 1, 'class': 1, 'case': 1,
        'exception': 1, 'php_user_filter': 1, 'default': 1, 'die': 1, 'require': 1,
        '__FUNCTION__': 1, 'enddeclare': 1, 'final': 1, 'try': 1, 'this': 1,
        'switch': 1, 'continue': 1, 'endfor': 1, 'endif': 1, 'declare': 1,
        'unset': 1};
    var PHP_IDENTIFIER_RE = '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*';

    if (!dh['languages']) {
        dh.languages = {};
    }

    dh.languages.php = {
        // summary: PHP highlight definitions
        defaultMode: {
            lexems: [dhc.IDENT_RE],
            contains: ['comment', 'number', 'string', 'variable'],
            keywords: PHP5_KEYWORDS
        },
        case_insensitive: true,
        modes: [
            dhc.C_LINE_COMMENT_MODE,
            dhc.HASH_COMMENT_MODE,
            {
                className: 'comment',
                begin: '/\\*', end: '\\*/',
                contains: ['phpdoc']
            },
            {
                className: 'phpdoc',
                begin: '\\s@[A-Za-z]+', end: '^',
                relevance: 10
            },
            dhc.C_NUMBER_MODE,
            {
                className: 'string',
                begin: '\'', end: '\'',
                contains: ['escape'],
                relevance: 0
            },
            {
                className: 'string',
                begin: '"', end: '"',
                contains: ['escape'],
                relevance: 0
            },
            dhc.BACKSLASH_ESCAPE,
            {
                className: 'variable',
                begin: '\\$' + PHP_IDENTIFIER_RE, end: '^'
            }
        ]
    }
})();
<|endoftext|>


<commit_before>/*
This file is part of Kronekeeper, a web based application for
recording and managing wiring frame records.

Copyright (C) 2016 NP Broadcast Limited

Kronekeeper is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Kronekeeper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Kronekeeper.  If not, see <http://www.gnu.org/licenses/>.

*/

define([
	'block/jumper',
	'block/highlight',
	'backbone',
        'jquery',
	'jqueryui'
], function (
	jumper,
	highlight
) {
        'use strict';

	var Circuit_Model = Backbone.Model.extend({

		idAttribute: 'circuit_id',
		urlRoot: '/api/circuit',

		defaults: {
			block_id: null,
			circuit_id: null,
			designation: null,
			name: null,
			cable_reference: null,
			connection: null,
			jumpers: []
		},

		initialize: function(attributes) {

			/* Handle the possibility that we have no jumpers */
			if(!attributes.jumpers) {
				attributes.jumpers = [];
			}

			/* Build a discrete model for each jumper, so we
			 * can delete/patch/create these individually
			 */
			this.jumper_models = [];
			attributes.jumpers.forEach(function(jumper_data, index) {
				this.jumper_models.push(new jumper.model({
					data: jumper_data,
				},
				{
					parse: true,
					circuit: this
				}));
			}, this);

			this.listenTo(
				this.collection,
				"circuit_jumper_change",
				this.jumper_changed
			);
			this.listenTo(
				this,
				"loaded_jumper_data",
				this.display_jumper_data
			);
		},

		jumper_changed: function(changed_circuit_id) {

			if(changed_circuit_id == this.id) {
				this.reload_jumpers();
			}
		},

		reload_jumpers: function() {

			var circuit_model = this;
			var url = '/api/circuit/' + this.id + '/jumpers';
			var data = {
				circuit_id: this.id
			};

			$.ajax({
				url: url,
				type: "GET",
				dataType: "json",
				success: function(json) {
					console.log("jumper data loaded OK");
					circuit_model.trigger("loaded_jumper_data", json);
				},
				error: function(xhr, status) {
					var error_code = xhr.status + " " + xhr.statusText;
					console.log("failed to reload jumper data:", error_code);
				}
			});
		},

		display_jumper_data: function(data) {

			var jumpers = this.jumper_models;
			console.log("cells_needed:", jumpers.length);
			console.log("jumpers:", jumpers);

			data.jumpers.forEach(function(jumper_data) {

				/* Is this jumper already displayed?
				 * nothing to do if so - at present we don't update jumpers,
				 * we delete and add new for any changes
				 */
				var jumper_model = this.jumper_model_by_id(jumper_data.jumper_id);
				if(jumper_model) {
					console.log("already have jumper_id", jumper_data.jumper_id);
					jumper_model.set(
						jumper_model.parse({data: jumper_data})
					);
				}
				else {
					console.log("adding new jumper_id", jumper_data.jumper_id);

					/* Is there an existing model we can populate? */
					var jumper_model = this.get_empty_jumper_model();

					if(jumper_model) {
						console.log("cells_needed pre-populate-existing:", jumpers.length);
						console.log("populating existing jumper model");
						jumper_model.set(
							jumper_model.parse({data: jumper_data})
						);
						console.log("cells_needed after populate-existing:", jumpers.length);
					}
					else {
						console.log("No empty jumper models found - adding one");

						jumper_model = new jumper.model({
							data: jumper_data,
						},
						{
							parse: true,
							circuit: this
						});
						this.jumper_models.push(jumper_model);
					}
				}
			}, this);

			this.trigger("render_jumpers_request");
		},

		jumper_model_by_id: function(wanted_jumper_id) {

			/* Returns the jumper model having the given jumper_id */
			return this.jumper_models.find(function(jumper_model) {
				return wanted_jumper_id == jumper_model.get("id");
			});
		},

		get_empty_jumper_model: function() {

			/* Returns the first unpopulated jumper model, or undef if none */
			return this.jumper_models.find(function(jumper_model) {
				return !jumper_model.get("id");
			});
		}

	});

	var Circuits_Collection = Backbone.Collection.extend({

		model: Circuit_Model,
		url: function() {
			return '/api/block/' + this.block_id;
		},

		initialize: function(models, options) {
			this.block_id = options.block_id;
		},

		parse: function(data) {
			return data.circuits;
		},

		provision_jumper_fields: function(required_count) {
			/* This routine will ensure at least the specified
			 * number of jumper field cells are available. This
			 * collection keeps track of how many should be
			 * provided, but delegates their creation to views
			 * which listen to the provision_jumper_fields event.
			 */
			this.trigger("provision_jumper_fields", this.jumper_count);
		}
	});

	var Circuit_View = Backbone.View.extend({

		tagName: 'tr',
		className: 'circuit',

		events: {
			'click a.add_jumper' : 'add_jumper',
			'input .circuit_name input' : 'circuit_name_input',
			'input .cable_reference input' : 'cable_reference_input',
			'input .connection input' : 'connection_input',

			'keypress .circuit_name input': function(e) {
				this.handle_keypress(e, 'name');
			},
			'keypress .cable_reference input': function(e) {
				this.handle_keypress(e, 'cable_reference');
			},
			'keypress .connection input': function(e) {
				this.handle_keypress(e, 'connection');
			},
			'change .circuit_name input' : 'circuit_name_change',
			'change .cable_reference input' : 'cable_reference_change',
			'change .connection input' : 'connection_change',
		},

		initialize: function() {
			this.listenTo(
				this.model,
				'sync',
				this.model_synced
			);
			this.listenTo(
				this.model.collection,
				"table_structure_rendered",
				this.render_jumpers
			);
			this.listenTo(
				this.model.collection,
				"provision_jumper_fields",
				this.provision_jumper_fields
			);
			this.listenTo(
				this.model,
				"render_jumpers_request",
				this.render_jumpers
			);
		},

		template: _.template( $('#row_template').html() ),

		render: function() {
			/* Jumpers are populated lates, once the basic
			 * table structure is in place so that we can
			 * handle any requirement for extra columns
			 * without race conditions.
			 */
			var json = this.model.toJSON();
			this.$el.html(this.template(json));
			return this;
		},

		render_jumpers: function() {

			console.log("render_jumpers()");

			/* Typically a circuit has two jumper fields, but it can have more
			 * Ensure we have enough blank cells for every jumper model
			 */
			var jumpers = this.model.jumper_models;
			var cells_needed = jumpers.length;
			while(this.$el.children("td.jumper").not(".inactive").size() < cells_needed) {
				this.add_jumper();
			}

			/* Populate the cells */
			var circuit_model = this.model;
			this.$el.children("td.jumper").not(".inactive").each(function(index, cell) {

				console.log("populating jumper cell index", index);

				if(!jumpers[index]) {
					console.log("supposedly null jumper:", jumpers[index]);
					jumpers[index] = new jumper.model(null, {circuit:circuit_model});
					var view = new jumper.view({
						model: jumpers[index]
					});
					$(cell).replaceWith(view.render().$el);
				}
				else {
					jumpers[index].trigger("change");
				}
			});
		},

		add_jumper: function(e) {

			/* Add an active jumper cell.
			 * First see if there is an inactive cell to which we can assign
			 * a model and view. (An inactive cell is an existing table cell
			 * which is greyed-out and has neither model or view associated).
			 * If there are no inactive cells in this table row, we expand
			 * the table to add an active jumper cell to this row and an
			 * inactive table cell to every other circuit row.
			 */

			var inactive_cell_count = this.$el.children("td.jumper.inactive").size();

			if(inactive_cell_count < 1) {
				/* Need to provision another column */
				var jumper_cell_count = this.$el.children("td.jumper").size();
				this.model.collection.trigger(
					"provision_jumper_fields",
					jumper_cell_count + 1
				);
			}

			/* Activate an inactive cell */
			var jumper_model = new jumper.model(null, {circuit:this.model});
			this.model.jumper_models.push(jumper_model);
			var jumper_view = new jumper.view({
				model: jumper_model
			});
			this.$el.children("td.jumper.inactive").first().replaceWith(jumper_view.render().$el);
		},

		handle_keypress: function(e, attribute_name) {
			if(e.keyCode == 27) {
				e.target.value = this.model.get(attribute_name);
				e.target.parentNode.classList.remove('change_pending');
			}
		},

		circuit_name_input: function(e) {
			this.highlight_change(e, 'name');
		},

		cable_reference_input: function(e) {
			this.highlight_change(e, 'cable_reference');
		},

		connection_input: function(e) {
			this.highlight_change(e, 'connection');
		},

		highlight_change: function(e, attribute_name) {
			if(e.target.value != this.model.get(attribute_name)) {
				e.target.parentNode.classList.add('change_pending');
			}
			else {
				e.target.parentNode.classList.remove('change_pending');
			}
		},

		circuit_name_change: function(e) {
			this.save_data({name: e.target.value});
		},

		cable_reference_change: function(e) {
			this.save_data({cable_reference: e.target.value});
		},

		connection_change: function(e) {
			this.save_data({connection: e.target.value});
		},

		save_data: function(data) {
			this.model.save(data, {
				patch: true,
				success: function(model, response, options) {
					console.log("circuit data saved");
				},
				error: function(model, xhr, options) {
					console.log("ERROR saving circuit data");
				}
			});
		},

		model_synced: function(model, response, options) {
			/* Clear field highlighting and flash green to indicate successful save
			 * Server returns the changed fields to confirm which have been updated
			 */
			if('name' in response) {
				highlight.element_change_applied(this.$el, "td.circuit_name");
			}
			if('cable_reference' in response) {
				highlight.element_change_applied(this.$el, "td.cable_reference");
			}
			if('connection' in response) {
				highlight.element_change_applied(this.$el, "td.connection");
			}
		},

		provision_jumper_fields: function(required_count) {

			var jumper_cell_count = this.$el.children("td.jumper").size();
			var td_buttons = this.$el.children("td.circuit_buttons").first();
			var template = $('#inactive_jumper_cell_template').html();

			while(jumper_cell_count < required_count) {
				/* Insert new cell in row before the buttons */
				td_buttons.before(template);
				jumper_cell_count ++;
			}
		}

	});

	console.log("loaded circuit.js");

	/* Expose public methods */
	return {
		model: Circuit_Model,
		view: Circuit_View,
		collection: Circuits_Collection
	};

});

<commit_msg>Simplify circuit event handler code<commit_after>/*
This file is part of Kronekeeper, a web based application for
recording and managing wiring frame records.

Copyright (C) 2016 NP Broadcast Limited

Kronekeeper is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Kronekeeper is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with Kronekeeper.  If not, see <http://www.gnu.org/licenses/>.

*/

define([
	'block/jumper',
	'block/highlight',
	'backbone',
        'jquery',
	'jqueryui'
], function (
	jumper,
	highlight
) {
        'use strict';

	var Circuit_Model = Backbone.Model.extend({

		idAttribute: 'circuit_id',
		urlRoot: '/api/circuit',

		defaults: {
			block_id: null,
			circuit_id: null,
			designation: null,
			name: null,
			cable_reference: null,
			connection: null,
			jumpers: []
		},

		initialize: function(attributes) {

			/* Handle the possibility that we have no jumpers */
			if(!attributes.jumpers) {
				attributes.jumpers = [];
			}

			/* Build a discrete model for each jumper, so we
			 * can delete/patch/create these individually
			 */
			this.jumper_models = [];
			attributes.jumpers.forEach(function(jumper_data, index) {
				this.jumper_models.push(new jumper.model({
					data: jumper_data,
				},
				{
					parse: true,
					circuit: this
				}));
			}, this);

			this.listenTo(
				this.collection,
				"circuit_jumper_change",
				this.jumper_changed
			);
			this.listenTo(
				this,
				"loaded_jumper_data",
				this.display_jumper_data
			);
		},

		jumper_changed: function(changed_circuit_id) {

			if(changed_circuit_id == this.id) {
				this.reload_jumpers();
			}
		},

		reload_jumpers: function() {

			var circuit_model = this;
			var url = '/api/circuit/' + this.id + '/jumpers';
			var data = {
				circuit_id: this.id
			};

			$.ajax({
				url: url,
				type: "GET",
				dataType: "json",
				success: function(json) {
					console.log("jumper data loaded OK");
					circuit_model.trigger("loaded_jumper_data", json);
				},
				error: function(xhr, status) {
					var error_code = xhr.status + " " + xhr.statusText;
					console.log("failed to reload jumper data:", error_code);
				}
			});
		},

		display_jumper_data: function(data) {

			var jumpers = this.jumper_models;
			console.log("cells_needed:", jumpers.length);
			console.log("jumpers:", jumpers);

			data.jumpers.forEach(function(jumper_data) {

				/* Is this jumper already displayed?
				 * nothing to do if so - at present we don't update jumpers,
				 * we delete and add new for any changes
				 */
				var jumper_model = this.jumper_model_by_id(jumper_data.jumper_id);
				if(jumper_model) {
					console.log("already have jumper_id", jumper_data.jumper_id);
					jumper_model.set(
						jumper_model.parse({data: jumper_data})
					);
				}
				else {
					console.log("adding new jumper_id", jumper_data.jumper_id);

					/* Is there an existing model we can populate? */
					var jumper_model = this.get_empty_jumper_model();

					if(jumper_model) {
						console.log("cells_needed pre-populate-existing:", jumpers.length);
						console.log("populating existing jumper model");
						jumper_model.set(
							jumper_model.parse({data: jumper_data})
						);
						console.log("cells_needed after populate-existing:", jumpers.length);
					}
					else {
						console.log("No empty jumper models found - adding one");

						jumper_model = new jumper.model({
							data: jumper_data,
						},
						{
							parse: true,
							circuit: this
						});
						this.jumper_models.push(jumper_model);
					}
				}
			}, this);

			this.trigger("render_jumpers_request");
		},

		jumper_model_by_id: function(wanted_jumper_id) {

			/* Returns the jumper model having the given jumper_id */
			return this.jumper_models.find(function(jumper_model) {
				return wanted_jumper_id == jumper_model.get("id");
			});
		},

		get_empty_jumper_model: function() {

			/* Returns the first unpopulated jumper model, or undef if none */
			return this.jumper_models.find(function(jumper_model) {
				return !jumper_model.get("id");
			});
		}

	});

	var Circuits_Collection = Backbone.Collection.extend({

		model: Circuit_Model,
		url: function() {
			return '/api/block/' + this.block_id;
		},

		initialize: function(models, options) {
			this.block_id = options.block_id;
		},

		parse: function(data) {
			return data.circuits;
		},

		provision_jumper_fields: function(required_count) {
			/* This routine will ensure at least the specified
			 * number of jumper field cells are available. This
			 * collection keeps track of how many should be
			 * provided, but delegates their creation to views
			 * which listen to the provision_jumper_fields event.
			 */
			this.trigger("provision_jumper_fields", this.jumper_count);
		}
	});

	var Circuit_View = Backbone.View.extend({

		tagName: 'tr',
		className: 'circuit',

		events: {
			'click a.add_jumper'              : 'add_jumper',
			'input .circuit_name input'       : function(e) {this.highlight_change(e, 'name')},
			'input .cable_reference input'    : function(e) {this.highlight_change(e, 'cable_reference')},
			'input .connection input'         : function(e) {this.highlight_change(e, 'connection')},
			'keypress .circuit_name input'    : function(e) {this.handle_keypress(e, 'name')},
			'keypress .cable_reference input' : function(e) {this.handle_keypress(e, 'cable_reference')},
			'keypress .connection input'      : function(e) {this.handle_keypress(e, 'connection')},
			'change .circuit_name input'      : function(e) {this.save_data({name: e.target.value})},
			'change .cable_reference input'   : function(e) {this.save_data({cable_reference: e.target.value})},
			'change .connection input'        : function(e) {this.save_data({connection: e.target.value})}
		},

		initialize: function() {
			this.listenTo(
				this.model,
				'sync',
				this.model_synced
			);
			this.listenTo(
				this.model.collection,
				"table_structure_rendered",
				this.render_jumpers
			);
			this.listenTo(
				this.model.collection,
				"provision_jumper_fields",
				this.provision_jumper_fields
			);
			this.listenTo(
				this.model,
				"render_jumpers_request",
				this.render_jumpers
			);
		},

		template: _.template( $('#row_template').html() ),

		render: function() {
			/* Jumpers are populated lates, once the basic
			 * table structure is in place so that we can
			 * handle any requirement for extra columns
			 * without race conditions.
			 */
			var json = this.model.toJSON();
			this.$el.html(this.template(json));
			return this;
		},

		render_jumpers: function() {

			console.log("render_jumpers()");

			/* Typically a circuit has two jumper fields, but it can have more
			 * Ensure we have enough blank cells for every jumper model
			 */
			var jumpers = this.model.jumper_models;
			var cells_needed = jumpers.length;
			while(this.$el.children("td.jumper").not(".inactive").size() < cells_needed) {
				this.add_jumper();
			}

			/* Populate the cells */
			var circuit_model = this.model;
			this.$el.children("td.jumper").not(".inactive").each(function(index, cell) {

				console.log("populating jumper cell index", index);

				if(!jumpers[index]) {
					console.log("supposedly null jumper:", jumpers[index]);
					jumpers[index] = new jumper.model(null, {circuit:circuit_model});
					var view = new jumper.view({
						model: jumpers[index]
					});
					$(cell).replaceWith(view.render().$el);
				}
				else {
					jumpers[index].trigger("change");
				}
			});
		},

		add_jumper: function(e) {

			/* Add an active jumper cell.
			 * First see if there is an inactive cell to which we can assign
			 * a model and view. (An inactive cell is an existing table cell
			 * which is greyed-out and has neither model or view associated).
			 * If there are no inactive cells in this table row, we expand
			 * the table to add an active jumper cell to this row and an
			 * inactive table cell to every other circuit row.
			 */

			var inactive_cell_count = this.$el.children("td.jumper.inactive").size();

			if(inactive_cell_count < 1) {
				/* Need to provision another column */
				var jumper_cell_count = this.$el.children("td.jumper").size();
				this.model.collection.trigger(
					"provision_jumper_fields",
					jumper_cell_count + 1
				);
			}

			/* Activate an inactive cell */
			var jumper_model = new jumper.model(null, {circuit:this.model});
			this.model.jumper_models.push(jumper_model);
			var jumper_view = new jumper.view({
				model: jumper_model
			});
			this.$el.children("td.jumper.inactive").first().replaceWith(jumper_view.render().$el);
		},

		handle_keypress: function(e, attribute_name) {
			if(e.keyCode == 27) {
				e.target.value = this.model.get(attribute_name);
				e.target.parentNode.classList.remove('change_pending');
			}
		},

		highlight_change: function(e, attribute_name) {
			if(e.target.value != this.model.get(attribute_name)) {
				e.target.parentNode.classList.add('change_pending');
			}
			else {
				e.target.parentNode.classList.remove('change_pending');
			}
		},

		save_data: function(data) {
			this.model.save(data, {
				patch: true,
				success: function(model, response, options) {
					console.log("circuit data saved");
				},
				error: function(model, xhr, options) {
					console.log("ERROR saving circuit data");
				}
			});
		},

		model_synced: function(model, response, options) {
			/* Clear field highlighting and flash green to indicate successful save
			 * Server returns the changed fields to confirm which have been updated
			 */
			if('name' in response) {
				highlight.element_change_applied(this.$el, "td.circuit_name");
			}
			if('cable_reference' in response) {
				highlight.element_change_applied(this.$el, "td.cable_reference");
			}
			if('connection' in response) {
				highlight.element_change_applied(this.$el, "td.connection");
			}
		},

		provision_jumper_fields: function(required_count) {

			var jumper_cell_count = this.$el.children("td.jumper").size();
			var td_buttons = this.$el.children("td.circuit_buttons").first();
			var template = $('#inactive_jumper_cell_template').html();

			while(jumper_cell_count < required_count) {
				/* Insert new cell in row before the buttons */
				td_buttons.before(template);
				jumper_cell_count ++;
			}
		}

	});

	console.log("loaded circuit.js");

	/* Expose public methods */
	return {
		model: Circuit_Model,
		view: Circuit_View,
		collection: Circuits_Collection
	};

});

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////
//
// Author Scott Herbert (www.scott-herbert.com)
//		  Dimitri Kourkoulis (http://dimitros.net/en/home)
//
// Version History
// 1 (10-Feb-2013) Inital release on to GitHub.
//
// 2 (12-Mar-2013) Small modification by Dimitri Kourkoulis.
//    This version of the script, keeps visitors on the web site
//    if they decline the use of cookies. However, in that event,
//    the cookie stored in their browser is named 'jsNoCookieCheck'
//    instead of 'jsCookieCheck'. This can be used by the software
//    and/or CMS of the web site to disable cookie producing content.
//    An example of how this has been used in one case on the Umbraco
//    CMS can be found here:
//    http://dimitros.net/en/blog/complyingwiththecookielaw
//
// 3 (03-April-2013) SAH - Added a variable that allows the developer to
//	  select if the script redirects (as it originally did) or carry?s
//    on (as per Dimitri?s great addition).
//
// Download from http://adf.ly/IvElY

function getCookie(c_name) {
    var i, x, y, ARRcookies = document.cookie.split(";");
    for (i = 0; i < ARRcookies.length; i++) {
        x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
        y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
        x = x.replace(/^\s+|\s+$/g, "");
        if (x == c_name) {
            return unescape(y);
        }
    }
}

function displayNotification(c_action) {

    // this sets the page background to semi-transparent black should work with all browsers
    var message = "
";

    // center vert
    message = message + "

";

    // this is the message displayed to the user.
    message = message + "This site uses heavy sarcasm, talks about imaginary friends and things that never happened or even might be physically possible.
If you are too much of a sissy to handle that, I prefer would prefer if you just go somewhere else
and click the \"I don't agree\" button.

Oh, also this site uses cookies:
In order for it to work correctly, we store a small file (called a cookie) on your computer.
 If you click \"I agree\" below we will create the cookies all is well. If you click on \"I don't agree\" we will send you far, VERY far away.
";

    // Displays the I agree/disagree buttons.
    // Feel free to change the address of the I disagree redirection to either a non-cookie site or a Google or the ICO web site
    message = message + "
<INPUT TYPE='button' VALUE='I Agree' onClick='JavaScript:doAccept();' /> <INPUT TYPE='button' VALUE=\"I don't agree\" onClick='JavaScript:doNotAccept("
	message = message + c_action;
	message = message + ");' />";

    // and this closes everything off.
    message = message + "

";

    document.writeln(message);
}

function doAccept() {
    setCookie("ILoveAr0xA", null, 365);
    location.reload(true);
}

function doNotAccept(c_action) {

	if (c_action == 1) {
        alert("You didn't want sarcasm or tracking cookies #sadpanda is sad. Hope you have more fun somewhere else.");
		window.location.replace("http://www.wikihow.com/Have-Fun-with-Grandma");
	} else {
		window.location.replace("http://www.wikihow.com/Have-Fun-with-Grandma");
	}
}

function setCookie(c_name, value, exdays) {
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString() + "; path=/");
    document.cookie = c_name + "=" + c_value;
}

function checkCookie(c_action) {

    var cookieName = "ILoveAr0xA";
    var cookieChk = getCookie(cookieName);
    if (cookieChk != null && cookieChk != "") {
        // the jsCookieCheck cookie exists so we can assume the person has read the notification
        // within the last year and has accepted the use of cookies
        setCookie(cookieName, cookieChk, 365); // set the cookie to expire in a year.
    }
    else {
        // No cookie exists, so display the lightbox effect notification.
        displayNotification(c_action);
    }
}

// blockOrCarryOn - 1 = Carry on, store a do not store cookies cookie and carry on
//					0 = Block, redirect the user to a different website (google for example)
var blockOrCarryOn = 1;
checkCookie(blockOrCarryOn);
<commit_msg>cookiedisclaimer, last commit i promise (for tonight)<commit_after>/////////////////////////////////////////////////////////////
//
// Author Scott Herbert (www.scott-herbert.com)
//		  Dimitri Kourkoulis (http://dimitros.net/en/home)
//
// Version History
// 1 (10-Feb-2013) Inital release on to GitHub.
//
// 2 (12-Mar-2013) Small modification by Dimitri Kourkoulis.
//    This version of the script, keeps visitors on the web site
//    if they decline the use of cookies. However, in that event,
//    the cookie stored in their browser is named 'jsNoCookieCheck'
//    instead of 'jsCookieCheck'. This can be used by the software
//    and/or CMS of the web site to disable cookie producing content.
//    An example of how this has been used in one case on the Umbraco
//    CMS can be found here:
//    http://dimitros.net/en/blog/complyingwiththecookielaw
//
// 3 (03-April-2013) SAH - Added a variable that allows the developer to
//	  select if the script redirects (as it originally did) or carry?s
//    on (as per Dimitri?s great addition).
//
// Download from http://adf.ly/IvElY

function getCookie(c_name) {
    var i, x, y, ARRcookies = document.cookie.split(";");
    for (i = 0; i < ARRcookies.length; i++) {
        x = ARRcookies[i].substr(0, ARRcookies[i].indexOf("="));
        y = ARRcookies[i].substr(ARRcookies[i].indexOf("=") + 1);
        x = x.replace(/^\s+|\s+$/g, "");
        if (x == c_name) {
            return unescape(y);
        }
    }
}

function displayNotification(c_action) {

    // this sets the page background to semi-transparent black should work with all browsers
    var message = "
";

    // center vert
    message = message + "

";

    // this is the message displayed to the user.
    message = message + "This site uses heavy sarcasm, talks about imaginary friends and things that never happened or even might be physically possible.
If you are too much of a sissy to handle that, I would suggest you just go somewhere else
and click the \"I don't agree\" button.

Oh, also this site uses cookies:
In order for it to work correctly, we store a small file (called a cookie) on your computer.
 If you click \"I agree\" below we will create the cookies all is well. If you click on \"I don't agree\" we will send you far, VERY far away.
";

    // Displays the I agree/disagree buttons.
    // Feel free to change the address of the I disagree redirection to either a non-cookie site or a Google or the ICO web site
    message = message + "
<INPUT TYPE='button' VALUE='I Agree' onClick='JavaScript:doAccept();' /> <INPUT TYPE='button' VALUE=\"I don't agree\" onClick='JavaScript:doNotAccept("
	message = message + c_action;
	message = message + ");' />";

    // and this closes everything off.
    message = message + "

";

    document.writeln(message);
}

function doAccept() {
    setCookie("ILoveAr0xA", null, 365);
    location.reload(true);
}

function doNotAccept(c_action) {

	if (c_action == 1) {
        alert("You didn't want sarcasm or tracking cookies #sadpanda is sad. Hope you have more fun somewhere else.");
		window.location.replace("http://www.wikihow.com/Have-Fun-with-Grandma");
	} else {
		window.location.replace("http://www.wikihow.com/Have-Fun-with-Grandma");
	}
}

function setCookie(c_name, value, exdays) {
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString() + "; path=/");
    document.cookie = c_name + "=" + c_value;
}

function checkCookie(c_action) {

    var cookieName = "ILoveAr0xA";
    var cookieChk = getCookie(cookieName);
    if (cookieChk != null && cookieChk != "") {
        // the jsCookieCheck cookie exists so we can assume the person has read the notification
        // within the last year and has accepted the use of cookies
        setCookie(cookieName, cookieChk, 365); // set the cookie to expire in a year.
    }
    else {
        // No cookie exists, so display the lightbox effect notification.
        displayNotification(c_action);
    }
}

// blockOrCarryOn - 1 = Carry on, store a do not store cookies cookie and carry on
//					0 = Block, redirect the user to a different website (google for example)
var blockOrCarryOn = 1;
checkCookie(blockOrCarryOn);
<|endoftext|>


<commit_before>var $document = $(document),
    $source = $('#source');

var editorModes = {
  html: 'htmlmixed',
  javascript: 'javascript',
  css: 'css'
};

var Panel = function (name, settings) {
  var panel = this,
      showPanelButton = true,
      $panel = null,
      splitterSettings = {},
      cmSettings = {};

  panel.settings = settings = settings || {};
  panel.id = panel.name = name;
  $panel = $('.panel.' + name);
  $panel.data('name', name);
  panel.$el = $panel.detach();
  panel.$el.appendTo($source);
  panel.$el.wrapAll('
');
  panel.$el = panel.$el.parent().hide();
  panel.el = document.getElementById(name);
  panel.order = ++Panel.order;

  panel.$el.data('panel', panel);

  // keyboard shortcut (set in keyboardcontrol.js)
  panelShortcuts[panelShortcuts.start + panel.order] = panel.id;

  if (panel.order === 1) {
    settings.nosplitter = true;
  }

  if (settings.editor) {
    cmSettings = {
      parserfile: [],
      tabMode: 'shift',
      readOnly: jsbin.state.embed ? 'nocursor' : false,
      dragDrop: false, // we handle it ourselves
      mode: editorModes[name],
      // lineNumbers: objectValue('jsbin.settings.editor.lineNumbers') || false,
      onChange: function (event) {
        $document.trigger('codeChange', [{ panelId: panel.id, revert: true }]);
        return true;
      },
      lineWrapping: true,
      theme: jsbin.settings.theme || 'jsbin'
    };

    $.extend(cmSettings, jsbin.settings.editor || {});

    panel.editor = CodeMirror.fromTextArea(panel.el, cmSettings);

    panel.processor = settings.processor || function (str) { return str; };

    panel._setupEditor(panel.editor, name);
  }

  if (!settings.nosplitter) {
    // console.log(panel.id, wrapper);
    panel.splitter = panel.$el.splitter(splitterSettings).data('splitter');
    panel.splitter.hide();
  } else {
    // create a fake splitter to let the rest of the code work
    panel.splitter = $();
  }

  if (settings.beforeRender) {
    $document.bind('render', $.proxy(settings.beforeRender, panel));
  }

  if (!settings.editor) {
    panel.ready = true;
  }

  // append panel to controls
  if (jsbin.state.embed) {
    // showPanelButton = window.location.search.indexOf(panel.id) !== -1;
  }

  if (showPanelButton) {
    this.controlButton = $('' + (settings.label || name) + '');
    this.controlButton.click(function () {
      panel.toggle();
      return false;
    });
    this.controlButton.appendTo('#panels');
  }

  $panel.focus(function () {
    panel.focus();
  });
  $panel.add(this.$el.find('.label')).click(function () {
    panel.focus();
  });
};

Panel.order = 0;

Panel.prototype = {
  virgin: true,
  visible: false,
  show: function (x) {
    // check to see if there's a panel to the left.
    // if there is, take it's size/2 and make this our
    // width
    var panel = this,
        panelCount = panel.$el.find('.panel').length;

    analytics.showPanel(panel.id);

    // panel.$el.show();
    if (panel.splitter.length) {
      if (panelCount === 0 || panelCount > 1) {
        var $panel = $('.panel.' + panel.id).show();
        // $panel.next().show(); // should be the splitter...
        $panel.closest('.panelwrapper').show();
      } else {
        panel.$el.show();
      }
      panel.splitter.show();
    } else {
      panel.$el.show();
    }

    $body.addClass('panelsVisible');

    if (panel.settings.show) {
      panel.settings.show.call(panel, true);
    }
    panel.controlButton.addClass('active');
    panel.visible = true;

    // update the splitter - but do it on the next tick
    // required to allow the splitter to see it's visible first
    setTimeout(function () {
      if (x !== undefined) {
        panel.splitter.trigger('init', x);
      } else {
        panel.distribute();
      }
      if (panel.editor) {
        // populate the panel for the first time
        if (panel.virgin) {
          $(panel.editor.win).find('.CodeMirror-scroll .CodeMirror-lines, .CodeMirror-gutter-text').css('padding-top', panel.$el.find('.label').outerHeight());

          populateEditor(panel, panel.name);
        }
        if (!panel.virgin) {
          panel.editor.focus();
          panel.focus();
        }
      }
      // update all splitter positions
      $document.trigger('sizeeditors');

      panel.virgin = false;
  }, 0);

    // TODO save which panels are visible in their profile - but check whether it's their code
  },
  hide: function () {
    var panel = this;
    // panel.$el.hide();
    panel.visible = false;
    analytics.hidePanel(panel.id);

    // update all splitter positions
    // LOGIC: when you go to hide, you need to check if there's
    // other panels inside the panel wrapper - if there are
    // hide the nested panel and any previous visible splitter
    // if there's only one - then hide the whole thing.
    // if (panel.splitter.length) {
    var panelCount = panel.$el.find('.panel').length;
    if (panelCount === 0 || panelCount > 1) {
      var $panel = $('.panel.' + panel.id).hide();
      $panel.prev().hide(); // hide the splitter if there is one

      // TODO trigger a distribute horizontally
      if ($panel.closest('.panelwrapper').find('.panel:visible').length === 0) {
        $panel.closest('.panelwrapper').hide();
        // panel.splitter.hide();
        // TODO FIXME
      }
    } else {
      panel.$el.hide();
      panel.splitter.hide();
    }
    // } else {
    //   panel.$el.hide();
    // }
    panel.controlButton.removeClass('active');
    panel.distribute();

    if (panel.settings.hide) {
      panel.settings.hide.call(panel, true);
    }

    // this.controlButton.show();
    setTimeout(function () {
      $document.trigger('sizeeditors');
    }, 110);
  },
  toggle: function () {
    (this)[this.visible ? 'hide' : 'show']();
  },
  getCode: function () {
    if (this.editor) {
      return this.editor.getCode();
    }
  },
  setCode: function (content) {
    if (this.editor) {
      this.codeSet = true;
      this.editor.setCode(content);
    }
  },
  codeSet: false,
  focus: function () {
    jsbin.panels.focus(this);
  },
  render: function () {
    var panel = this,
        ret = null;
    if (panel.editor) {
      return panel.processor(panel.getCode());
    } else if (this.visible && this.settings.render) {
      this.settings.render.apply(this, arguments);
    }
  },
  init: function () {
    if (this.settings.init) this.settings.init.call(this);
  },
  _setupEditor: function () {
    var focusedPanel = sessionStorage.getItem('panel'),
        panel = this,
        editor = panel.editor;

    // overhang from CodeMirror1
    editor.setCode = function (str) {
      //Cannot call method 'chunkSize' of undefined
      try {
        editor.setValue(str);
      } catch(err) {
        // console.error(panel.id, err + '');
      }
    };

    editor.getCode = function () {
      return editor.getValue();
    };

    editor.currentLine = function () {
      var pos = editor.getCursor();
      return pos.line;
    };

    // editor.setOption('onKeyEvent', keycontrol);
    // editor.setOption('onFocus', function () {
      // panel.$el.trigger('focus');
    // });

    editor.id = panel.name;

    editor.win = editor.getWrapperElement();
    editor.scroller = $(editor.getScrollerElement());

    $(editor.win).click(function () {
      editor.focus();
      panel.focus();
    });

    var $label = panel.$el.find('.label');
    if (document.body.className.indexOf('ie6') === -1 && $label.length) {
      editor.setOption('onScroll', function (event) {
        var scrollInfo = editor.getScrollInfo();
        if (scrollInfo.y > 10) {
          $label.stop().animate({ opacity: 0 }, 20, function () {
            $(this).hide();
          });
        } else {
          $label.show().stop().animate({ opacity: 1 }, 150);
        }
      });
    }

    var $error = null;
    $document.bind('sizeeditors', function () {
      if (panel.visible) {
        var height = panel.editor.scroller.closest('.panel').outerHeight(),
            offset = 0;
            // offset = panel.$el.find('> .label').outerHeight();

        // special case for the javascript panel
        if (panel.name === 'javascript') {
          if ($error === null) { // it wasn't there right away, so we populate
            $error = panel.$el.find('details');
          }
          offset += ($error.filter(':visible').height() || 0);
        }

        editor.scroller.height(height - offset);
        try { editor.refresh(); } catch (e) {}
      }
    });

    // required because the populate looks at the height, and at
    // this point in the code, the editor isn't visible, the browser
    // needs one more tick and it'll be there.
    setTimeout(function () {
      // if the panel isn't visible this only has the effect of putting
      // the code in the textarea (though probably costs us a lot more)
      // it has to be re-populated upon show for the first time because
      // it appears that CM2 uses the visible height to work out what
      // should be shown.
      panel.ready = true;
      populateEditor(panel, panel.name);

      if (focusedPanel == panel.name) {
        if (panel.visible) {
          // another fracking timeout to avoid conflict with other panels firing up
          setTimeout(function () {
            editor.focus();
            panel.focus();
            editor.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
          }, 0);
        }
      }
    }, 0);
  },
  populateEditor: function () {
    populateEditor(this, this.name);
  }
};

function populateEditor(editor, panel) {
  if (!editor.codeSet) {
    // populate - should eventually use: session, saved data, local storage
    var cached = sessionStorage.getItem('jsbin.content.' + panel), // session code
        saved = localStorage.getItem('saved-' + panel), // user template
        sessionURL = sessionStorage.getItem('url'),
        changed = false;

    if (sessionURL !== template.url) {
      // nuke the live saving checksum
      sessionStorage.removeItem('checksum');
      saveChecksum = false;
    }

    if (template && cached == template[panel]) { // restored from original saved
      editor.setCode(cached);
    } else if (cached && sessionURL == template.url) { // try to restore the session first - only if it matches this url
      editor.setCode(cached);
      // tell the document that it's currently being edited, but check that it doesn't match the saved template
      // because sessionStorage gets set on a reload
      changed = cached != saved && cached != template[panel];
    } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
      editor.setCode(saved);
    } else { // otherwise fall back on the JS Bin default
      editor.setCode(template[panel]);
    }
  } else {
    // this means it was set via the url
    changed = true;
  }

  if (changed) {
    $document.trigger('codeChange', [ { revert: false, onload: true } ]);
  }
}<commit_msg>Always select a panel if one is hidden<commit_after>var $document = $(document),
    $source = $('#source');

var editorModes = {
  html: 'htmlmixed',
  javascript: 'javascript',
  css: 'css'
};

var Panel = function (name, settings) {
  var panel = this,
      showPanelButton = true,
      $panel = null,
      splitterSettings = {},
      cmSettings = {};

  panel.settings = settings = settings || {};
  panel.id = panel.name = name;
  $panel = $('.panel.' + name);
  $panel.data('name', name);
  panel.$el = $panel.detach();
  panel.$el.appendTo($source);
  panel.$el.wrapAll('
');
  panel.$el = panel.$el.parent().hide();
  panel.el = document.getElementById(name);
  panel.order = ++Panel.order;

  panel.$el.data('panel', panel);

  // keyboard shortcut (set in keyboardcontrol.js)
  panelShortcuts[panelShortcuts.start + panel.order] = panel.id;

  if (panel.order === 1) {
    settings.nosplitter = true;
  }

  if (settings.editor) {
    cmSettings = {
      parserfile: [],
      tabMode: 'shift',
      readOnly: jsbin.state.embed ? 'nocursor' : false,
      dragDrop: false, // we handle it ourselves
      mode: editorModes[name],
      // lineNumbers: objectValue('jsbin.settings.editor.lineNumbers') || false,
      onChange: function (event) {
        $document.trigger('codeChange', [{ panelId: panel.id, revert: true }]);
        return true;
      },
      lineWrapping: true,
      theme: jsbin.settings.theme || 'jsbin'
    };

    $.extend(cmSettings, jsbin.settings.editor || {});

    panel.editor = CodeMirror.fromTextArea(panel.el, cmSettings);

    panel.processor = settings.processor || function (str) { return str; };

    panel._setupEditor(panel.editor, name);
  }

  if (!settings.nosplitter) {
    // console.log(panel.id, wrapper);
    panel.splitter = panel.$el.splitter(splitterSettings).data('splitter');
    panel.splitter.hide();
  } else {
    // create a fake splitter to let the rest of the code work
    panel.splitter = $();
  }

  if (settings.beforeRender) {
    $document.bind('render', $.proxy(settings.beforeRender, panel));
  }

  if (!settings.editor) {
    panel.ready = true;
  }

  // append panel to controls
  if (jsbin.state.embed) {
    // showPanelButton = window.location.search.indexOf(panel.id) !== -1;
  }

  if (showPanelButton) {
    this.controlButton = $('' + (settings.label || name) + '');
    this.controlButton.click(function () {
      panel.toggle();
      return false;
    });
    this.controlButton.appendTo('#panels');
  }

  $panel.focus(function () {
    panel.focus();
  });
  $panel.add(this.$el.find('.label')).click(function () {
    panel.focus();
  });
};

Panel.order = 0;

Panel.prototype = {
  virgin: true,
  visible: false,
  show: function (x) {
    // check to see if there's a panel to the left.
    // if there is, take it's size/2 and make this our
    // width
    var panel = this,
        panelCount = panel.$el.find('.panel').length;

    analytics.showPanel(panel.id);

    // panel.$el.show();
    if (panel.splitter.length) {
      if (panelCount === 0 || panelCount > 1) {
        var $panel = $('.panel.' + panel.id).show();
        // $panel.next().show(); // should be the splitter...
        $panel.closest('.panelwrapper').show();
      } else {
        panel.$el.show();
      }
      panel.splitter.show();
    } else {
      panel.$el.show();
    }

    $body.addClass('panelsVisible');

    if (panel.settings.show) {
      panel.settings.show.call(panel, true);
    }
    panel.controlButton.addClass('active');
    panel.visible = true;

    // update the splitter - but do it on the next tick
    // required to allow the splitter to see it's visible first
    setTimeout(function () {
      if (x !== undefined) {
        panel.splitter.trigger('init', x);
      } else {
        panel.distribute();
      }
      if (panel.editor) {
        // populate the panel for the first time
        if (panel.virgin) {
          $(panel.editor.win).find('.CodeMirror-scroll .CodeMirror-lines, .CodeMirror-gutter-text').css('padding-top', panel.$el.find('.label').outerHeight());

          populateEditor(panel, panel.name);
        }
        if (!panel.virgin || jsbin.panels.ready) {
          panel.editor.focus();
          panel.focus();
        }
      } else {
        panel.focus();
      }
      // update all splitter positions
      $document.trigger('sizeeditors');

      panel.virgin = false;
  }, 0);

    // TODO save which panels are visible in their profile - but check whether it's their code
  },
  hide: function () {
    var panel = this;
    // panel.$el.hide();
    panel.visible = false;
    analytics.hidePanel(panel.id);

    // update all splitter positions
    // LOGIC: when you go to hide, you need to check if there's
    // other panels inside the panel wrapper - if there are
    // hide the nested panel and any previous visible splitter
    // if there's only one - then hide the whole thing.
    // if (panel.splitter.length) {
    var panelCount = panel.$el.find('.panel').length;
    if (panelCount === 0 || panelCount > 1) {
      var $panel = $('.panel.' + panel.id).hide();
      $panel.prev().hide(); // hide the splitter if there is one

      // TODO trigger a distribute horizontally
      if ($panel.closest('.panelwrapper').find('.panel:visible').length === 0) {
        $panel.closest('.panelwrapper').hide();
        // panel.splitter.hide();
        // TODO FIXME
      }
    } else {
      panel.$el.hide();
      panel.splitter.hide();
    }
    // } else {
    //   panel.$el.hide();
    // }
    panel.controlButton.removeClass('active');
    panel.distribute();

    if (panel.settings.hide) {
      panel.settings.hide.call(panel, true);
    }

    // this.controlButton.show();
    setTimeout(function () {
      var visible = jsbin.panels.getVisible();
      if (visible.length) {
        jsbin.panels.focused = visible[0];
        if (jsbin.panels.focused.editor) {
          jsbin.panels.focused.editor.focus();
        } else {
          jsbin.panels.focused.$el.focus();
        }
        jsbin.panels.focused.focus();
      }

      $document.trigger('sizeeditors');
    }, 110);
  },
  toggle: function () {
    (this)[this.visible ? 'hide' : 'show']();
  },
  getCode: function () {
    if (this.editor) {
      return this.editor.getCode();
    }
  },
  setCode: function (content) {
    if (this.editor) {
      this.codeSet = true;
      this.editor.setCode(content);
    }
  },
  codeSet: false,
  focus: function () {
    jsbin.panels.focus(this);
  },
  render: function () {
    var panel = this,
        ret = null;
    if (panel.editor) {
      return panel.processor(panel.getCode());
    } else if (this.visible && this.settings.render) {
      this.settings.render.apply(this, arguments);
    }
  },
  init: function () {
    if (this.settings.init) this.settings.init.call(this);
  },
  _setupEditor: function () {
    var focusedPanel = sessionStorage.getItem('panel'),
        panel = this,
        editor = panel.editor;

    // overhang from CodeMirror1
    editor.setCode = function (str) {
      //Cannot call method 'chunkSize' of undefined
      try {
        editor.setValue(str);
      } catch(err) {
        // console.error(panel.id, err + '');
      }
    };

    editor.getCode = function () {
      return editor.getValue();
    };

    editor.currentLine = function () {
      var pos = editor.getCursor();
      return pos.line;
    };

    // editor.setOption('onKeyEvent', keycontrol);
    // editor.setOption('onFocus', function () {
      // panel.$el.trigger('focus');
    // });

    editor.id = panel.name;

    editor.win = editor.getWrapperElement();
    editor.scroller = $(editor.getScrollerElement());

    $(editor.win).click(function () {
      editor.focus();
      panel.focus();
    });

    var $label = panel.$el.find('.label');
    if (document.body.className.indexOf('ie6') === -1 && $label.length) {
      editor.setOption('onScroll', function (event) {
        var scrollInfo = editor.getScrollInfo();
        if (scrollInfo.y > 10) {
          $label.stop().animate({ opacity: 0 }, 20, function () {
            $(this).hide();
          });
        } else {
          $label.show().stop().animate({ opacity: 1 }, 150);
        }
      });
    }

    var $error = null;
    $document.bind('sizeeditors', function () {
      if (panel.visible) {
        var height = panel.editor.scroller.closest('.panel').outerHeight(),
            offset = 0;
            // offset = panel.$el.find('> .label').outerHeight();

        // special case for the javascript panel
        if (panel.name === 'javascript') {
          if ($error === null) { // it wasn't there right away, so we populate
            $error = panel.$el.find('details');
          }
          offset += ($error.filter(':visible').height() || 0);
        }

        editor.scroller.height(height - offset);
        try { editor.refresh(); } catch (e) {}
      }
    });

    // required because the populate looks at the height, and at
    // this point in the code, the editor isn't visible, the browser
    // needs one more tick and it'll be there.
    setTimeout(function () {
      // if the panel isn't visible this only has the effect of putting
      // the code in the textarea (though probably costs us a lot more)
      // it has to be re-populated upon show for the first time because
      // it appears that CM2 uses the visible height to work out what
      // should be shown.
      panel.ready = true;
      populateEditor(panel, panel.name);

      if (focusedPanel == panel.name) {
        if (panel.visible) {
          // another fracking timeout to avoid conflict with other panels firing up
          setTimeout(function () {
            editor.focus();
            panel.focus();
            editor.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
          }, 0);
        }
      }
    }, 0);
  },
  populateEditor: function () {
    populateEditor(this, this.name);
  }
};

function populateEditor(editor, panel) {
  if (!editor.codeSet) {
    // populate - should eventually use: session, saved data, local storage
    var cached = sessionStorage.getItem('jsbin.content.' + panel), // session code
        saved = localStorage.getItem('saved-' + panel), // user template
        sessionURL = sessionStorage.getItem('url'),
        changed = false;

    if (sessionURL !== template.url) {
      // nuke the live saving checksum
      sessionStorage.removeItem('checksum');
      saveChecksum = false;
    }

    if (template && cached == template[panel]) { // restored from original saved
      editor.setCode(cached);
    } else if (cached && sessionURL == template.url) { // try to restore the session first - only if it matches this url
      editor.setCode(cached);
      // tell the document that it's currently being edited, but check that it doesn't match the saved template
      // because sessionStorage gets set on a reload
      changed = cached != saved && cached != template[panel];
    } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
      editor.setCode(saved);
    } else { // otherwise fall back on the JS Bin default
      editor.setCode(template[panel]);
    }
  } else {
    // this means it was set via the url
    changed = true;
  }

  if (changed) {
    $document.trigger('codeChange', [ { revert: false, onload: true } ]);
  }
}<|endoftext|>