<commit_before>import React from 'react'
import { Redirect } from 'react-router'
import { HashLink as Link } from 'react-router-hash-link'
import { Progress } from 'semantic-ui-react'
import PropTypes from 'prop-types'
import * as options from '../settings/Option'
import Option from './Option'

const Quiz = ({rawQuizID, quizID, quiz, nextStep, quizIndex, totalStep, answer, onOptionClick}) => {

  if (quizID === 'report') {
    return (<Redirect to='/report' push />)
  }
  if (quizID !== rawQuizID) {
    return (<Redirect to={`/${quizID}`} push />)
  }

  const next = quiz.next.length > 0 ? quiz.next : nextStep

  let userInput, inputValue
  if (quiz.type === 'select') {
    const routes = quiz.route.split(';')
    userInput = (

        {
          Object.keys(options[quiz.option]).map((key, index) => (
          <Option
            key={`${quizID}-${key}`}
            title={options[quiz.option][key]}
            link={routes[index] || next}
            status={localStorage.getItem(quizID) === key ? 'teal' : ''}
            onClick={() => onOptionClick(quizID, key)}
          />
          ))
        }

    )
  } else if (quiz.type === 'input') {
    let placeholder = 'number...'
    if (localStorage.getItem(quizID) && localStorage.getItem(quizID).length > 0 && localStorage.getItem(quizID) !== 'null') {
      placeholder = localStorage.getItem(quizID)
    }
    userInput = (

      <input type='text' placeholder={placeholder} onChange={(e) => {inputValue = e.target.value}} />
      <Link to={`/${next}`} className='ui icon button' onClick={() => {inputValue = inputValue || localStorage.getItem(quizID); onOptionClick(quizID, inputValue)}}>

      </Link>

    )
  }

  return (

      <Progress value={quizIndex + 1} total={totalStep} size='tiny' color='teal' />

Q

            {quiz.title.length > 0 ? quiz.title : quiz.id}

            {quiz.description}

          {userInput}

  )
}

Quiz.proptypes = {
}

export default Quiz
<commit_msg>let user be able to clear previous answers<commit_after>import React from 'react'
import { Redirect } from 'react-router'
import { HashLink as Link } from 'react-router-hash-link'
import { Progress } from 'semantic-ui-react'
import PropTypes from 'prop-types'
import * as options from '../settings/Option'
import Option from './Option'

const Quiz = ({rawQuizID, quizID, quiz, nextStep, quizIndex, totalStep, answer, onOptionClick}) => {

  if (quizID === 'report') {
    return (<Redirect to='/report' push />)
  }
  if (quizID !== rawQuizID) {
    return (<Redirect to={`/${quizID}`} push />)
  }

  const next = quiz.next.length > 0 ? quiz.next : nextStep
  const previousVal = localStorage.getItem(quizID)
  let userInputJSX

  if (quiz.type === 'select') {
    const routes = quiz.route.split(';')
    userInputJSX = (

        {
          Object.keys(options[quiz.option]).map((key, index) => (
          <Option
            key={`${quizID}-${key}`}
            title={options[quiz.option][key]}
            link={routes[index] || next}
            status={previousVal === key ? 'teal' : ''}
            onClick={() => onOptionClick(quizID, key)}
          />
          ))
        }

    )
  } else if (quiz.type === 'input') {
    let inputChanged = false
    let inputValue, placeholder
    switch (previousVal) {
      case undefined:
      case null:
      case '':
      case 'null':
        placeholder = 'number...'
        inputValue = null
        break
      default:
        placeholder = previousVal
        inputValue = previousVal
    }
    userInputJSX = (

      <input type='text' placeholder={placeholder} onChange={(e) => {inputValue = e.target.value; inputChanged = true }} />
      <Link to={`/${next}`} className='ui icon button' onClick={() => {inputValue = inputChanged ? inputValue : previousVal; onOptionClick(quizID, inputValue)}}>

      </Link>

    )
  }

  return (

      <Progress value={quizIndex + 1} total={totalStep} size='tiny' color='teal' />

Q

            {quiz.title.length > 0 ? quiz.title : quiz.id}

            {quiz.description}

          {userInputJSX}

  )
}

Quiz.proptypes = {
}

export default Quiz
<|endoftext|>


<commit_before>var chai = require('chai');
var assert = chai.assert;
var webdriverio = require('webdriverio');

describe('my webdriverio tests', function () {

  this.timeout(99999999);
  var client = {};

  before(function (done) {
    client = webdriverio.remote({
      desiredCapabilities: {
        browserName: 'phantomjs'
      }
    });
    client.init(done);
  });

  it('Github test', function (done) {
    client
      .url('https://github.com/')
      .getTitle(function (err, title) {
        assert.equal(undefined, err);
        assert.strictEqual(title,
          'GitHub · Build software better, together.');
      })
      .call(done);
  });

  after(function (done) {
    client.end(done);
  });
});
<commit_msg>add e2e tests<commit_after>var chai = require('chai');
var expect = chai.expect;
var webdriverio = require('webdriverio');

describe('Github.com contributions', function () {

  this.timeout(99999999);
  var client = {};
  var htmlResponse;
  var errResponse;
  before(function (done) {
    client = webdriverio.remote({
      desiredCapabilities: {
        browserName: 'phantomjs'
      }
    });
    client.init()
      .url('https://github.com/octocat')
      .getHTML('.contrib-number', false, function (err, html) {
        errResponse = err;
        htmlResponse = html;
      })
      .call(done);
  });

  it('should return html', function () {
    expect(errResponse).to.eql(null);
    expect(htmlResponse).to.not.eql(null);
  });

  it('should have 3 contributions', function () {
    expect(htmlResponse.length).to.eql(3);
  });

  it('should show last year\'s contributions', function () {
    expect(htmlResponse[0]).to.eql('2 total');
  });

  it('should show longest streak', function () {
    expect(htmlResponse[1]).to.eql('2 days');
  });

  it('should show current streak', function () {
    expect(htmlResponse[2]).to.eql('0 days');
  });

  after(function (done) {
    client.end(done);
  });
});
<|endoftext|>


<commit_before>var FancyForms = Class.create({
  initialize: function(){
    this.buttons = $$('a.fancy_form_button');
    this.bind_buttons();

    this.text_fields = $$('input.text_field');
    this.set_text_field_behaviour(this.text_fields);

		$$('input').each(function(input){
			input.observe('keypress', this.submit_form.bind(this));
		});
  },

	submit_form: function(event){
		keycode = window.event ? window.event.keyCode : event.which;
    if (keycode == 13) {
			this.button_click_event(event)
    }
	},

  set_text_field_behaviour: function(text_fields){
    text_fields.each(function(text_field){
        if(text_field.hasClassName("only_numbers")) text_field.observe('keypress', this.only_allow_numbers.bind(this));
    }, this);
  },

  only_allow_numbers: function(event){
    //event.stop();

    keycode = window.event ? window.event.keyCode : event.which;
    if (keycode > 31 && (keycode < 48 || keycode > 57)) {
      event.stop();
    }
  },

  bind_buttons: function(){
    this.buttons.each(function(button){
      button.observe('mousedown', this.button_mouse_down_event.bind(this));
      button.observe('mouseup', this.button_mouse_up_event.bind(this));
      button.observe('mouseout', this.button_mouse_up_event.bind(this));
      button.observe('click', this.button_click_event.bind(this));
      this.disableSelection(button);
    }, this);

    $$('a.fancy_form_link_button').each(function(button){
      button.observe('mousedown', this.button_mouse_down_event.bind(this));
      button.observe('mouseup', this.button_mouse_up_event.bind(this));
      button.observe('mouseout', this.button_mouse_up_event.bind(this));
      this.disableSelection(button);
    },this);

  },

  button_mouse_down_event: function(event){
    element = event.element();
    element = element.tagName == "A" ? element : element.up();
    element.addClassName("click");
  },

  button_mouse_up_event: function(event){
    element = event.element();
    element = element.tagName == "A" ? element : element.up();
    element.removeClassName("click");
  },

  valid_form: function(form){
    return form.select("input.text_field.required").all(function(text_field){
      return text_field.value != "";
    });
  },

  button_click_event: function(event){
    if( this.valid_form(event.element().up('form')) ){
      event.element().up('form').submit();
    } else {
      Dialog.showNotification('Velden error', 'Niet alle velden zijn gevuld');
    }
  },

  disableSelection: function(target){
    if (typeof target.onselectstart!="undefined") //IE route
    	target.onselectstart=function(){return false}
    else if (typeof target.style.MozUserSelect!="undefined") //Firefox route
    	target.style.MozUserSelect="none"
    else //All other route (ie: Opera)
    	target.onmousedown=function(){return false}
    target.style.cursor = "default"
  }

});

