<commit_before>const Point = require('./point')
const {traverse, traversal, compare, max, isEqual} = require('./point-helpers')

const HARD_TAB = 1 << 0
const LEADING_WHITESPACE = 1 << 2
const TRAILING_WHITESPACE = 1 << 3
const INVISIBLE_CHARACTER = 1 << 4
const INDENT_GUIDE = 1 << 5
const LINE_ENDING = 1 << 6
const FOLD = 1 << 7

const basicTagCache = new Map()
let nextScreenLineId = 1

module.exports =
class ScreenLineBuilder {
  constructor (displayLayer) {
    this.displayLayer = displayLayer
  }

  buildScreenLines (screenStartRow, screenEndRow) {
    screenEndRow = Math.min(screenEndRow, this.displayLayer.getScreenLineCount())
    const screenStart = Point(screenStartRow, 0)
    const screenEnd = Point(screenEndRow, 0)
    this.screenLines = []
    this.screenRow = screenStartRow
    this.bufferRow = this.displayLayer.translateScreenPosition(screenStart).row

    let hunkIndex = 0
    const hunks = this.displayLayer.spatialIndex.getHunksInNewRange(screenStart, screenEnd)
    while (this.screenRow < screenEndRow) {
      this.currentScreenLineText = ''
      this.currentScreenLineTagCodes = []
      this.currentTokenLength = 0
      this.screenColumn = 0
      this.currentTokenFlags = 0
      this.bufferLine = this.displayLayer.buffer.lineForRow(this.bufferRow)
      this.bufferColumn = 0
      this.trailingWhitespaceStartColumn = this.displayLayer.findTrailingWhitespaceStartColumn(this.bufferLine)
      this.inLeadingWhitespace = true
      this.inTrailingWhitespace = false

      // If the buffer line is empty, indent guides may extend beyond the line-ending
      // invisible, requiring this separate code path.
      while (this.bufferColumn <= this.bufferLine.length) {
        // Handle folds or soft wraps at the current position.
        let nextHunk = hunks[hunkIndex]
        while (nextHunk && nextHunk.oldStart.row < this.bufferRow) {
          hunkIndex++
          nextHunk = hunks[hunkIndex]
        }

        while (nextHunk && nextHunk.oldStart.row === this.bufferRow && nextHunk.oldStart.column === this.bufferColumn) {
          if (nextHunk.newText === this.displayLayer.foldCharacter) {
            this.emitFold(nextHunk)
          // If the oldExtent of the hunk is zero, this is a soft line break.
          } else if (isEqual(nextHunk.oldStart, nextHunk.oldEnd)) {
            this.emitSoftWrap(nextHunk)
          }

          hunkIndex++
          nextHunk = hunks[hunkIndex]
        }

        const nextCharacter = this.bufferLine[this.bufferColumn]
        if (this.bufferColumn >= this.trailingWhitespaceStartColumn) {
          this.inTrailingWhitespace = true
          this.inLeadingWhitespace = false
        }

        // Compute the flags for the current token describing how it should be
        // decorated. If these flags differ from the previous token flags, emit
        // a close tag for those flags. Also emit a close tag at a forced token
        // boundary, such as between two hard tabs or where we want to show
        // an indent guide between spaces.
        let previousTokenFlags = this.currentTokenFlags
        this.currentTokenFlags = 0
        this.forceTokenBoundary = false
        if (nextCharacter === ' ' || nextCharacter === '\t') {
          this.updateCurrentTokenFlags(nextCharacter)
        } else {
          this.inLeadingWhitespace = false
        }

        if (previousTokenFlags > 0 &&
            (this.currentTokenFlags !== previousTokenFlags || this.forceTokenBoundary)) {
          this.emitCloseTag(this.getBasicTag(previousTokenFlags))
        }

        // We loop up to the end of the buffer line in case a fold starts there,
        // but at this point we haven't found a fold, so we can terminate the
        // screen line if we have reached the end of the buffer line.
        if (this.bufferColumn === this.bufferLine.length) {
          this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
          this.emitEOLInvisible()
          if (this.bufferLine.length === 0 && this.displayLayer.showIndentGuides) {
            let whitespaceLength = this.displayLayer.leadingWhitespaceLengthForSurroundingLines(this.bufferRow)
            this.emitIndentWhitespace(whitespaceLength)
          }
          // Ensure empty lines have at least one empty token to make it easier on
          // the caller
          if (this.currentScreenLineTagCodes.length === 0) this.currentScreenLineTagCodes.push(0)
          this.emitNewline()
          this.bufferRow++
          break
        }

        if (this.currentTokenFlags > 0 &&
            this.currentTokenFlags !== previousTokenFlags || this.forceTokenBoundary) {
          this.emitOpenTag(this.getBasicTag(this.currentTokenFlags))
        }

        // Handle tabs and leading / trailing whitespace invisibles specially.
        // Otherwise just append the next character to the screen line.
        if (nextCharacter === '\t') {
          this.emitHardTab()
        } else if ((this.inLeadingWhitespace || this.inTrailingWhitespace) &&
                    nextCharacter === ' ' && this.displayLayer.invisibles.space) {
          this.emitText(this.displayLayer.invisibles.space)
        } else {
          this.emitText(nextCharacter)
        }
        this.bufferColumn++
      }
    }

    return this.screenLines
  }

  getBasicTag (flags) {
    let tag = basicTagCache.get(flags)
    if (tag) {
      return tag
    } else {
      let tag = ''
      if (flags & INVISIBLE_CHARACTER) tag += 'invisible-character '
      if (flags & HARD_TAB) tag += 'hard-tab '
      if (flags & LEADING_WHITESPACE) tag += 'leading-whitespace '
      if (flags & TRAILING_WHITESPACE) tag += 'trailing-whitespace '
      if (flags & LINE_ENDING) tag += 'eol '
      if (flags & INDENT_GUIDE) tag += 'indent-guide '
      if (flags & FOLD) tag += 'fold-marker '
      tag = tag.trim()
      basicTagCache.set(flags, tag)
      return tag
    }
  }

  updateCurrentTokenFlags (nextCharacter) {
    const showIndentGuides = this.displayLayer.showIndentGuides && (this.inLeadingWhitespace || this.trailingWhitespaceStartColumn === 0)
    if (this.inLeadingWhitespace) this.currentTokenFlags |= LEADING_WHITESPACE
    if (this.inTrailingWhitespace) this.currentTokenFlags |= TRAILING_WHITESPACE

    if (nextCharacter === ' ') {
      if ((this.inLeadingWhitespace || this.inTrailingWhitespace) && this.displayLayer.invisibles.space) {
        this.currentTokenFlags |= INVISIBLE_CHARACTER
      }

      if (showIndentGuides) {
        this.currentTokenFlags |= INDENT_GUIDE
        if (this.screenColumn % this.displayLayer.tabLength === 0) this.forceTokenBoundary = true
      }
    } else { // nextCharacter === \t
      this.currentTokenFlags |= HARD_TAB
      if (this.displayLayer.invisibles.tab) this.currentTokenFlags |= INVISIBLE_CHARACTER
      if (showIndentGuides && this.screenColumn % this.displayLayer.tabLength === 0) {
        this.currentTokenFlags |= INDENT_GUIDE
      }

      this.forceTokenBoundary = true
    }
  }

  emitText (text) {
    this.currentScreenLineText += text
    const length = text.length
    this.screenColumn += length
    this.currentTokenLength += length
  }

  emitTokenBoundary () {
    if (this.currentTokenLength > 0) {
      this.currentScreenLineTagCodes.push(this.currentTokenLength)
      this.currentTokenLength = 0
    }
  }

  emitCloseTag (closeTag) {
    this.emitTokenBoundary()
    if (closeTag.length > 0) {
      this.currentScreenLineTagCodes.push(this.displayLayer.codeForCloseTag(closeTag))
    }
  }

  emitOpenTag (openTag) {
    this.emitTokenBoundary()
    if (openTag.length > 0) {
      this.currentScreenLineTagCodes.push(this.displayLayer.codeForOpenTag(openTag))
    }
  }

  emitNewline () {
    this.screenLines.push({
      id: nextScreenLineId++,
      lineText: this.currentScreenLineText,
      tagCodes: this.currentScreenLineTagCodes
    })
    this.screenRow++
    this.currentScreenLineText = ''
    this.currentScreenLineTagCodes = []
    this.screenColumn = 0
  }

  emitEOLInvisible () {
    let lineEnding = this.displayLayer.buffer.lineEndingForRow(this.bufferRow)
    const eolInvisible = this.displayLayer.eolInvisibles[lineEnding]
    if (eolInvisible) {
      let eolFlags = INVISIBLE_CHARACTER | LINE_ENDING
      if (this.bufferLine.length === 0 && this.displayLayer.showIndentGuides) eolFlags |= INDENT_GUIDE
      this.emitOpenTag(this.getBasicTag(eolFlags))
      this.emitText(eolInvisible)
      this.emitCloseTag(this.getBasicTag(eolFlags))
    }
  }

