<commit_before>// A selfie toggle button that can be attached to the document.
function GitHubSelfieButtons() {
  this.elem = $(
    '
' +
    '<button type="button" class="totallyAwesomeSelfieButton btn btn-default">' +
    '' +
    ' Selfie!' +
    '</button>' +
    '
');

  this.selfieButton = this.elem.find('.totallyAwesomeSelfieButton');
  this.videoPreview = null;

  // TODO: This passthrough sucks
  this.onselfie = function(isDynamic, video, canvas, ctx, callback) {};

  this.selfieButton
    .on('click', () => {
      if (this.videoPreview === null) {
        this.selfieButton.addClass('selected');
        this.showVideoPreview();
        this.videoPreview.startPreview();
      } else {
        this.videoPreview.destroy();
        this.videoPreview = null;
        this.selfieButton.removeClass('selected');
      }
    });
}

GitHubSelfieButtons.prototype = {
  insert: function(element) {
    // Be careful not to insert more than one!
    this.elem.eq(0).appendTo(element);
  },

  destroy: function() {
    this.elem.remove();
    this.selfieButton = null;
    if (this.videoPreview !== null) {
      this.videoPreview.destroy();
    }
    this.videoPreview = null;
    this.onselfie = null;
  },

  showVideoPreview: function() {
    if (this.videoPreview === null) {
      // Insert the preview before the buttons
      this.videoPreview = new GitHubSelfieVideoPreview();
      this.videoPreview.onselfie = this.onselfie;
      this.videoPreview.insert(this.elem);
    }
  },

  disableButton: function() {
    this.selfieButton.prop('disabled', true);
  },

  enableButton: function() {
    this.selfieButton.prop('disabled', false);
  }
};

// A selfie video preview and buttons that can be attached to the document.
function GitHubSelfieVideoPreview() {
  this.elem = $(
    '
' +
    '

' +
    '
' +
    '

' +
    '<video autoplay id="selfieVideo"></video>' +
    '
' +
    '

' +
    '<canvas id="selfieCanvas" class="hidden"></canvas>' +
    '
' +
    '<button type="button" class="selfiePhotoButton btn btn-sm selected">' +
    '' +
    ' Photo' +
    '</button>' +
    '<button type="button" class="selfieVideoButton btn btn-sm">' +
    '' +
    ' Video' +
    '</button>' +
    '
' +
    '<select class="selfieDuration">' +
    '<option>1</option>' +
    '<option>2</option>' +
    '<option>3</option>' +
    '<option>4</option>' +
    '</select>' +
    '<button type="button" class="selfieTakeButton btn btn-primary btn-sm">' +
    ' Take a selfie!' +
    '</button>' +
    '
'
  );

  this.onselfie = function(isDynamic, video, canvas, ctx, callback) {};

  this.videoElem = this.elem.find('video').get(0);
  this.canvasElem = this.elem.find('canvas').get(0);
  this.textOverlay = this.elem.find('.selfieVideoOverlay');
  this.counterContainer = this.elem.find('.counter-container');
  this.photoButton = this.elem.find('.selfiePhotoButton');
  this.photoButton
    .on('click', this.setSelfieType.bind(this));
  this.videoButton = this.elem.find('.selfieVideoButton');
  this.videoButton
    .on('click', this.setSelfieType.bind(this));
  this.takeButton = this.elem.find('.selfieTakeButton');
  this.takeButton
    .on('click', () => this.onselfie(this.dynamic));
  this.progress = this.elem.find('.selfieProgress');
  this.stream = null;
  this.dynamic = false; // dynamic == video
  this.videoDuration = 2; // seconds
  this.loadPreferences();

  this.durationSelector = this.elem.find('.selfieDuration');
  this.durationSelector.val(this.videoDuration);
  this.durationSelector.on('change', () => {
    this.setVideoDuration(this.durationSelector.val());
    this.savePreferences();
  });

  if (this.dynamic) {
    this.videoButton.addClass('selected');
    this.photoButton.removeClass('selected');
  }
  this.durationSelector.toggle(this.dynamic);

  // Turn off the preview when the page is not visible to save battery
  // and reduce the creepy feeling when your camera light is on because of
  // a page you forgot about.
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === 'visible') {
      if (this.stream === null) {
        this.startPreview();
      }
    } else {
      this.stopPreview();
    }
  }, false);
}

GitHubSelfieVideoPreview.prototype = {
  insert: function(element) {
    // Be careful not to insert more than one!
    this.elem.eq(0).insertAfter(element);
  },

  // Video (dynamic) needs to be resized smaller for preformnce
  resizeCanvas: function(isDynamic) {
    var scalefactor = 1 / (isDynamic ? 2 : 1);
    if (isDynamic) {
      // Video is always 320x240
      this.canvasElem.setAttribute('width', 320);
      this.canvasElem.setAttribute('height', 240);
    } else {
      this.canvasElem.setAttribute('width', this.videoElem.videoWidth);
      this.canvasElem.setAttribute('height', this.videoElem.videoHeight);
    }
  },

  setMessage: function(message) {
    if (this.textOverlay !== null) {
      this.textOverlay.text(message);
    }
  },

  // Progress in [0,1]
  setProgress: function(percent) {
    this.progress.css('width', percent*100 + "%");
  },

  destroy: function() {
    // No memory leaks here!
    this.stopPreview();
    this.elem.remove();
    this.videoElem = null;
    this.canvasElem = null;
    this.textOverlay = null;
    this.counterContainer = null;
    this.photoButton = null;
    this.videoButton = null;
    this.takeButton = null;
    this.onselfie = null;
    this.progress = null;
  },

  setVideoDuration: function(val) {
    // Just to be careful, clamp 1-4
    this.videoDuration = Math.max(1, Math.min(parseInt(val), 4));
  },

  loadPreferences: function() {
    this.dynamic = localStorage.getItem('selfieDynamic') === 'true';
    this.setVideoDuration(localStorage.getItem('selfieVideoDuration') || "2");
  },

  savePreferences: function() {
    localStorage.setItem('selfieDynamic', this.dynamic ? 'true' : 'false');
    localStorage.setItem('selfieVideoDuration', this.videoDuration.toString());
  },

  setSelfieType: function(e) {
    if ((e.target === this.photoButton.get(0) &&
         !this.photoButton.hasClass('selected')) ||
        (e.target === this.videoButton.get(0) &&
         !this.videoButton.hasClass('selected'))) {
      this.videoButton.toggleClass('selected');
      this.photoButton.toggleClass('selected');
      this.dynamic = !this.dynamic;
      this.durationSelector.toggle(this.dynamic);
      this.savePreferences();
    }
  },

  startPreview: function() {
    if (!this.videoElem) {
      return;
    }

    this.setMessage('Fetching camera stream...');

    var getUserMedia;
    if (typeof navigator.webkitGetUserMedia === 'function') {
      getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
    } else if (typeof navigator.mozGetUserMedia === 'function') {
      getUserMedia = navigator.mozGetUserMedia.bind(navigator);
    } else {
      getUserMedia = function() { alert("Your browser does not support camera input!"); };
    }

    getUserMedia({video: true}, (_stream) => {
      this.setMessage('');
      this.stream = _stream;
      this.videoElem.src = window.URL.createObjectURL(_stream);
    }, (e) => {
      this.setMessage("You don't have a camera available!");
    });
  },

  stopPreview: function() {
    if (this.stream !== null) {
      this.stream.getTracks()[0].stop();
    }
    this.stream = null;
  },

  snapSelfie: function(dynamic, takeSelfieCallback, fileCallback) {
    this.resizeCanvas(dynamic);
    var ctx = this.canvasElem.getContext('2d');
    this.selfieCountdown(
      3,
      takeSelfieCallback(this.videoElem, this.canvasElem, ctx, fileCallback));
  },

  selfieCountdown: function(count, callback) {
    if (count > 0) {
      this.counterContainer.html('
' + count + '
');
      setTimeout(() => this.selfieCountdown(count - 1, callback), 1000);
    } else {
      this.counterContainer.empty();
      if (!this.dynamic) {
        // Camera flash
        this.counterContainer.addClass('selfie-flash');
        setTimeout(() => this.counterContainer.removeClass('selfie-flash'), 1100);
      }
      callback();
    }
  }
};

// Just to be tidy, only allow one of these to exist at once. Clean up
// the old ones if we add a new one.
var selfieSingleton = null;

function GitHubSelfies() {
  this.selfiesTaken = 0;
  // Imgur client ID
  this.clientId = 'cc9df57988494ca';
  // This selector works on all pages
  this.insertAt = '.timeline-new-comment .form-actions:visible';
  this.buttons = null;
  this.textarea = null;
}

GitHubSelfies.prototype = {
  setupSelfieStream: function() {
    if (selfieSingleton !== null) {
      selfieSingleton.destroy();
      selfieSingleton = null;
    }
    selfieSingleton = this;

    var candidate = $(this.insertAt);
    if (candidate.length === 0) {
      // Try again later
      setTimeout(() => this.setupSelfieStream(), 250);
    } else {
      $('.form-actions-protip').hide();
      this.buttons = new GitHubSelfieButtons();
      this.buttons.insert(candidate);
      // TODO: this is too fragile!
      this.textarea = this.buttons.elem.parent().parent().find('textarea');
      this.setupEvents();
    }
  },

  destroy: function() {
    if (this.buttons !== null) {
      this.buttons.destroy();
    }
    this.buttons = null;
    this.textarea = null;
  },

  hideAllElements: function() {
    $('.github-selfies').addClass('hidden');
  },

  showAllElements: function() {
    $('.github-selfies').removeClass('hidden');
  },

  setupEvents: function() {
    this.buttons.onselfie = this.addSelfie.bind(this);
    $('.write-tab').on('click', this.showAllElements.bind(this));
    $('.preview-tab').on('click', this.hideAllElements.bind(this));
  },

  addSelfie: function(isDynamic) {
    var thisSelfieNumber = this.selfiesTaken++;

    var success = (res) => {
      this.replacePlaceholderInBody(thisSelfieNumber, res.data.link);
    };

    var imageSuccess = (_imageData) => {
      this.addSelfiePlaceholder(thisSelfieNumber);
      this.uploadSelfie(_imageData, success, (err) => {
        this.buttons.videoPreview.setMessage("Something went wrong :-(");
        console.error("Error uploading selfie", err);
      });
    };

    this.buttons.videoPreview.snapSelfie(
      isDynamic,
      isDynamic ? this.dynamicSelfie.bind(this) : this.staticSelfie.bind(this),
      imageSuccess);

  },

  staticSelfie: function(video, canvas, ctx, callback) {
    return function() {
      var imgBinary;

      ctx.save();
      // We used to flip this, but now the preview is just flipped in CSS.
      // Save the image non-mirrored so writing goes the right way.
      //ctx.translate(video.videoWidth, 0);
      //ctx.scale(-1, 1);
      ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, video.videoWidth, video.videoHeight);
      imgBinary = canvas.toDataURL('/image/jpeg', 1).split(',')[1];
      ctx.restore();
      callback(imgBinary);
    };
  },

  dynamicSelfie: function(video, canvas, ctx, callback) {
    return () => {
      var fps = 15;
      var totalFrames = Math.floor(this.buttons.videoPreview.videoDuration * fps);
      var interval = Math.floor(1000 / fps);
      // Height and width must be integral or the LZWEncoder will hang
      var height = Math.floor(canvas.height);
      var width = Math.floor(canvas.width);
      var frames = [];
      var frameNum = 0;
      var lastFrameTime = 0;

      var addFrame = function (encoder, frame) {
        return () => {
          return new Promise(function (resolve, reject) {
            encoder.setDelay(frame[1]);
            if (encoder.addFrame(frame[0], true)) {
              resolve(encoder);
            } else {
              reject("Error adding frame");
            }
          });
        };
      };

      var makeGif = () => {
        var encoder = new GIFEncoder();
        encoder.setSize(width, height);
        encoder.setRepeat(0);
        encoder.start();
        var promise = Promise.resolve(true);
        for (var i = 0; i < frames.length; i++) {
          promise.then(addFrame(encoder, frames[i]));
        }
        return promise
          .then(() => {
            encoder.finish();
            frames = null;
            return encoder.stream().getData();
          })
          .then(encode64)
          .then(callback);
      };

      // We use requestAnimationFrame instead of setInterval so that
      // we are better sync'ed with the video.
      var captureFrame = () => {
        // schedule another frame right away
        var rafRequest = requestAnimationFrame(captureFrame);

        var frameTime = performance.now();
        var frameDelay = frameTime - lastFrameTime;
        // Limit to a set fps by skipping this callback unless the
        // interval is greater than what we want.
        if (frameDelay >= interval) {
          frameNum++;
          lastFrameTime = frameTime;
          if (frameNum === 1) {
            frameDelay = 0;
          }
          ctx.drawImage(video,
                        0, 0, video.videoWidth, video.videoHeight,
                        0, 0, width, height);
          frames.push([ctx.getImageData(0, 0, width, height).data, frameDelay]);
          this.buttons.videoPreview.setProgress(frameNum / totalFrames);
          if (frameNum >= totalFrames) {
            cancelAnimationFrame(rafRequest);
            makeGif().then(() => this.buttons.videoPreview.setProgress(0));
          }
        }
      };

      requestAnimationFrame(captureFrame);
    };
  },

  uploadSelfie: function(imageData, successCb, errorCb) {
    $.ajax({
      url  : 'https://api.imgur.com/3/upload',
      type : 'POST',
      beforeSend: (xhr) => {
        xhr.setRequestHeader('Authorization', 'Client-ID ' + this.clientId);
      },
      data: {
        type  : 'base64',
        image : imageData
      },
      dataType : 'json',
      success  : successCb,
      error    : errorCb
    });
  },

  addSelfiePlaceholder: function(number) {
    var currentContents = this.textarea.val();
    if (currentContents !== '') {
      this.textarea.val(currentContents + '\n');
    }
    this.textarea.val(currentContents + '[[selfie-' + number + ' uploading...]]\n');
  },

  replacePlaceholderInBody: function(number, link) {
    var toReplace = '[[selfie-' + number + ' uploading...]]';

    this.textarea.val(
      this.textarea.val()
        .replace(toReplace, '[![selfie-' + number + '](' + link + ')](https://github.com/thieman/github-selfies/)'));
    this.textarea.focus();
    // Cursor to end
    var textareaElem = this.textarea.get(0);
    var textareaLength = textareaElem.textLength;
    textareaElem.setSelectionRange(textareaLength, textareaLength);
  }
};
<commit_msg>Move GitHub's markdown help link out of the way during selfies.<commit_after>// A selfie toggle button that can be attached to the document.
function GitHubSelfieButtons() {
  this.elem = $(
    '
' +
    '<button type="button" class="totallyAwesomeSelfieButton btn btn-default">' +
    '' +
    ' Selfie!' +
    '</button>' +
    '
');

  this.selfieButton = this.elem.find('.totallyAwesomeSelfieButton');
  this.videoPreview = null;

  // TODO: This passthrough sucks
  this.onselfie = function(isDynamic, video, canvas, ctx, callback) {};

  this.selfieButton
    .on('click', () => {
      if (this.videoPreview === null) {
        this.selfieButton.addClass('selected');
        this.showVideoPreview();
        $('.toolbar-help').hide();
        this.videoPreview.startPreview();
      } else {
        this.videoPreview.destroy();
        this.videoPreview = null;
        $('.toolbar-help').show();
        this.selfieButton.removeClass('selected');
      }
    });
}

GitHubSelfieButtons.prototype = {
  insert: function(element) {
    // Be careful not to insert more than one!
    this.elem.eq(0).appendTo(element);
  },

  destroy: function() {
    this.elem.remove();
    this.selfieButton = null;
    if (this.videoPreview !== null) {
      this.videoPreview.destroy();
    }
    this.videoPreview = null;
    this.onselfie = null;
  },

  showVideoPreview: function() {
    if (this.videoPreview === null) {
      // Insert the preview before the buttons
      this.videoPreview = new GitHubSelfieVideoPreview();
      this.videoPreview.onselfie = this.onselfie;
      this.videoPreview.insert(this.elem);
    }
  },

  disableButton: function() {
    this.selfieButton.prop('disabled', true);
  },

  enableButton: function() {
    this.selfieButton.prop('disabled', false);
  }
};

// A selfie video preview and buttons that can be attached to the document.
function GitHubSelfieVideoPreview() {
  this.elem = $(
    '
' +
    '

' +
    '
' +
    '

' +
    '<video autoplay id="selfieVideo"></video>' +
    '
' +
    '

' +
    '<canvas id="selfieCanvas" class="hidden"></canvas>' +
    '
' +
    '<button type="button" class="selfiePhotoButton btn btn-sm selected">' +
    '' +
    ' Photo' +
    '</button>' +
    '<button type="button" class="selfieVideoButton btn btn-sm">' +
    '' +
    ' Video' +
    '</button>' +
    '
' +
    '<select class="selfieDuration">' +
    '<option>1</option>' +
    '<option>2</option>' +
    '<option>3</option>' +
    '<option>4</option>' +
    '</select>' +
    '<button type="button" class="selfieTakeButton btn btn-primary btn-sm">' +
    ' Take a selfie!' +
    '</button>' +
    '
'
  );

  this.onselfie = function(isDynamic, video, canvas, ctx, callback) {};

  this.videoElem = this.elem.find('video').get(0);
  this.canvasElem = this.elem.find('canvas').get(0);
  this.textOverlay = this.elem.find('.selfieVideoOverlay');
  this.counterContainer = this.elem.find('.counter-container');
  this.photoButton = this.elem.find('.selfiePhotoButton');
  this.photoButton
    .on('click', this.setSelfieType.bind(this));
  this.videoButton = this.elem.find('.selfieVideoButton');
  this.videoButton
    .on('click', this.setSelfieType.bind(this));
  this.takeButton = this.elem.find('.selfieTakeButton');
  this.takeButton
    .on('click', () => this.onselfie(this.dynamic));
  this.progress = this.elem.find('.selfieProgress');
  this.stream = null;
  this.dynamic = false; // dynamic == video
  this.videoDuration = 2; // seconds
  this.loadPreferences();

  this.durationSelector = this.elem.find('.selfieDuration');
  this.durationSelector.val(this.videoDuration);
  this.durationSelector.on('change', () => {
    this.setVideoDuration(this.durationSelector.val());
    this.savePreferences();
  });

  if (this.dynamic) {
    this.videoButton.addClass('selected');
    this.photoButton.removeClass('selected');
  }
  this.durationSelector.toggle(this.dynamic);

  // Turn off the preview when the page is not visible to save battery
  // and reduce the creepy feeling when your camera light is on because of
  // a page you forgot about.
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === 'visible') {
      if (this.stream === null) {
        this.startPreview();
      }
    } else {
      this.stopPreview();
    }
  }, false);
}