document.observe("dom:loaded", function(event){
  fancy_forms = new FancyForms();
});
<commit_msg>submit form bug<commit_after>var FancyForms = Class.create({
  initialize: function(){
    this.buttons = $$('a.fancy_form_button');
    this.bind_buttons();

    this.text_fields = $$('input.text_field');
    this.set_text_field_behaviour(this.text_fields);

		$$('input').each(function(input){
			input.observe('keypress', this.submit_form.bind(this));
		}, this);
  },

	submit_form: function(event){
		keycode = window.event ? window.event.keyCode : event.which;
    if (keycode == 13) {
			this.button_click_event(event)
    }
	},

  set_text_field_behaviour: function(text_fields){
    text_fields.each(function(text_field){
        if(text_field.hasClassName("only_numbers")) text_field.observe('keypress', this.only_allow_numbers.bind(this));
    }, this);
  },

  only_allow_numbers: function(event){
    //event.stop();

    keycode = window.event ? window.event.keyCode : event.which;
    if (keycode > 31 && (keycode < 48 || keycode > 57)) {
      event.stop();
    }
  },

  bind_buttons: function(){
    this.buttons.each(function(button){
      button.observe('mousedown', this.button_mouse_down_event.bind(this));
      button.observe('mouseup', this.button_mouse_up_event.bind(this));
      button.observe('mouseout', this.button_mouse_up_event.bind(this));
      button.observe('click', this.button_click_event.bind(this));
      this.disableSelection(button);
    }, this);

    $$('a.fancy_form_link_button').each(function(button){
      button.observe('mousedown', this.button_mouse_down_event.bind(this));
      button.observe('mouseup', this.button_mouse_up_event.bind(this));
      button.observe('mouseout', this.button_mouse_up_event.bind(this));
      this.disableSelection(button);
    },this);

  },

  button_mouse_down_event: function(event){
    element = event.element();
    element = element.tagName == "A" ? element : element.up();
    element.addClassName("click");
  },

  button_mouse_up_event: function(event){
    element = event.element();
    element = element.tagName == "A" ? element : element.up();
    element.removeClassName("click");
  },

  valid_form: function(form){
    return form.select("input.text_field.required").all(function(text_field){
      return text_field.value != "";
    });
  },

  button_click_event: function(event){
    if( this.valid_form(event.element().up('form')) ){
      event.element().up('form').submit();
    } else {
      Dialog.showNotification('Velden error', 'Niet alle velden zijn gevuld');
    }
  },

  disableSelection: function(target){
    if (typeof target.onselectstart!="undefined") //IE route
    	target.onselectstart=function(){return false}
    else if (typeof target.style.MozUserSelect!="undefined") //Firefox route
    	target.style.MozUserSelect="none"
    else //All other route (ie: Opera)
    	target.onmousedown=function(){return false}
    target.style.cursor = "default"
  }

});

document.observe("dom:loaded", function(event){
  fancy_forms = new FancyForms();
});
<|endoftext|>


<commit_before>'use strict'

var fs = require('fs')
var redis = require('redis')
var RedisClient = require('../../lib/redis-client')
var helpers = require('../helpers')
var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var test = require('selenium-webdriver/testing')
var webdriver = require('selenium-webdriver')
var chrome = require('selenium-webdriver/chrome')
var By = webdriver.By
var Key = webdriver.Key
var until = webdriver.until

chai.should()
chai.use(chaiAsPromised)

test.describe('End-to-end test', function() {
  var driver,
      serverInfo,
      redisClient,
      url,
      targetLocation,
      activeElement,
      createNewLink,
      waitForFormInput,
      waitForActiveLink

  // eslint-disable-next-line no-unused-vars
  var takeScreenshot

  this.timeout(5000)

  test.before(function() {
    driver = new webdriver.Builder().forBrowser('chrome')

    if (process.env.CI === 'true') {
      // See https://docs.travis-ci.com/user/chrome#Sandboxing for details on
      // why sandboxing is disabled.
      driver = driver.setChromeOptions(new chrome.Options()
        .headless()
        .addArguments('--no-sandbox'))
    }
    driver = driver.build()

    return helpers.launchAll().then(result => {
      serverInfo = result
      url = 'http://localhost:' + serverInfo.port + '/'
      targetLocation = url + 'tests/redirect-target.html'
      redisClient = new RedisClient(
        redis.createClient({ port: serverInfo.redis.port }))
    })
  })

  test.beforeEach(function() {
    driver.get(url)
    return waitForActiveLink('Create a new custom link')
  })

  test.afterEach(function() {
    return new Promise(function(resolve, reject) {
      redisClient.impl.flushdb(err => err ? reject(err) : resolve())
    })
  })

  test.after(function() {
    return driver.quit()
      .then(() => helpers.killServer(serverInfo.server))
      .then(() => helpers.killServer(serverInfo.redis.server))
  })

  activeElement = () => driver.switchTo().activeElement()

  takeScreenshot = (filename) => {
    driver.takeScreenshot().then(screenshot => {
      return new Promise((resolve, reject) => {
        fs.writeFile('screenshot' + (filename ? ('-' + filename) : '') + '.png',
          screenshot, 'base64', err => err ? reject(err) : resolve())
      })
    })
  }

  createNewLink = (link, target) => {
    driver.findElement(By.linkText('New link')).click()
    driver.wait(until.urlIs(url + '#create'))
    waitForFormInput().click()
    activeElement().sendKeys(
      Key.HOME, Key.chord(Key.SHIFT, Key.END), link + Key.TAB)
    activeElement().sendKeys(
      Key.HOME, Key.chord(Key.SHIFT, Key.END), target + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + link)
  }

  waitForFormInput = () => {
    return driver.wait(until.elementLocated(By.css('input'), 3000,
      'timeout waiting for form input element to appear'))
  }

  waitForActiveLink = (linkText) => {
    var link = driver.wait(until.elementLocated(By.linkText(linkText)), 3000,
      'timeout waiting for "' + linkText + '" link to appear')

    driver.wait(() => webdriver.WebElement.equals(activeElement(), link), 3000,
      'timeout waiting for "' + linkText + '" link to become active')
    return link
  }

  test.it('shows the no-links message before any links created', function() {
    activeElement().getAttribute('href').should.become(url + '#create')
    activeElement().sendKeys(Key.ENTER)
    driver.wait(until.urlIs(url + '#create'))
  })

  test.it('logs out of the application', function() {
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().getText().should.become('Log out')
    activeElement().getAttribute('href').should.become(url + 'logout')
    activeElement().sendKeys(Key.ENTER)
    // Note that since we're using the dummy test auth instance, we'll get
    // redirected back to the landing page.
    driver.wait(until.urlIs(url))
  })

  test.it('creates a new short link', function() {
    // Rather than click on the active "Create a new custom link" link, let's
    // make sure we can navigate to "New link" in the nav bar as expected.
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().getText().should.become('New link')
    activeElement().sendKeys(Key.ENTER)
    driver.wait(until.urlIs(url + '#create'))
    waitForFormInput()

    activeElement().sendKeys('foo' + Key.TAB)
    activeElement().sendKeys(targetLocation + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + 'foo').sendKeys(Key.ENTER)
    driver.wait(until.urlIs(targetLocation))
  })

  test.it('opens the new link form for an unknown link', function() {
    driver.get(url + 'foo')
    driver.wait(until.urlIs(url + '#create-/foo'))
    waitForFormInput().getAttribute('value').should.become('foo')
    activeElement().sendKeys(targetLocation + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + 'foo')
  })

  test.it('fails to create a link that already exists', function() {
    createNewLink('foo', targetLocation)
    // Back up to the "Create link" button and submit a second time.
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB), Key.SPACE)

    driver.wait(until.elementLocated(By.css('.result .failure')), 3000,
      'timeout waiting for failure message link to appear')
      .getText().should.eventually.contain(url + 'foo already exists')
  })

  test.it('shows user\'s links on the "My links" page', function() {
    this.timeout(10000)
    createNewLink('foo', targetLocation)
    createNewLink('baz', targetLocation)
    createNewLink('bar', targetLocation)

    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))
    waitForActiveLink('/bar')
    driver.findElement(By.linkText('/baz'))
    driver.findElement(By.linkText('/foo'))
    driver.findElement(By.xpath('//*[text() = "3 links"]'))
  })

  test.it('deletes a link from the "My links" page', function() {
    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Delete" button.
    waitForActiveLink('/foo')
    driver.findElement(By.xpath('//*[text() = "1 link"]'))
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.TAB)

    // Open the dialog, then cancel the operation (default option).
    activeElement().sendKeys(Key.SPACE, Key.SPACE)
    driver.findElement(By.linkText('/foo'))

    // Open it again, and now delete the link.
    activeElement().sendKeys(Key.SPACE, Key.TAB, Key.SPACE)
    driver.wait(until.elementLocated(
      By.xpath('//*[text() = "/foo has been deleted"]')))
    driver.findElement(By.xpath('//*[text() = "0 links"]'))
    driver.findElement(By.linkText('/foo')).should.be.rejected
  })

  test.it('edits the target URL', function() {
    var updatedTarget = url + 'tests/updated-target.html'

    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Edit" button and open the dialog.
    waitForActiveLink('/foo')
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.SPACE)
    driver.wait(until.urlIs(url + '#edit-/foo'))
    waitForFormInput().getAttribute('value').should.become(targetLocation)

    // Replace the already-selected target URL, tab to the button, and submit.
    activeElement().sendKeys(updatedTarget, Key.TAB, Key.SPACE)
    waitForActiveLink(url + 'foo').sendKeys(Key.ENTER)
    driver.wait(until.urlIs(updatedTarget))
  })

  test.it('transfers ownership of the link', function() {
    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Edit" button and open the dialog.
    waitForActiveLink('/foo')
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.SPACE)
    driver.wait(until.urlIs(url + '#edit-/foo'))
    waitForFormInput()

    // Tab over to the owner input
    activeElement().sendKeys(Key.TAB, Key.TAB)
    activeElement().getAttribute('value').should.become('mbland@acm.org')

    // Create a user to which we will transfer ownership.
    redisClient.findOrCreateUser('foo@example.com')

    // Enter the user ID, tab to the button, submit, then confirm our decision
    // in the dialog box.
    activeElement().sendKeys('foo@example.com', Key.TAB, Key.SPACE)
    activeElement().sendKeys(Key.TAB, Key.SPACE)
    driver.wait(until.elementLocated(By.css('.result .success'), 3000,
      'timeout waiting for success element to appear'))
    driver.findElement(By.css('.result .success')).getText()
      .should.eventually.contain('foo@example.com')

    // We should no longer see the link in "My links".
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))
    waitForActiveLink('Create a new custom link')
  })
})
<commit_msg>e2e: Fix RedisClient import<commit_after>'use strict'

