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

    angular
        .module('mturk.hit.controllers', [])
        .controller('HITController', HITController);

    HITController.$inject = ['$scope', '$state', '$mdToast', 'HIT', '$filter', '$sce', '$websocket', '$rootScope', '$stateParams', '$location'];

    function HITController($scope, $state, $mdToast, HIT, $filter, $sce, $websocket, $rootScope, $stateParams, $location) {
        var self = this;
        self.isAccepted = false;
        self.submit = submit;
        self.currentStatus = null;
        self.pk = null;
        self.MTURK_HOST = 'https://workersandbox.mturk.com/mturk/externalSubmit';
        self.getHost = getHost;
        self.showSubmit = showSubmit;
        self.showTruth = showTruth;
        self.submitMturk = submitMturk;
        self.showRejectForm = false;
        self.notAllowed = false;
        self.noErrors = false;
        self.rejectionReason = null;
        self.rejectionDetail = null;
        self.rejectHIT = rejectHIT;
        self.HITRejected = false;
        self.hasTruth = false;

        activate();

        self.reject_reason = {
            REASON_LOW_PAY: 1,
            REASON_INAPPROPRIATE: 2,
            OTHER: 3
        };

        function stringify(obj) {
          function flatten(obj) {
            if (_.isObject(obj)) {
              return _.sortBy(_.map(
                  _.pairs(obj),
                  function(p) { return [p[0], flatten(p[1])]; }
                ),
                function(p) { return p[0]; }
              );
            }
            return obj;
          }
          return JSON.stringify(flatten(obj));
        }

        function activate() {
            var hitId = $stateParams.hitId;
            var assignmentId = $stateParams.assignmentId;
            self.assignmentId = assignmentId;
            var workerId = $stateParams.workerId;
            var taskId = $stateParams.taskId;

            HIT.get_or_create(taskId, hitId, assignmentId, workerId).then(
                function success(response) {
                    self.taskData = response[0].task;
                    self.is_review = response[0].is_review;
                    self.HITRejected = response[0].is_rejected;
                    self.task_id = self.taskData.id;
                    self.pk = response[0].assignment;
                    self.isAccepted = assignmentId !== 'ASSIGNMENT_ID_NOT_AVAILABLE';
                    if (self.isAccepted) {
                        initializeWebSocket();
                    }
                    self.noErrors = true;
                },
                function error(response) {
                    if (response[1] == 403) {
                        self.notAllowed = true;
                        return;
                    }
                    self.noErrors = false;
                    $mdToast.showSimple('Something went wrong, please try again.');
                }
            ).finally(function () {
            });

            HIT.get_url().then(
                function success(response) {
                    self.MTURK_HOST = response[0].url;
                },
                function error(response) {
                    $mdToast.showSimple('Could not get worker host.');
                }
            ).finally(function () {

            });
        }

        function submit() {
            var itemsToSubmit = $filter('filter')(self.taskData.template.items, {role: 'input'});
            var itemAnswers = [];
            var missing = false;

            self.status = {
                RETURNED: 5,
                REJECTED: 4,
                ACCEPTED: 3,
                SUBMITTED: 2,
                CREATED: 1
            };

            var finalAnswer = {};

            angular.forEach(itemsToSubmit, function (obj) {
                if ((!obj.answer || obj.answer == "") && obj.type != 'checkbox') {
                    missing = true;
                }

                if (obj.type != 'checkbox') {
                    itemAnswers.push(
                        {
                            template_item: obj.id,
                            result: obj.answer || ""
                        }
                    );

                    finalAnswer[obj.name] = obj.answer || "";
                }
                else {
                    itemAnswers.push(
                        {
                            template_item: obj.id,
                            result: obj.aux_attributes.options
                        }
                    );

                    finalAnswer[obj.name] = obj.aux_attributes.options;
                }
            });

            if (missing) {
                $mdToast.showSimple('All fields are required.');
                return;
            }

            var requestData = {
                task: self.taskData.id,
                items: itemAnswers,
                worker_id: $stateParams.workerId,
                assignment_id: $stateParams.assignmentId,
                hit_id: $stateParams.hitId
            };

            HIT.submit_results(self.pk, requestData).then(
                function success(response, status) {
                    self.currentStatus = true;
                    var data = response[0];

                    if (data.hasOwnProperty("message") && data.message=="truth"){
                        self.hasTruth = true;

                        self.truth = {};
                        var truthAnswer = {};
                        var items = angular.copy(self.taskData.template.items);

                        self.truth.match = true;

                        self.truth.items = _.map(items, function (item){
                          if(item.role=='input'){
                              if (data.hasOwnProperty("truth") && data.truth.hasOwnProperty(item.name)){

                                  if(item.type != 'checkbox') {
                                      item.answer = data.truth[item.name];
                                      truthAnswer[item.name] = data.truth[item.name] || "";
                                  }else{
                                      var correctChoices = data.truth[item.name];

                                      item.aux_attributes.options = _.map(item.aux_attributes.options, function(option){
                                          delete option.answer;

                                          if(correctChoices.indexOf(option.value) >= 0){
                                              option.answer=true;
                                          }
                                          return option;
                                      });

                                      truthAnswer[item.name] = item.aux_attributes.options;
                                  }
                              }
                          }

                          return item;
                        });

                        console.log(finalAnswer);
                        console.log(truthAnswer);

                        console.log(stringify(finalAnswer));
                        console.log(stringify(truthAnswer));
                        console.log(stringify(finalAnswer)===stringify(truthAnswer));

                        submitMturk(false);

                    }else {
                       submitMturk(true);
                    }
                },
                function error(data, status) {
                    $mdToast.showSimple('Could not submit task!');

                }).finally(function () {
                }
            );
        }

        function getHost() {
            return $sce.trustAsResourceUrl(self.MTURK_HOST);
        }

        function showSubmit() {
            if (self.isAccepted && !self.currentStatus) {
                return $filter('filter')(self.taskData.template.items, {role: 'input'}).length > 0 && self.noErrors;
            }
            return false;
        }

        function showTruth() {
           return self.isAccepted && self.currentStatus && self.hasTruth;
        }

        function submitMturk(refresh) {
            $('#mturkForm').submit(function () {
                return refresh;
            });
        }

        function initializeWebSocket() {
            self.ws = $websocket.$new({
                url: $rootScope.getWebsocketUrl() + '/ws/external?subscribe-broadcast',
                lazy: true,
                reconnect: true
            });

            self.ws
                .$on('$message', function (data) {
                    receiveMessage(data);
                })
                .$on('$close', function () {

                })
                .$on('$open', function () {
                    console.log('opened');
                })
                .$open();
        }

        function receiveMessage(data) {
            if (!self.taskData) {
                return;
            }
            var message = JSON.parse(data);
            if ($location.search().taskId != message.task_id) return;
            var inputItems = $filter('filter')(self.taskData.template.items, {role: 'input'});
            var remoteContentItems = $filter('filter')(self.taskData.template.items, {type: 'iframe'});
            var item = $filter('filter')(self.taskData.template.items, {id: message.template_item});
            if (inputItems.length == 0 && item.length && item[0].aux_attributes.src.indexOf(message.daemo_id) > 0) {
                item[0].isSubmitted = true;
                var submitted = $filter('filter')(self.taskData.template.items, {
                    isSubmitted: true,
                    type: 'iframe'
                });
                if (remoteContentItems.length == submitted.length) {
                    self.submit();
                }
            }
            $scope.$apply();
        }

        function rejectHIT() {
            if (!self.rejectionReason) {
                $mdToast.showSimple('Please choose a reason');
                return;
            }

            if (self.rejectionReason == self.reject_reason.OTHER && (!self.rejectionDetail || self.rejectionDetail == '')) {
                $mdToast.showSimple('Please provide details for flagging');
                return;
            }

            var request_data = {
                worker_id: $stateParams.workerId,
                assignment_id: $stateParams.assignmentId,
                hit_id: $stateParams.hitId,
                reason: self.rejectionReason,
                detail: self.rejectionDetail
            };

            HIT.reject(self.pk, request_data).then(
                function success(data, status) {
                    self.HITRejected = true;
                },
                function error(data, status) {
                    $mdToast.showSimple("Could not reject HIT!");
                }).finally(function () {
                }
            );
        }
    }
})
();