GitHubSelfieVideoPreview.prototype = {
  insert: function(element) {
    // Be careful not to insert more than one!
    this.elem.eq(0).insertAfter(element);
  },

  // Video (dynamic) needs to be resized smaller for preformnce
  resizeCanvas: function(isDynamic) {
    var scalefactor = 1 / (isDynamic ? 2 : 1);
    if (isDynamic) {
      // Video is always 320x240
      this.canvasElem.setAttribute('width', 320);
      this.canvasElem.setAttribute('height', 240);
    } else {
      this.canvasElem.setAttribute('width', this.videoElem.videoWidth);
      this.canvasElem.setAttribute('height', this.videoElem.videoHeight);
    }
  },

  setMessage: function(message) {
    if (this.textOverlay !== null) {
      this.textOverlay.text(message);
    }
  },

  // Progress in [0,1]
  setProgress: function(percent) {
    this.progress.css('width', percent*100 + "%");
  },

  destroy: function() {
    // No memory leaks here!
    this.stopPreview();
    this.elem.remove();
    this.videoElem = null;
    this.canvasElem = null;
    this.textOverlay = null;
    this.counterContainer = null;
    this.photoButton = null;
    this.videoButton = null;
    this.takeButton = null;
    this.onselfie = null;
    this.progress = null;
  },

  setVideoDuration: function(val) {
    // Just to be careful, clamp 1-4
    this.videoDuration = Math.max(1, Math.min(parseInt(val), 4));
  },

  loadPreferences: function() {
    this.dynamic = localStorage.getItem('selfieDynamic') === 'true';
    this.setVideoDuration(localStorage.getItem('selfieVideoDuration') || "2");
  },

  savePreferences: function() {
    localStorage.setItem('selfieDynamic', this.dynamic ? 'true' : 'false');
    localStorage.setItem('selfieVideoDuration', this.videoDuration.toString());
  },

  setSelfieType: function(e) {
    if ((e.target === this.photoButton.get(0) &&
         !this.photoButton.hasClass('selected')) ||
        (e.target === this.videoButton.get(0) &&
         !this.videoButton.hasClass('selected'))) {
      this.videoButton.toggleClass('selected');
      this.photoButton.toggleClass('selected');
      this.dynamic = !this.dynamic;
      this.durationSelector.toggle(this.dynamic);
      this.savePreferences();
    }
  },

  startPreview: function() {
    if (!this.videoElem) {
      return;
    }

    this.setMessage('Fetching camera stream...');

    var getUserMedia;
    if (typeof navigator.webkitGetUserMedia === 'function') {
      getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
    } else if (typeof navigator.mozGetUserMedia === 'function') {
      getUserMedia = navigator.mozGetUserMedia.bind(navigator);
    } else {
      getUserMedia = function() { alert("Your browser does not support camera input!"); };
    }

    getUserMedia({video: true}, (_stream) => {
      this.setMessage('');
      this.stream = _stream;
      this.videoElem.src = window.URL.createObjectURL(_stream);
    }, (e) => {
      this.setMessage("You don't have a camera available!");
    });
  },

  stopPreview: function() {
    if (this.stream !== null) {
      this.stream.getTracks()[0].stop();
    }
    this.stream = null;
  },

  snapSelfie: function(dynamic, takeSelfieCallback, fileCallback) {
    this.resizeCanvas(dynamic);
    var ctx = this.canvasElem.getContext('2d');
    this.selfieCountdown(
      3,
      takeSelfieCallback(this.videoElem, this.canvasElem, ctx, fileCallback));
  },

  selfieCountdown: function(count, callback) {
    if (count > 0) {
      this.counterContainer.html('
' + count + '
');
      setTimeout(() => this.selfieCountdown(count - 1, callback), 1000);
    } else {
      this.counterContainer.empty();
      if (!this.dynamic) {
        // Camera flash
        this.counterContainer.addClass('selfie-flash');
        setTimeout(() => this.counterContainer.removeClass('selfie-flash'), 1100);
      }
      callback();
    }
  }
};

// Just to be tidy, only allow one of these to exist at once. Clean up
// the old ones if we add a new one.
var selfieSingleton = null;

function GitHubSelfies() {
  this.selfiesTaken = 0;
  // Imgur client ID
  this.clientId = 'cc9df57988494ca';
  // This selector works on all pages
  this.insertAt = '.timeline-new-comment .form-actions:visible';
  this.buttons = null;
  this.textarea = null;
}

GitHubSelfies.prototype = {
  setupSelfieStream: function() {
    if (selfieSingleton !== null) {
      selfieSingleton.destroy();
      selfieSingleton = null;
    }
    selfieSingleton = this;

    var candidate = $(this.insertAt);
    if (candidate.length === 0) {
      // Try again later
      setTimeout(() => this.setupSelfieStream(), 250);
    } else {
      $('.form-actions-protip').hide();
      this.buttons = new GitHubSelfieButtons();
      this.buttons.insert(candidate);
      // TODO: this is too fragile!
      this.textarea = this.buttons.elem.parent().parent().find('textarea');
      this.setupEvents();
    }
  },

  destroy: function() {
    if (this.buttons !== null) {
      this.buttons.destroy();
    }
    this.buttons = null;
    this.textarea = null;
  },

  hideAllElements: function() {
    $('.github-selfies').addClass('hidden');
  },

  showAllElements: function() {
    $('.github-selfies').removeClass('hidden');
  },

  setupEvents: function() {
    this.buttons.onselfie = this.addSelfie.bind(this);
    $('.write-tab').on('click', this.showAllElements.bind(this));
    $('.preview-tab').on('click', this.hideAllElements.bind(this));
  },

  addSelfie: function(isDynamic) {
    var thisSelfieNumber = this.selfiesTaken++;

    var success = (res) => {
      this.replacePlaceholderInBody(thisSelfieNumber, res.data.link);
    };

    var imageSuccess = (_imageData) => {
      this.addSelfiePlaceholder(thisSelfieNumber);
      this.uploadSelfie(_imageData, success, (err) => {
        this.buttons.videoPreview.setMessage("Something went wrong :-(");
        console.error("Error uploading selfie", err);
      });
    };

    this.buttons.videoPreview.snapSelfie(
      isDynamic,
      isDynamic ? this.dynamicSelfie.bind(this) : this.staticSelfie.bind(this),
      imageSuccess);

  },

  staticSelfie: function(video, canvas, ctx, callback) {
    return function() {
      var imgBinary;

      ctx.save();
      // We used to flip this, but now the preview is just flipped in CSS.
      // Save the image non-mirrored so writing goes the right way.
      //ctx.translate(video.videoWidth, 0);
      //ctx.scale(-1, 1);
      ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, video.videoWidth, video.videoHeight);
      imgBinary = canvas.toDataURL('/image/jpeg', 1).split(',')[1];
      ctx.restore();
      callback(imgBinary);
    };
  },

  dynamicSelfie: function(video, canvas, ctx, callback) {
    return () => {
      var fps = 15;
      var totalFrames = Math.floor(this.buttons.videoPreview.videoDuration * fps);
      var interval = Math.floor(1000 / fps);
      // Height and width must be integral or the LZWEncoder will hang
      var height = Math.floor(canvas.height);
      var width = Math.floor(canvas.width);
      var frames = [];
      var frameNum = 0;
      var lastFrameTime = 0;

      var addFrame = function (encoder, frame) {
        return () => {
          return new Promise(function (resolve, reject) {
            encoder.setDelay(frame[1]);
            if (encoder.addFrame(frame[0], true)) {
              resolve(encoder);
            } else {
              reject("Error adding frame");
            }
          });
        };
      };

      var makeGif = () => {
        var encoder = new GIFEncoder();
        encoder.setSize(width, height);
        encoder.setRepeat(0);
        encoder.start();
        var promise = Promise.resolve(true);
        for (var i = 0; i < frames.length; i++) {
          promise.then(addFrame(encoder, frames[i]));
        }
        return promise
          .then(() => {
            encoder.finish();
            frames = null;
            return encoder.stream().getData();
          })
          .then(encode64)
          .then(callback);
      };

      // We use requestAnimationFrame instead of setInterval so that
      // we are better sync'ed with the video.
      var captureFrame = () => {
        // schedule another frame right away
        var rafRequest = requestAnimationFrame(captureFrame);

        var frameTime = performance.now();
        var frameDelay = frameTime - lastFrameTime;
        // Limit to a set fps by skipping this callback unless the
        // interval is greater than what we want.
        if (frameDelay >= interval) {
          frameNum++;
          lastFrameTime = frameTime;
          if (frameNum === 1) {
            frameDelay = 0;
          }
          ctx.drawImage(video,
                        0, 0, video.videoWidth, video.videoHeight,
                        0, 0, width, height);
          frames.push([ctx.getImageData(0, 0, width, height).data, frameDelay]);
          this.buttons.videoPreview.setProgress(frameNum / totalFrames);
          if (frameNum >= totalFrames) {
            cancelAnimationFrame(rafRequest);
            makeGif().then(() => this.buttons.videoPreview.setProgress(0));
          }
        }
      };

      requestAnimationFrame(captureFrame);
    };
  },

  uploadSelfie: function(imageData, successCb, errorCb) {
    $.ajax({
      url  : 'https://api.imgur.com/3/upload',
      type : 'POST',
      beforeSend: (xhr) => {
        xhr.setRequestHeader('Authorization', 'Client-ID ' + this.clientId);
      },
      data: {
        type  : 'base64',
        image : imageData
      },
      dataType : 'json',
      success  : successCb,
      error    : errorCb
    });
  },

  addSelfiePlaceholder: function(number) {
    var currentContents = this.textarea.val();
    if (currentContents !== '') {
      this.textarea.val(currentContents + '\n');
    }
    this.textarea.val(currentContents + '[[selfie-' + number + ' uploading...]]\n');
  },

  replacePlaceholderInBody: function(number, link) {
    var toReplace = '[[selfie-' + number + ' uploading...]]';

    this.textarea.val(
      this.textarea.val()
        .replace(toReplace, '[![selfie-' + number + '](' + link + ')](https://github.com/thieman/github-selfies/)'));
    this.textarea.focus();
    // Cursor to end
    var textareaElem = this.textarea.get(0);
    var textareaLength = textareaElem.textLength;
    textareaElem.setSelectionRange(textareaLength, textareaLength);
  }
};
<|endoftext|>