  emitIndentWhitespace (endColumn) {
    if (this.displayLayer.showIndentGuides) {
      let openedIndentGuide = false
      while (this.screenColumn < endColumn) {
        if (this.screenColumn % this.displayLayer.tabLength === 0) {
          if (openedIndentGuide) {
            this.emitCloseTag(this.getBasicTag(INDENT_GUIDE))
          }

          this.emitOpenTag(this.getBasicTag(INDENT_GUIDE))
          openedIndentGuide = true
        }
        this.emitText(' ')
      }

      if (openedIndentGuide) this.emitCloseTag(this.getBasicTag(INDENT_GUIDE))
    } else {
      this.emitText(' '.repeat(endColumn - this.screenColumn))
    }
  }

  emitHardTab () {
    const distanceToNextTabStop = this.displayLayer.tabLength - (this.screenColumn % this.displayLayer.tabLength)
    if (this.displayLayer.invisibles.tab) {
      this.emitText(this.displayLayer.invisibles.tab)
      this.emitText(' '.repeat(distanceToNextTabStop - 1))
    } else {
      this.emitText(' '.repeat(distanceToNextTabStop))
    }
  }

  emitFold (nextHunk) {
    this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
    this.currentTokenFlags = 0

    this.emitOpenTag(this.getBasicTag(FOLD))
    this.emitText(this.displayLayer.foldCharacter)
    this.emitCloseTag(this.getBasicTag(FOLD))

    this.bufferRow = nextHunk.oldEnd.row
    this.bufferColumn = nextHunk.oldEnd.column
    this.bufferLine = this.displayLayer.buffer.lineForRow(this.bufferRow)
    this.trailingWhitespaceStartColumn = this.displayLayer.findTrailingWhitespaceStartColumn(this.bufferLine)
  }

  emitSoftWrap (nextHunk) {
    this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
    this.currentTokenFlags = 0
    this.emitNewline()
    this.emitIndentWhitespace(nextHunk.newEnd.column)
  }
}
<commit_msg>Cleanup<commit_after>const Point = require('./point')
const {traverse, traversal, compare, max, isEqual} = require('./point-helpers')

const HARD_TAB = 1 << 0
const LEADING_WHITESPACE = 1 << 2
const TRAILING_WHITESPACE = 1 << 3
const INVISIBLE_CHARACTER = 1 << 4
const INDENT_GUIDE = 1 << 5
const LINE_ENDING = 1 << 6
const FOLD = 1 << 7

const basicTagCache = new Map()
let nextScreenLineId = 1

module.exports =
class ScreenLineBuilder {
  constructor (displayLayer) {
    this.displayLayer = displayLayer
  }

  buildScreenLines (screenStartRow, screenEndRow) {
    screenEndRow = Math.min(screenEndRow, this.displayLayer.getScreenLineCount())
    const screenStart = Point(screenStartRow, 0)
    const screenEnd = Point(screenEndRow, 0)
    this.screenLines = []
    this.screenRow = screenStartRow
    this.bufferRow = this.displayLayer.translateScreenPosition(screenStart).row

    let hunkIndex = 0
    const hunks = this.displayLayer.spatialIndex.getHunksInNewRange(screenStart, screenEnd)
    while (this.screenRow < screenEndRow) {
      this.currentScreenLineText = ''
      this.currentScreenLineTagCodes = []
      this.currentTokenLength = 0
      this.screenColumn = 0
      this.currentTokenFlags = 0
      this.bufferLine = this.displayLayer.buffer.lineForRow(this.bufferRow)
      this.bufferColumn = 0
      this.trailingWhitespaceStartColumn = this.displayLayer.findTrailingWhitespaceStartColumn(this.bufferLine)
      this.inLeadingWhitespace = true
      this.inTrailingWhitespace = false

      while (this.bufferColumn <= this.bufferLine.length) {
        // Discard hunks starting before the current row
        let nextHunk = hunks[hunkIndex]
        while (nextHunk && nextHunk.oldStart.row < this.bufferRow) {
          hunkIndex++
          nextHunk = hunks[hunkIndex]
        }

        // Handle folds or soft wraps at the current position.
        while (nextHunk && nextHunk.oldStart.row === this.bufferRow && nextHunk.oldStart.column === this.bufferColumn) {
          if (nextHunk.newText === this.displayLayer.foldCharacter) {
            this.emitFold(nextHunk)
          } else if (isEqual(nextHunk.oldStart, nextHunk.oldEnd)) {
            this.emitSoftWrap(nextHunk)
          }

          hunkIndex++
          nextHunk = hunks[hunkIndex]
        }

        const nextCharacter = this.bufferLine[this.bufferColumn]
        if (this.bufferColumn >= this.trailingWhitespaceStartColumn) {
          this.inTrailingWhitespace = true
          this.inLeadingWhitespace = false
        } else if (nextCharacter !== ' ' && nextCharacter !== '\t') {
          this.inLeadingWhitespace = false
        }

        // Compute the flags for the current token describing how it should be
        // decorated.
        let previousTokenFlags = this.currentTokenFlags
        this.updateCurrentTokenFlags(nextCharacter)

        if (previousTokenFlags > 0 &&
            (this.currentTokenFlags !== previousTokenFlags || this.forceTokenBoundary)) {
          this.emitCloseTag(this.getBasicTag(previousTokenFlags))
        }

        // We loop up to the end of the buffer line in case a fold starts there,
        // but at this point we haven't found a fold, so we can terminate the
        // screen line if we have reached the end of the buffer line.
        if (this.bufferColumn === this.bufferLine.length) {
          this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
          this.emitEOLInvisible()
          if (this.bufferLine.length === 0 && this.displayLayer.showIndentGuides) {
            let whitespaceLength = this.displayLayer.leadingWhitespaceLengthForSurroundingLines(this.bufferRow)
            this.emitIndentWhitespace(whitespaceLength)
          }
          // Ensure empty lines have at least one empty token to make it easier on
          // the caller
          if (this.currentScreenLineTagCodes.length === 0) this.currentScreenLineTagCodes.push(0)
          this.emitNewline()
          this.bufferRow++
          break
        }

        if (this.currentTokenFlags > 0 &&
            this.currentTokenFlags !== previousTokenFlags || this.forceTokenBoundary) {
          this.emitOpenTag(this.getBasicTag(this.currentTokenFlags))
        }

        // Handle tabs and leading / trailing whitespace invisibles specially.
        // Otherwise just append the next character to the screen line.
        if (nextCharacter === '\t') {
          this.emitHardTab()
        } else if ((this.inLeadingWhitespace || this.inTrailingWhitespace) &&
                    nextCharacter === ' ' && this.displayLayer.invisibles.space) {
          this.emitText(this.displayLayer.invisibles.space)
        } else {
          this.emitText(nextCharacter)
        }
        this.bufferColumn++
      }
    }

    return this.screenLines
  }

  getBasicTag (flags) {
    let tag = basicTagCache.get(flags)
    if (tag) {
      return tag
    } else {
      let tag = ''
      if (flags & INVISIBLE_CHARACTER) tag += 'invisible-character '
      if (flags & HARD_TAB) tag += 'hard-tab '
      if (flags & LEADING_WHITESPACE) tag += 'leading-whitespace '
      if (flags & TRAILING_WHITESPACE) tag += 'trailing-whitespace '
      if (flags & LINE_ENDING) tag += 'eol '
      if (flags & INDENT_GUIDE) tag += 'indent-guide '
      if (flags & FOLD) tag += 'fold-marker '
      tag = tag.trim()
      basicTagCache.set(flags, tag)
      return tag
    }
  }

  updateCurrentTokenFlags (nextCharacter) {
    this.currentTokenFlags = 0
    this.forceTokenBoundary = false
    if (nextCharacter !== ' ' && nextCharacter !== '\t') return

    const showIndentGuides = this.displayLayer.showIndentGuides && (this.inLeadingWhitespace || this.trailingWhitespaceStartColumn === 0)
    if (this.inLeadingWhitespace) this.currentTokenFlags |= LEADING_WHITESPACE
    if (this.inTrailingWhitespace) this.currentTokenFlags |= TRAILING_WHITESPACE

    if (nextCharacter === ' ') {
      if ((this.inLeadingWhitespace || this.inTrailingWhitespace) && this.displayLayer.invisibles.space) {
        this.currentTokenFlags |= INVISIBLE_CHARACTER
      }

      if (showIndentGuides) {
        this.currentTokenFlags |= INDENT_GUIDE
        if (this.screenColumn % this.displayLayer.tabLength === 0) this.forceTokenBoundary = true
      }
    } else { // nextCharacter === \t
      this.currentTokenFlags |= HARD_TAB
      if (this.displayLayer.invisibles.tab) this.currentTokenFlags |= INVISIBLE_CHARACTER
      if (showIndentGuides && this.screenColumn % this.displayLayer.tabLength === 0) {
        this.currentTokenFlags |= INDENT_GUIDE
      }

      this.forceTokenBoundary = true
    }
  }

  emitText (text) {
    this.currentScreenLineText += text
    const length = text.length
    this.screenColumn += length
    this.currentTokenLength += length
  }

  emitTokenBoundary () {
    if (this.currentTokenLength > 0) {
      this.currentScreenLineTagCodes.push(this.currentTokenLength)
      this.currentTokenLength = 0
    }
  }