<commit_msg>remove angular properties<commit_after>(function () {
    'use strict';

    angular
        .module('mturk.hit.controllers', [])
        .controller('HITController', HITController);

    HITController.$inject = ['$scope', '$state', '$mdToast', 'HIT', '$filter', '$sce', '$websocket', '$rootScope', '$stateParams', '$location'];

    function HITController($scope, $state, $mdToast, HIT, $filter, $sce, $websocket, $rootScope, $stateParams, $location) {
        var self = this;
        self.isAccepted = false;
        self.submit = submit;
        self.currentStatus = null;
        self.pk = null;
        self.MTURK_HOST = 'https://workersandbox.mturk.com/mturk/externalSubmit';
        self.getHost = getHost;
        self.showSubmit = showSubmit;
        self.showTruth = showTruth;
        self.submitMturk = submitMturk;
        self.showRejectForm = false;
        self.notAllowed = false;
        self.noErrors = false;
        self.rejectionReason = null;
        self.rejectionDetail = null;
        self.rejectHIT = rejectHIT;
        self.HITRejected = false;
        self.hasTruth = false;

        activate();

        self.reject_reason = {
            REASON_LOW_PAY: 1,
            REASON_INAPPROPRIATE: 2,
            OTHER: 3
        };

        function stringify(obj) {
          function flatten(obj) {
            if (_.isObject(obj)) {
              return _.sortBy(_.map(
                  _.pairs(obj),
                  function(p) { return [p[0], flatten(p[1])]; }
                ),
                function(p) { return p[0]; }
              );
            }
            return obj;
          }

          var converted = JSON.parse(angular.toJson(obj));
          return JSON.stringify(flatten(converted));
        }

        function activate() {
            var hitId = $stateParams.hitId;
            var assignmentId = $stateParams.assignmentId;
            self.assignmentId = assignmentId;
            var workerId = $stateParams.workerId;
            var taskId = $stateParams.taskId;

            HIT.get_or_create(taskId, hitId, assignmentId, workerId).then(
                function success(response) {
                    self.taskData = response[0].task;
                    self.is_review = response[0].is_review;
                    self.HITRejected = response[0].is_rejected;
                    self.task_id = self.taskData.id;
                    self.pk = response[0].assignment;
                    self.isAccepted = assignmentId !== 'ASSIGNMENT_ID_NOT_AVAILABLE';
                    if (self.isAccepted) {
                        initializeWebSocket();
                    }
                    self.noErrors = true;
                },
                function error(response) {
                    if (response[1] == 403) {
                        self.notAllowed = true;
                        return;
                    }
                    self.noErrors = false;
                    $mdToast.showSimple('Something went wrong, please try again.');
                }
            ).finally(function () {
            });

            HIT.get_url().then(
                function success(response) {
                    self.MTURK_HOST = response[0].url;
                },
                function error(response) {
                    $mdToast.showSimple('Could not get worker host.');
                }
            ).finally(function () {

            });
        }

        function submit() {
            var itemsToSubmit = $filter('filter')(self.taskData.template.items, {role: 'input'});
            var itemAnswers = [];
            var missing = false;

            self.status = {
                RETURNED: 5,
                REJECTED: 4,
                ACCEPTED: 3,
                SUBMITTED: 2,
                CREATED: 1
            };

            var finalAnswer = {};

            angular.forEach(itemsToSubmit, function (obj) {
                if ((!obj.answer || obj.answer == "") && obj.type != 'checkbox') {
                    missing = true;
                }

                if (obj.type != 'checkbox') {
                    itemAnswers.push(
                        {
                            template_item: obj.id,
                            result: obj.answer || ""
                        }
                    );

                    finalAnswer[obj.name] = obj.answer || "";
                }
                else {
                    itemAnswers.push(
                        {
                            template_item: obj.id,
                            result: obj.aux_attributes.options
                        }
                    );

                    finalAnswer[obj.name] = obj.aux_attributes.options;
                }
            });

            if (missing) {
                $mdToast.showSimple('All fields are required.');
                return;
            }

            var requestData = {
                task: self.taskData.id,
                items: itemAnswers,
                worker_id: $stateParams.workerId,
                assignment_id: $stateParams.assignmentId,
                hit_id: $stateParams.hitId
            };

            HIT.submit_results(self.pk, requestData).then(
                function success(response, status) {
                    self.currentStatus = true;
                    var data = response[0];

                    if (data.hasOwnProperty("message") && data.message=="truth"){
                        self.hasTruth = true;

                        self.truth = {};
                        var truthAnswer = {};
                        var items = angular.copy(self.taskData.template.items);

                        self.truth.match = true;

                        self.truth.items = _.map(items, function (item){
                          if(item.role=='input'){
                              if (data.hasOwnProperty("truth") && data.truth.hasOwnProperty(item.name)){

                                  if(item.type != 'checkbox') {
                                      item.answer = data.truth[item.name];
                                      truthAnswer[item.name] = data.truth[item.name] || "";
                                  }else{
                                      var correctChoices = data.truth[item.name];

                                      item.aux_attributes.options = _.map(item.aux_attributes.options, function(option){
                                          delete option.answer;

                                          if(correctChoices.indexOf(option.value) >= 0){
                                              option.answer=true;
                                          }
                                          return option;
                                      });

                                      truthAnswer[item.name] = item.aux_attributes.options;
                                  }
                              }
                          }

                          return item;
                        });

                        console.log(finalAnswer);
                        console.log(truthAnswer);

                        console.log(stringify(finalAnswer));
                        console.log(stringify(truthAnswer));
                        console.log(stringify(finalAnswer)===stringify(truthAnswer));

                        submitMturk(false);

                    }else {
                       submitMturk(true);
                    }
                },
                function error(data, status) {
                    $mdToast.showSimple('Could not submit task!');

                }).finally(function () {
                }
            );
        }

        function getHost() {
            return $sce.trustAsResourceUrl(self.MTURK_HOST);
        }

        function showSubmit() {
            if (self.isAccepted && !self.currentStatus) {
                return $filter('filter')(self.taskData.template.items, {role: 'input'}).length > 0 && self.noErrors;
            }
            return false;
        }

        function showTruth() {
           return self.isAccepted && self.currentStatus && self.hasTruth;
        }

        function submitMturk(refresh) {
            $('#mturkForm').submit(function () {
                return refresh;
            });
        }

        function initializeWebSocket() {
            self.ws = $websocket.$new({
                url: $rootScope.getWebsocketUrl() + '/ws/external?subscribe-broadcast',
                lazy: true,
                reconnect: true
            });

            self.ws
                .$on('$message', function (data) {
                    receiveMessage(data);
                })
                .$on('$close', function () {

                })
                .$on('$open', function () {
                    console.log('opened');
                })
                .$open();
        }

        function receiveMessage(data) {
            if (!self.taskData) {
                return;
            }
            var message = JSON.parse(data);
            if ($location.search().taskId != message.task_id) return;
            var inputItems = $filter('filter')(self.taskData.template.items, {role: 'input'});
            var remoteContentItems = $filter('filter')(self.taskData.template.items, {type: 'iframe'});
            var item = $filter('filter')(self.taskData.template.items, {id: message.template_item});
            if (inputItems.length == 0 && item.length && item[0].aux_attributes.src.indexOf(message.daemo_id) > 0) {
                item[0].isSubmitted = true;
                var submitted = $filter('filter')(self.taskData.template.items, {
                    isSubmitted: true,
                    type: 'iframe'
                });
                if (remoteContentItems.length == submitted.length) {
                    self.submit();
                }
            }
            $scope.$apply();
        }

        function rejectHIT() {
            if (!self.rejectionReason) {
                $mdToast.showSimple('Please choose a reason');
                return;
            }

            if (self.rejectionReason == self.reject_reason.OTHER && (!self.rejectionDetail || self.rejectionDetail == '')) {
                $mdToast.showSimple('Please provide details for flagging');
                return;
            }

            var request_data = {
                worker_id: $stateParams.workerId,
                assignment_id: $stateParams.assignmentId,
                hit_id: $stateParams.hitId,
                reason: self.rejectionReason,
                detail: self.rejectionDetail
            };

            HIT.reject(self.pk, request_data).then(
                function success(data, status) {
                    self.HITRejected = true;
                },
                function error(data, status) {
                    $mdToast.showSimple("Could not reject HIT!");
                }).finally(function () {
                }
            );
        }
    }
})
();

<|endoftext|>


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

/**
 * @fileoverview Events fired as a result of actions in Blockly's editor.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

/**
 * Events fired as a result of actions in Blockly's editor.
 * @namespace Blockly.Events
 */
goog.provide('Blockly.Events');

goog.require('Blockly.utils');

/**
 * Group ID for new events.  Grouped events are indivisible.
 * @type {string}
 * @private
 */
Blockly.Events.group_ = '';

/**
 * Sets whether the next event should be added to the undo stack.
 * @type {boolean}
 */
Blockly.Events.recordUndo = true;

/**
 * Allow change events to be created and fired.
 * @type {number}
 * @private
 */
Blockly.Events.disabled_ = 0;

/**
 * Name of event that creates a block. Will be deprecated for BLOCK_CREATE.
 * @const
 */
Blockly.Events.CREATE = 'create';

/**
 * Name of event that creates a block.
 * @const
 */
Blockly.Events.BLOCK_CREATE = Blockly.Events.CREATE;

/**
 * Name of event that deletes a block. Will be deprecated for BLOCK_DELETE.
 * @const
 */
Blockly.Events.DELETE = 'delete';

/**
 * Name of event that deletes a block.
 * @const
 */
Blockly.Events.BLOCK_DELETE = Blockly.Events.DELETE;

/**
 * Name of event that changes a block. Will be deprecated for BLOCK_CHANGE.
 * @const
 */
Blockly.Events.CHANGE = 'change';

/**
 * Name of event that changes a block.
 * @const
 */
Blockly.Events.BLOCK_CHANGE = Blockly.Events.CHANGE;

/**
 * Name of event that moves a block. Will be deprecated for BLOCK_MOVE.
 * @const
 */
Blockly.Events.MOVE = 'move';

/**
 * Name of event that moves a block.
 * @const
 */
Blockly.Events.BLOCK_MOVE = Blockly.Events.MOVE;

/**
 * Name of event that creates a variable.
 * @const
 */
Blockly.Events.VAR_CREATE = 'var_create';

/**
 * Name of event that deletes a variable.
 * @const
 */
Blockly.Events.VAR_DELETE = 'var_delete';

/**
 * Name of event that renames a variable.
 * @const
 */
Blockly.Events.VAR_RENAME = 'var_rename';

/**
 * Name of event that records a UI change.
 * @const
 */
Blockly.Events.UI = 'ui';

/**
 * Name of event that creates a comment.
 * @const
 */
Blockly.Events.COMMENT_CREATE = 'comment_create';

/**
 * Name of event that deletes a comment.
 * @const
 */
Blockly.Events.COMMENT_DELETE = 'comment_delete';

/**
 * Name of event that changes a comment.
 * @const
 */
Blockly.Events.COMMENT_CHANGE = 'comment_change';

/**
 * Name of event that moves a comment.
 * @const
 */
Blockly.Events.COMMENT_MOVE = 'comment_move';

/**
 * Name of event that records a workspace load.
 */
Blockly.Events.FINISHED_LOADING = 'finished_loading';

/**
 * List of events that cause objects to be bumped back into the visible
 * portion of the workspace (only used for non-movable workspaces).
 *
 * Not to be confused with bumping so that disconnected connections to do
 * not appear connected.
 * @const
 */
Blockly.Events.BUMP_EVENTS = [
  Blockly.Events.BLOCK_CREATE,
  Blockly.Events.BLOCK_MOVE,
  Blockly.Events.COMMENT_CREATE,
  Blockly.Events.COMMENT_MOVE
];

/**
 * List of events queued for firing.
 * @private
 */
Blockly.Events.FIRE_QUEUE_ = [];

/**
 * Create a custom event and fire it.
 * @param {!Blockly.Events.Abstract} event Custom data for event.
 */
Blockly.Events.fire = function(event) {
  if (!Blockly.Events.isEnabled()) {
    return;
  }
  if (!Blockly.Events.FIRE_QUEUE_.length) {
    // First event added; schedule a firing of the event queue.
    setTimeout(Blockly.Events.fireNow_, 0);
  }
  Blockly.Events.FIRE_QUEUE_.push(event);
};