<commit_before>// Specifies a function to be executed when the DOM is fully loaded.
$(document).ready(function() {

	// Main function to run.
	var main = function(lat, lon, acc) {
		// Prints out the latitude, longitude and accuracy in the console.
		console.log('Latitude: ' + lat + '\r\n' + 'Longitude: ' + lon + '\r\n' + 'Accuracy: ' + acc);
		// Loads the JSON-encoded data from the server using a GET HTTP request.
		$.getJSON('http://ssd.api.port.ac.uk/v1/buildings/openaccess?access_token=bd368b12-4aed-4f5e-8797-3aa9cfe21395&callback=?', function (openaccess) {
			// Sets the open access areas.
			var oaa = openaccess;
			// Loads the JSON-encoded data from the server using a GET HTTP request.
			$.getJSON('http://ssd.api.port.ac.uk/v1/buildings?access_token=bd368b12-4aed-4f5e-8797-3aa9cfe21395&callback=?', function (buildings) {
				// Loops through all the open access areas in the array.
				for (var i = 0; i < openaccess.length; i++) {
					// Loops through all the buildings in the array.
					for (var j = 0; j < buildings.length; j++) {
						// Checks if the open access area and building references are the same.
						if (openaccess[i].building.reference == buildings[j].reference) {
							// Construct array as required.
							oaa[i]['name'] = openaccess[i].building.name;
							oaa[i]['reference'] = openaccess[i].building.reference;
							oaa[i]['latitude'] = buildings[j].latitude;
							oaa[i]['longitude'] = buildings[j].longitude;
						}
					}
					// Creates a local variable for the current building.
				}
				// Loops through all the open access areas in the array.
				for (var k = 0; k < oaa.length; k++) {
					var openacc = oaa[k];
					// Gets the availability of the PCs available in the building.
					var availability = 'Available: ' + (openacc.total - openacc.in_use) + ' / ' + openacc.total;

					// Checks if the building is open.
					if (openacc.open) {
						// Gets the percentage of available PCS in the building.
						var percentage = (openacc.total - openacc.in_use) / openacc.total * 100;
						// Tidies up the percentage and adds a percentage symbol.
						var percentagePretty = Math.floor(percentage) + '%';

						// Creates an HSL colour so as to keep the tone and just change the hue.
						var colour = 'hsl(' + percentage + ', 60%, 60%)';

						// Sets the width of the percentage bar to the percentage of available PCs.
						$('#' + openacc.reference + ' .percent').css('width', percentagePretty);
						$('#' + openacc.reference + ' .percent').text(percentagePretty);
						// Sets the colour of the percentage bar to the HSL colour.
						$('#' + openacc.reference + ' .percent').css('background', colour);

						// Checks if the inline element in the paragraph exists.
						if ($('#' + openacc.reference + ' p span').length === 0) {
							// Changes the text in the availability paragraph for the building.
							$('#' + openacc.reference + ' p').html(availability + ' ');
						}
					} else {
						// Resets the width of the percentage bar to the percentage of available PCs.
						$('#' + openacc.reference + ' .percent').css('width', '0');

						// Changes the text in the availability paragraph for the building.
						$('#' + openacc.reference + ' p').html('Closed');
					}

					// Checks that the latitude and longitude are not empty and the
					// accuracy is at a maximum of 150.
					if (lat != '' && lon != '') {
						// Runs the function to get the distance in kilometres.
						geo(openacc.reference, openacc);

						// Checks if the inline element in the heading exists.
						if ($('#' + openacc.reference + ' h1 span').length === 0) {
							// Creates a link that navigates the user from their current location to the building.
							$('#' + openacc.reference + ' h1').append('MAP');
						}
					} else {
						// Checks if the inline element in the heading exists.
						if ($('#' + openacc.reference + ' h1 span').length === 0) {
							// Creates a link that pinpoints to the building's location.
							$('#' + openacc.reference + ' h1').append('MAP');
						}
					}
				}

				// Checks that the latitude and longitude are not empty and that the
				// accuracy is at a maximum of 150.
				if (lat != '' && lon != '') {
					// Sets the first building in the array as the closest by default.
					var closest_building = oaa[0];

					// Loops through all the buildings.
					for (var l = 0; l < oaa.length; l++) {
						// Sets the current building in a variable.
						var building = oaa[l];

						// Checks if the building is open and if it's closer to
						// the user's location that the current closest building.
						if (building.open && building.distance < closest_building.distance) {
							// Sets the current building as the new closest building.
							closest_building = building;
						}
					}

					// Changes the text in the inline element accordingly.
					$('#' + closest_building.reference + ' p span').html('' + $('#' + closest_building.reference + ' p span').text() + '');
				}
			});
		});
	};

	// Runs the main function once geolocation variables are received.
	var start = function(lat, lon, acc) {
		// Runs the function for a first time with the geolocation variables.
		main(lat, lon, acc);

		// Runs the function again every 5 seconds.
		setInterval(function() {
			main(lat, lon, acc);
		}, 5000);
	};

	// Sets the PositionOptions to be used to get the user's current location.
	var options = {
		enableHighAccuracy: true,
		maximumAge: 0
	};

	// Callback function that takes a Position object as its sole input parameter.
	var success = function(pos) {
		// Clears the timeout of the fail timer.
		clearTimeout(fail_timeout);
		// Creates a variable that gets the coordinates from the input parameter.
		var current = pos.coords;

		// Passes the coordinates to the variables created earlier.
		lat = current.latitude;
		lon = current.longitude;
		acc = current.accuracy;

		// Runs the start function with the geolocation variables received.
		start(lat, lon, acc);
	};

	// Callback that takes a PositionError object as its sole input parameter.
	var error = function(err) {
		// Clears the timeout of the fail timer.
		clearTimeout(fail_timeout);
		// Runs the start function with no geolocation.
		start('', '', '');
	};

	// Gets the distance in kilometres and returns it on the building availability.
	var geo = function(id, building) {
		building.distance = latlontokm(lat, lon, building.latitude, building.longitude);
		var dist = building.distance.toString().substr(0, building.distance.toString().indexOf('.'));
		var time = dist / 0.7;
		var hours = Math.floor(time / 3600);
		var minutes = Math.floor(time / 60);
		$('#' + id + ' p span').html(dist + 'm  • ETA: ' + minutes + 'm');
	};

	// Gets the difference in kilometres for the two destinations.
	var latlontokm = function(lat1, lon1, lat2, lon2) {
		var R = 6371;
		var dLat = deg2rad(lat2-lat1);
		var dLon = deg2rad(lon2-lon1);
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		var d = R * c;
		return d * 1000;
	};

	// Converts degrees to radius.
	var deg2rad = function(deg) {
		return deg * (Math.PI/180);
	};

	// Runs the function without geolocation while we are awaiting confirmation
	// for using geolocation.
	var fail = function() {
		start('', '', '');
	};

	// Sets the default values for the latitude, longitude and accuracy variables.
	var lat = '';
	var lon = '';
	var acc = '';

	// Runs a timer while we are waiting for the user to allow geolocation.
	var fail_timeout = setTimeout(function() { fail(); }, 2000);

	// Checks if geolocation is available on this device.
	if (navigator.geolocation) {
		// Uses a geolocation method to get the current position of the device.
		navigator.geolocation.getCurrentPosition(success, error, options);
	} else {
		// Runs the function without geolocation.
		console.dir('Geolocation is not supported by this browser');
		fail();
	}
});<commit_msg>Updated the timer.<commit_after>// Specifies a function to be executed when the DOM is fully loaded.
$(document).ready(function() {

	// Main function to run.
	var main = function(lat, lon, acc) {
		// Prints out the latitude, longitude and accuracy in the console.
		console.log('Latitude: ' + lat + '\r\n' + 'Longitude: ' + lon + '\r\n' + 'Accuracy: ' + acc);
		// Loads the JSON-encoded data from the server using a GET HTTP request.
		$.getJSON('http://ssd.api.port.ac.uk/v1/buildings/openaccess?access_token=bd368b12-4aed-4f5e-8797-3aa9cfe21395&callback=?', function (openaccess) {
			// Sets the open access areas.
			var oaa = openaccess;
			// Loads the JSON-encoded data from the server using a GET HTTP request.
			$.getJSON('http://ssd.api.port.ac.uk/v1/buildings?access_token=bd368b12-4aed-4f5e-8797-3aa9cfe21395&callback=?', function (buildings) {
				// Loops through all the open access areas in the array.
				for (var i = 0; i < openaccess.length; i++) {
					// Loops through all the buildings in the array.
					for (var j = 0; j < buildings.length; j++) {
						// Checks if the open access area and building references are the same.
						if (openaccess[i].building.reference == buildings[j].reference) {
							// Construct array as required.
							oaa[i]['name'] = openaccess[i].building.name;
							oaa[i]['reference'] = openaccess[i].building.reference;
							oaa[i]['latitude'] = buildings[j].latitude;
							oaa[i]['longitude'] = buildings[j].longitude;
						}
					}
					// Creates a local variable for the current building.
				}
				// Loops through all the open access areas in the array.
				for (var k = 0; k < oaa.length; k++) {
					var openacc = oaa[k];
					// Gets the availability of the PCs available in the building.
					var availability = 'Available: ' + (openacc.total - openacc.in_use) + ' / ' + openacc.total;

					// Checks if the building is open.
					if (openacc.open) {
						// Gets the percentage of available PCS in the building.
						var percentage = (openacc.total - openacc.in_use) / openacc.total * 100;
						// Tidies up the percentage and adds a percentage symbol.
						var percentagePretty = Math.floor(percentage) + '%';

						// Creates an HSL colour so as to keep the tone and just change the hue.
						var colour = 'hsl(' + percentage + ', 60%, 60%)';

						// Sets the width of the percentage bar to the percentage of available PCs.
						$('#' + openacc.reference + ' .percent').css('width', percentagePretty);
						$('#' + openacc.reference + ' .percent').text(percentagePretty);
						// Sets the colour of the percentage bar to the HSL colour.
						$('#' + openacc.reference + ' .percent').css('background', colour);

						// Checks if the inline element in the paragraph exists.
						if ($('#' + openacc.reference + ' p span').length === 0) {
							// Changes the text in the availability paragraph for the building.
							$('#' + openacc.reference + ' p').html(availability + ' ');
						}
					} else {
						// Resets the width of the percentage bar to the percentage of available PCs.
						$('#' + openacc.reference + ' .percent').css('width', '0');

						// Changes the text in the availability paragraph for the building.
						$('#' + openacc.reference + ' p').html('Closed');
					}

					// Checks that the latitude and longitude are not empty and the
					// accuracy is at a maximum of 150.
					if (lat != '' && lon != '') {
						// Runs the function to get the distance in kilometres.
						geo(openacc.reference, openacc);

						// Checks if the inline element in the heading exists.
						if ($('#' + openacc.reference + ' h1 span').length === 0) {
							// Creates a link that navigates the user from their current location to the building.
							$('#' + openacc.reference + ' h1').append('MAP');
						}
					} else {
						// Checks if the inline element in the heading exists.
						if ($('#' + openacc.reference + ' h1 span').length === 0) {
							// Creates a link that pinpoints to the building's location.
							$('#' + openacc.reference + ' h1').append('MAP');
						}
					}
				}

				// Checks that the latitude and longitude are not empty and that the
				// accuracy is at a maximum of 150.
				if (lat != '' && lon != '') {
					// Sets the first building in the array as the closest by default.
					var closest_building = oaa[0];

					// Loops through all the buildings.
					for (var l = 0; l < oaa.length; l++) {
						// Sets the current building in a variable.
						var building = oaa[l];

						// Checks if the building is open and if it's closer to
						// the user's location that the current closest building.
						if (building.open && building.distance < closest_building.distance) {
							// Sets the current building as the new closest building.
							closest_building = building;
						}
					}

					// Changes the text in the inline element accordingly.
					$('#' + closest_building.reference + ' p span').html('' + $('#' + closest_building.reference + ' p span').text() + '');
				}
			});
		});
	};

	// Runs the main function once geolocation variables are received.
	var start = function(lat, lon, acc) {
		// Runs the function for a first time with the geolocation variables.
		main(lat, lon, acc);

		// Runs the function again every 5 seconds.
		setInterval(function() {
			main(lat, lon, acc);
		}, 2000);
	};

	// Sets the PositionOptions to be used to get the user's current location.
	var options = {
		enableHighAccuracy: true,
		maximumAge: 0
	};

	// Callback function that takes a Position object as its sole input parameter.
	var success = function(pos) {
		// Clears the timeout of the fail timer.
		clearTimeout(fail_timeout);
		// Creates a variable that gets the coordinates from the input parameter.
		var current = pos.coords;

		// Passes the coordinates to the variables created earlier.
		lat = current.latitude;
		lon = current.longitude;
		acc = current.accuracy;

		// Runs the start function with the geolocation variables received.
		start(lat, lon, acc);
	};

	// Callback that takes a PositionError object as its sole input parameter.
	var error = function(err) {
		// Clears the timeout of the fail timer.
		clearTimeout(fail_timeout);
		// Runs the start function with no geolocation.
		start('', '', '');
	};

	// Gets the distance in kilometres and returns it on the building availability.
	var geo = function(id, building) {
		building.distance = latlontokm(lat, lon, building.latitude, building.longitude);
		var dist = building.distance.toString().substr(0, building.distance.toString().indexOf('.'));
		var time = dist / 0.7;
		var hours = Math.floor(time / 3600);
		var minutes = Math.floor(time / 60);
		$('#' + id + ' p span').html(dist + 'm  • ETA: ' + minutes + 'm');
	};

	// Gets the difference in kilometres for the two destinations.
	var latlontokm = function(lat1, lon1, lat2, lon2) {
		var R = 6371;
		var dLat = deg2rad(lat2-lat1);
		var dLon = deg2rad(lon2-lon1);
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon/2) * Math.sin(dLon/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		var d = R * c;
		return d * 1000;
	};

	// Converts degrees to radius.
	var deg2rad = function(deg) {
		return deg * (Math.PI/180);
	};

	// Runs the function without geolocation while we are awaiting confirmation
	// for using geolocation.
	var fail = function() {
		start('', '', '');
	};

	// Sets the default values for the latitude, longitude and accuracy variables.
	var lat = '';
	var lon = '';
	var acc = '';

	// Runs a timer while we are waiting for the user to allow geolocation.
	var fail_timeout = setTimeout(function() { fail(); }, 2000);

	// Checks if geolocation is available on this device.
	if (navigator.geolocation) {
		// Uses a geolocation method to get the current position of the device.
		navigator.geolocation.getCurrentPosition(success, error, options);
	} else {
		// Runs the function without geolocation.
		console.dir('Geolocation is not supported by this browser');
		fail();
	}
});<|endoftext|>