  emitCloseTag (closeTag) {
    this.emitTokenBoundary()
    if (closeTag.length > 0) {
      this.currentScreenLineTagCodes.push(this.displayLayer.codeForCloseTag(closeTag))
    }
  }

  emitOpenTag (openTag) {
    this.emitTokenBoundary()
    if (openTag.length > 0) {
      this.currentScreenLineTagCodes.push(this.displayLayer.codeForOpenTag(openTag))
    }
  }

  emitNewline () {
    this.screenLines.push({
      id: nextScreenLineId++,
      lineText: this.currentScreenLineText,
      tagCodes: this.currentScreenLineTagCodes
    })
    this.screenRow++
    this.currentScreenLineText = ''
    this.currentScreenLineTagCodes = []
    this.screenColumn = 0
  }

  emitEOLInvisible () {
    let lineEnding = this.displayLayer.buffer.lineEndingForRow(this.bufferRow)
    const eolInvisible = this.displayLayer.eolInvisibles[lineEnding]
    if (eolInvisible) {
      let eolFlags = INVISIBLE_CHARACTER | LINE_ENDING
      if (this.bufferLine.length === 0 && this.displayLayer.showIndentGuides) eolFlags |= INDENT_GUIDE
      this.emitOpenTag(this.getBasicTag(eolFlags))
      this.emitText(eolInvisible)
      this.emitCloseTag(this.getBasicTag(eolFlags))
    }
  }

  emitIndentWhitespace (endColumn) {
    if (this.displayLayer.showIndentGuides) {
      let openedIndentGuide = false
      while (this.screenColumn < endColumn) {
        if (this.screenColumn % this.displayLayer.tabLength === 0) {
          if (openedIndentGuide) {
            this.emitCloseTag(this.getBasicTag(INDENT_GUIDE))
          }

          this.emitOpenTag(this.getBasicTag(INDENT_GUIDE))
          openedIndentGuide = true
        }
        this.emitText(' ')
      }

      if (openedIndentGuide) this.emitCloseTag(this.getBasicTag(INDENT_GUIDE))
    } else {
      this.emitText(' '.repeat(endColumn - this.screenColumn))
    }
  }

  emitHardTab () {
    const distanceToNextTabStop = this.displayLayer.tabLength - (this.screenColumn % this.displayLayer.tabLength)
    if (this.displayLayer.invisibles.tab) {
      this.emitText(this.displayLayer.invisibles.tab)
      this.emitText(' '.repeat(distanceToNextTabStop - 1))
    } else {
      this.emitText(' '.repeat(distanceToNextTabStop))
    }
  }

  emitFold (nextHunk) {
    this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
    this.currentTokenFlags = 0

    this.emitOpenTag(this.getBasicTag(FOLD))
    this.emitText(this.displayLayer.foldCharacter)
    this.emitCloseTag(this.getBasicTag(FOLD))

    this.bufferRow = nextHunk.oldEnd.row
    this.bufferColumn = nextHunk.oldEnd.column
    this.bufferLine = this.displayLayer.buffer.lineForRow(this.bufferRow)
    this.trailingWhitespaceStartColumn = this.displayLayer.findTrailingWhitespaceStartColumn(this.bufferLine)
  }

  emitSoftWrap (nextHunk) {
    this.emitCloseTag(this.getBasicTag(this.currentTokenFlags))
    this.currentTokenFlags = 0
    this.emitNewline()
    this.emitIndentWhitespace(nextHunk.newEnd.column)
  }
}
<|endoftext|>


<commit_before>

    $(document).ready(function(){

      //Add fake password
      $('input#user_password').val('lalalala');
      $('input#user_password_confirmation').val('lalalala');

      // Focus hide label
      $('div.unlock_window input[type="password"]').focusin(function(){
        $('span.top label').hide();
      });

      // Focus show label
      $('div.unlock_window input[type="password"]').focusout(function(){
        var value = $(this).val();
        if (value=="") {
          $('div.unlock_window span.top label').show();
        }
      });

      // Unlock form
      $('div.unlock_window form').submit(function(ev){
        ev.preventDefault();
        $.post($(this).attr('action'), $(this).serialize())
        .success(function(){
          $('div.unlock_window div.error_content').hide()
          $('#user_email, #user_password, #user_password_confirmation').attr('disabled', null);
          $('#user_password_confirmation, #user_password')
            .val('')
            .css({color:'#333333'})
            .removeClass('error')
            .closest('span')
            .find('span.block').hide();
          $('a.delete_account').removeClass('disabled');
          $('input.close').removeClass('close');
          $('div.error_content').hide();
          $('span.submit_block p').text('You have verified your account').css({color:'#999999'});
          close_mamufas();
        })
        .error(function(){
          $('div.unlock_window div.error_content').show()
        });
      });

      //Close all modal windows
      $('div.mamufas a.cancel, div.mamufas a.close_unlock, , div.mamufas a.close_delete').click(function(ev){
        ev.preventDefault();
        ev.stopPropagation();
        close_mamufas();
      });

      //Unlock window
      $('a.open_unlock').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.mamufas div.unlock_window').show();
        $('div.mamufas').fadeIn('fast');
        bindESC();
      });

      //Delete account
      $('.disabled, .close').live('click', function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.mamufas div.unlock_window').show();
        $('div.mamufas').fadeIn('fast');
      });

      // Show delete window
      $('a.delete_account:not(.disabled)').live('click', function(ev){
        $('div.mamufas div.delete_window').show();
        $('div.mamufas').fadeIn('fast');
        bindESC();
      });

      // Show forget window effect
      $('a.forget').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        showForget();
      });

      //Close notification
      $('div.notification a.close_notification').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.notification').fadeOut();
      });
    });

    function bindESC() {
      $(document).keydown(function(event){
        if (event.which == '27') {
          $('div.mamufas').fadeOut('fast',function(){
            $('div.mamufas div.settings_window').hide();
            $('div.mamufas div.delete_window').hide();
            $('div.mamufas div.create_window').hide();
          });
        }
      });
    };

    function unbindESC() {
      $(document).unbind('keydown');
    };

    function close_mamufas(){
      $('div.mamufas').fadeOut('fast',function(){
        $('div.mamufas div.unlock_window').hide(function(){
          resetUnlock();
        });
      });
      unbindESC();
    };

    function showForget() {
      $('div.unlock_window .inner_').animate({height:'72px'},300);
      $('div.unlock_window form').animate({opacity:0,},300,function(){
        $('div.unlock_window form').hide();
        $('div.unlock_window div.inner_').css('background-position','-200px -200px');
        $('div.email_sent').show();
        $('div.email_sent').animate({opacity:1},300);
      });
    };

    function resetUnlock() {
      $('div.unlock_window .inner_').animate({height:'120px'},300);
      $('div.unlock_window form').css('opacity',1);
      $('div.unlock_window form').show();
      $('div.unlock_window div.inner_').css('background-position','15px 15px');
      $('div.email_sent').hide();
      $('div.email_sent').css('opacity',1);
    }<commit_msg>another feature with user change password<commit_after>

    $(document).ready(function(){

      // Hide notification if it is opened
      $('div.notification').delay(4000).fadeOut();

      //Add fake password
      $('input#user_password').val('lalalala');
      $('input#user_password_confirmation').val('lalalala');

      // Focus hide label
      $('div.unlock_window input[type="password"]').focusin(function(){
        $('span.top label').hide();
      });

      // Focus show label
      $('div.unlock_window input[type="password"]').focusout(function(){
        var value = $(this).val();
        if (value=="") {
          $('div.unlock_window span.top label').show();
        }
      });

      // Unlock form
      $('div.unlock_window form').submit(function(ev){
        ev.preventDefault();
        $.post($(this).attr('action'), $(this).serialize())
        .success(function(){
          $('div.unlock_window div.error_content').hide()
          $('#user_email, #user_password, #user_password_confirmation').attr('disabled', null);
          $('#user_password_confirmation, #user_password')
            .val('')
            .css({color:'#333333'})
            .removeClass('error')
            .closest('span')
            .find('span.block').hide();
          $('#user_password').focus();
          $('a.delete_account').removeClass('disabled');
          $('input.close').removeClass('close');
          $('div.error_content').hide();
          $('span.submit_block p').text('You have verified your account').css({color:'#999999'});
          close_mamufas();
        })
        .error(function(){
          $('div.unlock_window div.error_content').show()
        });
      });

      //Close all modal windows
      $('div.mamufas a.cancel, div.mamufas a.close_unlock, , div.mamufas a.close_delete').click(function(ev){
        ev.preventDefault();
        ev.stopPropagation();
        close_mamufas();
      });

      //Unlock window
      $('a.open_unlock').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.mamufas div.unlock_window').show();
        $('div.mamufas').fadeIn('fast');
        bindESC();
      });

      //Delete account
      $('.disabled, .close').live('click', function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.mamufas div.unlock_window').show();
        $('div.mamufas').fadeIn('fast');
      });

      // Show delete window
      $('a.delete_account:not(.disabled)').live('click', function(ev){
        $('div.mamufas div.delete_window').show();
        $('div.mamufas').fadeIn('fast');
        bindESC();
      });

      // Show forget window effect
      $('a.forget').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        showForget();
      });

      //Close notification
      $('div.notification a.close_notification').click(function(ev){
        ev.stopPropagation();
        ev.preventDefault();
        $('div.notification').fadeOut();
      });
    });

    function bindESC() {
      $(document).keydown(function(event){
        if (event.which == '27') {
          $('div.mamufas').fadeOut('fast',function(){
            $('div.mamufas div.settings_window').hide();
            $('div.mamufas div.delete_window').hide();
            $('div.mamufas div.create_window').hide();
          });
        }
      });
    };

    function unbindESC() {
      $(document).unbind('keydown');
    };

    function close_mamufas(){
      $('div.mamufas').fadeOut('fast',function(){
        $('div.mamufas div.unlock_window').hide(function(){
          resetUnlock();
        });
      });
      unbindESC();
    };

    function showForget() {
      $('div.unlock_window .inner_').animate({height:'72px'},300);
      $('div.unlock_window form').animate({opacity:0,},300,function(){
        $('div.unlock_window form').hide();
        $('div.unlock_window div.inner_').css('background-position','-200px -200px');
        $('div.email_sent').show();
        $('div.email_sent').animate({opacity:1},300);
      });
    };

    function resetUnlock() {
      $('div.unlock_window .inner_').animate({height:'120px'},300);
      $('div.unlock_window form').css('opacity',1);
      $('div.unlock_window form').show();
      $('div.unlock_window div.inner_').css('background-position','15px 15px');
      $('div.email_sent').hide();
      $('div.email_sent').css('opacity',1);
    }<|endoftext|>