/**
 * Fire all queued events.
 * @private
 */
Blockly.Events.fireNow_ = function() {
  var queue = Blockly.Events.filter(Blockly.Events.FIRE_QUEUE_, true);
  Blockly.Events.FIRE_QUEUE_.length = 0;
  for (var i = 0, event; event = queue[i]; i++) {
    var workspace = Blockly.Workspace.getById(event.workspaceId);
    if (workspace) {
      workspace.fireChangeListener(event);
    }
  }
};

/**
 * Filter the queued events and merge duplicates.
 * @param {!Array.<!Blockly.Events.Abstract>} queueIn Array of events.
 * @param {boolean} forward True if forward (redo), false if backward (undo).
 * @return {!Array.<!Blockly.Events.Abstract>} Array of filtered events.
 */
Blockly.Events.filter = function(queueIn, forward) {
  var queue = queueIn.slice();  // Shallow copy of queue.
  if (!forward) {
    // Undo is merged in reverse order.
    queue.reverse();
  }
  var mergedQueue = [];
  var hash = Object.create(null);
  // Merge duplicates.
  for (var i = 0, event; event = queue[i]; i++) {
    if (!event.isNull()) {
      var key = [event.type, event.blockId, event.workspaceId].join(' ');

      var lastEntry = hash[key];
      var lastEvent = lastEntry ? lastEntry.event : null;
      if (!lastEntry) {
        // Each item in the hash table has the event and the index of that event
        // in the input array.  This lets us make sure we only merge adjacent
        // move events.
        hash[key] = { event: event, index: i};
        mergedQueue.push(event);
      } else if (event.type == Blockly.Events.MOVE &&
          lastEntry.index == i - 1) {
        // Merge move events.
        lastEvent.newParentId = event.newParentId;
        lastEvent.newInputName = event.newInputName;
        lastEvent.newCoordinate = event.newCoordinate;
        lastEntry.index = i;
      } else if (event.type == Blockly.Events.CHANGE &&
          event.element == lastEvent.element &&
          event.name == lastEvent.name) {
        // Merge change events.
        lastEvent.newValue = event.newValue;
      } else if (event.type == Blockly.Events.UI &&
          event.element == 'click' &&
          (lastEvent.element == 'commentOpen' ||
           lastEvent.element == 'mutatorOpen' ||
           lastEvent.element == 'warningOpen')) {
        // Drop click events caused by opening/closing bubbles.
      } else {
        // Collision: newer events should merge into this event to maintain
        // order.
        hash[key] = {event: event, index: 1};
        mergedQueue.push(event);
      }
    }
  }
  // Filter out any events that have become null due to merging.
  queue = mergedQueue.filter(function(e) { return !e.isNull(); });
  if (!forward) {
    // Restore undo order.
    queue.reverse();
  }
  // Move mutation events to the top of the queue.
  // Intentionally skip first event.
  for (var i = 1, event; event = queue[i]; i++) {
    if (event.type == Blockly.Events.CHANGE &&
        event.element == 'mutation') {
      queue.unshift(queue.splice(i, 1)[0]);
    }
  }
  return queue;
};

/**
 * Modify pending undo events so that when they are fired they don't land
 * in the undo stack.  Called by Blockly.Workspace.clearUndo.
 */
Blockly.Events.clearPendingUndo = function() {
  for (var i = 0, event; event = Blockly.Events.FIRE_QUEUE_[i]; i++) {
    event.recordUndo = false;
  }
};

/**
 * Stop sending events.  Every call to this function MUST also call enable.
 */
Blockly.Events.disable = function() {
  Blockly.Events.disabled_++;
};

/**
 * Start sending events.  Unless events were already disabled when the
 * corresponding call to disable was made.
 */
Blockly.Events.enable = function() {
  Blockly.Events.disabled_--;
};

/**
 * Returns whether events may be fired or not.
 * @return {boolean} True if enabled.
 */
Blockly.Events.isEnabled = function() {
  return Blockly.Events.disabled_ == 0;
};

/**
 * Current group.
 * @return {string} ID string.
 */
Blockly.Events.getGroup = function() {
  return Blockly.Events.group_;
};

/**
 * Start or stop a group.
 * @param {boolean|string} state True to start new group, false to end group.
 *   String to set group explicitly.
 */
Blockly.Events.setGroup = function(state) {
  if (typeof state == 'boolean') {
    Blockly.Events.group_ = state ? Blockly.utils.genUid() : '';
  } else {
    Blockly.Events.group_ = state;
  }
};

/**
 * Compute a list of the IDs of the specified block and all its descendants.
 * @param {!Blockly.Block} block The root block.
 * @return {!Array.<string>} List of block IDs.
 * @private
 */
Blockly.Events.getDescendantIds_ = function(block) {
  var ids = [];
  var descendants = block.getDescendants(false);
  for (var i = 0, descendant; descendant = descendants[i]; i++) {
    ids[i] = descendant.id;
  }
  return ids;
};

/**
 * Decode the JSON into an event.
 * @param {!Object} json JSON representation.
 * @param {!Blockly.Workspace} workspace Target workspace for event.
 * @return {!Blockly.Events.Abstract} The event represented by the JSON.
 */
Blockly.Events.fromJson = function(json, workspace) {
  // TODO: Should I have a way to register a new event into here?
  var event;
  switch (json.type) {
    case Blockly.Events.CREATE:
      event = new Blockly.Events.Create(null);
      break;
    case Blockly.Events.DELETE:
      event = new Blockly.Events.Delete(null);
      break;
    case Blockly.Events.CHANGE:
      event = new Blockly.Events.Change(null, '', '', '', '');
      break;
    case Blockly.Events.MOVE:
      event = new Blockly.Events.Move(null);
      break;
    case Blockly.Events.VAR_CREATE:
      event = new Blockly.Events.VarCreate(null);
      break;
    case Blockly.Events.VAR_DELETE:
      event = new Blockly.Events.VarDelete(null);
      break;
    case Blockly.Events.VAR_RENAME:
      event = new Blockly.Events.VarRename(null, '');
      break;
    case Blockly.Events.UI:
      event = new Blockly.Events.Ui(null);
      break;
    case Blockly.Events.COMMENT_CREATE:
      event = new Blockly.Events.CommentCreate(null);
      break;
    case Blockly.Events.COMMENT_CHANGE:
      event = new Blockly.Events.CommentChange(null);
      break;
    case Blockly.Events.COMMENT_MOVE:
      event = new Blockly.Events.CommentMove(null);
      break;
    case Blockly.Events.COMMENT_DELETE:
      event = new Blockly.Events.CommentDelete(null);
      break;
    default:
      throw Error('Unknown event type.');
  }
  event.fromJson(json);
  event.workspaceId = workspace.id;
  return event;
};

/**
 * Enable/disable a block depending on whether it is properly connected.
 * Use this on applications where all blocks should be connected to a top block.
 * Recommend setting the 'disable' option to 'false' in the config so that
 * users don't try to reenable disabled orphan blocks.
 * @param {!Blockly.Events.Abstract} event Custom data for event.
 */
Blockly.Events.disableOrphans = function(event) {
  if (event.type == Blockly.Events.MOVE ||
      event.type == Blockly.Events.CREATE) {
    var workspace = Blockly.Workspace.getById(event.workspaceId);
    var block = workspace.getBlockById(event.blockId);
    if (block) {
      var parent = block.getParent()
      if (parent && parent.isEnabled()) {
        var children = block.getDescendants(false);
        for (var i = 0, child; child = children[i]; i++) {
          child.setEnabled(true);
        }
      } else if ((block.outputConnection || block.previousConnection) &&
                 !workspace.isDragging()) {
        do {
          block.setEnabled(false);
          block = block.getNextBlock();
        } while (block);
      }
    }
  }
};
<commit_msg>Missing semicolon<commit_after>/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2016 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Events fired as a result of actions in Blockly's editor.
 * @author fraser@google.com (Neil Fraser)
 */
'use strict';

/**
 * Events fired as a result of actions in Blockly's editor.
 * @namespace Blockly.Events
 */
goog.provide('Blockly.Events');

goog.require('Blockly.utils');

/**
 * Group ID for new events.  Grouped events are indivisible.
 * @type {string}
 * @private
 */
Blockly.Events.group_ = '';

/**
 * Sets whether the next event should be added to the undo stack.
 * @type {boolean}
 */
Blockly.Events.recordUndo = true;

/**
 * Allow change events to be created and fired.
 * @type {number}
 * @private
 */
Blockly.Events.disabled_ = 0;

/**
 * Name of event that creates a block. Will be deprecated for BLOCK_CREATE.
 * @const
 */
Blockly.Events.CREATE = 'create';

/**
 * Name of event that creates a block.
 * @const
 */
Blockly.Events.BLOCK_CREATE = Blockly.Events.CREATE;

/**
 * Name of event that deletes a block. Will be deprecated for BLOCK_DELETE.
 * @const
 */
Blockly.Events.DELETE = 'delete';

/**
 * Name of event that deletes a block.
 * @const
 */
Blockly.Events.BLOCK_DELETE = Blockly.Events.DELETE;

/**
 * Name of event that changes a block. Will be deprecated for BLOCK_CHANGE.
 * @const
 */
Blockly.Events.CHANGE = 'change';

/**
 * Name of event that changes a block.
 * @const
 */
Blockly.Events.BLOCK_CHANGE = Blockly.Events.CHANGE;

/**
 * Name of event that moves a block. Will be deprecated for BLOCK_MOVE.
 * @const
 */
Blockly.Events.MOVE = 'move';

/**
 * Name of event that moves a block.
 * @const
 */
Blockly.Events.BLOCK_MOVE = Blockly.Events.MOVE;

/**
 * Name of event that creates a variable.
 * @const
 */
Blockly.Events.VAR_CREATE = 'var_create';

/**
 * Name of event that deletes a variable.
 * @const
 */
Blockly.Events.VAR_DELETE = 'var_delete';

/**
 * Name of event that renames a variable.
 * @const
 */
Blockly.Events.VAR_RENAME = 'var_rename';

/**
 * Name of event that records a UI change.
 * @const
 */
Blockly.Events.UI = 'ui';

/**
 * Name of event that creates a comment.
 * @const
 */
Blockly.Events.COMMENT_CREATE = 'comment_create';

/**
 * Name of event that deletes a comment.
 * @const
 */