<commit_before>/*
for each li
	color = find span color --- this.text
	url = find main prod image -- this.url
	category Swatch Color Button = matching color.url
end

on click
*/

var colorBtnSrc = {};

$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').each( function getColorPhotosSrcs(){

	var listings = $(this);
		prodColor = $(this).find('.name').text();
	console.log(prodColor);
	$(this).find('label').click();

	// find url of img when this li is checked and store it
//	for (i = 0; i < listings.length; i++) {
//		var colorImgSrc += $(document).find('.MagicZoomPlus img').attr('src');
//		console.log(colorImgSrc);
//	}

	var colorBtnSrc[color] = $(document).find('.MagicZoomPlus img').attr('src');

})

console.log(colorBtnSrc);

//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').removeClass('selectedValue').find('.radio span').removeClass('checked');
//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').eq(2).addClass('selectedValue').find('.radio span').addClass('checked');

//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').eq(2).find('label').click();<commit_msg>URL still not working<commit_after>/*
for each li
	color = find span color --- this.text
	url = find main prod image -- this.url
	category Swatch Color Button = matching color.url
end

on click
*/

var colorBtnSrc = {};

$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').each( function getColorPhotosSrcs(){

	var listings = $(this);
		prodColor = $(this).find('.name').text();
	console.log(prodColor);
	$(this).find('label').click();

	// find url of img when this li is checked and store it
//	for (i = 0; i < listings.length; i++) {
//		var colorImgSrc += $(document).find('.MagicZoomPlus img').attr('src');
//		console.log(colorImgSrc);
//	}

	colorBtnSrc[prodColor] = $(document).find('.MagicZoomPlus img').attr('src');

})

console.log(colorBtnSrc);

//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').removeClass('selectedValue').find('.radio span').removeClass('checked');
//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').eq(2).addClass('selectedValue').find('.radio span').addClass('checked');

//$("span:contains('Color')").parents().eq(2).find('.productAttributeValue li').eq(2).find('label').click();<|endoftext|>