var fs = require('fs')
var redis = require('redis')
var RedisClient = require('../../lib/redis')
var helpers = require('../helpers')
var chai = require('chai')
var chaiAsPromised = require('chai-as-promised')
var test = require('selenium-webdriver/testing')
var webdriver = require('selenium-webdriver')
var chrome = require('selenium-webdriver/chrome')
var By = webdriver.By
var Key = webdriver.Key
var until = webdriver.until

chai.should()
chai.use(chaiAsPromised)

test.describe('End-to-end test', function() {
  var driver,
      serverInfo,
      redisClient,
      url,
      targetLocation,
      activeElement,
      createNewLink,
      waitForFormInput,
      waitForActiveLink

  // eslint-disable-next-line no-unused-vars
  var takeScreenshot

  this.timeout(5000)

  test.before(function() {
    driver = new webdriver.Builder().forBrowser('chrome')

    if (process.env.CI === 'true') {
      // See https://docs.travis-ci.com/user/chrome#Sandboxing for details on
      // why sandboxing is disabled.
      driver = driver.setChromeOptions(new chrome.Options()
        .headless()
        .addArguments('--no-sandbox'))
    }
    driver = driver.build()

    return helpers.launchAll().then(result => {
      serverInfo = result
      url = 'http://localhost:' + serverInfo.port + '/'
      targetLocation = url + 'tests/redirect-target.html'
      redisClient = new RedisClient(
        redis.createClient({ port: serverInfo.redis.port }))
    })
  })

  test.beforeEach(function() {
    driver.get(url)
    return waitForActiveLink('Create a new custom link')
  })

  test.afterEach(function() {
    return new Promise(function(resolve, reject) {
      redisClient.impl.flushdb(err => err ? reject(err) : resolve())
    })
  })

  test.after(function() {
    return driver.quit()
      .then(() => helpers.killServer(serverInfo.server))
      .then(() => helpers.killServer(serverInfo.redis.server))
  })

  activeElement = () => driver.switchTo().activeElement()

  takeScreenshot = (filename) => {
    driver.takeScreenshot().then(screenshot => {
      return new Promise((resolve, reject) => {
        fs.writeFile('screenshot' + (filename ? ('-' + filename) : '') + '.png',
          screenshot, 'base64', err => err ? reject(err) : resolve())
      })
    })
  }

  createNewLink = (link, target) => {
    driver.findElement(By.linkText('New link')).click()
    driver.wait(until.urlIs(url + '#create'))
    waitForFormInput().click()
    activeElement().sendKeys(
      Key.HOME, Key.chord(Key.SHIFT, Key.END), link + Key.TAB)
    activeElement().sendKeys(
      Key.HOME, Key.chord(Key.SHIFT, Key.END), target + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + link)
  }

  waitForFormInput = () => {
    return driver.wait(until.elementLocated(By.css('input'), 3000,
      'timeout waiting for form input element to appear'))
  }

  waitForActiveLink = (linkText) => {
    var link = driver.wait(until.elementLocated(By.linkText(linkText)), 3000,
      'timeout waiting for "' + linkText + '" link to appear')

    driver.wait(() => webdriver.WebElement.equals(activeElement(), link), 3000,
      'timeout waiting for "' + linkText + '" link to become active')
    return link
  }

  test.it('shows the no-links message before any links created', function() {
    activeElement().getAttribute('href').should.become(url + '#create')
    activeElement().sendKeys(Key.ENTER)
    driver.wait(until.urlIs(url + '#create'))
  })

  test.it('logs out of the application', function() {
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().getText().should.become('Log out')
    activeElement().getAttribute('href').should.become(url + 'logout')
    activeElement().sendKeys(Key.ENTER)
    // Note that since we're using the dummy test auth instance, we'll get
    // redirected back to the landing page.
    driver.wait(until.urlIs(url))
  })

  test.it('creates a new short link', function() {
    // Rather than click on the active "Create a new custom link" link, let's
    // make sure we can navigate to "New link" in the nav bar as expected.
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB))
    activeElement().getText().should.become('New link')
    activeElement().sendKeys(Key.ENTER)
    driver.wait(until.urlIs(url + '#create'))
    waitForFormInput()

    activeElement().sendKeys('foo' + Key.TAB)
    activeElement().sendKeys(targetLocation + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + 'foo').sendKeys(Key.ENTER)
    driver.wait(until.urlIs(targetLocation))
  })

  test.it('opens the new link form for an unknown link', function() {
    driver.get(url + 'foo')
    driver.wait(until.urlIs(url + '#create-/foo'))
    waitForFormInput().getAttribute('value').should.become('foo')
    activeElement().sendKeys(targetLocation + Key.TAB)
    activeElement().sendKeys(Key.SPACE)
    waitForActiveLink(url + 'foo')
  })

  test.it('fails to create a link that already exists', function() {
    createNewLink('foo', targetLocation)
    // Back up to the "Create link" button and submit a second time.
    activeElement().sendKeys(Key.chord(Key.SHIFT, Key.TAB), Key.SPACE)

    driver.wait(until.elementLocated(By.css('.result .failure')), 3000,
      'timeout waiting for failure message link to appear')
      .getText().should.eventually.contain(url + 'foo already exists')
  })

  test.it('shows user\'s links on the "My links" page', function() {
    this.timeout(10000)
    createNewLink('foo', targetLocation)
    createNewLink('baz', targetLocation)
    createNewLink('bar', targetLocation)

    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))
    waitForActiveLink('/bar')
    driver.findElement(By.linkText('/baz'))
    driver.findElement(By.linkText('/foo'))
    driver.findElement(By.xpath('//*[text() = "3 links"]'))
  })

  test.it('deletes a link from the "My links" page', function() {
    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Delete" button.
    waitForActiveLink('/foo')
    driver.findElement(By.xpath('//*[text() = "1 link"]'))
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.TAB)

    // Open the dialog, then cancel the operation (default option).
    activeElement().sendKeys(Key.SPACE, Key.SPACE)
    driver.findElement(By.linkText('/foo'))

    // Open it again, and now delete the link.
    activeElement().sendKeys(Key.SPACE, Key.TAB, Key.SPACE)
    driver.wait(until.elementLocated(
      By.xpath('//*[text() = "/foo has been deleted"]')))
    driver.findElement(By.xpath('//*[text() = "0 links"]'))
    driver.findElement(By.linkText('/foo')).should.be.rejected
  })

  test.it('edits the target URL', function() {
    var updatedTarget = url + 'tests/updated-target.html'

    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Edit" button and open the dialog.
    waitForActiveLink('/foo')
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.SPACE)
    driver.wait(until.urlIs(url + '#edit-/foo'))
    waitForFormInput().getAttribute('value').should.become(targetLocation)

    // Replace the already-selected target URL, tab to the button, and submit.
    activeElement().sendKeys(updatedTarget, Key.TAB, Key.SPACE)
    waitForActiveLink(url + 'foo').sendKeys(Key.ENTER)
    driver.wait(until.urlIs(updatedTarget))
  })

  test.it('transfers ownership of the link', function() {
    createNewLink('foo', targetLocation)
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))

    // Tab over to the "Edit" button and open the dialog.
    waitForActiveLink('/foo')
    activeElement().sendKeys(Key.TAB, Key.TAB, Key.SPACE)
    driver.wait(until.urlIs(url + '#edit-/foo'))
    waitForFormInput()

    // Tab over to the owner input
    activeElement().sendKeys(Key.TAB, Key.TAB)
    activeElement().getAttribute('value').should.become('mbland@acm.org')

    // Create a user to which we will transfer ownership.
    redisClient.findOrCreateUser('foo@example.com')

    // Enter the user ID, tab to the button, submit, then confirm our decision
    // in the dialog box.
    activeElement().sendKeys('foo@example.com', Key.TAB, Key.SPACE)
    activeElement().sendKeys(Key.TAB, Key.SPACE)
    driver.wait(until.elementLocated(By.css('.result .success'), 3000,
      'timeout waiting for success element to appear'))
    driver.findElement(By.css('.result .success')).getText()
      .should.eventually.contain('foo@example.com')

    // We should no longer see the link in "My links".
    driver.findElement(By.linkText('My links')).click()
    driver.wait(until.urlIs(url + '#'))
    waitForActiveLink('Create a new custom link')
  })
})
<|endoftext|>


<commit_before>'use strict'

define(['socket', 'underscore', 'eventEmitter', 'modules/RequestResponseSocketClient'], function (io, _, EventEmitter, RequestResponseSocketClient){
	function SocketConnector(io){
		var self = this;
		this.status = 'connecting';
		this.socket = io.connect('http://localhost:3000');
		this.reqClient = new RequestResponseSocketClient(this.socket);
		this.reconnectFlag = false;
		this.socket.on('connect', function () {
			self.setStatus('connected'); self.emit('connected');
			if (self.reconnectFlag){
				self.reconnectFlag = false;
				self.emit('reconnected');
			}
		});
		this.socket.on('connecting', function () {self.setStatus('connecting');});
		this.socket.on('disconnect', function () {self.setStatus('disconnect');});
		this.socket.on('connect_failed', function () {self.setStatus('connect_failed');});
		this.socket.on('error', function () {self.setStatus('error');});
		this.socket.on('reconnect_failed', function () {self.setStatus('reconnect_failed');});
		this.socket.on('reconnect', function () {self.setStatus('reconnect'); self.reconnectFlag = true;});
		this.socket.on('reconnecting', function () {self.setStatus('reconnecting');});

		this.socket.on('onNewTalk', function (channelData){self.channelEmit('onNewTalk', channelData);});
		this.socket.on('onAddUser', function (channelData){self.channelEmit('onAddUser', channelData);});
		this.socket.on('onRemoveUser', function (channelData){self.channelEmit('onRemoveUser', channelData);});
		this.socket.on('onUpdateUser', function (channelData){self.channelEmit('onUpdateUser', channelData);});
	};

	SocketConnector.prototype.setStatus = function (status){
		var self = this;
		self.status = status;
		self.emit('statusChanged', self.status);
	};

	SocketConnector.prototype.addEventListener = function (eventName, channelId, callback){
		this.addListener(eventName + '-' + channelId, callback);
	};

	SocketConnector.prototype.removeEventListener = function (eventName, channelId, callback){
		this.removeListener(eventName + '-' + channelId, callback);
	};

	SocketConnector.prototype.request = function (url, data, callback){
		this.reqClient.request(url, data, callback);
	};

	SocketConnector.prototype.channelEmit = function (eventName, channelData){
		if (channelData && channelData.channelId){
			this.emit(eventName + '-' + channelData.channelId, channelData.data);
		}
	};

	SocketConnector.prototype.runWithConnection = function (callback){
		if (_.isFunction(callback)){
			if (this.status === 'connected'){
				callback();
			}
			else{
				this.addOnceListener('connected', callback);
			}
		}
	};

	_.extend(SocketConnector.prototype, EventEmitter.prototype);

	return new SocketConnector(io)
});<commit_msg>connect socket current host.<commit_after>'use strict'