Blockly.Events.COMMENT_DELETE = 'comment_delete';

/**
 * Name of event that changes a comment.
 * @const
 */
Blockly.Events.COMMENT_CHANGE = 'comment_change';

/**
 * Name of event that moves a comment.
 * @const
 */
Blockly.Events.COMMENT_MOVE = 'comment_move';

/**
 * Name of event that records a workspace load.
 */
Blockly.Events.FINISHED_LOADING = 'finished_loading';

/**
 * List of events that cause objects to be bumped back into the visible
 * portion of the workspace (only used for non-movable workspaces).
 *
 * Not to be confused with bumping so that disconnected connections to do
 * not appear connected.
 * @const
 */
Blockly.Events.BUMP_EVENTS = [
  Blockly.Events.BLOCK_CREATE,
  Blockly.Events.BLOCK_MOVE,
  Blockly.Events.COMMENT_CREATE,
  Blockly.Events.COMMENT_MOVE
];

/**
 * List of events queued for firing.
 * @private
 */
Blockly.Events.FIRE_QUEUE_ = [];

/**
 * Create a custom event and fire it.
 * @param {!Blockly.Events.Abstract} event Custom data for event.
 */
Blockly.Events.fire = function(event) {
  if (!Blockly.Events.isEnabled()) {
    return;
  }
  if (!Blockly.Events.FIRE_QUEUE_.length) {
    // First event added; schedule a firing of the event queue.
    setTimeout(Blockly.Events.fireNow_, 0);
  }
  Blockly.Events.FIRE_QUEUE_.push(event);
};

/**
 * Fire all queued events.
 * @private
 */
Blockly.Events.fireNow_ = function() {
  var queue = Blockly.Events.filter(Blockly.Events.FIRE_QUEUE_, true);
  Blockly.Events.FIRE_QUEUE_.length = 0;
  for (var i = 0, event; event = queue[i]; i++) {
    var workspace = Blockly.Workspace.getById(event.workspaceId);
    if (workspace) {
      workspace.fireChangeListener(event);
    }
  }
};

/**
 * Filter the queued events and merge duplicates.
 * @param {!Array.<!Blockly.Events.Abstract>} queueIn Array of events.
 * @param {boolean} forward True if forward (redo), false if backward (undo).
 * @return {!Array.<!Blockly.Events.Abstract>} Array of filtered events.
 */
Blockly.Events.filter = function(queueIn, forward) {
  var queue = queueIn.slice();  // Shallow copy of queue.
  if (!forward) {
    // Undo is merged in reverse order.
    queue.reverse();
  }
  var mergedQueue = [];
  var hash = Object.create(null);
  // Merge duplicates.
  for (var i = 0, event; event = queue[i]; i++) {
    if (!event.isNull()) {
      var key = [event.type, event.blockId, event.workspaceId].join(' ');

      var lastEntry = hash[key];
      var lastEvent = lastEntry ? lastEntry.event : null;
      if (!lastEntry) {
        // Each item in the hash table has the event and the index of that event
        // in the input array.  This lets us make sure we only merge adjacent
        // move events.
        hash[key] = { event: event, index: i};
        mergedQueue.push(event);
      } else if (event.type == Blockly.Events.MOVE &&
          lastEntry.index == i - 1) {
        // Merge move events.
        lastEvent.newParentId = event.newParentId;
        lastEvent.newInputName = event.newInputName;
        lastEvent.newCoordinate = event.newCoordinate;
        lastEntry.index = i;
      } else if (event.type == Blockly.Events.CHANGE &&
          event.element == lastEvent.element &&
          event.name == lastEvent.name) {
        // Merge change events.
        lastEvent.newValue = event.newValue;
      } else if (event.type == Blockly.Events.UI &&
          event.element == 'click' &&
          (lastEvent.element == 'commentOpen' ||
           lastEvent.element == 'mutatorOpen' ||
           lastEvent.element == 'warningOpen')) {
        // Drop click events caused by opening/closing bubbles.
      } else {
        // Collision: newer events should merge into this event to maintain
        // order.
        hash[key] = {event: event, index: 1};
        mergedQueue.push(event);
      }
    }
  }
  // Filter out any events that have become null due to merging.
  queue = mergedQueue.filter(function(e) { return !e.isNull(); });
  if (!forward) {
    // Restore undo order.
    queue.reverse();
  }
  // Move mutation events to the top of the queue.
  // Intentionally skip first event.
  for (var i = 1, event; event = queue[i]; i++) {
    if (event.type == Blockly.Events.CHANGE &&
        event.element == 'mutation') {
      queue.unshift(queue.splice(i, 1)[0]);
    }
  }
  return queue;
};

/**
 * Modify pending undo events so that when they are fired they don't land
 * in the undo stack.  Called by Blockly.Workspace.clearUndo.
 */
Blockly.Events.clearPendingUndo = function() {
  for (var i = 0, event; event = Blockly.Events.FIRE_QUEUE_[i]; i++) {
    event.recordUndo = false;
  }
};

/**
 * Stop sending events.  Every call to this function MUST also call enable.
 */
Blockly.Events.disable = function() {
  Blockly.Events.disabled_++;
};

/**
 * Start sending events.  Unless events were already disabled when the
 * corresponding call to disable was made.
 */
Blockly.Events.enable = function() {
  Blockly.Events.disabled_--;
};

/**
 * Returns whether events may be fired or not.
 * @return {boolean} True if enabled.
 */
Blockly.Events.isEnabled = function() {
  return Blockly.Events.disabled_ == 0;
};

/**
 * Current group.
 * @return {string} ID string.
 */
Blockly.Events.getGroup = function() {
  return Blockly.Events.group_;
};

/**
 * Start or stop a group.
 * @param {boolean|string} state True to start new group, false to end group.
 *   String to set group explicitly.
 */
Blockly.Events.setGroup = function(state) {
  if (typeof state == 'boolean') {
    Blockly.Events.group_ = state ? Blockly.utils.genUid() : '';
  } else {
    Blockly.Events.group_ = state;
  }
};

/**
 * Compute a list of the IDs of the specified block and all its descendants.
 * @param {!Blockly.Block} block The root block.
 * @return {!Array.<string>} List of block IDs.
 * @private
 */
Blockly.Events.getDescendantIds_ = function(block) {
  var ids = [];
  var descendants = block.getDescendants(false);
  for (var i = 0, descendant; descendant = descendants[i]; i++) {
    ids[i] = descendant.id;
  }
  return ids;
};

/**
 * Decode the JSON into an event.
 * @param {!Object} json JSON representation.
 * @param {!Blockly.Workspace} workspace Target workspace for event.
 * @return {!Blockly.Events.Abstract} The event represented by the JSON.
 */
Blockly.Events.fromJson = function(json, workspace) {
  // TODO: Should I have a way to register a new event into here?
  var event;
  switch (json.type) {
    case Blockly.Events.CREATE:
      event = new Blockly.Events.Create(null);
      break;
    case Blockly.Events.DELETE:
      event = new Blockly.Events.Delete(null);
      break;
    case Blockly.Events.CHANGE:
      event = new Blockly.Events.Change(null, '', '', '', '');
      break;
    case Blockly.Events.MOVE:
      event = new Blockly.Events.Move(null);
      break;
    case Blockly.Events.VAR_CREATE:
      event = new Blockly.Events.VarCreate(null);
      break;
    case Blockly.Events.VAR_DELETE:
      event = new Blockly.Events.VarDelete(null);
      break;
    case Blockly.Events.VAR_RENAME:
      event = new Blockly.Events.VarRename(null, '');
      break;
    case Blockly.Events.UI:
      event = new Blockly.Events.Ui(null);
      break;
    case Blockly.Events.COMMENT_CREATE:
      event = new Blockly.Events.CommentCreate(null);
      break;
    case Blockly.Events.COMMENT_CHANGE:
      event = new Blockly.Events.CommentChange(null);
      break;
    case Blockly.Events.COMMENT_MOVE:
      event = new Blockly.Events.CommentMove(null);
      break;
    case Blockly.Events.COMMENT_DELETE:
      event = new Blockly.Events.CommentDelete(null);
      break;
    default:
      throw Error('Unknown event type.');
  }
  event.fromJson(json);
  event.workspaceId = workspace.id;
  return event;
};

/**
 * Enable/disable a block depending on whether it is properly connected.
 * Use this on applications where all blocks should be connected to a top block.
 * Recommend setting the 'disable' option to 'false' in the config so that
 * users don't try to re-enable disabled orphan blocks.
 * @param {!Blockly.Events.Abstract} event Custom data for event.
 */