<commit_before>		//Classe para emular o objeto de geolocalizacao
		function Position(latitude, longitude, altitude, accurary, altitudeAccuracy, heading, speed) {
			this.coords = function(latitude, longitude, altitude, accurary, altitudeAccuracy, heading, speed) {
				this.latitude = latitude;
				this.longitude = longitude;
				this.altitude = altitude;
				this.accuracy = accuracy;
				this.altitudeAccuracy = altitudeAccuracy;
				this.heading = heading;
				this.speed = speed;
			}
		}

		var Position2 = {
			coords : {
				latitude : "",
				longitude : "",
				altitude : "",
				accuracy : "",
				altitudeAccuracy : "",
				heading : "",
				speed : ""
			}
		}

		function echeck(str) {
			var at="@"
			var dot="."
			var lat=str.indexOf(at)
			var lstr=str.length
			var ldot=str.indexOf(dot)
			if (str.indexOf(at)==-1){
			   //alert("Invalid E-mail ID")
			   return false
			}

			if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
			   //alert("Invalid E-mail ID")
			   return false
			}

			if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
				//alert("Invalid E-mail ID")
				return false
			}

			 if (str.indexOf(at,(lat+1))!=-1){
				//alert("Invalid E-mail ID")
				return false
			 }

			 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
				//alert("Invalid E-mail ID")
				return false
			 }

			 if (str.indexOf(dot,(lat+2))==-1){
				//alert("Invalid E-mail ID")
				return false
			 }

			 if (str.indexOf(" ")!=-1){
				//alert("Invalid E-mail ID")
				return false
			 }

			 return true
		}

		function rand(min,max,interval)	{
			if (typeof(interval)==='undefined') interval = 1;
			var r = Math.floor(Math.random()*(max-min+interval)/interval);
			return r*interval+min;
		}

		//Funcoes especificas do Phonegap

		var celular_modelo = "";
		var celular_plataforma = "";
		var celular_uuid = "";
		var celular_versao = "";
		var isPhoneGapReady = false;
		var isConnected = false;
		var isHighSpeed = false;
		var status_bateria = "aguarde...";
		var watchID;
		var retorno_rastreio = "(nao houve o envio de dados)";

		//Variaveis da aplicacao
		var email_aplicativo;
		var var_chave;

		// Wait for device API libraries to load
		// device APIs are available
		//

		document.addEventListener("deviceready", onDeviceReady, false);

		function onDeviceReady() {

			isPhoneGapReady = true;
			// detect for network access
			networkDetection();
			// attach events for online and offline detection
			document.addEventListener("online", onOnline, false);
			document.addEventListener("offline", onOffline, false);
			document.addEventListener("batterystatus", onBatteryStatus, false);

			var conteudo = "";
			conteudo = conteudo + 'Modelo: '    + device.model    + '
';
			conteudo = conteudo + 'Plataforma: ' + device.platform + '
';
			conteudo = conteudo + 'UUID: '     + device.uuid     + '
';
			conteudo = conteudo + 'Verso: '  + device.version  + '
';
			conteudo = conteudo + 'Bateria: '  + status_bateria  + '
';

			celular_modelo = device.model;
			celular_plataforma = device.platform;
			celular_uuid = device.uuid;
			celular_versao = device.version;

			$("#deviceproperties").append(conteudo);
		}

		 // alert dialog dismissed
		function alertDismissed() {
			// do something
		}

		function formatAMPM() {
			var date = new Date();
			var hours = date.getHours();
			var days = date.getDay();
			var minutes = date.getMinutes();
			var ampm = hours >= 12 ? 'pm' : 'am';
			hours = hours % 12;
			hours = hours ? hours : 12; // the hour '0' should be '12'
			minutes = minutes < 10 ? '0'+minutes : minutes;
			var strTime = date + ' ' + hours + ':' + minutes + ' ' + ampm;
			return strTime;
		}

		function networkDetection() {
			if (isPhoneGapReady) {
				// as long as the connection type is not none,
				// the device should have Internet access

				isConnected = true;
				isHighSpeed = true;
				//O codigo abaixo somente funciona no dispositivo
				//if (navigator.network.connection.type != Connection.NONE) {
				//	isConnected = true;
				//}
				// determine whether this connection is high-speed
				//switch (navigator.network.connection.type) {
				//	case Connection.UNKNOWN:
				//	case Connection.CELL_2G:
				//	isHighSpeed = false;
				//	break;
				//	default:
				//	isHighSpeed = true;
				//	break;
				//}
			}
		}

		function onOnline() {
			isConnected = true;
		}
		function onOffline() {
			isConnected = false;
		}

		function onBatteryStatus(battery_info) {
			status_bateria = battery_info.level + '%';
		}

		$(document).on('pageshow', '#posicao', function(){
			if (isPhoneGapReady){
				if (isConnected) {
					// load the google api
					var fileref=document.createElement('script');
					fileref.setAttribute("type","text/javascript");
					fileref.setAttribute("src",	"http://maps.googleapis.com/maps/api/js?sensor=true&callback=" + "getGeolocation");
					document.getElementsByTagName("head")[0].appendChild(fileref);
				} else {
					navigator.notification.alert('No existe conexo com a Internet', alertDismissed, 'Rastreio Mobile', 'OK');
					$.mobile.changePage("#pageone");
				}
			} else {
				navigator.notification.alert('O aplicativo no est pronto!', alertDismissed, 'Rastreio Mobile', 'OK');
				$.mobile.changePage("#pageone");
			}
		});

		//Funcoes para exibir o mapa
		function getGeolocation() {
			$.mobile.loading('show', {
				theme: "a",
				text: "Aguarde...",
				textonly: true,
				textVisible: true
			});
			// get the user's gps coordinates and display map
			var options = {
			maximumAge: 3000,
			timeout: 5000,
			enableHighAccuracy: true
			};
			navigator.geolocation.getCurrentPosition(loadMap, geoError, options);
		}

		function loadMap(position) {
			var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
			var myOptions = {
			zoom: 16,
			center: latlng,
			mapTypeId: google.maps.MapTypeId.ROADMAP
			};

			var mapObj = document.getElementById("map_canvas");
			var map = new google.maps.Map(mapObj, myOptions);
			var marker = new google.maps.Marker({
			position: latlng,
			map: map,
			title:"You"
			});
			$.mobile.loading('hide');
		}

		function geoError(error) {
			alert('codigo: ' + error.code + '\n' + 'mensagem: ' + error.message + '\n');
		}

		function ajaxCallBackRASTREIO(retString){
			retorno_rastreio = retString;
		}

		//Funcoes para o rastremanto automatico
		function onSuccessRastreio(position){

			var var_latitude = position.coords.latitude;
			var var_longitude = position.coords.longitude;
			var var_altitude = position.coords.altitude;
			var var_accuracy = position.coords.accuracy;
			var var_altitude_accuracy = position.coords.altitudeAccuracy;
			var var_heading = position.coords.heading;
			var var_speed = position.coords.speed;

			//Zerando campos que podem vir nulos
			if(!var_altitude) {
				var_altitude = 0;
			}
			if(!var_altitude_accuracy) {
				var_altitude_accuracy = 0;
			}
			if(!var_heading) {
				var_heading = 0;
			}
			if(!var_speed) {
				var_speed = 0;
			}

			$.ajax({
			type: "POST",
			url: "http://www.interiornaweb.com.br/rastreio_mobile_teste.php",
			dataType:"text",
			data: {latitude: var_latitude, longitude: var_longitude, altitude: var_altitude, accuracy: var_accuracy, altitude_accuracy: var_altitude_accuracy, heading: var_heading, speed: var_speed, gravar: "SIM", chave: var_chave, email: email_aplicativo},
			async: true,
			error: function(request, status, error) {

				//alert(request.responseText);
				ajaxCallBackRASTREIO("(Houve um problema de comunicacao com os nossos sistemas)");
			}
			}).done(function(data) {
				//Nao faz nada

				if (data == 1){
					ajaxCallBackRASTREIO("(Dados gravados com sucesso - ultima atualizacao:" + formatAMPM() + ")");
					var element = document.getElementById("posicao_atual");
					element.innerHTML = "Latitude: " + position.coords.latitude + "
" +
					"Longitude: " + position.coords.longitude + "
"+ "Altitude: " + var_altitude + "
" + "Accuracy:" + var_accuracy + "
" + "Altitude Accuracy:" + var_altitude_accuracy + "
" + "Heading: " + var_heading + "
" + "Speed: " + var_speed + "
Dados gravados com sucesso - ultima atualizacao:" + formatAMPM() + ")
";
				} else {
					ajaxCallBackRASTREIO("(Houve um problema ao gravar os dados)");
				}
			});
			var element = document.getElementById("posicao_atual");
			element.innerHTML = "Latitude: " + position.coords.latitude + "
" +
			"Longitude: " + position.coords.longitude + "