define(['socket', 'underscore', 'eventEmitter', 'modules/RequestResponseSocketClient'], function (io, _, EventEmitter, RequestResponseSocketClient){
	function SocketConnector(io){
		var self = this;
		this.status = 'connecting';
		this.socket = io.connect(window.location.origin);
		this.reqClient = new RequestResponseSocketClient(this.socket);
		this.reconnectFlag = false;
		this.socket.on('connect', function () {
			self.setStatus('connected'); self.emit('connected');
			if (self.reconnectFlag){
				self.reconnectFlag = false;
				self.emit('reconnected');
			}
		});
		this.socket.on('connecting', function () {self.setStatus('connecting');});
		this.socket.on('disconnect', function () {self.setStatus('disconnect');});
		this.socket.on('connect_failed', function () {self.setStatus('connect_failed');});
		this.socket.on('error', function () {self.setStatus('error');});
		this.socket.on('reconnect_failed', function () {self.setStatus('reconnect_failed');});
		this.socket.on('reconnect', function () {self.setStatus('reconnect'); self.reconnectFlag = true;});
		this.socket.on('reconnecting', function () {self.setStatus('reconnecting');});

		this.socket.on('onNewTalk', function (channelData){self.channelEmit('onNewTalk', channelData);});
		this.socket.on('onAddUser', function (channelData){self.channelEmit('onAddUser', channelData);});
		this.socket.on('onRemoveUser', function (channelData){self.channelEmit('onRemoveUser', channelData);});
		this.socket.on('onUpdateUser', function (channelData){self.channelEmit('onUpdateUser', channelData);});
	};

	SocketConnector.prototype.setStatus = function (status){
		var self = this;
		self.status = status;
		self.emit('statusChanged', self.status);
	};

	SocketConnector.prototype.addEventListener = function (eventName, channelId, callback){
		this.addListener(eventName + '-' + channelId, callback);
	};

	SocketConnector.prototype.removeEventListener = function (eventName, channelId, callback){
		this.removeListener(eventName + '-' + channelId, callback);
	};

	SocketConnector.prototype.request = function (url, data, callback){
		this.reqClient.request(url, data, callback);
	};

	SocketConnector.prototype.channelEmit = function (eventName, channelData){
		if (channelData && channelData.channelId){
			this.emit(eventName + '-' + channelData.channelId, channelData.data);
		}
	};

	SocketConnector.prototype.runWithConnection = function (callback){
		if (_.isFunction(callback)){
			if (this.status === 'connected'){
				callback();
			}
			else{
				this.addOnceListener('connected', callback);
			}
		}
	};

	_.extend(SocketConnector.prototype, EventEmitter.prototype);

	return new SocketConnector(io)
});<|endoftext|>


<commit_before>/**
 * @(#)yobi.issue.View.js 2013.03.13
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */

(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         * @param {Hash Table} htOptions
         */
        function _init(htOptions){
            _initVar(htOptions || {});
            _initElement(htOptions || {});
            _attachEvent();

            _initFileUploader();
            _initFileDownloader();
            _setLabelTextColor();

            _setTimelineUpdateTimer();
        }

        /**
         * initialize variables except HTML Element
         */
        function _initVar(htOptions){
            htVar.sTplFileItem = $('#tplAttachedFile').text();

            htVar.sIssueId = htOptions.sIssueId;
            htVar.sIssuesUrl = htOptions.sIssuesUrl;

            htVar.sWatchUrl   = htOptions.sWatchUrl;
            htVar.sUnwatchUrl = htOptions.sUnwatchUrl;
            htVar.sTimelineUrl = htOptions.sTimelineUrl;

            htVar.oAssignee  = new yobi.ui.Dropdown({"elContainer": htOptions.welAssignee});
            htVar.oMilestone = new yobi.ui.Dropdown({"elContainer": htOptions.welMilestone});

            htVar.bTimelineUpdating = false;
            htVar.nTimelineUpdateTimer = null;
            htVar.nTimelineUpdatePeriod = htOptions.nTimelineUpdatePeriod || 60000; // 60000ms = 60s = 1m
            htVar.sTimelineHTML = "";
        }

        /**
         * initialize HTML Element variables
         */
        function _initElement(htOptions){
            htElement.welUploader = $("#upload");
            htElement.welTextarea = $("#comment-editor");

            htElement.welAttachments = $(".attachments");
            htElement.welLabels = $('.issue-label');
            htElement.welBtnWatch = $('#watch-button');

            htElement.welIssueUpdateForm = htOptions.welIssueUpdateForm;
            htElement.sIssueCheckBoxesSelector = htOptions.sIssueCheckBoxesSelector;

            htElement.welChkIssueOpen = $("#issueOpen");
            htElement.welTimeline = $("#timeline");
            htVar.sTimelineHTML = htElement.welTimeline.html();
        }

        /**
         * attach event handler
         */
        function _attachEvent(){
            // 지켜보기
            htElement.welBtnWatch.click(_onClickBtnWatch);

            // 이슈 정보 업데이트
            htElement.welChkIssueOpen.change(_onChangeIssueOpen);
            htVar.oMilestone.onChange(_onChangeMilestone);
            htVar.oAssignee.onChange(_onChangeAssignee);
        }

        /**
         * 지켜보기 버튼 클릭시 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         */
        function _onClickBtnWatch(weEvt){
            var welTarget = $(weEvt.target);
            var bWatched = (welTarget.attr("data-watching") == "true") ? true : false;

            $yobi.sendForm({
                "sURL": bWatched ? htVar.sUnwatchUrl : htVar.sWatchUrl,
                "fOnLoad": function(){
                    welTarget.attr("data-watching", !bWatched);
                    welTarget.html(Messages(!bWatched ? "project.unwatch" : "project.watch"));
                    $yobi.notify(Messages(bWatched ? "issue.unwatch.start" : "issue.watch.start"), 3000);
                }
            });
        }

        /**
         * 이슈 해결/미해결 스위치 변경시
         */
        function _onChangeIssueOpen(){
            var welTarget  = $(this);
            var bChecked   = welTarget.prop("checked");
            var sNextState = bChecked ? "OPEN" : "CLOSED";

            _requestUpdateIssue({
               "htData" : {"state": sNextState},
               "fOnLoad": function(){
                    welTarget.prop("checked", bChecked);
                    _updateTimeline();
                },
               "fOnError": function(){
                    welTarget.prop("checked", !bChecked);
                    _onErrorRequest();
               }
            });
        }

        /**
         * 담당자 변경시
         *
         * @param {String} sValue 선택된 항목의 값
         */
        function _onChangeAssignee(sValue){
            _requestUpdateIssue({
               "htData"  : {"assignee.id": sValue},
               "fOnLoad" : function(){
                   $yobi.notify(Messages("issue.update.assignee"), 3000);
                   htVar.oAssignee.selectItem("li[data-id=" + sValue + "]");
                   _updateTimeline();
               },
               "fOnError": _onErrorRequest
            });
        }

        /**
         * 마일스톤 변경시
         *
         * @param {String} sValue 선택된 항목의 값
         */
        function _onChangeMilestone(sValue){
            _requestUpdateIssue({
               "htData"  : {"milestone.id": sValue},
               "fOnLoad" : function(){
                   $yobi.notify(Messages("issue.update.milestone"), 3000);
               },
               "fOnError": _onErrorRequest
            });
        }

        /**
         * 이슈 정보 업데이트 AJAX 호출
         *
         * @param {Hash Table} htOptions
         */
        function _requestUpdateIssue(htOptions){
            var htReqData = {"issues[0].id": htVar.sIssueId};
            for(var sKey in htOptions.htData){
                htReqData[sKey] = htOptions.htData[sKey];
            }

            $.ajax(htVar.sIssuesUrl, {
                "method" : "post",
                "data"   : htReqData,
                "success": htOptions.fOnLoad,
                "error"  : htOptions.fOnError
            });
        }

        /**
         * 이슈 정보 업데이트 호출 실패시
         */
        function _onErrorRequest(){
            $yobi.alert(Messages("error.internalServerError"));
        }

        /**
         * initialize fileUploader
         */
        function _initFileUploader(){
            var oUploader = yobi.Files.getUploader(htElement.welUploader, htElement.welTextarea);

            if(oUploader){
                (new yobi.Attachments({
                    "elContainer"  : htElement.welUploader,
                    "elTextarea"   : htElement.welTextarea,
                    "sTplFileItem" : htVar.sTplFileItem,
                    "sUploaderId"  : oUploader.attr("data-namespace")
                }));
            }
        }

        /**
         * initialize fileDownloader
         */
        function _initFileDownloader(){
            htElement.welAttachments.each(function(i, elContainer){
                if(!$(elContainer).data("isYobiAttachment")){
                    (new yobi.Attachments({"elContainer": elContainer}));
                }
            });
        }

        /**
         * set Labels foreground color as contrast to background color
         */
        function _setLabelTextColor(){
            var welLabel;
            var sBgColor, sColor;

            htElement.welLabels.each(function(nIndex, elLabel){
                welLabel = $(elLabel);
                sBgColor = welLabel.css("background-color");
                sColor = $yobi.getContrastColor(sBgColor);
                welLabel.css("color", sColor);
            });

            welLabel = null;
        }

        /**
         * update IssueTimeline
         */
        function _updateTimeline(){
            if(htVar.bTimelineUpdating){
                return;
            }

            htVar.bTimelineUpdating = true;

            $.get(htVar.sTimelineUrl, function(sResult){
                if(sResult != htVar.sTimelineHTML){ // update only HTML has changed
                    htVar.sTimelineHTML = sResult;
                    htElement.welTimeline.html(sResult); // update timeline HTML
                    yobi.Markdown.enableMarkdown(htElement.welTimeline.find("[markdown]")); // enable markdown
                    htElement.welTimeline.find("[data-request-method]").requestAs(); // delete button
                }
            }).always(function(){
                htVar.bTimelineUpdating = false;
            });
        }

        /**
         * update IssueTimeline automatically
         * with interval timer
         */
        function _setTimelineUpdateTimer(){
            if(htVar.nTimelineUpdateTimer != null){
                clearInterval(htVar.nTimelineUpdateTimer);
                htVar.nTimelineUpdateTimer = null;
            }

            htVar.nTimelineUpdateTimer = setInterval(function(){
                if(htVar.bTimelineUpdating !== true){
                    _updateTimeline();
                }
            }, htVar.nTimelineUpdatePeriod);
        }

        // initialize
        _init(htOptions || {});
    };
})("yobi.issue.View");
<commit_msg>Issue: init fileDownloader for autoUpdate timeline<commit_after>/**
 * @(#)yobi.issue.View.js 2013.03.13
 *
 * Copyright NHN Corporation.
 * Released under the MIT license
 *
 * http://yobi.dev.naver.com/license
 */