Blockly.Events.disableOrphans = function(event) {
  if (event.type == Blockly.Events.MOVE ||
      event.type == Blockly.Events.CREATE) {
    var workspace = Blockly.Workspace.getById(event.workspaceId);
    var block = workspace.getBlockById(event.blockId);
    if (block) {
      var parent = block.getParent();
      if (parent && parent.isEnabled()) {
        var children = block.getDescendants(false);
        for (var i = 0, child; child = children[i]; i++) {
          child.setEnabled(true);
        }
      } else if ((block.outputConnection || block.previousConnection) &&
                 !workspace.isDragging()) {
        do {
          block.setEnabled(false);
          block = block.getNextBlock();
        } while (block);
      }
    }
  }
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name       Twitch Player Plus
// @namespace  http://twitch.tv/ehsankia
// @version    0.6
// @description  Various tweaks to the Twitch HTML5 player UI
// @match      http://www.twitch.tv/*
// @match      http://player.twitch.tv/*
// @grant      GM_addStyle
// @require    http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @copyright  2015+, Ehsan Kia
// ==/UserScript==

var html5Player;
var qualityOptions;
var waitForPlayerReadyTimer = setInterval(function() {
    html5Player = $('div.player');
    if (html5Player.length > 0) {
        setTimeout(applyFixes, 3000);
        clearInterval(waitForPlayerReadyTimer);
    }
}, 1000);

function applyFixes() {
    // Sticky volume slider
    $('.js-volume-container').css('width', '13em');

    // Move quality options to main bar and style appropriately
    qualityOptions = $(".js-quality");
    qualityOptions.insertAfter($('.js-quality-display-contain'));
    qualityOptions.css({
      float: "left",
      height: "29px",
      margin: "0 6px 0 4px",
      padding: "0",
      color: "white",
      fontWeight: "bold",
      background: "none",
      border: "none",
      boxShadow: "0 0 black",
      appearance: "none",
      "-moz-appearance": "none",
      "-webkit-appearance": "none",
      cursor: "pointer",
    });
    qualityOptions.find("> option").css({
      background: "black",
      padding: "0 5px",
      marginRight: "-15px",
      fontWeight: "normal",
    });
    qualityOptions.mouseover(function() {
        $(this).css("color","#a991d4");
        $(this).find("> option").css({
          color: "white",
        });
    }).mouseout(function() {
        $(this).css("color","white");
    });

    // Remove remaining label
    $("span:contains('Video Quality:')").remove();

    // Hide options if there are no transcoders
    setInterval(checkForQualityOptions, 5000);
    // Remove initially, otherwise there's an empty space for a bit
    checkForQualityOptions()

    // Bind F key to toggle fullscreen
    $('body').keypress(function(e) {
      if (e.which === 102) {
        // fallback to event.target just in case
        var el = document.activeElement || e.target;
        var t  = (el && el.tagName.toLowerCase()) || '';

        // pass through to elements that take keyboard input
        if (/(input|textarea|select)/.test(t)) {
            return true;
        }

        $('.js-control-fullscreen').click();
        return false;
      }
    });
}

function checkForQualityOptions() {
  var numQualityOptions = $(".js-quality > option").length;
  if (numQualityOptions > 1) {
    qualityOptions.css('display', 'block');
  } else {
    qualityOptions.css('display', 'none');
  }
}

GM_addStyle("select:-moz-focusring { outline: none; }");
GM_addStyle(".js-quality:focus { outline: none; }");

<commit_msg>Add missing semi colon at end of line<commit_after>// ==UserScript==
// @name       Twitch Player Plus
// @namespace  http://twitch.tv/ehsankia
// @version    0.6
// @description  Various tweaks to the Twitch HTML5 player UI
// @match      http://www.twitch.tv/*
// @match      http://player.twitch.tv/*
// @grant      GM_addStyle
// @require    http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @copyright  2015+, Ehsan Kia
// ==/UserScript==

var html5Player;
var qualityOptions;
var waitForPlayerReadyTimer = setInterval(function() {
    html5Player = $('div.player');
    if (html5Player.length > 0) {
        setTimeout(applyFixes, 3000);
        clearInterval(waitForPlayerReadyTimer);
    }
}, 1000);

function applyFixes() {
    // Sticky volume slider
    $('.js-volume-container').css('width', '13em');

    // Move quality options to main bar and style appropriately
    qualityOptions = $(".js-quality");
    qualityOptions.insertAfter($('.js-quality-display-contain'));
    qualityOptions.css({
      float: "left",
      height: "29px",
      margin: "0 6px 0 4px",
      padding: "0",
      color: "white",
      fontWeight: "bold",
      background: "none",
      border: "none",
      boxShadow: "0 0 black",
      appearance: "none",
      "-moz-appearance": "none",
      "-webkit-appearance": "none",
      cursor: "pointer",
    });
    qualityOptions.find("> option").css({
      background: "black",
      padding: "0 5px",
      marginRight: "-15px",
      fontWeight: "normal",
    });
    qualityOptions.mouseover(function() {
        $(this).css("color","#a991d4");
        $(this).find("> option").css({
          color: "white",
        });
    }).mouseout(function() {
        $(this).css("color","white");
    });

    // Remove remaining label
    $("span:contains('Video Quality:')").remove();

    // Hide options if there are no transcoders
    setInterval(checkForQualityOptions, 5000);
    // Remove initially, otherwise there's an empty space for a bit
    checkForQualityOptions();

    // Bind F key to toggle fullscreen
    $('body').keypress(function(e) {
      if (e.which === 102) {
        // fallback to event.target just in case
        var el = document.activeElement || e.target;
        var t  = (el && el.tagName.toLowerCase()) || '';

        // pass through to elements that take keyboard input
        if (/(input|textarea|select)/.test(t)) {
            return true;
        }

        $('.js-control-fullscreen').click();
        return false;
      }
    });
}

function checkForQualityOptions() {
  var numQualityOptions = $(".js-quality > option").length;
  if (numQualityOptions > 1) {
    qualityOptions.css('display', 'block');
  } else {
    qualityOptions.css('display', 'none');
  }
}

GM_addStyle("select:-moz-focusring { outline: none; }");
GM_addStyle(".js-quality:focus { outline: none; }");

<|endoftext|>


<commit_before>// $Revision$

/*
 * This is based loosely on the jQuery validation plugin 1.6 available at
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * I wrote my own version after it became too frustrating to customise for usage in EnsEMBL
 * This plugin is much less customisable, but hey, it does what we want and I'm not putting
 * it out on the web.
 *
 * Simon Brent
 */

(function($) {

$.extend($.fn, {
  validate: function (options) {
    return this.each(function () {
      if (this.nodeName === 'FORM') {
        var validator = $(this).data('validator');

        if (!validator) {
          validator = new $.validator(options, this);
          $(this).data('validator', validator);
        }

        validator.validateInputs(null, 'initial');
      } else {
        if (this.nodeName.match(/SELECT|INPUT|TEXTAREA/)) {
          var inp = $(this);
          if (inp.parents('form').data('validator')) {
            inp.data('required', options === false ? false : true);
          }
        }
      }
    });
  }
});

$.validator = function (options, form) {
  var validator = this;

  this.settings      = $.extend({}, $.validator.defaults, options);
  this.rules         = this.settings.rules;
  this.tests         = this.settings.tests; // Precompiled regular expressions
  this.inputs        = $('input[type="text"], input[type="password"], input[type="file"], textarea, select', form);
  this.submitButtons = $('input[type="submit"]', form);
  this.result        = true;

  $(form).on('submit.validate', function (e) {
    validator.result = true;
    validator.validateInputs(null, 'showError');

    if (!validator.result) {
      e.stopImmediatePropagation();
      e.preventDefault();
    }
  });

  this.inputs.each(function () {
    var el    = $(this);
    var input = { valid: true };

    if (this.className) {
      if (el.hasClass(validator.settings.requiredClass)) {
        input.required = true;
      }

      var rule = this.className.match(/.*\b_(\w+)\b.*/);

      if (rule) {
        input.rule = rule[1];

        var min = this.className.match(/\bmin_(.+)\b/);
        var max = this.className.match(/\bmax_(.+)\b/);

        if (min) {
          input.min = parseFloat(min[1], 10);
        }

        if (max) {
          input.max = parseFloat(max[1], 10);
        }
      }
    }

    el.data(input);

    el = null;
  }).on({
    'keyup.validate':  function (e) { if (e.keyCode !== 9) { validator.validateInputs($(this), 'delay'); } }, // Ignored if the tab key is pressed, since this will cause blur to fire
    'change.validate': function ()  { validator.validateInputs($(this), 'delay'); },
    'blur.validate':   function ()  { validator.validateInputs($(this), 'showError'); }
  });

  form = null;
};

$.extend($.validator, {
  defaults: {
    validClass:    'valid',
    invalidClass:  'invalid',
    requiredClass: 'required',
    tests: {
      'int':    new RegExp(/^[\-+]?\d+$/),
      'float':  new RegExp(/^([\-+]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([\-+]?\d+))?$/),
      password: new RegExp(/^\S{6,32}$/),
      email:    new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i),
      url:      new RegExp(/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i)
    },
    rules: {
      nonnegint:   function (val) { return this.tests['int'].test(val)   && val >= 0; },
      posint:      function (val) { return this.tests['int'].test(val)   && val >  0; },
      nonnegfloat: function (val) { return this.tests['float'].test(val) && val >= 0; },
      posfloat:    function (val) { return this.tests['float'].test(val) && val >  0; }
    },
    messages: {
      required:    'This field is required',
      'int':       'Please enter an integer',
      nonnegint:   'Please enter an integer (minimum 0)',
      posint:      'Please enter an integer (minimum 1)',
      'float':     'Please enter a number',
      nonnegfloat: 'Please enter a number (minimum 0)',
      posfloat:    'Please enter a number (minimum 1)',
      password:    'The password you have entered is invalid',
      email:       'Please enter a valid email address',
      url:         'Please enter a valid URL'
    }
  },

  prototype: {
    validateInputs: function (inputs, flag) {
      inputs = inputs || this.inputs;

      var validator = this;

      var setClass = {
        'true':  function (el) { $(el).removeClass(validator.settings.invalidClass).addClass(validator.settings.validClass); },
        'false': function (el) { $(el).removeClass(validator.settings.validClass).addClass(validator.settings.invalidClass); },
        'null':  function (el) { $(el).removeClass(validator.settings.validClass + ' ' + validator.settings.invalidClass);   }
      };

      function validate() {
        var isValid = true;
        var i;

        inputs.each(function () {
          var el    = $(this);
          var input = $.extend({}, el.data());

          var state = (flag === 'initial' || !input.required) && !this.value ? null :                                       // Not required and no value - do nothing. On initial run, ignore empty fields
                      input.rule && validator.rules[input.rule] ? validator.rules[input.rule].call(validator, this.value) : // Validate against rule
                      input.rule && validator.tests[input.rule] ? validator.tests[input.rule].test(this.value) :            // Validate against test
                      input.required ? !!this.value : null;                                                                 // No rule - check if required

          if (state && input.min) {
            state = parseFloat(this.value, 10) >= input.min;
          }

          if (state && input.max) {
            state = parseFloat(this.value, 10) <= input.max;
          }

          setClass[state](this);
          el.data('valid', state);

          if (state === false) {
            if (input.required && !this.value) {
              input.rule = 'required';
            }

            var message = validator.settings.messages[input.rule];

            if (input.rule.match(/int$/)) {
              if (input.min && input.max) {
                message = 'Please enter an integer between ' + input.min + ' and ' + input.max;
              } else if (input.min || input.max) {
                message = 'Please enter an integer (' + (input.min ? 'min' : 'max') + 'imum ' + (input.min || input.max) + ')';
              }
            }

            if (!input.error) {
              input.error = {
                rule: input.rule,
                el: $('<label>', {
                  'class': validator.settings.invalidClass,
                  'for':   this.id,
                  html:    message
                }).hide().appendTo(el.parent())
              };

              el.data('error', input.error);
            } else if (input.error.rule !== input.rule) {
              input.error.el.html(message);
              input.error.rule = input.rule;
            }

            if (flag === 'showError') {
              input.error.el.css('display', 'inline');
            }
          } else if (input.error) {
            input.error.el.remove();
            el.data('error', false);
          }

          el = null;
        });

        for (i in validator.inputs.toArray()) {
          if ($(validator.inputs[i]).data('valid') === false) {
            isValid = false;
            break;
          }
        }

        if (isValid) {
          validator.submitButtons.prop('disabled', false).removeClass('disabled');
        } else {
          validator.submitButtons.prop('disabled', true).addClass('disabled');
        }

        if (!isValid) {
          validator.result = false;
        }
      }

      if (this.timeout) {
        clearTimeout(this.timeout);
      }

      if (flag === 'delay') {
        this.timeout = setTimeout(validate, 250);
      } else {
        validate();
      }
    }
  }
});

})(jQuery);
<commit_msg>add a validate callback, make state be disabled on initial run when required inputs aren't completed<commit_after>// $Revision$