"+ "Altitude: " + var_altitude + "
" + "Accuracy:" + var_accuracy + "
" + "Altitude Accuracy:" + var_altitude_accuracy + "
" + "Heading: " + var_heading + "
" + "Speed: " + var_speed + "
" + retorno_rastreio + "
";
		}

		function DesativarRastreio(){
			//Habilitar em producao
			navigator.geolocation.clearWatch(watchID);
			clearTimeout(watchID);

			//Mandar por e-mail o resultado
			$.ajax({
			type: "POST",
			url: "http://www.interiornaweb.com.br/rastreio_mobile_teste_email.php",
			dataType:"text",
			data: {gravar: "SIM", chave: var_chave, email: email_aplicativo},
			async: true,
			error: function(request, status, error) {

				//alert(request.responseText);
				ajaxCallBackRASTREIO("(Houve um problema de comunicacao com os nossos sistemas)");
			}
			}).done(function(data) {
				//Nao faz nada
			});

			$.mobile.changePage("#pageone");
		}

		$(document).on('pageshow', '#rastreio', function(){
			if (isPhoneGapReady){
				if (isConnected) {
					//rastreando
					navigator.notification.alert('iniciando o rastreio...', alertDismissed, 'Rastreio Mobile', 'OK');
					objeto_position = new Position("43,425397", "-80,442334", 100, 10, 10, 0, 0);
					console.log(objeto_position);
					//Ambiente de testes
					//watchID = setInterval(onSuccessRastreio(objeto_position), 3000);
					//Habilitar em producao
					watchID = navigator.geolocation.watchPosition(onSuccessRastreio, geoError,{timeout: 10000, enableHighAccuracy: false, frequency: 10000 }); //10 segundos

					//watchID = setInterval(function(){navigator.geolocation.getCurrentPosition(onSuccessRastreio, geoError, ,{timeout: 10000, enableHighAccuracy: false})},10000); //10 segundos

				} else {
					navigator.notification.alert('No existe conexo com a Internet', alertDismissed, 'Rastreio Mobile', 'OK');
					$.mobile.changePage("#pageone");
				}
			} else {
				navigator.notification.alert('O aplicativo no est pronto!', alertDismissed, 'Rastreio Mobile', 'OK');
				$.mobile.changePage("#pageone");
			}
		});

		$(document).on('pageinit', '#pageone', function(){

			var_chave = rand(1000,9999,1);

			$(document).on('click', '#enviar_contato', function() { // catch the form's submit event

				var continuar = true;
				var mensagem ="Ocorreram os seguintes erros:\n";

				if ($('#email_contato').val() == "") {
					mensagem = mensagem +  'Digite o endereco de e-mail\n';
					continuar = false;
				} else {
					if (echeck($('#email_contato').val())==false){
					mensagem = mensagem + 'Preencha corretamente o endereco de e-mail\n';
					continuar = false;
					}
				}

				if (continuar){
					email_aplicativo = $('#email_contato').val();
					$.mobile.changePage("#posicao");
				} else {
					alert(mensagem);
				}
				return false; // cancel original event to prevent form submitting

			});
		});

		<commit_msg>2015-11-07<commit_after>		//http://www.javascriptlint.com/online_lint.php

		//Classe para emular o objeto de geolocalizacao
		function Position(latitude, longitude, altitude, accurary, altitudeAccuracy, heading, speed) {
			this.coords = function(latitude, longitude, altitude, accurary, altitudeAccuracy, heading, speed) {
				this.latitude = latitude;
				this.longitude = longitude;
				this.altitude = altitude;
				this.accuracy = accuracy;
				this.altitudeAccuracy = altitudeAccuracy;
				this.heading = heading;
				this.speed = speed;
			};
		}

		var Position2 = {
			coords : {
				latitude : "",
				longitude : "",
				altitude : "",
				accuracy : "",
				altitudeAccuracy : "",
				heading : "",
				speed : ""
			}
		};

		function echeck(str) {
			var at="@";
			var dot=".";
			var lat=str.indexOf(at);
			var lstr=str.length;
			var ldot=str.indexOf(dot);
			if (str.indexOf(at)==-1){
			   //alert("Invalid E-mail ID")
			   return false;
			}

			if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){
			   //alert("Invalid E-mail ID")
			   return false;
			}

			if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){
				//alert("Invalid E-mail ID")
				return false;
			}

			 if (str.indexOf(at,(lat+1))!=-1){
				//alert("Invalid E-mail ID")
				return false;
			 }

			 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){
				//alert("Invalid E-mail ID")
				return false;
			 }

			 if (str.indexOf(dot,(lat+2))==-1){
				//alert("Invalid E-mail ID")
				return false;
			 }

			 if (str.indexOf(" ")!=-1){
				//alert("Invalid E-mail ID")
				return false;
			 }

			 return true;
		}

		function rand(min,max,interval)	{
			if (typeof(interval)==='undefined') {
			interval = 1;
			}
			var r = Math.floor(Math.random()*(max-min+interval)/interval);
			return r*interval+min;
		}

		//Funcoes especificas do Phonegap

		var celular_modelo = "";
		var celular_plataforma = "";
		var celular_uuid = "";
		var celular_versao = "";
		var isPhoneGapReady = false;
		var isConnected = false;
		var isHighSpeed = false;
		var status_bateria = "aguarde...";
		var watchID;
		var retorno_rastreio = "(nao houve o envio de dados)";

		//Variaveis da aplicacao
		var email_aplicativo;
		var var_chave;

		// Wait for device API libraries to load
		// device APIs are available
		//

		document.addEventListener("deviceready", onDeviceReady, false);

		function onDeviceReady() {

			isPhoneGapReady = true;
			// detect for network access
			networkDetection();
			// attach events for online and offline detection
			document.addEventListener("online", onOnline, false);
			document.addEventListener("offline", onOffline, false);
			document.addEventListener("batterystatus", onBatteryStatus, false);

			var conteudo = "";
			conteudo = conteudo + 'Modelo: '    + device.model    + '
';
			conteudo = conteudo + 'Plataforma: ' + device.platform + '
';
			conteudo = conteudo + 'UUID: '     + device.uuid     + '
';
			conteudo = conteudo + 'Verso: '  + device.version  + '
';
			conteudo = conteudo + 'Bateria: '  + status_bateria  + '
';

			celular_modelo = device.model;
			celular_plataforma = device.platform;
			celular_uuid = device.uuid;
			celular_versao = device.version;

			$("#deviceproperties").append(conteudo);
		}

		 // alert dialog dismissed
		function alertDismissed() {
			// do something
		}

		function formatAMPM() {
			var date = new Date();
			var hours = date.getHours();
			var days = date.getDay();
			var minutes = date.getMinutes();
			var ampm = hours >= 12 ? 'pm' : 'am';
			hours = hours % 12;
			hours = hours ? hours : 12; // the hour '0' should be '12'
			minutes = minutes < 10 ? '0'+minutes : minutes;
			var strTime = date + ' ' + hours + ':' + minutes + ' ' + ampm;
			return strTime;
		}

		function networkDetection() {
			if (isPhoneGapReady) {
				// as long as the connection type is not none,
				// the device should have Internet access

				isConnected = true;
				isHighSpeed = true;
				//O codigo abaixo somente funciona no dispositivo
				//if (navigator.network.connection.type != Connection.NONE) {
				//	isConnected = true;
				//}
				// determine whether this connection is high-speed
				//switch (navigator.network.connection.type) {
				//	case Connection.UNKNOWN:
				//	case Connection.CELL_2G:
				//	isHighSpeed = false;
				//	break;
				//	default:
				//	isHighSpeed = true;
				//	break;
				//}
			}
		}

		function onOnline() {
			isConnected = true;
		}
		function onOffline() {
			isConnected = false;
		}

		function onBatteryStatus(battery_info) {
			status_bateria = battery_info.level + '%';
		}

		$(document).on('pageshow', '#posicao', function(){
			if (isPhoneGapReady){
				if (isConnected) {
					// load the google api
					var fileref=document.createElement('script');
					fileref.setAttribute("type","text/javascript");
					fileref.setAttribute("src",	"http://maps.googleapis.com/maps/api/js?sensor=true&callback=" + "getGeolocation");
					document.getElementsByTagName("head")[0].appendChild(fileref);
				} else {
					navigator.notification.alert('No existe conexo com a Internet', alertDismissed, 'Rastreio Mobile', 'OK');
					$.mobile.changePage("#pageone");
				}
			} else {
				navigator.notification.alert('O aplicativo no est pronto!', alertDismissed, 'Rastreio Mobile', 'OK');
				$.mobile.changePage("#pageone");
			}
		});

		//Funcoes para exibir o mapa
		function getGeolocation() {
			$.mobile.loading('show', {
				theme: "a",
				text: "Aguarde...",
				textonly: true,
				textVisible: true
			});
			// get the user's gps coordinates and display map
			var options = {
			maximumAge: 3000,
			timeout: 5000,
			enableHighAccuracy: true
			};
			navigator.geolocation.getCurrentPosition(loadMap, geoError, options);
		}

		function loadMap(position) {
			var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
			var myOptions = {
			zoom: 16,
			center: latlng,
			mapTypeId: google.maps.MapTypeId.ROADMAP
			};

			var mapObj = document.getElementById("map_canvas");
			var map = new google.maps.Map(mapObj, myOptions);
			var marker = new google.maps.Marker({
			position: latlng,
			map: map,
			title:"You"
			});
			$.mobile.loading('hide');
		}

		function geoError(error) {
			alert('codigo: ' + error.code + '\n' + 'mensagem: ' + error.message + '\n');
		}

		function ajaxCallBackRASTREIO(retString){
			retorno_rastreio = retString;
		}

		//Funcoes para o rastremanto automatico
		function onSuccessRastreio(position){

			var var_latitude = position.coords.latitude;
			var var_longitude = position.coords.longitude;
			var var_altitude = position.coords.altitude;
			var var_accuracy = position.coords.accuracy;
			var var_altitude_accuracy = position.coords.altitudeAccuracy;
			var var_heading = position.coords.heading;
			var var_speed = position.coords.speed;

			//Zerando campos que podem vir nulos
			if(!var_altitude) {
				var_altitude = 0;
			}
			if(!var_altitude_accuracy) {
				var_altitude_accuracy = 0;
			}
			if(!var_heading) {
				var_heading = 0;
			}
			if(!var_speed) {
				var_speed = 0;
			}

			$.ajax({
			type: "POST",
			url: "http://www.interiornaweb.com.br/rastreio_mobile_teste.php",
			dataType:"text",
			data: {latitude: var_latitude, longitude: var_longitude, altitude: var_altitude, accuracy: var_accuracy, altitude_accuracy: var_altitude_accuracy, heading: var_heading, speed: var_speed, gravar: "SIM", chave: var_chave, email: email_aplicativo},
			async: true,
			error: function(request, status, error) {

				//alert(request.responseText);
				ajaxCallBackRASTREIO("(Houve um problema de comunicacao com os nossos sistemas)");
			}
			}).done(function(data) {
				//Nao faz nada

				if (data == 1){
					ajaxCallBackRASTREIO("(Dados gravados com sucesso - ultima atualizacao:" + formatAMPM() + ")");
					var element = document.getElementById("posicao_atual");
					element.innerHTML = "Latitude: " + position.coords.latitude + "
" +
					"Longitude: " + position.coords.longitude + "
"+ "Altitude: " + var_altitude + "
" + "Accuracy:" + var_accuracy + "
" + "Altitude Accuracy:" + var_altitude_accuracy + "
" + "Heading: " + var_heading + "
" + "Speed: " + var_speed + "
Dados gravados com sucesso - ultima atualizacao:" + formatAMPM() + ")
";
				} else {
					ajaxCallBackRASTREIO("(Houve um problema ao gravar os dados)");
				}
			});
			var element = document.getElementById("posicao_atual");
			element.innerHTML = "Latitude: " + position.coords.latitude + "
" +
			"Longitude: " + position.coords.longitude + "
"+ "Altitude: " + var_altitude + "
" + "Accuracy:" + var_accuracy + "
" + "Altitude Accuracy:" + var_altitude_accuracy + "
" + "Heading: " + var_heading + "
" + "Speed: " + var_speed + "
" + retorno_rastreio + "
";
		}

		function DesativarRastreio(){
			//Habilitar em producao
			navigator.geolocation.clearWatch(watchID);
			clearTimeout(watchID);

			//Mandar por e-mail o resultado
			$.ajax({
			type: "POST",
			url: "http://www.interiornaweb.com.br/rastreio_mobile_teste_email.php",
			dataType:"text",
			data: {gravar: "SIM", chave: var_chave, email: email_aplicativo},
			async: true,
			error: function(request, status, error) {

				//alert(request.responseText);
				ajaxCallBackRASTREIO("(Houve um problema de comunicacao com os nossos sistemas)");
			}
			}).done(function(data) {
				//Nao faz nada
			});

			$.mobile.changePage("#pageone");
		}

		$(document).on('pageshow', '#rastreio', function(){
			if (isPhoneGapReady){
				if (isConnected) {
					//rastreando
					navigator.notification.alert('iniciando o rastreio...', alertDismissed, 'Rastreio Mobile', 'OK');
					objeto_position = new Position("43,425397", "-80,442334", 100, 10, 10, 0, 0);
					console.log(objeto_position);
					//Ambiente de testes
					//watchID = setInterval(onSuccessRastreio(objeto_position), 3000);
					//Habilitar em producao
					watchID = navigator.geolocation.watchPosition(onSuccessRastreio, geoError,{timeout: 10000, enableHighAccuracy: false, frequency: 10000 }); //10 segundos

					//watchID = setInterval(function(){navigator.geolocation.getCurrentPosition(onSuccessRastreio, geoError, ,{timeout: 10000, enableHighAccuracy: false})},10000); //10 segundos

				} else {
					navigator.notification.alert('No existe conexo com a Internet', alertDismissed, 'Rastreio Mobile', 'OK');
					$.mobile.changePage("#pageone");
				}
			} else {
				navigator.notification.alert('O aplicativo no est pronto!', alertDismissed, 'Rastreio Mobile', 'OK');
				$.mobile.changePage("#pageone");
			}
		});

		$(document).on('pageinit', '#pageone', function(){

			var_chave = rand(1000,9999,1);

			$(document).on('click', '#enviar_contato', function() { // catch the form's submit event

				var continuar = true;
				var mensagem ="Ocorreram os seguintes erros:\n";

				if ($('#email_contato').val() == "") {
					mensagem = mensagem +  'Digite o endereco de e-mail\n';
					continuar = false;
				} else {
					if (echeck($('#email_contato').val())==false){
					mensagem = mensagem + 'Preencha corretamente o endereco de e-mail\n';
					continuar = false;
					}
				}

				if (continuar){
					email_aplicativo = $('#email_contato').val();
					$.mobile.changePage("#posicao");
				} else {
					alert(mensagem);
				}
				return false; // cancel original event to prevent form submitting

			});
		});

		<|endoftext|>