<commit_before>var localVideo;
var localStream;
var remoteVideo;
var peerConnection;
var uuid;
var serverConnection;

var peerConnectionConfig = {
  'iceServers': [
    {'urls': 'stun:stun.services.mozilla.com'},
    {'urls': 'stun:stun.l.google.com:19302'},
  ]
};

function pageReady() {
  uuid = createUUID();

  localVideo = document.getElementById('localVideo');
  remoteVideo = document.getElementById('remoteVideo');

  serverConnection = new WebSocket('wss://' + window.location.hostname + ':8443');
  serverConnection.onmessage = gotMessageFromServer;

  var constraints = {
    video: true,
    audio: true,
  };

  if(navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia(constraints).then(getUserMediaSuccess).catch(errorHandler);
  } else {
    alert('Your browser does not support getUserMedia API');
  }
}

function getUserMediaSuccess(stream) {
  localStream = stream;
  localVideo.srcObject = stream;
}

function start(isCaller) {
  peerConnection = new RTCPeerConnection(peerConnectionConfig);
  peerConnection.onicecandidate = gotIceCandidate;
  peerConnection.ontrack = gotRemoteStream;
  peerConnection.addStream(localStream);

  if(isCaller) {
    peerConnection.createOffer().then(createdDescription).catch(errorHandler);
  }
}

function gotMessageFromServer(message) {
  if(!peerConnection) start(false);

  var signal = JSON.parse(message.data);

  // Ignore messages from ourself
  if(signal.uuid == uuid) return;

  if(signal.sdp) {
    peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(function() {
      // Only create answers in response to offers
      if(signal.sdp.type == 'offer') {
        peerConnection.createAnswer().then(createdDescription).catch(errorHandler);
      }
    }).catch(errorHandler);
  } else if(signal.ice) {
    peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
  }
}

function gotIceCandidate(event) {
  if(event.candidate != null) {
    serverConnection.send(JSON.stringify({'ice': event.candidate, 'uuid': uuid}));
  }
}

function createdDescription(description) {
  console.log('got description');

  peerConnection.setLocalDescription(description).then(function() {
    serverConnection.send(JSON.stringify({'sdp': peerConnection.localDescription, 'uuid': uuid}));
  }).catch(errorHandler);
}

function gotRemoteStream(event) {
  console.log('got remote stream');
  remoteVideo.srcObject = event.streams[0];
}

function errorHandler(error) {
  console.log(error);
}

// Taken from http://stackoverflow.com/a/105074/515584
// Strictly speaking, it's not a real UUID, but it gets the job done here
function createUUID() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  }

  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
<commit_msg>fix #27: update stun servers<commit_after>var localVideo;
var localStream;
var remoteVideo;
var peerConnection;
var uuid;
var serverConnection;

var peerConnectionConfig = {
  'iceServers': [
    {'urls': 'stun.stunprotocol.org:3478'},
    {'urls': 'stun:stun.l.google.com:19302'},
  ]
};

function pageReady() {
  uuid = createUUID();

  localVideo = document.getElementById('localVideo');
  remoteVideo = document.getElementById('remoteVideo');

  serverConnection = new WebSocket('wss://' + window.location.hostname + ':8443');
  serverConnection.onmessage = gotMessageFromServer;

  var constraints = {
    video: true,
    audio: true,
  };

  if(navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia(constraints).then(getUserMediaSuccess).catch(errorHandler);
  } else {
    alert('Your browser does not support getUserMedia API');
  }
}

function getUserMediaSuccess(stream) {
  localStream = stream;
  localVideo.srcObject = stream;
}

function start(isCaller) {
  peerConnection = new RTCPeerConnection(peerConnectionConfig);
  peerConnection.onicecandidate = gotIceCandidate;
  peerConnection.ontrack = gotRemoteStream;
  peerConnection.addStream(localStream);

  if(isCaller) {
    peerConnection.createOffer().then(createdDescription).catch(errorHandler);
  }
}

function gotMessageFromServer(message) {
  if(!peerConnection) start(false);

  var signal = JSON.parse(message.data);

  // Ignore messages from ourself
  if(signal.uuid == uuid) return;

  if(signal.sdp) {
    peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(function() {
      // Only create answers in response to offers
      if(signal.sdp.type == 'offer') {
        peerConnection.createAnswer().then(createdDescription).catch(errorHandler);
      }
    }).catch(errorHandler);
  } else if(signal.ice) {
    peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice)).catch(errorHandler);
  }
}

function gotIceCandidate(event) {
  if(event.candidate != null) {
    serverConnection.send(JSON.stringify({'ice': event.candidate, 'uuid': uuid}));
  }
}

function createdDescription(description) {
  console.log('got description');

  peerConnection.setLocalDescription(description).then(function() {
    serverConnection.send(JSON.stringify({'sdp': peerConnection.localDescription, 'uuid': uuid}));
  }).catch(errorHandler);
}

function gotRemoteStream(event) {
  console.log('got remote stream');
  remoteVideo.srcObject = event.streams[0];
}

function errorHandler(error) {
  console.log(error);
}

// Taken from http://stackoverflow.com/a/105074/515584
// Strictly speaking, it's not a real UUID, but it gets the job done here
function createUUID() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
  }

  return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
}
<|endoftext|>


<commit_before>// Description:
//   Random cat images from Cat Overflow
//
// Dependencies:
//   underscore
//
// Commands:
//   hubot cat me - Random cat gif from www.catoverflow.com
//   hubot cat bomb (n) - n/5 random cat gifs from www.catoverflow.com
//
// Author:
//   andromedado

var _ = require('underscore');
var util = require('util');
var max = 338;

module.exports = function(robot) {

    function getSrcs (num, callback) {
        num = num || 1;
        url = util.format('http://catoverflow.com/api/query?limit=%s&offset=%s', num, (Math.ceil(Math.random() * (max - num + 1))));
        robot.http(url).get()(function (err, res, body) {
            if (err) {
                callback(err);
                return;
            }
            var urls = (body + '').replace(/^\s*|\s*$/, '').split('\n');
            urls = _.filter(urls, function (url) {
                return url && url.length && url.length > 0 && /\S/.test(url);
            });
            var urlsToUse = _.map(urls, function (url) {
                return url + '#.png';
            });
            callback(null, urlsToUse);
        });
    }

    function fetchAndSend (num, msg) {
        getSrcs(num, function (err, srcs) {
            if (err) {
                msg.send(':flushed: ' + err);
            } else {
                _.map(srcs, function (src) {
                    msg.send(src);
                });
            }
        })
    }

    robot.respond(/cat bomb( (\d+))?/i, function (msg) {
        var num = Math.min(30, msg.match[2] || 5);
        fetchAndSend(num, msg);
    });

    robot.respond(/cat me/i, function (msg) {
        fetchAndSend(1, msg);
    });

};

<commit_msg>nsfw added to catoverflow<commit_after>// Description:
//   Random cat images from Cat Overflow
//
// Dependencies:
//   underscore
//
// Commands:
//   hubot cat me - Random cat gif from www.catoverflow.com
//   hubot cat bomb (n) - n/5 random cat gifs from www.catoverflow.com
//
// Author:
//   andromedado

var _ = require('underscore');
var util = require('util');
var max = 338;