/*
 * This is based loosely on the jQuery validation plugin 1.6 available at
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 *
 * I wrote my own version after it became too frustrating to customise for usage in EnsEMBL
 * This plugin is much less customisable, but hey, it does what we want and I'm not putting
 * it out on the web.
 *
 * Simon Brent
 */

(function($) {

$.extend($.fn, {
  validate: function (options) {
    return this.each(function () {
      if (this.nodeName === 'FORM') {
        var validator = $(this).data('validator');

        if (!validator) {
          validator = new $.validator(options, this);
          $(this).data('validator', validator);
        }

        validator.validateInputs(null, 'initial');
      } else {
        if (this.nodeName.match(/SELECT|INPUT|TEXTAREA/)) {
          var inp = $(this);
          if (inp.parents('form').data('validator')) {
            inp.data('required', options === false ? false : true);
          }
        }
      }
    });
  }
});

$.validator = function (options, form) {
  var validator = this;

  this.settings      = $.extend({}, $.validator.defaults, options);
  this.rules         = this.settings.rules;
  this.tests         = this.settings.tests; // Precompiled regular expressions
  this.inputs        = $('input[type="text"], input[type="password"], input[type="file"], textarea, select', form);
  this.submitButtons = $('input[type="submit"]', form);
  this.result        = true;

  $(form).on('submit.validate', function (e) {
    validator.result = true;
    validator.validateInputs(null, 'showError');

    if (!validator.result) {
      e.stopImmediatePropagation();
      e.preventDefault();
    }
  });

  this.inputs.each(function () {
    var el    = $(this);
    var input = { valid: true };

    if (this.className) {
      if (el.hasClass(validator.settings.requiredClass)) {
        input.required = true;
      }

      var rule = this.className.match(/.*\b_(\w+)\b.*/);

      if (rule) {
        input.rule = rule[1];

        var min = this.className.match(/\bmin_(.+)\b/);
        var max = this.className.match(/\bmax_(.+)\b/);

        if (min) {
          input.min = parseFloat(min[1], 10);
        }

        if (max) {
          input.max = parseFloat(max[1], 10);
        }
      }
    }

    el.data(input);

    el = null;
  }).on({
    'keyup.validate':  function (e) { if (e.keyCode !== 9) { validator.validateInputs($(this), 'delay'); } }, // Ignored if the tab key is pressed, since this will cause blur to fire
    'change.validate': function ()  { validator.validateInputs($(this), 'delay'); },
    'blur.validate':   function ()  { validator.validateInputs($(this), 'showError'); }
  });

  form = null;
};

$.extend($.validator, {
  defaults: {
    validClass:    'valid',
    invalidClass:  'invalid',
    requiredClass: 'required',
    tests: {
      'int':    new RegExp(/^[\-+]?\d+$/),
      'float':  new RegExp(/^([\-+]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([\-+]?\d+))?$/),
      password: new RegExp(/^\S{6,32}$/),
      email:    new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i),
      url:      new RegExp(/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i)
    },
    rules: {
      nonnegint:   function (val) { return this.tests['int'].test(val)   && val >= 0; },
      posint:      function (val) { return this.tests['int'].test(val)   && val >  0; },
      nonnegfloat: function (val) { return this.tests['float'].test(val) && val >= 0; },
      posfloat:    function (val) { return this.tests['float'].test(val) && val >  0; }
    },
    messages: {
      required:    'This field is required',
      'int':       'Please enter an integer',
      nonnegint:   'Please enter an integer (minimum 0)',
      posint:      'Please enter an integer (minimum 1)',
      'float':     'Please enter a number',
      nonnegfloat: 'Please enter a number (minimum 0)',
      posfloat:    'Please enter a number (minimum 1)',
      password:    'The password you have entered is invalid',
      email:       'Please enter a valid email address',
      url:         'Please enter a valid URL'
    }
  },

  prototype: {
    validateInputs: function (inputs, flag) {
      inputs = inputs || this.inputs;

      var validator = this;

      var setClass = {
        'true':  function (el) { $(el).removeClass(validator.settings.invalidClass).addClass(validator.settings.validClass); },
        'false': function (el) { $(el).removeClass(validator.settings.validClass).addClass(validator.settings.invalidClass); },
        'null':  function (el) { $(el).removeClass(validator.settings.validClass + ' ' + validator.settings.invalidClass);   }
      };

      function validate() {
        var isValid = true;
        var i;

        inputs.each(function () {
          var el    = $(this);
          var input = $.extend({}, el.data());

          var state = (flag === 'initial' || !input.required) && !this.value ? null :                                       // Not required and no value - do nothing. On initial run, ignore empty fields
                      input.rule && validator.rules[input.rule] ? validator.rules[input.rule].call(validator, this.value) : // Validate against rule
                      input.rule && validator.tests[input.rule] ? validator.tests[input.rule].test(this.value) :            // Validate against test
                      input.required ? !!this.value : null;                                                                 // No rule - check if required

          if (state && input.min) {
            state = parseFloat(this.value, 10) >= input.min;
          }

          if (state && input.max) {
            state = parseFloat(this.value, 10) <= input.max;
          }

          setClass[state](this);
          el.data('valid', state === null && input.required ? false : state);

          if (state === false) {
            if (input.required && !this.value) {
              input.rule = 'required';
            }

            var message = validator.settings.messages[input.rule];

            if (input.rule.match(/int$/)) {
              if (input.min && input.max) {
                message = 'Please enter an integer between ' + input.min + ' and ' + input.max;
              } else if (input.min || input.max) {
                message = 'Please enter an integer (' + (input.min ? 'min' : 'max') + 'imum ' + (input.min || input.max) + ')';
              }
            }

            if (!input.error) {
              input.error = {
                rule: input.rule,
                el: $('<label>', {
                  'class': validator.settings.invalidClass,
                  'for':   this.id,
                  html:    message
                }).hide().appendTo(el.parent())
              };

              el.data('error', input.error);
            } else if (input.error.rule !== input.rule) {
              input.error.el.html(message);
              input.error.rule = input.rule;
            }

            if (flag === 'showError') {
              input.error.el.css('display', 'inline');
            }
          } else if (input.error) {
            input.error.el.remove();
            el.data('error', false);
          }

          el = null;
        });

        for (i in validator.inputs.toArray()) {
          if ($(validator.inputs[i]).data('valid') === false) {
            isValid = false;
            break;
          }
        }

        if (typeof validator.settings.validate === 'function') {
          isValid = validator.settings.validate.call(validator, isValid, inputs, flag);
        }

        if (isValid) {
          validator.submitButtons.prop('disabled', false).removeClass('disabled');
        } else {
          validator.submitButtons.prop('disabled', true).addClass('disabled');
        }

        if (!isValid) {
          validator.result = false;
        }
      }

      if (this.timeout) {
        clearTimeout(this.timeout);
      }

      if (flag === 'delay') {
        this.timeout = setTimeout(validate, 250);
      } else {
        validate();
      }
    }
  }
});

})(jQuery);
<|endoftext|>


<commit_before>var path = require("path"),
    fs = require("fs-extra"),
    glob = require("glob"),
    _ = require('lodash'),
    request = require("superagent"),
    async = require("async"),
    tarball = require('tarball-extract'),
    mkdirp = require('mkdirp');

var parse = function (json_file, ignore_missing, ignore_parse_fail) {
    var content;

    try {
        content = fs.readFileSync(json_file, 'utf8');
    } catch (err1) {
        if (!ignore_missing) {
            assert.ok(0, json_file + " doesn't exist!");
        }
        return null;
    }
    try {
        return JSON.parse(content);
    } catch (err2) {
        if (!ignore_parse_fail) {
            assert.ok(0, json_file + " failed to parse");
        }
        return null;
    }
}