<commit_before>/*
Template Name: Appx360
Author: Nam
Version: 1.0
*/

jQuery(function ($) {

    'use strict';

    /* ======= Blank Wrapper ======= */
    (function () {

        // content here...

    }());

    /* ======= Preloader ======= */
    (function () {
        $('#status').fadeOut();
        $('#preloader').delay(200).fadeOut('slow');
    }());

    /* ======= Search box ======= */
    (function () {
        $("#search-box").hide();
            var searchIcon = $(".search-icon");
            var searchBox = $("#search-box");
            searchIcon.on('click', function(event) {
            searchIcon.toggleClass("active");
            searchBox.slideToggle();
        });
    }());

    /* === jQuery for page scrolling feature - requires jQuery Easing plugin === */
    (function () {
        $('a.page-scroll').on('click', function(event) {
            var $anchor = $(this);
            $('html, body').stop().animate({
                scrollTop: $($anchor.attr('href')).offset().top
            }, 1500, 'easeInOutExpo');
            event.preventDefault();
        });
    }());

    /* === Sticky Menu === */
    (function () {
        var nav = $('.navbar');
        var scrolled = false;

        $(window).scroll(function () {

            if (110 < $(window).scrollTop() && !scrolled) {
                nav.addClass('sticky animated fadeInDown').animate({ 'margin-top': '0px' });

                scrolled = true;
            }

            if (110 > $(window).scrollTop() && scrolled) {
                nav.removeClass('sticky animated fadeInDown').css('margin-top', '0px');

                scrolled = false;
            }
        });
    }());

    /* === Progress Bar === */
    (function () {
        $('.progress').on('inview', function(event, visible, visiblePartX, visiblePartY) {
            if (visible) {
                $.each($('div.progress-bar'),function(){
                    $(this).css('width', $(this).attr('aria-valuenow')+'%');
                });
                $(this).off('inview');
            }
        });
    }());

    /* === Counter === */
    (function () {
        $('.counter-section').on('inview', function(event, visible, visiblePartX, visiblePartY) {
            if (visible) {
                $(this).find('.timer').each(function () {
                    var $this = $(this);
                    $({ Counter: 0 }).animate({ Counter: $this.text() }, {
                        duration: 2000,
                        easing: 'swing',
                        step: function () {
                            $this.text(Math.ceil(this.Counter));
                        }
                    });
                });
                $(this).off('inview');
            }
        });
    }());

    /* === Shuffle === */
    (function () {
        /* initialize shuffle plugin */
        var $grid = $('#grid');

        $grid.shuffle({
            itemSelector: '.portfolio-item' // the selector for the items in the grid
        });

        /* reshuffle when user clicks a filter item */
        $('#filter li').on('click', function (e) {
            e.preventDefault();

            // set active class
            $('#filter li').removeClass('active');
            $(this).addClass('active');

            // get group name from clicked item
            var groupName = $(this).attr('data-group');

            // reshuffle grid
            $grid.shuffle('shuffle', groupName );
        });
    }());

    /* ======= Recent project carousel ======= */
    (function () {

      var owl = $(".recent-project-carousel");

      owl.owlCarousel({
          items : 5, //5 items above 1000px browser width
          itemsDesktop : [1024,4], //4 items between 1000px and 901px
          itemsDesktopSmall : [900,3], // betweem 900px and 601px
          itemsTablet: [600,2], //2 items between 600 and 480
          itemsMobile : [479,1], //1 item between 480 and 0
          pagination : false // Show pagination
      });

      // Custom Navigation Events
      $(".btn-next").on('click', function(){
        owl.trigger('owl.next');
      })
      $(".btn-prev").on('click', function(){
        owl.trigger('owl.prev');
      })

    }());

    /* ======= Partner Carousel ======= */
    (function () {

      var owl = $(".partner-carousel");

      owl.owlCarousel({
          items : 4, //5 items above 1000px browser width
          itemsDesktop : [1024,4], //4 items between 1000px and 901px
          itemsDesktopSmall : [900,3], // betweem 900px and 601px
          itemsTablet: [600,2], //2 items between 600 and 480
          itemsMobile : [479,1], //1 item between 480 and 0
          pagination : false // Show pagination
      });

    }());

    /* ======= BlackAndWhite Script ======= */
    (function () {
        $('.bwWrapper').BlackAndWhite({
            hoverEffect : true, // default true
            // set the path to BnWWorker.js for a superfast implementation
            webworkerPath : false,
            // to invert the hover effect
            invertHoverEffect: false,
            // this option works only on the modern browsers ( on IE lower than 9 it remains always 1)
            intensity:1,
            speed: { //this property could also be just speed: value for both fadeIn and fadeOut
                fadeIn: 200, // 200ms for fadeIn animations
                fadeOut: 800 // 800ms for fadeOut animations
            },
            onImageReady:function(img) {
                // this callback gets executed anytime an image is converted
            }
        });
    }());

    /* ======= Contact Form ======= */
    (function () {

        $('#contactForm').on('submit',function(e){

            e.preventDefault();

            var $action = $(this).prop('action');
            var $data = $(this).serialize();
            var $this = $(this);

            $this.prevAll('.alert').remove();

            $.post( $action, $data, function( data ) {

                if( data.response=='error' ){

                    $this.before( '
'+data.message+'
' );
                }

                if( data.response=='success' ){

                    $this.before( '
'+data.message+'
' );
                    $this.find('input, textarea').val('');
                }

            }, "json");

        });
    }());

    /* ======= GOOGLE MAP ======= */
    (function () {
        //set your google maps parameters
        var $latitude = 40.716304, //If you unable to find latitude and longitude of your address. Please visit http://www.latlong.net/convert-address-to-lat-long.html you can easily generate.
            $longitude = -73.995763,
            $map_zoom = 16 /* ZOOM SETTING */

        //google map custom marker icon
        var $marker_url = 'assets/images/pin.png';

        //we define here the style of the map
        var style = [{
            "stylers": [{
                "hue": "#000"
            }, {
                "saturation": -70
            }, {
                "gamma": 2.15
            }, {
                "lightness": 12
            }]
        }];

        //set google map options
        var map_options = {
            center: new google.maps.LatLng($latitude, $longitude),
            zoom: $map_zoom,
            panControl: true,
            zoomControl: true,
            mapTypeControl: true,
            streetViewControl: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scrollwheel: false,
            styles: style
        }
        //inizialize the map
        var map = new google.maps.Map(document.getElementById('myMap'), map_options);
        //add a custom marker to the map
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng($latitude, $longitude),
            map: map,
            visible: true,
            icon: $marker_url
        });

        var contentString = '
' + '
69Studio, 795 Folsom Ave, San Francisco.

';
        var infowindow = new google.maps.InfoWindow({
            maxWidth: 320,
            content: contentString
        });

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map, marker);
        });

    }());

}); // JQuery end<commit_msg>andreas<commit_after>/*
Template Name: Appx360
Author: Nam
Version: 1.0
*/

jQuery(function ($) {

    'use strict';

    /* ======= Blank Wrapper ======= */
    (function () {

        // content here...

    }());

    /* ======= Preloader ======= */
    (function () {
        $('#status').fadeOut();
        $('#preloader').delay(200).fadeOut('slow');
    }());

    /* ======= Search box ======= */
    (function () {
        $("#search-box").hide();
            var searchIcon = $(".search-icon");
            var searchBox = $("#search-box");
            searchIcon.on('click', function(event) {
            searchIcon.toggleClass("active");
            searchBox.slideToggle();
        });
    }());

    /* === jQuery for page scrolling feature - requires jQuery Easing plugin === */
    (function () {
        $('a.page-scroll').on('click', function(event) {
            var $anchor = $(this);
            $('html, body').stop().animate({
                scrollTop: $($anchor.attr('href')).offset().top
            }, 1500, 'easeInOutExpo');
            event.preventDefault();
        });
    }());

    /* === Sticky Menu === */
    (function () {
        var nav = $('.navbar');
        var scrolled = false;

        $(window).scroll(function () {

            if (110 < $(window).scrollTop() && !scrolled) {
                nav.addClass('sticky animated fadeInDown').animate({ 'margin-top': '0px' });

                scrolled = true;
            }

            if (110 > $(window).scrollTop() && scrolled) {
                nav.removeClass('sticky animated fadeInDown').css('margin-top', '0px');

                scrolled = false;
            }
        });
    }());

    /* === Progress Bar === */
    (function () {
        $('.progress').on('inview', function(event, visible, visiblePartX, visiblePartY) {
            if (visible) {
                $.each($('div.progress-bar'),function(){
                    $(this).css('width', $(this).attr('aria-valuenow')+'%');
                });
                $(this).off('inview');
            }
        });
    }());

    /* === Counter === */
    (function () {
        $('.counter-section').on('inview', function(event, visible, visiblePartX, visiblePartY) {
            if (visible) {
                $(this).find('.timer').each(function () {
                    var $this = $(this);
                    $({ Counter: 0 }).animate({ Counter: $this.text() }, {
                        duration: 2000,
                        easing: 'swing',
                        step: function () {
                            $this.text(Math.ceil(this.Counter));
                        }
                    });
                });
                $(this).off('inview');
            }
        });
    }());

    /* === Shuffle === */
    (function () {
        /* initialize shuffle plugin */
        var $grid = $('#grid');

        $grid.shuffle({
            itemSelector: '.portfolio-item' // the selector for the items in the grid
        });

        /* reshuffle when user clicks a filter item */
        $('#filter a').on('click', function (e) {
            e.preventDefault();

            // set active class
            $('#filter a').removeClass('active');
            $(this).addClass('active');

            // get group name from clicked item
            var groupName = $(this).attr('data-group');

            // reshuffle grid
            $grid.shuffle('shuffle', groupName );
        });
    }());

    /* ======= Recent project carousel ======= */
    (function () {

      var owl = $(".recent-project-carousel");

      owl.owlCarousel({
          items : 5, //5 items above 1000px browser width
          itemsDesktop : [1024,4], //4 items between 1000px and 901px
          itemsDesktopSmall : [900,3], // betweem 900px and 601px
          itemsTablet: [600,2], //2 items between 600 and 480
          itemsMobile : [479,1], //1 item between 480 and 0
          pagination : false // Show pagination
      });

      // Custom Navigation Events
      $(".btn-next").on('click', function(){
        owl.trigger('owl.next');
      })
      $(".btn-prev").on('click', function(){
        owl.trigger('owl.prev');
      })

    }());

    /* ======= Partner Carousel ======= */
    (function () {

      var owl = $(".partner-carousel");

      owl.owlCarousel({
          items : 4, //5 items above 1000px browser width
          itemsDesktop : [1024,4], //4 items between 1000px and 901px
          itemsDesktopSmall : [900,3], // betweem 900px and 601px
          itemsTablet: [600,2], //2 items between 600 and 480
          itemsMobile : [479,1], //1 item between 480 and 0
          pagination : false // Show pagination
      });

    }());

    /* ======= BlackAndWhite Script ======= */
    (function () {
        $('.bwWrapper').BlackAndWhite({
            hoverEffect : true, // default true
            // set the path to BnWWorker.js for a superfast implementation
            webworkerPath : false,
            // to invert the hover effect
            invertHoverEffect: false,
            // this option works only on the modern browsers ( on IE lower than 9 it remains always 1)
            intensity:1,
            speed: { //this property could also be just speed: value for both fadeIn and fadeOut
                fadeIn: 200, // 200ms for fadeIn animations
                fadeOut: 800 // 800ms for fadeOut animations
            },
            onImageReady:function(img) {
                // this callback gets executed anytime an image is converted
            }
        });
    }());

    /* ======= Contact Form ======= */
    (function () {

        $('#contactForm').on('submit',function(e){

            e.preventDefault();

            var $action = $(this).prop('action');
            var $data = $(this).serialize();
            var $this = $(this);

            $this.prevAll('.alert').remove();

            $.post( $action, $data, function( data ) {

                if( data.response=='error' ){

                    $this.before( '
'+data.message+'
' );
                }

                if( data.response=='success' ){

                    $this.before( '
'+data.message+'
' );
                    $this.find('input, textarea').val('');
                }

            }, "json");

        });
    }());

    /* ======= GOOGLE MAP ======= */
    (function () {
        //set your google maps parameters
        var $latitude = 40.716304, //If you unable to find latitude and longitude of your address. Please visit http://www.latlong.net/convert-address-to-lat-long.html you can easily generate.
            $longitude = -73.995763,
            $map_zoom = 16 /* ZOOM SETTING */

        //google map custom marker icon
        var $marker_url = 'assets/images/pin.png';

        //we define here the style of the map
        var style = [{
            "stylers": [{
                "hue": "#000"
            }, {
                "saturation": -70
            }, {
                "gamma": 2.15
            }, {
                "lightness": 12
            }]
        }];

        //set google map options
        var map_options = {
            center: new google.maps.LatLng($latitude, $longitude),
            zoom: $map_zoom,
            panControl: true,
            zoomControl: true,
            mapTypeControl: true,
            streetViewControl: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scrollwheel: false,
            styles: style
        }
        //inizialize the map
        var map = new google.maps.Map(document.getElementById('myMap'), map_options);
        //add a custom marker to the map
        var marker = new google.maps.Marker({
            position: new google.maps.LatLng($latitude, $longitude),
            map: map,
            visible: true,
            icon: $marker_url
        });

        var contentString = '
' + '
69Studio, 795 Folsom Ave, San Francisco.

';
        var infowindow = new google.maps.InfoWindow({
            maxWidth: 320,
            content: contentString
        });

        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map, marker);
        });

    }());

}); // JQuery end<|endoftext|>