module.exports = function(robot) {

    function getSrcs (num, callback) {
        num = num || 1;
        url = util.format('http://catoverflow.com/api/query?limit=%s&offset=%s', num, (Math.ceil(Math.random() * (max - num + 1))));
        robot.http(url).get()(function (err, res, body) {
            if (err) {
                callback(err);
                return;
            }
            var urls = (body + '').replace(/^\s*|\s*$/, '').split('\n');
            urls = _.filter(urls, function (url) {
                return url && url.length && url.length > 0 && /\S/.test(url);
            });
            var urlsToUse = _.map(urls, function (url) {
                return url + '#.png';
            });
            callback(null, urlsToUse);
        });
    }

    function fetchAndSend (num, msg) {
        getSrcs(num, function (err, srcs) {
            if (err) {
                msg.send(':flushed: ' + err);
            } else {
                _.map(srcs, function (src) {
                    msg.send(src);
                });
            }
        })
    }

    robot.respond(/cat bomb( (\d+))?/i, function (msg) {
        var num = Math.min(30, msg.match[2] || 5);
        fetchAndSend(num, msg);
    });

    robot.respond(/cat me/i, function (msg) {
        fetchAndSend(1, msg);
    });

    robot.hear(/nsfw/i, function (msg) {
        fetchAndSend(6, msg);
    });

};

<|endoftext|>


<commit_before>define([
  'dojo/_base/declare', 'dijit/_WidgetBase', 'dojo/on',
  'dojo/dom-class', 'dijit/_TemplatedMixin', 'dijit/_WidgetsInTemplateMixin',
  'dojo/text!./templates/CreateWorkspace.html', 'dijit/form/Form',
  'dojo/topic', '../WorkspaceManager'
], function (
  declare, WidgetBase, on,
  domClass, Templated, WidgetsInTemplate,
  Template, FormMixin, Topic, WorkspaceManager
) {
  return declare([WidgetBase, FormMixin, Templated, WidgetsInTemplate], {
    baseClass: 'CreateWorkspace',
    templateString: Template,
    cws: null,
    startup: function () {
      this.saveButton.set('disabled', true);
      this.cws = document.getElementsByClassName('cws')[0];
      // console.log(this.cws);
      this.cws.addEventListener('keyup', this.checkChars);
      this.cws.addEventListener('input', this.checkChars);
      this.cws.button = this.saveButton;
      this.cws.errorMessage = document.getElementsByClassName('charError')[0];
    },
    checkChars: function (evt) {
      document.getElementsByClassName('cws')[0].button.set('disabled', true);
      // console.log('checking for no slashes');
      // console.log(evt.target.value);
      if (evt.target.value.indexOf('/') === -1 && evt.target.value.indexOf('\\') === -1 && evt.target.value !== '') {
        // console.log(document.getElementsByClassName('cws')[0].button);
        document.getElementsByClassName('cws')[0].button.set('disabled', false);
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = ' ';
        return true;
      }
      if (evt.target.value !== '') {
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = 'Workspace name shall not contain any slashes';
      }
      if (evt.target.value === '') {
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = ' ';
      }
      return false;
    },
    validate: function () {
      var valid = this.inherited(arguments);
      if (valid) {
        this.saveButton.set('disabled', false);
      } else {
        this.saveButton.set('disabled', true);
      }
      return valid;
    },

    onSubmit: function (evt) {
      var _self = this;

      evt.preventDefault();
      evt.stopPropagation();

      if (this.validate()) {
        var values = this.getValues();
        domClass.add(this.domNode, 'Working');

        WorkspaceManager.createWorkspace(values.name).then(function (results) {
          domClass.remove(_self.domNode, 'Working');
          // var path = '/' + ['workspace', results.path].join('/');
          Topic.publish('/refreshWorkspace', {});

          on.emit(_self.domNode, 'dialogAction', {
            action: 'close',
            bubbles: true
          });

          Topic.publish('/Notification', {
            message: 'Wroksapce Created',
            positionDirection: 'bl-up'
          });

        }, function (err) {
          domClass.remove(_self.domNode, 'Working');
          domClass.add(_self.domNode, 'Error');
          _self.errorMessage.innerHTML = err;

          Topic.publish('/Notification', {
            message: 'Error Creating Workspace',
            type: 'error'
          });
        });
      } else {
        // console.log("Form is incomplete");
      }
    },

    onCancel: function (evt) {
      on.emit(this.domNode, 'dialogAction', {
        action: 'close',
        bubbles: true
      });
    }
  });
});
<commit_msg>fix typo; fixes PATRIC3/patric3_website#2262<commit_after>define([
  'dojo/_base/declare', 'dijit/_WidgetBase', 'dojo/on',
  'dojo/dom-class', 'dijit/_TemplatedMixin', 'dijit/_WidgetsInTemplateMixin',
  'dojo/text!./templates/CreateWorkspace.html', 'dijit/form/Form',
  'dojo/topic', '../WorkspaceManager'
], function (
  declare, WidgetBase, on,
  domClass, Templated, WidgetsInTemplate,
  Template, FormMixin, Topic, WorkspaceManager
) {
  return declare([WidgetBase, FormMixin, Templated, WidgetsInTemplate], {
    baseClass: 'CreateWorkspace',
    templateString: Template,
    cws: null,
    startup: function () {
      this.saveButton.set('disabled', true);
      this.cws = document.getElementsByClassName('cws')[0];

      this.cws.addEventListener('keyup', this.checkChars);
      this.cws.addEventListener('input', this.checkChars);
      this.cws.button = this.saveButton;
      this.cws.errorMessage = document.getElementsByClassName('charError')[0];
    },
    checkChars: function (evt) {
      document.getElementsByClassName('cws')[0].button.set('disabled', true);

      if (evt.target.value.indexOf('/') === -1 && evt.target.value.indexOf('\\') === -1 && evt.target.value !== '') {
        document.getElementsByClassName('cws')[0].button.set('disabled', false);
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = ' ';
        return true;
      }
      if (evt.target.value !== '') {
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = 'Workspace name shall not contain any slashes';
      }
      if (evt.target.value === '') {
        document.getElementsByClassName('cws')[0].errorMessage.innerHTML = ' ';
      }
      return false;
    },
    validate: function () {
      var valid = this.inherited(arguments);
      if (valid) {
        this.saveButton.set('disabled', false);
      } else {
        this.saveButton.set('disabled', true);
      }
      return valid;
    },

    onSubmit: function (evt) {
      var _self = this;

      evt.preventDefault();
      evt.stopPropagation();

      if (this.validate()) {
        var values = this.getValues();
        domClass.add(this.domNode, 'Working');

        WorkspaceManager.createWorkspace(values.name).then(function (results) {
          domClass.remove(_self.domNode, 'Working');

          Topic.publish('/refreshWorkspace', {});

          on.emit(_self.domNode, 'dialogAction', {
            action: 'close',
            bubbles: true
          });

          Topic.publish('/Notification', {
            message: 'Workspace Created',
            positionDirection: 'bl-up'
          });

        }, function (err) {
          domClass.remove(_self.domNode, 'Working');
          domClass.add(_self.domNode, 'Error');
          _self.errorMessage.innerHTML = err;

          Topic.publish('/Notification', {
            message: 'Error Creating Workspace',
            type: 'error'
          });
        });
      } else {
        // console.log("Form is incomplete");
      }
    },

    onCancel: function (evt) {
      on.emit(this.domNode, 'dialogAction', {
        action: 'close',
        bubbles: true
      });
    }
  });
});
<|endoftext|>


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

	angular
		.module('wi.blocks.router', [
             // don't we need to include ui-router dependency?
        ]);

	routerHelperProvider.$inject = ['$locationProvider', '$stateProvider', '$urlRouterProvider'];
	/* @ngInject */
	function routerHelperProvider($locationProvider, $stateProvider, $urlRouterProvider) {
	    /* jshint validthis:true */
	    this.$get = RouterHelper;

	    $locationProvider.html5Mode(true);

	    RouterHelper.$inject = ['$state'];
	    /* @ngInject */
	    function RouterHelper($state) {
	        var hasOtherwise = false;

	        var service = {
	            configureStates: configureStates,
	            getStates: getStates
	        };

	        return service;

	        ///////////////

	        function configureStates(states, otherwisePath) {
	            states.forEach(function(state) {
	                $stateProvider.state(state.state, state.config);
	            });
	            if (otherwisePath && !hasOtherwise) {
	                hasOtherwise = true;
	                $urlRouterProvider.otherwise(otherwisePath);
	            }
	        }

	        function getStates() { return $state.get(); }
	    }
	}

})();<commit_msg>Create router module (router provider)<commit_after>/*
 * wi.blocks.router
 * Router Module
 *
 * This module handles all application routing
 *
 */
(function() {
	'use strict';

	angular
		.module('wi.blocks.router', [
         	'ui.router'
        ]);

})();<|endoftext|>


<commit_before>import DropZoneComponent from './DropZoneComponent';
import DropZoneInstanceManager from './DropZoneInstanceManager';
import DropZoneFactory from './DropZoneFactory';
import DropZoneOptionsManager from './DropZoneOptionsManager';
import DropZoneComponentUtils from './DropZoneComponentUtils';
import DropZoneComponentValidationManager from './DropZoneComponentValidationManager';
import DropZoneBodyClassManager from './DropZoneBodyClassManager';
import MimeTyper from '../libs/MimeTyper';