var updateLibrary = function (pkg, callback) {
    console.log('Checking versions for ' + pkg.npmName);
    request.get('http://registry.npmjs.org/' + pkg.npmName, function(result) {
        _.each(result.body.versions, function(data, version) {
            var path = './ajax/libs/' + pkg.name + '/' + version;
            console.log(path);
            if(!fs.existsSync(path)) {
                console.log('dont have', version);
                fs.mkdirSync(path);
                var url = data.dist.tarball;
                var download_file = path + '/dist.tar.gz';
                tarball.extractTarballDownload(url , download_file, path, {}, function(err, result) {
                    console.log('this is happening sync');
                    fs.unlinkSync(download_file);
                    var folderName = fs.readdirSync(path)[0];

                    var npmFileMap = pkg.npmFileMap;

                    _.each(npmFileMap, function(fileSpec) {
                        var basePath = fileSpec.basePath || "";

                        _.each(fileSpec.files, function(file) {
                            var extractPath = basePath + "/" + file;
                            var files = glob.sync(path + "/" + folderName + "/" + basePath + "/" + file);

                            _.each(files, function(extractFilePath) {
                                var replacePath = folderName + "/" + basePath + "/";
                                replacePath = replacePath.replace(/\/\//g, "/");
                                var actualPath = extractFilePath.replace(replacePath, "");
                                fs.renameSync(extractFilePath, actualPath);
                            });
                        });
                    });

                    fs.removeSync(path + '/' + folderName);
                });
                console.log("Do not have version", version, "of", pkg.npmName);
            }
        });
        var npmVersion = result.body['dist-tags'].latest;
        pkg.version = npmVersion;
        fs.writeFileSync('ajax/libs/' + pkg.name + '/package.json', JSON.stringify(pkg, null, 2), 'utf8');

        callback(null, pkg['npm-name']);
    });
}

console.log('Looking for npm enabled libraries...');

// load up those files
var packages = glob.sync("./ajax/libs/**/package.json");
packages = _(packages).map(function (pkg) {
    var parsedPkg = parse(pkg);
    return parsedPkg.npmName ? parsedPkg : null;
}).compact().value();

console.log('Found ' + packages.length + ' npm enabled libraries');
var libraryUpdates = [];
_.each(packages, function(pkg) {
    libraryUpdates.push(function (callback) {
      updateLibrary(pkg, callback);
    });;
});
async.series(libraryUpdates, function(err, results) {
  console.log('Script completed');
});
<commit_msg>Updated npm auto update script to ignore certain types of files and directories<commit_after>var path = require("path"),
    fs = require("fs-extra"),
    glob = require("glob"),
    _ = require('lodash'),
    request = require("superagent"),
    async = require("async"),
    tarball = require('tarball-extract'),
    mkdirp = require('mkdirp');

var parse = function (json_file, ignore_missing, ignore_parse_fail) {
    var content;

    try {
        content = fs.readFileSync(json_file, 'utf8');
    } catch (err1) {
        if (!ignore_missing) {
            assert.ok(0, json_file + " doesn't exist!");
        }
        return null;
    }
    try {
        return JSON.parse(content);
    } catch (err2) {
        if (!ignore_parse_fail) {
            assert.ok(0, json_file + " failed to parse");
        }
        return null;
    }
}

var updateLibrary = function (pkg, callback) {
    console.log('Checking versions for ' + pkg.npmName);
    request.get('http://registry.npmjs.org/' + pkg.npmName, function(result) {
        _.each(result.body.versions, function(data, version) {
            var path = './ajax/libs/' + pkg.name + '/' + version;
            console.log(path);
            if(!fs.existsSync(path)) {
                console.log('dont have', version);
                fs.mkdirSync(path);
                var url = data.dist.tarball;
                var download_file = path + '/dist.tar.gz';
                tarball.extractTarballDownload(url , download_file, path, {}, function(err, result) {
                    console.log('this is happening sync');
                    fs.unlinkSync(download_file);
                    var folderName = fs.readdirSync(path)[0];

                    var npmFileMap = pkg.npmFileMap;

                    _.each(npmFileMap, function(fileSpec) {
                        var basePath = fileSpec.basePath || "";

                        _.each(fileSpec.files, function(file) {
                            var extractPath = basePath + "/" + file;
                            var files = glob.sync(path + "/" + folderName + "/" + basePath + "/" + file);

                            _.each(files, function(extractFilePath) {
                                if(extractFilePath.slice(-4) == ".zip") return;
                                if(extractFilePath.indexOf("dependencies") !== -1) return;
                                var replacePath = folderName + "/" + basePath + "/";
                                replacePath = replacePath.replace(/\/\//g, "/");
                                var actualPath = extractFilePath.replace(replacePath, "");
                                fs.renameSync(extractFilePath, actualPath);
                            });
                        });
                    });

                    fs.removeSync(path + '/' + folderName);
                });
                console.log("Do not have version", version, "of", pkg.npmName);
            }
        });
        var npmVersion = result.body['dist-tags'].latest;
        pkg.version = npmVersion;
        fs.writeFileSync('ajax/libs/' + pkg.name + '/package.json', JSON.stringify(pkg, null, 2), 'utf8');

        callback(null, pkg['npm-name']);
    });
}

console.log('Looking for npm enabled libraries...');

// load up those files
var packages = glob.sync("./ajax/libs/**/package.json");
packages = _(packages).map(function (pkg) {
    var parsedPkg = parse(pkg);
    return parsedPkg.npmName ? parsedPkg : null;
}).compact().value();

console.log('Found ' + packages.length + ' npm enabled libraries');
var libraryUpdates = [];
_.each(packages, function(pkg) {
    libraryUpdates.push(function (callback) {
      updateLibrary(pkg, callback);
    });;
});
async.series(libraryUpdates, function(err, results) {
  console.log('Script completed');
});
<|endoftext|>


<commit_before>import { pushManager } from './index';

window.onload = function() {
  // Ensure that the user can receive Safari Push Notifications.
  if ('safari' in window && 'pushNotification' in window.safari) {
    var permissionData = window.safari.pushNotification.permission('web.org.schul-cloud');
    checkRemotePermission(permissionData);
  }
};

var checkRemotePermission = function(permissionData) {
  if (permissionData.permission === 'default') {
    console.log('[INFO] Requesting permission...');
    // This is a new web service URL and its validity is unknown.
    window.safari.pushNotification.requestPermission(
      'https://schul-cloud.org:3030', // The web service URL.
      'web.org.schul-cloud',     // The Website Push ID.
      {userToken: 'usertokenwithmin16chars'}, // Data that you choose to send to your server to help you identify the user.
      checkRemotePermission         // The callback function.
    );
  }
  else if (permissionData.permission === 'denied') {
    // The user said no.
    console.log('[INFO] Permission denied.');
  }
  else if (permissionData.permission === 'granted') {
    // The web service URL is a valid push provider, and the user said yes.
    // permissionData.deviceToken is now available to use.
    console.log('[INFO] Permission granted. Token:', permissionData.deviceToken);
    pushManager.setRegistrationId(permissionData.deviceToken, 'apn', 'safari');
  }
  console.log('[INFO] Permission data:', permissionData);
};
<commit_msg>Update indexSafari.js<commit_after><|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';

import { Link } from 'routes';

function Header(props) {
  return (

      <Link route="home">

      </Link>

        {props.showEarthViewLink &&

          <Link route="splash">

          </Link>
          <Link route="splash">
            EARTH VIEW
          </Link>

        }
        <Link route="home">
          GO TO RESOURCE WATCH
        </Link>

  );
}

Header.defaultProps = {
  showEarthViewLink: false
};

Header.propTypes = {
  showEarthViewLink: PropTypes.bool
};

export default Header;
<commit_msg>Wording of go to button changed<commit_after>import React from 'react';
import PropTypes from 'prop-types';

import { Link } from 'routes';

function Header(props) {
  return (

      <Link route="home">

      </Link>

        {props.showEarthViewLink &&

          <Link route="splash">

          </Link>
          <Link route="splash">
            EARTH VIEW
          </Link>

        }
        <Link route="home">
          GO TO SITE
        </Link>

  );
}

Header.defaultProps = {
  showEarthViewLink: false
};

Header.propTypes = {
  showEarthViewLink: PropTypes.bool
};

export default Header;
<|endoftext|>


<commit_before>// ==UserScript==
// @name       Twitch Player Plus
// @namespace  http://twitch.tv/ehsankia
// @version    1.0
// @description  Various tweaks to the Twitch HTML5 player UI
// @match      http://www.twitch.tv/*
// @match      http://player.twitch.tv/*
// @grant      GM_addStyle
// @grant      GM_getValue
// @grant      GM_setValue
// @require    http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @copyright  2015+, Ehsan Kia
// ==/UserScript==

var html5Player;
var waitForPlayerReadyTimer = setInterval(function() {
    html5Player = $('div.player');
    if (html5Player.length > 0) {
      if (html5Player.attr('data-loading') === "false") {
        clearInterval(waitForPlayerReadyTimer);
        window.eval("var flashBackend = $('div.player-video object')[0];");
        setTimeout(applyFixes, 100);
      }
    }
}, 100);

function applyFixes() {

    // Move quality options to main bar
    $(".js-quality").insertAfter($('.js-quality-display-contain'));

    // Remove remaining label
    $("span:contains('Video Quality:')").remove();

    // Hide options if there are no transcoders
    checkForQualityOptions();
    setInterval(checkForQualityOptions, 5000);

    // Bind F key to toggle fullscreen
    $('body').keypress(function(e) {
      if (e.which === 102) {
        // fallback to event.target just in case
        var el = document.activeElement || e.target;
        var t  = (el && el.tagName.toLowerCase()) || '';

        // pass through to elements that take keyboard input
        if (/(input|textarea|select)/.test(t)) {
          return true;
        }

        $('.js-control-fullscreen').click();
        return false;
      }
    });

    // Add latency status under Live icon
    var liveIcon = $('.player-livestatus__online');
    liveIcon.append("

");
    window.eval('flashBackend.startPlaybackStatistics();');
    setTimeout(updateLatency, 5000);

    // Remove old stats button and add new one
    $('.player-menu__item--stats').css('display', 'none');
    $('.js-control-fullscreen').before(" \
      <button type='button' class='player-button js-custom-stats-toggle'> \
         \
        <svg id='icon-stats' viewBox='0 0 1024 1024' style='width: 16px; fill: white; margin: 1px 6px;'> \
          <path d='M960 0h-896c-35.328 0-64 28.672-64 64v640c0 35.328 28.672 64 64 64h256l-128 256h32l230.4-256h115.2l230.4 256h32l-128-256h256c35.328 0 64-28.672 64-64v-640c0-35.328-28.672-64-64-64zM960 672c0 17.696-14.304 32-32 32h-832c-17.696 0-32-14.304-32-32v-576c0-17.696 14.304-32 32-32h832c17.696 0 32 14.304 32 32v576zM668.096 500.192l-144.672-372.128-158.016 297.28-88.192-90.72-149.216 92.992 42.112 24.256 95.616-59.584 115.36 118.784 133.6-251.296 147.712 380.128 125.984-265.216 51.328 109.248 56.288-9.44-107.328-228.224-120.576 253.92z'></path> \
        </svg> \
      </button>");
    $('.js-custom-stats-toggle').click(function(){
      var prev = $('.js-playback-stats').attr('data-state');
      var state = prev === 'on' ? 'off' : 'on';
      $('.js-playback-stats').attr('data-state', state);
    });

    // Check if it's a VOD and there isn't a seek argument in the url
    var vodID = html5Player.attr('data-video');
    var hasSeekParam = document.location.search.search("t=") >= 0;
    if (vodID !== undefined && !hasSeekParam) {
      //seek to previous position and keep track of the position
      var oldTime = GM_getValue("seek_" + vodID);
      if (oldTime !== undefined) {
        oldTime = parseFloat(oldTime);
        window.eval('flashBackend.videoSeek(' + oldTime + ');');
      }
      setTimeout(function() {
        setInterval(trackSeekTime, 15000);
      }, 5 * 60 * 1000);
    }
}

function checkForQualityOptions() {
  var numQualityOptions = $(".js-quality > option").length;
  if (numQualityOptions > 1) {
    $('.js-quality').css('display', 'block');
  } else {
    $('.js-quality').css('display', 'none');
  }
}

function updateLatency() {
  var lat = $('.js-stat-hls-latency-broadcaster').text();
  if (lat === "" || lat === "NaN") {
    window.eval('flashBackend.stopPlaybackStatistics();');
    window.eval('flashBackend.startPlaybackStatistics();');
    setTimeout(updateLatency, 5000);
  } else {
    $('.lag-status').text(lat + ' sec.');
    setTimeout(updateLatency, 1000);
  }
}

function trackSeekTime() {
  var vodID = html5Player.attr('data-video');
  var seekTime = window.eval('flashBackend.getVideoTime();');
  if (seekTime < 5 * 60) return;
  GM_setValue("seek_" + vodID, seekTime);
}

GM_addStyle(" \
.js-volume-container { width: 13em; } \
select.js-quality:hover { color: #a991d4 !important; } \
select.js-quality, select.js-quality:focus { \
  float: left; \
  height: 29px; \
  margin: 0 6px 0 4px; \
  padding: 0; \
  color: white; \
  font-weight: bold; \
  background: none; \
  border: none; \
  box-shadow: 0 0 black; \
  appearance: none; \
  -moz-appearance: none; \
  -webkit-appearance: none; \
  outline: none; \
  cursor: pointer; \
} \
select.js-quality > option { \
  color: white; \
  background: black; \
  padding: 0 5px; \
  margin-right: -15px; \
  font-weight: bold; \
} \
.lag-status { \
  width: 60px; \
  margin-left: -20px; \
  text-align: center; \
} \
.js-custom-stats-toggle:hover > svg { \
  fill: #a991d4 !important; \
}");
<commit_msg>Fix quality settings location for hosting player<commit_after>// ==UserScript==
// @name       Twitch Player Plus
// @namespace  http://twitch.tv/ehsankia
// @version    1.1
// @description  Various tweaks to the Twitch HTML5 player UI
// @match      http://www.twitch.tv/*
// @match      http://player.twitch.tv/*
// @grant      GM_addStyle
// @grant      GM_getValue
// @grant      GM_setValue
// @require    http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @copyright  2015+, Ehsan Kia
// ==/UserScript==

var html5Player;
var waitForPlayerReadyTimer = setInterval(function() {
    html5Player = $('div.player');
    if (html5Player.length > 0) {
      if (html5Player.attr('data-loading') === 'false') {
        html5Player.attr('data-tpp', 'true');
        clearInterval(waitForPlayerReadyTimer);
        window.eval("var flashBackend = $('div.player-video object')[0];");
        setTimeout(applyFixes, 100);
        hostPlayerCheck();
      }
    }
}, 100);

function applyFixes() {

    // Move quality options to main bar
    $(".js-quality").insertAfter($('.js-quality-display-contain'));

    // Remove remaining label
    $("span:contains('Video Quality:')").remove();

    // Hide options if there are no transcoders
    checkForQualityOptions();
    setInterval(checkForQualityOptions, 5000);

    // Bind F key to toggle fullscreen
    $('body').keypress(function(e) {
      if (e.which === 102) {
        // fallback to event.target just in case
        var el = document.activeElement || e.target;
        var t  = (el && el.tagName.toLowerCase()) || '';

        // pass through to elements that take keyboard input
        if (/(input|textarea|select)/.test(t)) {
          return true;
        }

        $('.js-control-fullscreen').click();
        return false;
      }
    });

    // Add latency status under Live icon
    var liveIcon = $('.player-livestatus__online');
    liveIcon.append("

");
    window.eval('flashBackend.startPlaybackStatistics();');
    setTimeout(updateLatency, 5000);

    // Remove old stats button and add new one
    $('.player-menu__item--stats').css('display', 'none');
    $('.js-control-fullscreen').before(" \
      <button type='button' class='player-button js-custom-stats-toggle'> \
         \
        <svg id='icon-stats' viewBox='0 0 1024 1024' style='width: 16px; fill: white; margin: 1px 6px;'> \
          <path d='M960 0h-896c-35.328 0-64 28.672-64 64v640c0 35.328 28.672 64 64 64h256l-128 256h32l230.4-256h115.2l230.4 256h32l-128-256h256c35.328 0 64-28.672 64-64v-640c0-35.328-28.672-64-64-64zM960 672c0 17.696-14.304 32-32 32h-832c-17.696 0-32-14.304-32-32v-576c0-17.696 14.304-32 32-32h832c17.696 0 32 14.304 32 32v576zM668.096 500.192l-144.672-372.128-158.016 297.28-88.192-90.72-149.216 92.992 42.112 24.256 95.616-59.584 115.36 118.784 133.6-251.296 147.712 380.128 125.984-265.216 51.328 109.248 56.288-9.44-107.328-228.224-120.576 253.92z'></path> \
        </svg> \
      </button>");
    $('.js-custom-stats-toggle').click(function(){
      var prev = $('.js-playback-stats').attr('data-state');
      var state = prev === 'on' ? 'off' : 'on';
      $('.js-playback-stats').attr('data-state', state);
    });

    // Check if it's a VOD and there isn't a seek argument in the url
    var vodID = html5Player.attr('data-video');
    var hasSeekParam = document.location.search.search("t=") >= 0;
    if (vodID !== undefined && !hasSeekParam) {
      //seek to previous position and keep track of the position
      var oldTime = GM_getValue("seek_" + vodID);
      if (oldTime !== undefined) {
        oldTime = parseFloat(oldTime);
        window.eval('flashBackend.videoSeek(' + oldTime + ');');
      }
      setTimeout(function() {
        setInterval(trackSeekTime, 15000);
      }, 5 * 60 * 1000);
    }

    // Mark that we've fixed the player
    html5Player.attr('data-tpp', 'true');
}

function checkForQualityOptions() {
  var numQualityOptions = $(".js-quality > option").length;
  if (numQualityOptions > 1) {
    $('.js-quality').css('display', 'block');
  } else {
    $('.js-quality').css('display', 'none');
  }
}

function updateLatency() {
  var lat = $('.js-stat-hls-latency-broadcaster').text();
  if (lat === "" || lat === "NaN") {
    window.eval('flashBackend.stopPlaybackStatistics();');
    window.eval('flashBackend.startPlaybackStatistics();');
    setTimeout(updateLatency, 5000);
  } else {
    $('.lag-status').text(lat + ' sec.');
    setTimeout(updateLatency, 1000);
  }
}

function trackSeekTime() {
  var vodID = html5Player.attr('data-video');
  var seekTime = window.eval('flashBackend.getVideoTime();');
  if (seekTime < 5 * 60) return;
  GM_setValue("seek_" + vodID, seekTime);
}

function hostPlayerCheck() {
  setInterval(function() {
      $('div.player').each(function(ind, el){
        var player = $(el);
        if (player.attr('data-tpp') === 'true') return;
        if (player.attr('data-loading') !== 'false') return;

        // Move quality options to main bar
        container = player.find('.js-quality-display-contain');
        player.find(".js-quality").insertAfter(container);

        // Remove remaining label
        player.find("span:contains('Video Quality:')").remove();

        // Mark that we've fixed the player
        player.attr('data-tpp', 'true');
      });
  }, 5000);
}

GM_addStyle(" \
.js-volume-container { width: 13em; } \
select.js-quality:hover { color: #a991d4 !important; } \
select.js-quality, select.js-quality:focus { \
  float: left; \
  height: 29px; \
  margin: 0 6px 0 4px; \
  padding: 0; \
  color: white; \
  font-weight: bold; \
  background: none; \
  border: none; \
  box-shadow: 0 0 black; \
  appearance: none; \
  -moz-appearance: none; \
  -webkit-appearance: none; \
  outline: none; \
  cursor: pointer; \
} \
select.js-quality > option { \
  color: white; \
  background: black; \
  padding: 0 5px; \
  margin-right: -15px; \
  font-weight: bold; \
} \
.lag-status { \
  width: 60px; \
  margin-left: -20px; \
  text-align: center; \
} \
.js-custom-stats-toggle:hover > svg { \
  fill: #a991d4 !important; \
}");
<|endoftext|>


<commit_before>!function(e){"use strict";function n(){e.addEventListener("load",function(){try{var e=document.querySelectorAll("code.hljs");for(var n in e)e.hasOwnProperty(n)&&t(e[n])}catch(r){console.error("LineNumbers error: ",r)}})}function t(e){if("object"==typeof e){var n=e.parentNode,t=n.textContent.match(/\r\n|\r|\n/g);if(t=t?t.length:0,r()&&(t+=1),t>1){for(var o="",i=0;t>i;i++)o+=i+1+"\n";var l=document.createElement("code");l.className="hljs hljs-line-numbers",l.style["float"]="left",l.textContent=o,n.insertBefore(l,e)}}}function r(n){return n=n||e.navigator.userAgent,n.indexOf("MSIE ")>-1||n.indexOf("Trident/")>-1}"undefined"==typeof e.hljs?console.error("highlight.js not detected!"):(e.hljs.initLineNumbersOnLoad=n,e.hljs.lineNumbersBlock=t)}(window);<commit_msg>Build<commit_after>!function(e){"use strict";function t(){e.addEventListener("load",function(){try{var e=document.querySelectorAll("code.hljs");for(var t in e)e.hasOwnProperty(t)&&n(e[t])}catch(r){console.error("LineNumbers error: ",r)}})}function n(e){if("object"==typeof e){var t=e.parentNode,n=r(t.textContent);if(n>1){for(var o="",l=0;n>l;l++)o+=l+1+"\n";var c=document.createElement("code");c.className="hljs hljs-line-numbers",c.style["float"]="left",c.textContent=o,t.insertBefore(c,e)}}}function r(e){if(0===e.length)return 0;var t=/\r\n|\r|\n/g,n=e.match(t);return n=n?n.length:0,e[e.length-1].match(t)||(n+=1),n}"undefined"==typeof e.hljs?console.error("highlight.js not detected!"):(e.hljs.initLineNumbersOnLoad=t,e.hljs.lineNumbersBlock=n)}(window);<|endoftext|>