<commit_before>var $ = function (elem) {
    return document.querySelector(elem);
};
var $$ = function (elem) {
    return document.querySelectorAll(elem);
};
//This is the "Offline copy of pages" service worker

//Add this below content to your HTML page, or add the js file to your page at the very top to register service worker
if (navigator.serviceWorker.controller) {
    console.log('[PWA Builder] active service worker found, no need to register')
} else {
    //Register the ServiceWorker
    navigator.serviceWorker.register('pwabuilder-sw.js', {
        scope: './'
    }).then(function (reg) {
        console.log('Service worker has been registered for scope:' + reg.scope);
    });
}

window.addEventListener('load', lazyloading, false);

function lazyloading() {
    var lazyloadImages;
    if ("IntersectionObserver" in window) {
        lazyloadImages = $$(".lazy");
        var imageObserver = new IntersectionObserver(function (entries, observer) {
            entries.forEach(function (entry) {
                if (entry.isIntersecting) {
                    var image = entry.target;
                    image.src = image.dataset.src;
                    image.classList.remove("lazy");
                    imageObserver.unobserve(image);
                }
            });
        });

        lazyloadImages.forEach(function (image) {
            imageObserver.observe(image);
        });
    } else {
        var lazyloadThrottleTimeout;
        lazyloadImages = $$(".lazy");

        function lazyload() {
            if (lazyloadThrottleTimeout) {
                clearTimeout(lazyloadThrottleTimeout);
            }

            lazyloadThrottleTimeout = setTimeout(function () {
                var scrollTop = window.pageYOffset;
                lazyloadImages.forEach(function (img) {
                    if (img.offsetTop < (window.innerHeight + scrollTop)) {
                        img.src = img.dataset.src;
                        img.classList.remove('lazy');
                    }
                });
                if (lazyloadImages.length == 0) {
                    document.removeEventListener("scroll", lazyload);
                    window.removeEventListener("resize", lazyload);
                    window.removeEventListener("orientationChange", lazyload);
                }
            }, 20);
        }

        document.addEventListener("scroll", lazyload);
        window.addEventListener("resize", lazyload);
        window.addEventListener("orientationChange", lazyload);
    }
}

// Remove no-js class
$('html').classList.remove('no-js');

// Animate to section when nav is clicked
$$('#menu a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();
        window.scrollTo({
            top: $(this.getAttribute('href')).getBoundingClientRect().top,
            behavior: 'smooth'
        })
        if ($('header').classList.contains('active')) {
            $$('header, body').forEach(e => e.classList.remove('active'));
        }
    });
});

// Scroll to top
$('#to-top').addEventListener('click', function (e) {
    window.scrollTo({
        top: 0,
        behavior: 'smooth'
    });
});

// Scroll to first element
$('#lead-down span').addEventListener('click', function (e) {
    window.scrollTo({
        top: $("#about").getBoundingClientRect().top,
        behavior: 'smooth'
    })
});

// Open mobile menu
$('#mobile-menu-open').addEventListener('click', function (e) {
    $$('header, body').forEach(e => e.classList.add('active'));
});<commit_msg>Change service worker location<commit_after>var $ = function (elem) {
    return document.querySelector(elem);
};
var $$ = function (elem) {
    return document.querySelectorAll(elem);
};
//This is the "Offline copy of pages" service worker

//Add this below content to your HTML page, or add the js file to your page at the very top to register service worker
if (navigator.serviceWorker.controller) {
    console.log('[PWA Builder] active service worker found, no need to register')
} else {
    //Register the ServiceWorker
    navigator.serviceWorker.register('sw.js', {
        scope: './'
    }).then(function (reg) {
        console.log('Service worker has been registered for scope:' + reg.scope);
    });
}

window.addEventListener('load', lazyloading, false);

function lazyloading() {
    var lazyloadImages;
    if ("IntersectionObserver" in window) {
        lazyloadImages = $$(".lazy");
        var imageObserver = new IntersectionObserver(function (entries, observer) {
            entries.forEach(function (entry) {
                if (entry.isIntersecting) {
                    var image = entry.target;
                    image.src = image.dataset.src;
                    image.classList.remove("lazy");
                    imageObserver.unobserve(image);
                }
            });
        });

        lazyloadImages.forEach(function (image) {
            imageObserver.observe(image);
        });
    } else {
        var lazyloadThrottleTimeout;
        lazyloadImages = $$(".lazy");

        function lazyload() {
            if (lazyloadThrottleTimeout) {
                clearTimeout(lazyloadThrottleTimeout);
            }

            lazyloadThrottleTimeout = setTimeout(function () {
                var scrollTop = window.pageYOffset;
                lazyloadImages.forEach(function (img) {
                    if (img.offsetTop < (window.innerHeight + scrollTop)) {
                        img.src = img.dataset.src;
                        img.classList.remove('lazy');
                    }
                });
                if (lazyloadImages.length == 0) {
                    document.removeEventListener("scroll", lazyload);
                    window.removeEventListener("resize", lazyload);
                    window.removeEventListener("orientationChange", lazyload);
                }
            }, 20);
        }

        document.addEventListener("scroll", lazyload);
        window.addEventListener("resize", lazyload);
        window.addEventListener("orientationChange", lazyload);
    }
}

// Remove no-js class
$('html').classList.remove('no-js');

// Animate to section when nav is clicked
$$('#menu a[href^="#"]').forEach(anchor => {
    anchor.addEventListener('click', function (e) {
        e.preventDefault();
        window.scrollTo({
            top: $(this.getAttribute('href')).getBoundingClientRect().top,
            behavior: 'smooth'
        })
        if ($('header').classList.contains('active')) {
            $$('header, body').forEach(e => e.classList.remove('active'));
        }
    });
});

// Scroll to top
$('#to-top').addEventListener('click', function (e) {
    window.scrollTo({
        top: 0,
        behavior: 'smooth'
    });
});

// Scroll to first element
$('#lead-down span').addEventListener('click', function (e) {
    window.scrollTo({
        top: $("#about").getBoundingClientRect().top,
        behavior: 'smooth'
    })
});

// Open mobile menu
$('#mobile-menu-open').addEventListener('click', function (e) {
    $$('header, body').forEach(e => e.classList.add('active'));
});<|endoftext|>


<commit_before>function data() {
	var url = "https://cepatsembuh.firebaseio.com/";
	var ref = new Firebase(url);

	// Hospital input
	var rs = document.getElementById('hospital_form').value();
	var name_rs = document.getElementById('name_rs').value();
	var bpjs_rs = document.getElementById('bpjs_rs').value();
	var nik_rs = document.getElementById('nik_rs').value();
	var sex_rs = document.getElementById('sex_rs').value();
	var date_rs = document.getElementById('date_rs').value();

	// Puskesmas input
	var puskesmas = document.getElementById('puskesmas_form').value;
	var name_puskesmas = document.getElementById('name_puskesmas').value();
	var bpjs_puskesmas = document.getElementById('bpjs_puskesmas').value();
	var nik_puskesmas = document.getElementById('nik_puskesmas').value();
	var sex_puskesmas = document.getElementById('sex_puskesmas').value();
	var date_puskesmas = document.getElementById('date_puskesmas').value();

	var rs-all = ref.child("rs");
	rs-all.set({
	  person: {
	    nama: name_rs,
	    bpjs: bpjs_rs,
	    nik: nik_rs,
	    sex: sex_rs,
	    date: date_rs,
	  },
	});

	var puskesmas-all = ref.child("puskesmas");
	puskesmas-all.set({
	  person: {
	    nama: name_puskesmas,
	    bpjs: bpjs_puskesmas,
	    nik: nik_puskesmas,
	    sex: sex_puskesmas,
	    date: date_puskesmas,
	  },
	});

	if (var rs == '') {
		return false;
		console.log('BPJS input is empty')
	};
	else {
		return true;
	}
	if (var puskesmas == '') {
		return false;
		console.log('BPJS input is empty')
	};
	else {
		return true;
	}
}<commit_msg>Input is empty!<commit_after>function data() {
	var url = "https://cepatsembuh.firebaseio.com/";
	var ref = new Firebase(url);

	// Hospital input
	var rs = document.getElementById('hospital_form').value();
	var name_rs = document.getElementById('name_rs').value();
	var bpjs_rs = document.getElementById('bpjs_rs').value();
	var nik_rs = document.getElementById('nik_rs').value();
	var sex_rs = document.getElementById('sex_rs').value();
	var date_rs = document.getElementById('date_rs').value();

	// Puskesmas input
	var puskesmas = document.getElementById('puskesmas_form').value;
	var name_puskesmas = document.getElementById('name_puskesmas').value();
	var bpjs_puskesmas = document.getElementById('bpjs_puskesmas').value();
	var nik_puskesmas = document.getElementById('nik_puskesmas').value();
	var sex_puskesmas = document.getElementById('sex_puskesmas').value();
	var date_puskesmas = document.getElementById('date_puskesmas').value();

	var rs-all = ref.child("rs");
	rs-all.set({
	  person: {
	    nama: name_rs,
	    bpjs: bpjs_rs,
	    nik: nik_rs,
	    sex: sex_rs,
	    date: date_rs,
	  },
	});

	var puskesmas-all = ref.child("puskesmas");
	puskesmas-all.set({
	  person: {
	    nama: name_puskesmas,
	    bpjs: bpjs_puskesmas,
	    nik: nik_puskesmas,
	    sex: sex_puskesmas,
	    date: date_puskesmas,
	  },
	});

	if (var rs == '') {
		return false;
		console.log('Input is empty')
	};
	else {
		return true;
	}
	if (var puskesmas == '') {
		return false;
		console.log('Input is empty')
	};
	else {
		return true;
	}
}<|endoftext|>