class DropZoneComonentFactory {
    /**
     * Create an instance of the DropZoneComponent with it's dependencies
     * @param {Element} html
     * @param {String} selector
     * @returns {DropZoneComponent}
     */
    static create (html, selector) {
        return new DropZoneComponent(
            html,
            selector,
            new DropZoneInstanceManager(
                html,
                DropZoneFactory
            ),
            new DropZoneOptionsManager(
                new DropZoneComponentUtils(
                    new MimeTyper()
                )
            ),
            new DropZoneComponentUtils(
                new DropZoneComponentUtils(
                    new MimeTyper()
                )
            ),
            new DropZoneComponentValidationManager(),
            new DropZoneBodyClassManager()
        );
    }
}

module.exports = DropZoneComonentFactory;
<commit_msg>quick fix to the ComponentFactory<commit_after>import DropZoneComponent from './DropZoneComponent';
import DropZoneInstanceManager from './DropZoneInstanceManager';
import DropZoneFactory from './DropZoneFactory';
import DropZoneOptionsManager from './DropZoneOptionsManager';
import DropZoneComponentUtils from './DropZoneComponentUtils';
import DropZoneComponentValidationManager from './DropZoneComponentValidationManager';
import DropZoneBodyClassManager from './DropZoneBodyClassManager';
import MimeTyper from '../libs/MimeTyper';

class DropZoneComonentFactory {
    /**
     * Create an instance of the DropZoneComponent with it's dependencies
     * @param {Element} html
     * @param {String} selector
     * @returns {DropZoneComponent}
     */
    static create (html, selector) {
        return new DropZoneComponent(
            html,
            selector,
            new DropZoneInstanceManager(
                html,
                DropZoneFactory
            ),
            new DropZoneOptionsManager(
                new DropZoneComponentUtils(
                    new MimeTyper()
                )
            ),
            new DropZoneComponentUtils(
                new MimeTyper()
            ),
            new DropZoneComponentValidationManager(),
            new DropZoneBodyClassManager()
        );
    }
}

module.exports = DropZoneComonentFactory;
<|endoftext|>


<commit_before>/**
 * PDX Roaster Mapping Javascript
 *
 * @dependencies:
 * http://maps.google.com/maps/api/js?sensor=false
 * /static/js/pdx.js
 *
 * @see:
 * https://developers.google.com/maps/documentation/javascript/reference
 *
 */
(function ( window, undefined ) {

// Map namespace
window.pdx.maps = {
    lib: "http://maps.google.com/maps/api/js",

    query: {
        sensor: false,
        callback: "pdx.maps.init"
    },

    callbacks: [],

    mapsloaded: false,

    lazyload: function () {
        var g = document.createElement( "script" ),
            s = document.getElementsByTagName( "script" )[ 0 ];

            g.src = this.lib+"?"+this.parseQuery();
            g.type = "text/javascript";
            g.async = true;

            s.parentNode.insertBefore( g, s );
    },

    onmapsready: function ( fn ) {
        if ( this.mapsloaded ) {
        	console.log( "[window.pdx.maps]: mapsloaded, can't push callbacks" );

        	return false;
        }

        this.callbacks.push( fn );
    },

    firemapsready: function () {
        if ( this.mapsloaded ) {
        	console.log( "[window.pdx.maps]: mapsloaded, can't fire callbacks" );

        	return false;
        }

        for ( var i = 0, len = this.callbacks.length; i < len; i++ ) {
        	if ( typeof this.callbacks[ i ] === "function" ) {
        		this.callbacks[ i ]();
        	}
        }
    },

    parseQuery: function ( q ) {
        var query = q || this.query,
            ret = [];

        for ( var p in query ) {
            ret.push( p+"="+query[ p ] );
        }

        return ret.join( "&" );
    }
};

// Lazyload googlemaps
window.pdx.maps.lazyload();

// To be called when maps are loaded
window.pdx.maps.init = function () {

if ( window.pdx.maps.mapsloaded ) {
    console.log( "[window.pdx.maps]: init method already fired" );

	return false;
}

// Closure global vars
var geocoder = new google.maps.Geocoder();

/**
 * Extendable Overlay Class for google.maps
 * Following the Class inheritance example by @resig:
 * http://ejohn.org/blog/simple-javascript-inheritance/
 *
 * The google.maps.OverlayView Class has these methods:
 *
 * addListener
 * bindTo
 * changed
 * get
 * getMap
 * getPanes
 * getProjection
 * map_changed
 * notify
 * set
 * setMap
 * setOptions
 * setValues
 * unbind
 * unbindAll
 *
 */
(function () {
// Create the dummy Class
var Overlay = function () {};

// Set this Classes prototype to an instance of OverlayView
Overlay.prototype = new google.maps.OverlayView();

// Give Overlay an extend method
Overlay.extend = function ( prop ) {
	var prototype = new this();

	for ( var name in prop ) {
		if ( !prototype[ name ] ) {
			prototype[ name ] = prop[ name ];
		}
	}

	// Dummy constructor, use init method
	function Overlay() {
		if ( this.init ) {
			this.init.apply( this, arguments );
		}
	}

	Overlay.prototype = prototype;
	Overlay.prototype.constructor = Overlay;
	Overlay.extend = arguments.callee;

	return Overlay;
};

// Expose Overlay
window.pdx.maps.Overlay = Overlay;
})();

// Adhere to strict after Overlays arguments.callee
"use strict";

// Marker Class
window.pdx.maps.Marker = window.pdx.maps.Overlay.extend({
    init: function ( options ) {
        if ( !options || !options.latLng || !options.map ) {
        	console.log( "[Marker requires latLng and map]" );

        	return false;
        }

        var self = this;

        this.element = document.createElement( "div" );
        this.loaded = false;

        for ( var prop in options ) {
        	this[ prop ] = options[ prop ];
        }

        this.setMap( this.map );

        this.beChange = google.maps.event.addListener(
            this.map,
            "bounds_changed",
            function () {
                return self.panMap.apply( self );
			}
		);
    },

    onAdd: function () {
        var self = this;

        // Build marker html
        this.element.style.position = "absolute";
        this.element.className = "marker-custom";
        this.element.innerHTML = "

";
        this.tooltip = document.createElement( "span" );
        this.tooltip.className = "tooltip";
        this.tooltip.innerHTML = "
"+this.name+"
";
        this.loader = document.createElement( "span" );
        this.loader.className = "plus-spinner";
        this.loader.innerHTML = "

";
        this.element.appendChild( this.tooltip );
        this.element.appendChild( this.loader );
        this.getPanes().floatPane.appendChild( this.element );

        // Open to custom marker actions
        if ( this.onAddCallback && typeof this.onAddCallback === "function" ) {
        	this.onAddCallback( this );
        }
    },

    draw: function () {
        var pixelPosition = this.getProjection().fromLatLngToDivPixel( this.latLng );

        if ( !pixelPosition ) {
        	console.log( "[Marker failed]" );

        	return false;
        }

        this.tooltip.style.left = -((this.tooltip.clientWidth/2)-(this.element.clientWidth/2))+"px";
        this.loader.style.left = -((this.loader.clientWidth/2)-(this.element.clientWidth/2))+"px";
        this.loader.style.top = -(this.loader.clientHeight+3)+"px";
        this.element.style.left = (pixelPosition.x-(this.element.clientWidth/2))+"px";
        this.element.style.top = (pixelPosition.y-(this.element.clientHeight))+"px";
    },

    setPosition: function ( position ) {
        if ( !this.element ) {
			return false;
		}

		this.latLng = position;
		this.draw();

		return true;
    },

    getPosition: function () {
        if ( !this.element ) {
			return null;
		}

		return this.latLng;
    },

    onRemove: function () {
        if ( !this.element ) {
			return false;
		}

		this.element.parentNode.removeChild( this.element );

		return true;
    },

    remove: function () {
        if ( !this.element ) {
			return;
		}

		this.element.parentNode.removeChild( this.element );
		this.element = null;
    },

    panMap: function () {
        if ( !this.map || !this.infowindow ) {
			return;
		}

		var bounds = this.map.getBounds(),

		    // Coords are center of latLng in pixels
			coords = this.getProjection().fromLatLngToDivPixel( this.latLng ),

			// Infowindow dimensions
			iwHeight = this.infowindow.clientHeight,
			iwWidth = this.infowindow.clientWidth,

			// Marker elements dimensions
			e = {
    			top: this.element.offsetTop,
    			left: this.element.offsetLeft,
    			width: this.element.clientWidth,
    			height: this.element.clientHeight
			},

			// Infowindows corners
			o = {
			    iwTopLeft: new google.maps.Point( coords.x-(iwWidth/2), coords.y-iwHeight ),
    			iwTopRight: new google.maps.Point( coords.x+(iwWidth/2), coords.y-iwHeight ),
    			iwBottomLeft: new google.maps.Point( coords.x-(iwWidth/2), coords.y ),
    			iwBottomRight: new google.maps.Point( coords.x+(iwWidth/2), coords.y )
			},

			// We need to figure these out
			containsNE,
			containsSW,
			iwNELatLng,
			iwSWLatLng,
			newLatLng,
			newPoint,
			newX,
			newY;

		if ( !bounds ) {
			return;
		}

		iwNELatLng = this.getProjection().fromDivPixelToLatLng( o.iwTopRight );
		iwSWLatLng = this.getProjection().fromDivPixelToLatLng( o.iwBottomLeft );

		containsNE = bounds.contains( iwNELatLng );
		containsSW = bounds.contains( iwSWLatLng );

		if ( !containsNE || !containsSW ) {
			// Need to figure out newX/newY better than this
			newX = coords.x;
			newY = coords.y;

			newPoint = new google.maps.Point( newX, newY );
			newLatLng = this.getProjection().fromDivPixelToLatLng( newPoint );

			this.map.panTo( newLatLng );
		}

		google.maps.event.removeListener( this.beChange );
    }
});

// Geocoding helper
// data is either {latLng:google.maps.LatLng} OR {address:""}
window.pdx.maps.geocode = function ( data, callback ) {
	geocoder.geocode( data, function ( results, status ) {
		if ( status !== google.maps.GeocoderStatus.OK ) {
			return;
		}

		if ( typeof callback === "function" ) {
			callback( results[ 0 ].geometry.location, results[ 0 ] );
		}
	});
};

// Location
window.pdx.maps.location = {
	lat: 45.5239,
    lng: -122.67,
    latLng: new google.maps.LatLng( 45.5239, -122.67 )
};

// Map settings
window.pdx.maps.settings = {
    center: window.pdx.maps.location.latLng,
	disableDoubleClickZoom: false,
	draggingCursor: "move",
	draggableCursor: "default",
	mapTypeId: google.maps.MapTypeId.ROADMAP,
	mapTypeControl: false,
	panControl: false,
	panControlOptions: {
		position: google.maps.ControlPosition.LEFT_CENTER
	},
	scrollwheel: false,
	styles: window.pdx.mapstyles || [],
	zoom: 15,
	zoomControlOptions: {
		position: google.maps.ControlPosition.LEFT_CENTER,
		style: google.maps.ZoomControlStyle.LARGE
	}
};

// Fire onmapsready callbacks
window.pdx.maps.firemapsready();

// Set the mapsloaded state
window.pdx.maps.mapsloaded = true;

} // END: window.pdx.maps.init

})( window );<commit_msg>adding 100px breather to clear fixed header for infowindows on map<commit_after>/**
 * PDX Roaster Mapping Javascript
 *
 * @dependencies:
 * http://maps.google.com/maps/api/js?sensor=false
 * /static/js/pdx.js
 *
 * @see:
 * https://developers.google.com/maps/documentation/javascript/reference
 *
 */