(function(ns){

    var oNS = $yobi.createNamespace(ns);
    oNS.container[oNS.name] = function(htOptions){

        var htVar = {};
        var htElement = {};

        /**
         * initialize
         * @param {Hash Table} htOptions
         */
        function _init(htOptions){
            _initVar(htOptions || {});
            _initElement(htOptions || {});
            _attachEvent();

            _initFileUploader();
            _initFileDownloader();
            _setLabelTextColor();

            _setTimelineUpdateTimer();
        }

        /**
         * initialize variables except HTML Element
         */
        function _initVar(htOptions){
            htVar.sTplFileItem = $('#tplAttachedFile').text();

            htVar.sIssueId = htOptions.sIssueId;
            htVar.sIssuesUrl = htOptions.sIssuesUrl;

            htVar.sWatchUrl   = htOptions.sWatchUrl;
            htVar.sUnwatchUrl = htOptions.sUnwatchUrl;
            htVar.sTimelineUrl = htOptions.sTimelineUrl;

            htVar.oAssignee  = new yobi.ui.Dropdown({"elContainer": htOptions.welAssignee});
            htVar.oMilestone = new yobi.ui.Dropdown({"elContainer": htOptions.welMilestone});

            htVar.bTimelineUpdating = false;
            htVar.nTimelineUpdateTimer = null;
            htVar.nTimelineUpdatePeriod = htOptions.nTimelineUpdatePeriod || 60000; // 60000ms = 60s = 1m
            htVar.sTimelineHTML = "";
        }

        /**
         * initialize HTML Element variables
         */
        function _initElement(htOptions){
            htElement.welUploader = $("#upload");
            htElement.welTextarea = $("#comment-editor");

            htElement.welLabels = $('.issue-label');
            htElement.welBtnWatch = $('#watch-button');

            htElement.welIssueUpdateForm = htOptions.welIssueUpdateForm;
            htElement.sIssueCheckBoxesSelector = htOptions.sIssueCheckBoxesSelector;

            htElement.welChkIssueOpen = $("#issueOpen");
            htElement.welTimeline = $("#timeline");
            htVar.sTimelineHTML = htElement.welTimeline.html();
        }

        /**
         * attach event handler
         */
        function _attachEvent(){
            // 지켜보기
            htElement.welBtnWatch.click(_onClickBtnWatch);

            // 이슈 정보 업데이트
            htElement.welChkIssueOpen.change(_onChangeIssueOpen);
            htVar.oMilestone.onChange(_onChangeMilestone);
            htVar.oAssignee.onChange(_onChangeAssignee);
        }

        /**
         * 지켜보기 버튼 클릭시 이벤트 핸들러
         *
         * @param {Wrapped Event} weEvt
         */
        function _onClickBtnWatch(weEvt){
            var welTarget = $(weEvt.target);
            var bWatched = (welTarget.attr("data-watching") == "true") ? true : false;

            $yobi.sendForm({
                "sURL": bWatched ? htVar.sUnwatchUrl : htVar.sWatchUrl,
                "fOnLoad": function(){
                    welTarget.attr("data-watching", !bWatched);
                    welTarget.html(Messages(!bWatched ? "project.unwatch" : "project.watch"));
                    $yobi.notify(Messages(bWatched ? "issue.unwatch.start" : "issue.watch.start"), 3000);
                }
            });
        }

        /**
         * 이슈 해결/미해결 스위치 변경시
         */
        function _onChangeIssueOpen(){
            var welTarget  = $(this);
            var bChecked   = welTarget.prop("checked");
            var sNextState = bChecked ? "OPEN" : "CLOSED";

            _requestUpdateIssue({
               "htData" : {"state": sNextState},
               "fOnLoad": function(){
                    welTarget.prop("checked", bChecked);
                    _updateTimeline();
                },
               "fOnError": function(){
                    welTarget.prop("checked", !bChecked);
                    _onErrorRequest();
               }
            });
        }

        /**
         * 담당자 변경시
         *
         * @param {String} sValue 선택된 항목의 값
         */
        function _onChangeAssignee(sValue){
            _requestUpdateIssue({
               "htData"  : {"assignee.id": sValue},
               "fOnLoad" : function(){
                   $yobi.notify(Messages("issue.update.assignee"), 3000);
                   htVar.oAssignee.selectItem("li[data-id=" + sValue + "]");
                   _updateTimeline();
               },
               "fOnError": _onErrorRequest
            });
        }

        /**
         * 마일스톤 변경시
         *
         * @param {String} sValue 선택된 항목의 값
         */
        function _onChangeMilestone(sValue){
            _requestUpdateIssue({
               "htData"  : {"milestone.id": sValue},
               "fOnLoad" : function(){
                   $yobi.notify(Messages("issue.update.milestone"), 3000);
               },
               "fOnError": _onErrorRequest
            });
        }

        /**
         * 이슈 정보 업데이트 AJAX 호출
         *
         * @param {Hash Table} htOptions
         */
        function _requestUpdateIssue(htOptions){
            var htReqData = {"issues[0].id": htVar.sIssueId};
            for(var sKey in htOptions.htData){
                htReqData[sKey] = htOptions.htData[sKey];
            }

            $.ajax(htVar.sIssuesUrl, {
                "method" : "post",
                "data"   : htReqData,
                "success": htOptions.fOnLoad,
                "error"  : htOptions.fOnError
            });
        }

        /**
         * 이슈 정보 업데이트 호출 실패시
         */
        function _onErrorRequest(){
            $yobi.alert(Messages("error.internalServerError"));
        }

        /**
         * initialize fileUploader
         */
        function _initFileUploader(){
            var oUploader = yobi.Files.getUploader(htElement.welUploader, htElement.welTextarea);

            if(oUploader){
                (new yobi.Attachments({
                    "elContainer"  : htElement.welUploader,
                    "elTextarea"   : htElement.welTextarea,
                    "sTplFileItem" : htVar.sTplFileItem,
                    "sUploaderId"  : oUploader.attr("data-namespace")
                }));
            }
        }

        /**
         * initialize fileDownloader
         */
        function _initFileDownloader(){
            $(".attachments").each(function(i, elContainer){
                if(!$(elContainer).data("isYobiAttachment")){
                    (new yobi.Attachments({"elContainer": elContainer}));
                }
            });
        }

        /**
         * set Labels foreground color as contrast to background color
         */
        function _setLabelTextColor(){
            var welLabel;
            var sBgColor, sColor;

            htElement.welLabels.each(function(nIndex, elLabel){
                welLabel = $(elLabel);
                sBgColor = welLabel.css("background-color");
                sColor = $yobi.getContrastColor(sBgColor);
                welLabel.css("color", sColor);
            });

            welLabel = null;
        }

        /**
         * update IssueTimeline
         */
        function _updateTimeline(){
            if(htVar.bTimelineUpdating){
                return;
            }

            htVar.bTimelineUpdating = true;

            $.get(htVar.sTimelineUrl, function(sResult){
                if(sResult != htVar.sTimelineHTML){ // update only HTML has changed
                    htVar.sTimelineHTML = sResult;
                    htElement.welTimeline.html(sResult); // update timeline HTML
                    yobi.Markdown.enableMarkdown(htElement.welTimeline.find("[markdown]")); // enable markdown
                    htElement.welTimeline.find("[data-request-method]").requestAs(); // delete button
                    _initFileDownloader(); // attachments on comment
                }
            }).always(function(){
                htVar.bTimelineUpdating = false;
            });
        }

        /**
         * update IssueTimeline automatically
         * with interval timer
         */
        function _setTimelineUpdateTimer(){
            if(htVar.nTimelineUpdateTimer != null){
                clearInterval(htVar.nTimelineUpdateTimer);
                htVar.nTimelineUpdateTimer = null;
            }

            htVar.nTimelineUpdateTimer = setInterval(function(){
                if(htVar.bTimelineUpdating !== true){
                    _updateTimeline();
                }
            }, htVar.nTimelineUpdatePeriod);
        }

        // initialize
        _init(htOptions || {});
    };
})("yobi.issue.View");
<|endoftext|>