(function ( window, undefined ) {

// Map namespace
window.pdx.maps = {
    lib: "http://maps.google.com/maps/api/js",

    query: {
        sensor: false,
        callback: "pdx.maps.init"
    },

    callbacks: [],

    mapsloaded: false,

    lazyload: function () {
        var g = document.createElement( "script" ),
            s = document.getElementsByTagName( "script" )[ 0 ];

            g.src = this.lib+"?"+this.parseQuery();
            g.type = "text/javascript";
            g.async = true;

            s.parentNode.insertBefore( g, s );
    },

    onmapsready: function ( fn ) {
        if ( this.mapsloaded ) {
        	console.log( "[window.pdx.maps]: mapsloaded, can't push callbacks" );

        	return false;
        }

        this.callbacks.push( fn );
    },

    firemapsready: function () {
        if ( this.mapsloaded ) {
        	console.log( "[window.pdx.maps]: mapsloaded, can't fire callbacks" );

        	return false;
        }

        for ( var i = 0, len = this.callbacks.length; i < len; i++ ) {
        	if ( typeof this.callbacks[ i ] === "function" ) {
        		this.callbacks[ i ]();
        	}
        }
    },

    parseQuery: function ( q ) {
        var query = q || this.query,
            ret = [];

        for ( var p in query ) {
            ret.push( p+"="+query[ p ] );
        }

        return ret.join( "&" );
    }
};

// Lazyload googlemaps
window.pdx.maps.lazyload();

// To be called when maps are loaded
window.pdx.maps.init = function () {

if ( window.pdx.maps.mapsloaded ) {
    console.log( "[window.pdx.maps]: init method already fired" );

	return false;
}

// Closure global vars
var geocoder = new google.maps.Geocoder();

/**
 * Extendable Overlay Class for google.maps
 * Following the Class inheritance example by @resig:
 * http://ejohn.org/blog/simple-javascript-inheritance/
 *
 * The google.maps.OverlayView Class has these methods:
 *
 * addListener
 * bindTo
 * changed
 * get
 * getMap
 * getPanes
 * getProjection
 * map_changed
 * notify
 * set
 * setMap
 * setOptions
 * setValues
 * unbind
 * unbindAll
 *
 */
(function () {
// Create the dummy Class
var Overlay = function () {};

// Set this Classes prototype to an instance of OverlayView
Overlay.prototype = new google.maps.OverlayView();

// Give Overlay an extend method
Overlay.extend = function ( prop ) {
	var prototype = new this();

	for ( var name in prop ) {
		if ( !prototype[ name ] ) {
			prototype[ name ] = prop[ name ];
		}
	}

	// Dummy constructor, use init method
	function Overlay() {
		if ( this.init ) {
			this.init.apply( this, arguments );
		}
	}

	Overlay.prototype = prototype;
	Overlay.prototype.constructor = Overlay;
	Overlay.extend = arguments.callee;

	return Overlay;
};

// Expose Overlay
window.pdx.maps.Overlay = Overlay;
})();

// Adhere to strict after Overlays arguments.callee
"use strict";

// Marker Class
window.pdx.maps.Marker = window.pdx.maps.Overlay.extend({
    init: function ( options ) {
        if ( !options || !options.latLng || !options.map ) {
        	console.log( "[Marker requires latLng and map]" );

        	return false;
        }

        var self = this;

        this.element = document.createElement( "div" );
        this.loaded = false;

        for ( var prop in options ) {
        	this[ prop ] = options[ prop ];
        }

        this.setMap( this.map );

        this.beChange = google.maps.event.addListener(
            this.map,
            "bounds_changed",
            function () {
                return self.panMap.apply( self );
			}
		);
    },

    onAdd: function () {
        var self = this;

        // Build marker html
        this.element.style.position = "absolute";
        this.element.className = "marker-custom";
        this.element.innerHTML = "

";
        this.tooltip = document.createElement( "span" );
        this.tooltip.className = "tooltip";
        this.tooltip.innerHTML = "
"+this.name+"
";
        this.loader = document.createElement( "span" );
        this.loader.className = "plus-spinner";
        this.loader.innerHTML = "

";
        this.element.appendChild( this.tooltip );
        this.element.appendChild( this.loader );
        this.getPanes().floatPane.appendChild( this.element );

        // Open to custom marker actions
        if ( this.onAddCallback && typeof this.onAddCallback === "function" ) {
        	this.onAddCallback( this );
        }
    },

    draw: function () {
        var pixelPosition = this.getProjection().fromLatLngToDivPixel( this.latLng );

        if ( !pixelPosition ) {
        	console.log( "[Marker failed]" );

        	return false;
        }

        this.tooltip.style.left = -((this.tooltip.clientWidth/2)-(this.element.clientWidth/2))+"px";
        this.loader.style.left = -((this.loader.clientWidth/2)-(this.element.clientWidth/2))+"px";
        this.loader.style.top = -(this.loader.clientHeight+3)+"px";
        this.element.style.left = (pixelPosition.x-(this.element.clientWidth/2))+"px";
        this.element.style.top = (pixelPosition.y-(this.element.clientHeight))+"px";
    },

    setPosition: function ( position ) {
        if ( !this.element ) {
			return false;
		}

		this.latLng = position;
		this.draw();

		return true;
    },

    getPosition: function () {
        if ( !this.element ) {
			return null;
		}

		return this.latLng;
    },

    onRemove: function () {
        if ( !this.element ) {
			return false;
		}

		this.element.parentNode.removeChild( this.element );

		return true;
    },

    remove: function () {
        if ( !this.element ) {
			return;
		}

		this.element.parentNode.removeChild( this.element );
		this.element = null;
    },

    panMap: function () {
        if ( !this.map || !this.infowindow ) {
			return;
		}

		var bounds = this.map.getBounds(),

		    // Coords are center of latLng in pixels
			coords = this.getProjection().fromLatLngToDivPixel( this.latLng ),

			// Infowindow dimensions
			iwHeight = this.infowindow.clientHeight,
			iwWidth = this.infowindow.clientWidth,

			// Marker elements dimensions
			e = {
    			top: this.element.offsetTop,
    			left: this.element.offsetLeft,
    			width: this.element.clientWidth,
    			height: this.element.clientHeight
			},

			// Infowindows corners
			o = {
			    iwTopLeft: new google.maps.Point( coords.x-(iwWidth/2), coords.y-iwHeight ),
    			iwTopRight: new google.maps.Point( coords.x+(iwWidth/2), coords.y-iwHeight ),
    			iwBottomLeft: new google.maps.Point( coords.x-(iwWidth/2), coords.y ),
    			iwBottomRight: new google.maps.Point( coords.x+(iwWidth/2), coords.y )
			},

			// We need to figure these out
			containsNE,
			containsSW,
			iwNELatLng,
			iwSWLatLng,
			newLatLng,
			newPoint,
			newX,
			newY;

		if ( !bounds ) {
			return;
		}

		iwNELatLng = this.getProjection().fromDivPixelToLatLng( o.iwTopRight );
		iwSWLatLng = this.getProjection().fromDivPixelToLatLng( o.iwBottomLeft );

		containsNE = bounds.contains( iwNELatLng );
		containsSW = bounds.contains( iwSWLatLng );

		if ( !containsNE || !containsSW ) {
			newX = coords.x;

			// Padding by 100px to clear the fixed header
			newY = coords.y-100;

			newPoint = new google.maps.Point( newX, newY );
			newLatLng = this.getProjection().fromDivPixelToLatLng( newPoint );

			this.map.panTo( newLatLng );
		}

		google.maps.event.removeListener( this.beChange );
    }
});

// Geocoding helper
// data is either {latLng:google.maps.LatLng} OR {address:""}
window.pdx.maps.geocode = function ( data, callback ) {
	geocoder.geocode( data, function ( results, status ) {
		if ( status !== google.maps.GeocoderStatus.OK ) {
			return;
		}

		if ( typeof callback === "function" ) {
			callback( results[ 0 ].geometry.location, results[ 0 ] );
		}
	});
};

// Location
window.pdx.maps.location = {
	lat: 45.5239,
    lng: -122.67,
    latLng: new google.maps.LatLng( 45.5239, -122.67 )
};

// Map settings
window.pdx.maps.settings = {
    center: window.pdx.maps.location.latLng,
	disableDoubleClickZoom: false,
	draggingCursor: "move",
	draggableCursor: "default",
	mapTypeId: google.maps.MapTypeId.ROADMAP,
	mapTypeControl: false,
	panControl: false,
	panControlOptions: {
		position: google.maps.ControlPosition.LEFT_CENTER
	},
	scrollwheel: false,
	styles: window.pdx.mapstyles || [],
	zoom: 15,
	zoomControlOptions: {
		position: google.maps.ControlPosition.LEFT_CENTER,
		style: google.maps.ZoomControlStyle.LARGE
	}
};

// Fire onmapsready callbacks
window.pdx.maps.firemapsready();

// Set the mapsloaded state
window.pdx.maps.mapsloaded = true;

} // END: window.pdx.maps.init

})( window );<|endoftext|>


<commit_before>import Component from 'flarum/components/Component';
import icon from 'flarum/helpers/icon';

export default class UploadButton extends Component {

    /**
     * Load the configured remote uploader service.
     */
    init() {
        // the service type handling uploads
        this.type = app.forum.attribute('flagrow.remote-image-upload.type') || 'oauth';

    }

    /**
     * Show the actual Upload Button.
     *
     * @returns {*}
     */
    view() {
        return m('div', {className: 'Button hasIcon flagrow-image-upload-button'}, [
            icon('paperclip', {className: 'Button-icon'}),
            m('span', {className: 'Button-label'}, app.translator.trans('flagrow-remote-image-upload.forum.buttons.attach')),
            m('input', {
                type: 'file',
                accept: 'image/*',
                name: 'flagrow-image-upload-input',
                onchange: this.process.bind(this)
            })
        ]);
    }

    /**
     * Process the upload event.
     */
    process() {

        // show loader
        this.markLoaderStarted();

        console.log(this);
        this.(this.type)();

    }

    oauth() {
        // api endpoint
        this.endpoint = app.forum.attribute('flagrow.remote-image-upload.endpoint');
        // client id
        this.client_id = app.forum.attribute('flagrow.remote-image-upload.client_id');
        // client bearer token if non-anonymous
        this.token = app.forum.attribute('flagrow.remote-image-upload.token') || null;
        // whether uploading is anonymous, not account bound
        this.isAnonymous = app.forum.attribute('flagrow.remote-image-upload.anonymous') || true;

        if (this.isAnonymous || !this.token) {
            var headers = {
                client_id: this.client_id
            };
        } else {
            var headers = {
                bearer: this.token
            };
        }

        var button = this;

        $.ajax(this.endpoint, {
            method: 'post',
            // authorization and other headers
            headers: headers,
            // upload success
            success: function (payload, statusCode, xhr) {

                button.markLoaderSuccess();
            },
            // upload error
            error: function(xhr, statusText, error) {

                button.markLoaderFailed();
            },
            statusCode: {
                // unauthorized
                401: function () {
                }
            }
        });
    }

    setIconClasses(classes) {
        this.$('i').removeClass('fa-paperclip fa-spin fa-circle-o-notch fa-check green fa-times red').addClass(classes);
    }
    setLabel(text, disable = false) {
        this.$('.Button-label').text(text);

        // enable on timeout
        if(disable === false && $('.item-submit > button').attr('disabled') === true ) {
            setTimeout(function() {
                $('.item-submit > button').attr('disabled', false);
            }, 1000);
        } else if(disable === true) {
            $('.item-submit > button').attr('disabled', true);
        }
    }

    /**
     * Modifies the file upload button to indicate upload started.
     */
    markLoaderStarted() {
        this.setIconClasses('fa-spin fa-circle-o-notch');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.loading'), true);
    }

    /**
     * Modifies the file upload button to indicate upload success.
     */
    markLoaderSuccess() {
        this.setIconClasses('fa-check green');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.success'), false);
    }

    /**
     * Modifies the file upload button to indicate upload failed.
     */
    markLoaderFailed() {
        this.setIconClasses('fa-times red');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.error'), false);
    }

    /**
     * Resets the file upload button to its original state.
     */
    resetLoader() {
        this.setIconClasses('fa-paperclip');
    }
}<commit_msg>documented methods<commit_after>import Component from 'flarum/components/Component';
import icon from 'flarum/helpers/icon';

export default class UploadButton extends Component {

    /**
     * Load the configured remote uploader service.
     */
    init() {
        // the service type handling uploads
        this.type = app.forum.attribute('flagrow.remote-image-upload.type') || 'oauth';

    }

    /**
     * Show the actual Upload Button.
     *
     * @returns {*}
     */
    view() {
        return m('div', {className: 'Button hasIcon flagrow-image-upload-button'}, [
            icon('paperclip', {className: 'Button-icon'}),
            m('span', {className: 'Button-label'}, app.translator.trans('flagrow-remote-image-upload.forum.buttons.attach')),
            m('input', {
                type: 'file',
                accept: 'image/*',
                name: 'flagrow-image-upload-input',
                onchange: this.process.bind(this)
            })
        ]);
    }

    /**
     * Process the upload event.
     */
    process() {

        // show loader
        this.markLoaderStarted();

        console.log(this);
        this.(this.type)();

    }

    oauth() {
        // api endpoint
        this.endpoint = app.forum.attribute('flagrow.remote-image-upload.endpoint');
        // client id
        this.client_id = app.forum.attribute('flagrow.remote-image-upload.client_id');
        // client bearer token if non-anonymous
        this.token = app.forum.attribute('flagrow.remote-image-upload.token') || null;
        // whether uploading is anonymous, not account bound
        this.isAnonymous = app.forum.attribute('flagrow.remote-image-upload.anonymous') || true;

        if (this.isAnonymous || !this.token) {
            var headers = {
                client_id: this.client_id
            };
        } else {
            var headers = {
                bearer: this.token
            };
        }

        var button = this;

        $.ajax(this.endpoint, {
            method: 'post',
            // authorization and other headers
            headers: headers,
            // upload success
            success: function (payload, statusCode, xhr) {

                button.markLoaderSuccess();
            },
            // upload error
            error: function(xhr, statusText, error) {

                button.markLoaderFailed();
            },
            statusCode: {
                // unauthorized
                401: function () {
                }
            }
        });
    }

    /**
     * Sets the icon classes of the icon in the upload input field.
     *
     * @param classes
     */
    setIconClasses(classes) {
        this.$('i').removeClass('fa-paperclip fa-spin fa-circle-o-notch fa-check green fa-times red').addClass(classes);
    }

    /**
     * Sets the label of the uploader button and allows disabling submits.
     *
     * @param text
     * @param disable
     */
    setLabel(text, disable = false) {
        this.$('.Button-label').text(text);

        // enable on timeout
        if(disable === false && $('.item-submit > button').attr('disabled') === true ) {
            setTimeout(function() {
                $('.item-submit > button').attr('disabled', false);
            }, 1000);
        } else if(disable === true) {
            $('.item-submit > button').attr('disabled', true);
        }
    }

    /**
     * Modifies the file upload button to indicate upload started.
     */
    markLoaderStarted() {
        this.setIconClasses('fa-spin fa-circle-o-notch');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.loading'), true);
    }

    /**
     * Modifies the file upload button to indicate upload success.
     */
    markLoaderSuccess() {
        this.setIconClasses('fa-check green');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.success'), false);
    }

    /**
     * Modifies the file upload button to indicate upload failed.
     */
    markLoaderFailed() {
        this.setIconClasses('fa-times red');
        this.setLabel(app.translator.trans('flagrow-remote-image-upload.forum.states.error'), false);
    }

    /**
     * Resets the file upload button to its original state.
     */
    resetLoader() {
        this.setIconClasses('fa-paperclip');
    }
}<|endoftext|>