<commit_before>'use strict';

var app = app || {};

(function (module) {
  const aboutController = {};

  aboutController.index = () => {
    $('body > :not(#about-us)').hide();
    $('#hide-div').css('visibility','hidden !important')
  };

  module.aboutController = aboutController;
})(app);<commit_msg>aboutcontroller hides certain things while showing UL names<commit_after>'use strict';

var app = app || {};

(function (module) {
  const aboutController = {};

  aboutController.index = () => {
    $('body > :not(#about-us)').hide();
    $('#hide-about').css('visibility','hidden')
  };

  module.aboutController = aboutController;
})(app);<|endoftext|>


<commit_before>var DNT = window.DNT || {};

(function (ns) {
    "use strict";

    var turtyper = {
        'Fottur': ['Alpint', 'Bærtur', 'Fisketur', 'Fjelltur', 'Grottetur', 'Hyttetur', 'Skogstur', 'Sopptur', 'Telttur', 'Topptur', 'Trilletur'],
        'Skitur': ['Alpint', 'Hyttetur', 'Langrenn', 'Snowboard', 'Snøhuletur', 'Telemark', 'Telttur', 'Topptur'],
        'Sykkeltur': ['Downhillsykling', 'Landeveissykling', 'Terrengsykling'],
        'Padletur': ['Kajakktur', 'Kanotur'],
        'Bretur': ['Alpint', 'Hyttetur', 'Telttur', 'Topptur'],
        'Klatretur': ['Alpint', 'Telttur', 'Topptur']
    };

    var passerForOptions = ['Barn', 'Voksen', 'Senior'];

    var tilrettelagtForOptions = ['Barnevogn', 'Rullestol'];

    ns.RouteFactsView = Backbone.View.extend({

        el: "#route-facts",

        bindings: {
            '[name="route-facts-field-navn"]': {
                observe: 'navn',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-beskrivelse"]': {
                observe: 'beskrivelse',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-adkomst_generell"]': 'adkomst',
            '[name="route-facts-field-ankomst_kollektivtransport"]': 'kollektiv',
            '[name="route-facts-field-typetur"]': {
                observe: 'turtype',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-gradering"]': {
                observe: 'gradering',
                setOptions: {
                    validate: true
                }
            },
            'select.form-control.route-facts-field-tidsbruk-normal-dager': 'tidsbrukDager',
            'select.form-control.route-facts-field-tidsbruk-normal-timer': 'tidsbrukTimer',
            'select.form-control.route-facts-field-tidsbruk-normal-minutter': 'tidsbrukMinutter',
            '.route-facts-field-sesong input': {
                observe: 'sesong',
                onGet: function(val) {
                    if (!!val && val.length) {
                        for (var i = 0; i < val.length; i++) {
                            val[i] = '' + val[i];
                        }
                    }
                    return val;
                },
                onSet: function(val) {
                    // for (var i = 0; i < val.length; i++) {
                    //     val[i] = parseInt(val[i], 10);
                    // }
                    // console.log('onSet');
                    // console.log(val);
                    return val;
                },
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-passer_for_barn"]': {
                observe: 'passer_for',
                onGet: 'onGetPasserForBarn',
                onSet: 'onSetPasserForBarn'
            }
        },

        events: {
            'click #checkbox_kollektivMulig': 'toggleKollektivFieldVisibility',
            'click #route-facts-field-sesong-select-all': 'selectAllSeasons',
            'click #route-facts-field-sesong-deselect-all': 'deselectAllSeasons',
            'click .route-facts-field-sesong input[type="checkbox"]': 'updateSeasonSelection',
            'click .route-facts-field-tags-primary label': 'setPrimaryTag'
        },

        initialize: function (options) {

            this.model.on('change:navn', this.updateRouteNamePlaceholders, this);
            this.model.on('change:tidsbrukDager', this.toggleHoursAndMinutesVisiblity, this);
            this.model.on('change:turtype', this.updateFlereTurtyperOptions, this);

            // Bind these methods to this scope
            _.bindAll(this, 'onGetPasserForBarn', 'onSetPasserForBarn');

            this.user = options.user;

            if (!!this.model.get('navn') && this.model.get('navn').length > 0) {
                this.updateRouteNamePlaceholders();
            }

            if (!!this.model.get('tidsbrukDager')) {
                this.toggleHoursAndMinutesVisiblity();
            }

            if (this.model.getRouteType() !== '') {
                var $routeTypeElement = this.$('input[value="' + this.model.getRouteType() + '"]');
                $routeTypeElement.parent('label').addClass('active');
            }

            if (!!this.model.get('gradering')) {
                var $graderingElement = this.$('input[value="' + this.model.get('gradering') + '"]');
                $graderingElement.parent('label').addClass('active');
            }

        },

        updateFlereTurtyperOptions: function () {
            var $flereTurtyperInput = this.$('[name="route-facts-field-flere-typer"]');

            if ($flereTurtyperInput.hasClass('select2-offscreen')) {
                $flereTurtyperInput.select2('val', '');
                $flereTurtyperInput.select2('destroy');
            }

            var turtype = this.model.get('turtype');

            $flereTurtyperInput.select2({
                formatNoMatches: function () { return 'Type tur ikke valgt eller ingen treff'; },
                tags: (!!turtype && turtype !== '') ? turtyper[turtype] : [], // If turtype is not set, no tags are available
                createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
            }).on('change', $.proxy(this.onFlereTurtyperChange, this));

        },

        onFlereTurtyperChange: function (e) {
            var flereTurtyper = e.val;
            this.model.set('flereTurtyper', flereTurtyper);
        },

        toggleHoursAndMinutesVisiblity: function () {
            var val = this.model.get('tidsbrukDager');
            if (val === '1') {
                this.$('.form-group.route-facts-field-tidsbruk-normal-timer-minutter').removeClass('hidden');
            } else {
                this.$('.form-group.route-facts-field-tidsbruk-normal-timer-minutter').addClass('hidden');
            }
        },

        toggleKollektivFieldVisibility: function (e) {
            if (e.currentTarget.checked) {
                this.$('#route-facts-field-ankomst_kollektivtransport').removeClass('hidden');
                this.$('#route-facts-field-ankomst_kollektivtransport_description').removeClass('hidden');
            } else {
                this.$('#route-facts-field-ankomst_kollektivtransport').addClass('hidden');
                this.$('#route-facts-field-ankomst_kollektivtransport_description').addClass('hidden');
                this.model.set('kollektiv', '');
            }
        },

        selectAllSeasons: function () {
            this.$('.route-facts-field-sesong input[type="checkbox"]').prop('checked', true);
            this.$('#route-facts-field-sesong-deselect-all').removeClass('hidden');
            this.$('#route-facts-field-sesong-select-all').addClass('hidden');
        },

        deselectAllSeasons: function () {
            this.$('.route-facts-field-sesong input[type="checkbox"]').prop('checked', false);
            this.$('#route-facts-field-sesong-deselect-all').addClass('hidden');
            this.$('#route-facts-field-sesong-select-all').removeClass('hidden');
        },

        updateSeasonSelection: function () {
            var checked = this.$('.route-facts-field-sesong input[type="checkbox"]:checked');
            var seasons = [];
            for (var i = 0; i < checked.length; i =  i + 1) {
                var val = this.$(checked[i]).val();
                seasons.push(val);
            }
            this.model.set('sesong', seasons);
        },

        onGetPasserForBarn: function (val, options) {
            var passerFor = val || [];
            return (passerFor.indexOf('Barn') > -1) ? true : false;
        },

        onSetPasserForBarn: function (val, options) {
            var passerForBarn = val;
            return (passerForBarn === true) ? ['Barn'] : [];
        },

        updateRouteNamePlaceholders: function () {
            var routeName = this.model.get('navn');
            $('[data-placeholder-for="route-name"]').html(routeName);
        },

        render: function () {

            this.updateFlereTurtyperOptions();
            this.$('[name="route-facts-field-flere-typer"]').select2('val', this.model.getAdditionalRouteTypes());

            $('input[name="route-facts-field-tilrettelagt_for"]').select2({
                tags: tilrettelagtForOptions,
                createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
            }).on('change', $.proxy(function (e) {
                var tilrettelagt_for = e.val;
                this.model.set('tilrettelagt_for', tilrettelagt_for);
            }, this));

            this.$('[name="route-facts-field-tilrettelagt_for"]').select2('val', this.model.get('tilrettelagt_for'));

            var userGroups = this.user.get('grupper');
            if (userGroups.length > 0) {
                var select2Groups = [];

                for (var i = 0; i < userGroups.length; i++) {
                    select2Groups[i] = {};
                    select2Groups[i].id = userGroups[i].object_id;
                    select2Groups[i].text = userGroups[i].navn;
                }

                $('input[name="route-facts-field-grupper"]').select2({
                    tags: select2Groups,
                    createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
                }).on('change', $.proxy(function (e) {
                    var routeGroups = e.val;
                    this.model.set('grupper', routeGroups);
                }, this));

                this.$('[name="route-facts-field-grupper"]').select2('val', this.model.get('grupper'));

            } else {
                // If user does not belong to any groups, do not show groups field.
                this.$('.form-group.route-facts-field-grupper').remove();
            }

            var routeFactsLinksView = new DNT.RouteFactsLinksView({ model: this.model });
            this.$('#routeFactsLinksInput').append(routeFactsLinksView.render().el);

            var publicTransportation = this.model.get('kollektiv');

            if (!!publicTransportation && publicTransportation.length > 0) {
                this.$('.route-facts-field-ankomst_kollektivtransport input[type="checkbox"]').prop('checked', true);
                this.$('.route-facts-field-ankomst_kollektivtransport textarea').removeClass('hidden');
            }

            this.stickit(); // Uses view.bindings and view.model to setup bindings
            Backbone.Validation.bind(this);

        },

        remove: function() {
            // Remove the validation binding
            // See: http://thedersen.com/projects/backbone-validation/#using-form-model-validation/unbinding
            Backbone.Validation.unbind(this);
            return Backbone.View.prototype.remove.apply(this, arguments);
        }
    });
}(DNT));
<commit_msg>Hide kollektiv field help text if model field is empty on page load<commit_after>var DNT = window.DNT || {};

(function (ns) {
    "use strict";

    var turtyper = {
        'Fottur': ['Alpint', 'Bærtur', 'Fisketur', 'Fjelltur', 'Grottetur', 'Hyttetur', 'Skogstur', 'Sopptur', 'Telttur', 'Topptur', 'Trilletur'],
        'Skitur': ['Alpint', 'Hyttetur', 'Langrenn', 'Snowboard', 'Snøhuletur', 'Telemark', 'Telttur', 'Topptur'],
        'Sykkeltur': ['Downhillsykling', 'Landeveissykling', 'Terrengsykling'],
        'Padletur': ['Kajakktur', 'Kanotur'],
        'Bretur': ['Alpint', 'Hyttetur', 'Telttur', 'Topptur'],
        'Klatretur': ['Alpint', 'Telttur', 'Topptur']
    };

    var passerForOptions = ['Barn', 'Voksen', 'Senior'];

    var tilrettelagtForOptions = ['Barnevogn', 'Rullestol'];

    ns.RouteFactsView = Backbone.View.extend({

        el: "#route-facts",

        bindings: {
            '[name="route-facts-field-navn"]': {
                observe: 'navn',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-beskrivelse"]': {
                observe: 'beskrivelse',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-adkomst_generell"]': 'adkomst',
            '[name="route-facts-field-ankomst_kollektivtransport"]': 'kollektiv',
            '[name="route-facts-field-typetur"]': {
                observe: 'turtype',
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-gradering"]': {
                observe: 'gradering',
                setOptions: {
                    validate: true
                }
            },
            'select.form-control.route-facts-field-tidsbruk-normal-dager': 'tidsbrukDager',
            'select.form-control.route-facts-field-tidsbruk-normal-timer': 'tidsbrukTimer',
            'select.form-control.route-facts-field-tidsbruk-normal-minutter': 'tidsbrukMinutter',
            '.route-facts-field-sesong input': {
                observe: 'sesong',
                onGet: function(val) {
                    if (!!val && val.length) {
                        for (var i = 0; i < val.length; i++) {
                            val[i] = '' + val[i];
                        }
                    }
                    return val;
                },
                onSet: function(val) {
                    // for (var i = 0; i < val.length; i++) {
                    //     val[i] = parseInt(val[i], 10);
                    // }
                    // console.log('onSet');
                    // console.log(val);
                    return val;
                },
                setOptions: {
                    validate: true
                }
            },
            '[name="route-facts-field-passer_for_barn"]': {
                observe: 'passer_for',
                onGet: 'onGetPasserForBarn',
                onSet: 'onSetPasserForBarn'
            }
        },

        events: {
            'click #checkbox_kollektivMulig': 'toggleKollektivFieldVisibility',
            'click #route-facts-field-sesong-select-all': 'selectAllSeasons',
            'click #route-facts-field-sesong-deselect-all': 'deselectAllSeasons',
            'click .route-facts-field-sesong input[type="checkbox"]': 'updateSeasonSelection',
            'click .route-facts-field-tags-primary label': 'setPrimaryTag'
        },

        initialize: function (options) {
            this.model.on('change:navn', this.updateRouteNamePlaceholders, this);
            this.model.on('change:tidsbrukDager', this.toggleHoursAndMinutesVisiblity, this);
            this.model.on('change:turtype', this.updateFlereTurtyperOptions, this);

            // Bind these methods to this scope
            _.bindAll(this, 'onGetPasserForBarn', 'onSetPasserForBarn');

            this.user = options.user;

            if (!!this.model.get('navn') && this.model.get('navn').length > 0) {
                this.updateRouteNamePlaceholders();
            }

            if (!!this.model.get('tidsbrukDager')) {
                this.toggleHoursAndMinutesVisiblity();
            }

            if (this.model.getRouteType() !== '') {
                var $routeTypeElement = this.$('input[value="' + this.model.getRouteType() + '"]');
                $routeTypeElement.parent('label').addClass('active');
            }

            if (!!this.model.get('gradering')) {
                var $graderingElement = this.$('input[value="' + this.model.get('gradering') + '"]');
                $graderingElement.parent('label').addClass('active');
            }

            if (this.model.get('kollektiv') === '') {
                this.$('#route-facts-field-ankomst_kollektivtransport_description').addClass('hidden');
            }

        },

        updateFlereTurtyperOptions: function () {
            var $flereTurtyperInput = this.$('[name="route-facts-field-flere-typer"]');

            if ($flereTurtyperInput.hasClass('select2-offscreen')) {
                $flereTurtyperInput.select2('val', '');
                $flereTurtyperInput.select2('destroy');
            }

            var turtype = this.model.get('turtype');

            $flereTurtyperInput.select2({
                formatNoMatches: function () { return 'Type tur ikke valgt eller ingen treff'; },
                tags: (!!turtype && turtype !== '') ? turtyper[turtype] : [], // If turtype is not set, no tags are available
                createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
            }).on('change', $.proxy(this.onFlereTurtyperChange, this));

        },

        onFlereTurtyperChange: function (e) {
            var flereTurtyper = e.val;
            this.model.set('flereTurtyper', flereTurtyper);
        },

        toggleHoursAndMinutesVisiblity: function () {
            var val = this.model.get('tidsbrukDager');
            if (val === '1') {
                this.$('.form-group.route-facts-field-tidsbruk-normal-timer-minutter').removeClass('hidden');
            } else {
                this.$('.form-group.route-facts-field-tidsbruk-normal-timer-minutter').addClass('hidden');
            }
        },

        toggleKollektivFieldVisibility: function (e) {
            if (e.currentTarget.checked) {
                this.$('#route-facts-field-ankomst_kollektivtransport').removeClass('hidden');
                this.$('#route-facts-field-ankomst_kollektivtransport_description').removeClass('hidden');
            } else {
                this.$('#route-facts-field-ankomst_kollektivtransport').addClass('hidden');
                this.$('#route-facts-field-ankomst_kollektivtransport_description').addClass('hidden');
                this.model.set('kollektiv', '');
            }
        },

        selectAllSeasons: function () {
            this.$('.route-facts-field-sesong input[type="checkbox"]').prop('checked', true);
            this.$('#route-facts-field-sesong-deselect-all').removeClass('hidden');
            this.$('#route-facts-field-sesong-select-all').addClass('hidden');
        },

        deselectAllSeasons: function () {
            this.$('.route-facts-field-sesong input[type="checkbox"]').prop('checked', false);
            this.$('#route-facts-field-sesong-deselect-all').addClass('hidden');
            this.$('#route-facts-field-sesong-select-all').removeClass('hidden');
        },

        updateSeasonSelection: function () {
            var checked = this.$('.route-facts-field-sesong input[type="checkbox"]:checked');
            var seasons = [];
            for (var i = 0; i < checked.length; i =  i + 1) {
                var val = this.$(checked[i]).val();
                seasons.push(val);
            }
            this.model.set('sesong', seasons);
        },

        onGetPasserForBarn: function (val, options) {
            var passerFor = val || [];
            return (passerFor.indexOf('Barn') > -1) ? true : false;
        },

        onSetPasserForBarn: function (val, options) {
            var passerForBarn = val;
            return (passerForBarn === true) ? ['Barn'] : [];
        },

        updateRouteNamePlaceholders: function () {
            var routeName = this.model.get('navn');
            $('[data-placeholder-for="route-name"]').html(routeName);
        },

        render: function () {

            this.updateFlereTurtyperOptions();
            this.$('[name="route-facts-field-flere-typer"]').select2('val', this.model.getAdditionalRouteTypes());

            $('input[name="route-facts-field-tilrettelagt_for"]').select2({
                tags: tilrettelagtForOptions,
                createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
            }).on('change', $.proxy(function (e) {
                var tilrettelagt_for = e.val;
                this.model.set('tilrettelagt_for', tilrettelagt_for);
            }, this));

            this.$('[name="route-facts-field-tilrettelagt_for"]').select2('val', this.model.get('tilrettelagt_for'));

            var userGroups = this.user.get('grupper');
            if (userGroups.length > 0) {
                var select2Groups = [];

                for (var i = 0; i < userGroups.length; i++) {
                    select2Groups[i] = {};
                    select2Groups[i].id = userGroups[i].object_id;
                    select2Groups[i].text = userGroups[i].navn;
                }

                $('input[name="route-facts-field-grupper"]').select2({
                    tags: select2Groups,
                    createSearchChoice: function () { return null; } // This will prevent the user from entering custom tags
                }).on('change', $.proxy(function (e) {
                    var routeGroups = e.val;
                    this.model.set('grupper', routeGroups);
                }, this));

                this.$('[name="route-facts-field-grupper"]').select2('val', this.model.get('grupper'));

            } else {
                // If user does not belong to any groups, do not show groups field.
                this.$('.form-group.route-facts-field-grupper').remove();
            }

            var routeFactsLinksView = new DNT.RouteFactsLinksView({ model: this.model });
            this.$('#routeFactsLinksInput').append(routeFactsLinksView.render().el);

            var publicTransportation = this.model.get('kollektiv');

            if (!!publicTransportation && publicTransportation.length > 0) {
                this.$('.route-facts-field-ankomst_kollektivtransport input[type="checkbox"]').prop('checked', true);
                this.$('.route-facts-field-ankomst_kollektivtransport textarea').removeClass('hidden');
            }

            this.stickit(); // Uses view.bindings and view.model to setup bindings
            Backbone.Validation.bind(this);

        },

        remove: function() {
            // Remove the validation binding
            // See: http://thedersen.com/projects/backbone-validation/#using-form-model-validation/unbinding
            Backbone.Validation.unbind(this);
            return Backbone.View.prototype.remove.apply(this, arguments);
        }
    });
}(DNT));
<|endoftext|>


<commit_before>function MinimalFieldView(options) {
    // a name is required, so throw if there isn't one passed in
    if (!options || !options.name) throw Error('must pass in a name');
    // If given an element as part of an options object
    // the view *should* store an element as `this.el`.
    this.el = options.el;
    this.value = options.value;
    this.parent = options.parent;
    this.name = options.name;
    this.valid = !!options.value;
}

// All views should have a `render` method that creates, replaces, or
// fills in the `this.el` property.
// If passed in when created this view may already have a `this.el`.
// If so, your render would method would populate it, or create a new
// one and replace it (if already part of the DOM tree).
MinimalFieldView.prototype.render = function () {
    if (!this.el) this.el = document.createElement('div');
    // The important thing is after calling `render` the view should have
    // a `this.el` that is a *real* DOM element.
    this.el.textContent = 'hello, awesome developer!';
};

// Form fields have to have a setValue method that sets it to what is passed
MinimalFieldView.prototype.setValue = function (value) {
    this.value = value;
    // if there is a parent call update
    if (this.parent) this.parent.update(this);
};

// It should have a `remove` method that does any tear down you may want
// to do. Including ideally removing itself from it's parent (if reasonable to do so)
MinimalFieldView.prototype.remove = function () {
    // you could do it with vanilla JS like this
    var parent = this.el.parentNode;
    if (parent) parent.removeChild(this.el);

    // ...or if you're using jQuery you could just do
    // $(this.el).remove();
};

// CommonJS module, of course
module.exports = MinimalFieldView;
<commit_msg>Revalidate minimal-field-view when value is updated<commit_after>function MinimalFieldView(options) {
    // a name is required, so throw if there isn't one passed in
    if (!options || !options.name) throw Error('must pass in a name');
    // If given an element as part of an options object
    // the view *should* store an element as `this.el`.
    this.el = options.el;
    this.value = options.value;
    this.parent = options.parent;
    this.name = options.name;
    this.valid = !!options.value;
}

// All views should have a `render` method that creates, replaces, or
// fills in the `this.el` property.
// If passed in when created this view may already have a `this.el`.
// If so, your render would method would populate it, or create a new
// one and replace it (if already part of the DOM tree).
MinimalFieldView.prototype.render = function () {
    if (!this.el) this.el = document.createElement('div');
    // The important thing is after calling `render` the view should have
    // a `this.el` that is a *real* DOM element.
    this.el.textContent = 'hello, awesome developer!';
};

// Form fields have to have a setValue method that sets it to what is passed
MinimalFieldView.prototype.setValue = function (value) {
    this.value = value;
    this.valid = !!value;

    // if there is a parent call update
    if (this.parent) this.parent.update(this);
};

// It should have a `remove` method that does any tear down you may want
// to do. Including ideally removing itself from it's parent (if reasonable to do so)
MinimalFieldView.prototype.remove = function () {
    // you could do it with vanilla JS like this
    var parent = this.el.parentNode;
    if (parent) parent.removeChild(this.el);

    // ...or if you're using jQuery you could just do
    // $(this.el).remove();
};

// CommonJS module, of course
module.exports = MinimalFieldView;
<|endoftext|>


<commit_before>
enyo.kind({
  name: "XT.InfoList",
  kind: "Panels",
  classes: "xt-info-list",
  draggable: false,
  components: [
    { name: "loader", classes: "xt-info-list-loader", content: "Loading content..." },
    { name: "error", classes: "xt-info-list-error", content: "There was an error" },
    { name: "list", kind: "XT.InfoListPrivate" }
  ],
  published: {
    collection: null,
    rowClass: ""
  },
  collectionChanged: function() {
    var col = this.getCollection();
    var query = col._listQuery || { rowLimit: 25 };

    if (!col) {
      this.setIndex(1);
      return;
    }

    // bind the change event to our handler
    col.bind("change", enyo.bind(this, "_collectionChanged", col));

    // attempt to fetch (if not already fetched) and handle the
    // various states appropriately
    col.fetch({
      success: enyo.bind(this, "_collectionFetchSuccess"),
      error: enyo.bind(this, "_collectionFetchError"),
      query: query
    });
  },
  _collectionChanged: function(collection) {
    this.log();
  },
  _collectionFetchSuccess: function() {
    this.log();
    this.waterfall("onCollectionUpdated");
  },
  _collectionFetchError: function() {
    this.log();
  },
  create: function() {
    this.inherited(arguments);
    this.rowClassChanged();
  },
  rowClassChanged: function() {
    // need to pass down some information to the list
    this.$.list.setRowClass(this.getRowClass());
  },
  showingChanged: function() {
    this.inherited(arguments);
    this.log(this.name, this.showing, this);
  }
});

enyo.kind({
  name: "XT.InfoListPrivate",
  kind: "List",
  classes: "xt-info-list-private",
  published: {
    rowClass:""
  },
  handlers: {
    onSetupItem: "setupRow",
    onCollectionUpdated: "collectionUpdated"
  },
  collectionUpdated: function() {
    var col = this.parent.getCollection();

    // take the properties as necessary...
    this.setCount(col.length);
    this.reset();

    // if we updated, let the parent know we want to be
    // visible now
    this.parent.setIndex(2);
  },
  resizeHandler: function(inSender, inEvent) {
    this.inherited(arguments);
    //this.log(this.owner.name, this);
    //if (!this.owner.getShowing()) {
    //  return true;
    //} else {
    //  this.inherited(arguments);
    //}
  },
  rowClassChanged: function() {
    //this.log(this.owner.name);

    var rowClass = this.getRowClass();
    var component;
    var item;

    if (rowClass) {
      if (XT.getObjectByName(rowClass)) {

        component = {
          name: "item",
          kind: rowClass
        };

        item = this.$.item;
        if (item) {
          this.removeComponent(item);
          item.destroy();
        }

        this.createComponent(component);
      }
    }
  },
  setupRow: function(inSender, inEvent) {
    //this.log(this.owner.name, this.owner.showing, this);

    var col = this.parent.getCollection();
    var row = this.$.item;
    var idx = inEvent.index;
    var mod = col.models[idx];

    // as the rows need to be rendered, we proxy the data to their
    // render function if they have it, otherwise, we skip
    if (row && row.renderModel) {
      row.renderModel(mod);
    }
  }

});
<commit_msg>get rid of annoying debugging<commit_after>
enyo.kind({
  name: "XT.InfoList",
  kind: "Panels",
  classes: "xt-info-list",
  draggable: false,
  components: [
    { name: "loader", classes: "xt-info-list-loader", content: "Loading content..." },
    { name: "error", classes: "xt-info-list-error", content: "There was an error" },
    { name: "list", kind: "XT.InfoListPrivate" }
  ],
  published: {
    collection: null,
    rowClass: ""
  },
  collectionChanged: function() {
    var col = this.getCollection();
    var query = col._listQuery || { rowLimit: 25 };

    if (!col) {
      this.setIndex(1);
      return;
    }

    // bind the change event to our handler
    col.bind("change", enyo.bind(this, "_collectionChanged", col));

    // attempt to fetch (if not already fetched) and handle the
    // various states appropriately
    col.fetch({
      success: enyo.bind(this, "_collectionFetchSuccess"),
      error: enyo.bind(this, "_collectionFetchError"),
      query: query
    });
  },
  _collectionChanged: function(collection) {
    //this.log();
  },
  _collectionFetchSuccess: function() {
    //this.log();
    this.waterfall("onCollectionUpdated");
  },
  _collectionFetchError: function() {
    this.log(this.name);
  },
  create: function() {
    this.inherited(arguments);
    this.rowClassChanged();
  },
  rowClassChanged: function() {
    // need to pass down some information to the list
    this.$.list.setRowClass(this.getRowClass());
  },
  showingChanged: function() {
    this.inherited(arguments);
    //this.log(this.name, this.showing, this);
  }
});

enyo.kind({
  name: "XT.InfoListPrivate",
  kind: "List",
  classes: "xt-info-list-private",
  published: {
    rowClass:""
  },
  handlers: {
    onSetupItem: "setupRow",
    onCollectionUpdated: "collectionUpdated"
  },
  collectionUpdated: function() {
    var col = this.parent.getCollection();

    // take the properties as necessary...
    this.setCount(col.length);
    this.reset();

    // if we updated, let the parent know we want to be
    // visible now
    this.parent.setIndex(2);
  },
  resizeHandler: function(inSender, inEvent) {
    this.inherited(arguments);
    //this.log(this.owner.name, this);
    //if (!this.owner.getShowing()) {
    //  return true;
    //} else {
    //  this.inherited(arguments);
    //}
  },
  rowClassChanged: function() {
    //this.log(this.owner.name);

    var rowClass = this.getRowClass();
    var component;
    var item;

    if (rowClass) {
      if (XT.getObjectByName(rowClass)) {

        component = {
          name: "item",
          kind: rowClass
        };

        item = this.$.item;
        if (item) {
          this.removeComponent(item);
          item.destroy();
        }

        this.createComponent(component);
      }
    }
  },
  setupRow: function(inSender, inEvent) {
    //this.log(this.owner.name, this.owner.showing, this);

    var col = this.parent.getCollection();
    var row = this.$.item;
    var idx = inEvent.index;
    var mod = col.models[idx];

    // as the rows need to be rendered, we proxy the data to their
    // render function if they have it, otherwise, we skip
    if (row && row.renderModel) {
      row.renderModel(mod);
    }
  }

});
<|endoftext|>