<commit_before>import { Display } from "../display/Display"
import { onFocus, onBlur } from "../display/focus"
import { setGuttersForLineNumbers, updateGutters } from "../display/gutters"
import { maybeUpdateLineNumberWidth } from "../display/line_numbers"
import { endOperation, operation, startOperation } from "../display/operations"
import { initScrollbars } from "../display/scrollbars"
import { onScrollWheel, setScrollLeft, setScrollTop } from "../display/scroll_events"
import { clipPos, Pos } from "../line/pos"
import { posFromMouse } from "../measurement/position_measurement"
import { eventInWidget } from "../measurement/widgets"
import Doc from "../model/Doc"
import { attachDoc } from "../model/document_data"
import { Range } from "../model/selection"
import { extendSelection } from "../model/selection_updates"
import { captureRightClick, ie, ie_version, mobile, webkit } from "../util/browser"
import { e_preventDefault, e_stop, on, signal, signalDOMEvent } from "../util/event"
import { bind, copyObj, Delayed } from "../util/misc"

import { clearDragCursor, onDragOver, onDragStart, onDrop } from "./drop_events"
import { ensureGlobalHandlers } from "./global_events"
import { onKeyDown, onKeyPress, onKeyUp } from "./key_events"
import { clickInGutter, onContextMenu, onMouseDown } from "./mouse_events"
import { themeChanged } from "./utils"
import { defaults, optionHandlers, Init } from "./options"

// A CodeMirror instance represents an editor. This is the object
// that user code is usually dealing with.

export function CodeMirror(place, options) {
  if (!(this instanceof CodeMirror)) return new CodeMirror(place, options)

  this.options = options = options ? copyObj(options) : {}
  // Determine effective options based on given values and defaults.
  copyObj(defaults, options, false)
  setGuttersForLineNumbers(options)

  let doc = options.value
  if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator)
  this.doc = doc

  let input = new CodeMirror.inputStyles[options.inputStyle](this)
  let display = this.display = new Display(place, doc, input)
  display.wrapper.CodeMirror = this
  updateGutters(this)
  themeChanged(this)
  if (options.lineWrapping)
    this.display.wrapper.className += " CodeMirror-wrap"
  if (options.autofocus && !mobile) display.input.focus()
  initScrollbars(this)

  this.state = {
    keyMaps: [],  // stores maps added by addKeyMap
    overlays: [], // highlighting overlays, as added by addOverlay
    modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
    overwrite: false,
    delayingBlurEvent: false,
    focused: false,
    suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
    pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
    selectingText: false,
    draggingText: false,
    highlight: new Delayed(), // stores highlight worker timeout
    keySeq: null,  // Unfinished key sequence
    specialChars: null
  }

  // Override magic textarea content restore that IE sometimes does
  // on our hidden textarea on reload
  if (ie && ie_version < 11) setTimeout(() => this.display.input.reset(true), 20)

  registerEventHandlers(this)
  ensureGlobalHandlers()

  startOperation(this)
  this.curOp.forceUpdate = true
  attachDoc(this, doc)

  if ((options.autofocus && !mobile) || this.hasFocus())
    setTimeout(bind(onFocus, this), 20)
  else
    onBlur(this)

  for (let opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
    optionHandlers[opt](this, options[opt], Init)
  maybeUpdateLineNumberWidth(this)
  if (options.finishInit) options.finishInit(this)
  for (let i = 0; i < initHooks.length; ++i) initHooks[i](this)
  endOperation(this)
  // Suppress optimizelegibility in Webkit, since it breaks text
  // measuring on line wrapping boundaries.
  if (webkit && options.lineWrapping &&
      getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
    display.lineDiv.style.textRendering = "auto"
}

// The default configuration options.
CodeMirror.defaults = defaults
// Functions to run when options are changed.
CodeMirror.optionHandlers = optionHandlers

export default CodeMirror

// Attach the necessary event handlers when initializing the editor
function registerEventHandlers(cm) {
  let d = cm.display
  on(d.scroller, "mousedown", operation(cm, onMouseDown))
  // Older IE's will not fire a second mousedown for a double click
  if (ie && ie_version < 11)
    on(d.scroller, "dblclick", operation(cm, e => {
      if (signalDOMEvent(cm, e)) return
      let pos = posFromMouse(cm, e)
      if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return
      e_preventDefault(e)
      let word = cm.findWordAt(pos)
      extendSelection(cm.doc, word.anchor, word.head)
    }))
  else
    on(d.scroller, "dblclick", e => signalDOMEvent(cm, e) || e_preventDefault(e))
  // Some browsers fire contextmenu *after* opening the menu, at
  // which point we can't mess with it anymore. Context menu is
  // handled in onMouseDown for these browsers.
  if (!captureRightClick) on(d.scroller, "contextmenu", e => onContextMenu(cm, e))

  // Used to suppress mouse event handling when a touch happens
  let touchFinished, prevTouch = {end: 0}
  function finishTouch() {
    if (d.activeTouch) {
      touchFinished = setTimeout(() => d.activeTouch = null, 1000)
      prevTouch = d.activeTouch
      prevTouch.end = +new Date
    }
  }
  function isMouseLikeTouchEvent(e) {
    if (e.touches.length != 1) return false
    let touch = e.touches[0]
    return touch.radiusX <= 1 && touch.radiusY <= 1
  }
  function farAway(touch, other) {
    if (other.left == null) return true
    let dx = other.left - touch.left, dy = other.top - touch.top
    return dx * dx + dy * dy > 20 * 20
  }
  on(d.scroller, "touchstart", e => {
    if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
      d.input.ensurePolled()
      clearTimeout(touchFinished)
      let now = +new Date
      d.activeTouch = {start: now, moved: false,
                       prev: now - prevTouch.end <= 300 ? prevTouch : null}
      if (e.touches.length == 1) {
        d.activeTouch.left = e.touches[0].pageX
        d.activeTouch.top = e.touches[0].pageY
      }
    }
  })
  on(d.scroller, "touchmove", () => {
    if (d.activeTouch) d.activeTouch.moved = true
  })
  on(d.scroller, "touchend", e => {
    let touch = d.activeTouch
    if (touch && !eventInWidget(d, e) && touch.left != null &&
        !touch.moved && new Date - touch.start < 300) {
      let pos = cm.coordsChar(d.activeTouch, "page"), range
      if (!touch.prev || farAway(touch, touch.prev)) // Single tap
        range = new Range(pos, pos)
      else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
        range = cm.findWordAt(pos)
      else // Triple tap
        range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)))
      cm.setSelection(range.anchor, range.head)
      cm.focus()
      e_preventDefault(e)
    }
    finishTouch()
  })
  on(d.scroller, "touchcancel", finishTouch)

  // Sync scrolling between fake scrollbars and real scrollable
  // area, ensure viewport is updated when scrolling.
  on(d.scroller, "scroll", () => {
    if (d.scroller.clientHeight) {
      setScrollTop(cm, d.scroller.scrollTop)
      setScrollLeft(cm, d.scroller.scrollLeft, true)
      signal(cm, "scroll", cm)
    }
  })

  // Listen to wheel events in order to try and update the viewport on time.
  on(d.scroller, "mousewheel", e => onScrollWheel(cm, e))
  on(d.scroller, "DOMMouseScroll", e => onScrollWheel(cm, e))

  // Prevent wrapper from ever scrolling
  on(d.wrapper, "scroll", () => d.wrapper.scrollTop = d.wrapper.scrollLeft = 0)

  d.dragFunctions = {
    enter: e => {if (!signalDOMEvent(cm, e)) e_stop(e)},
    over: e => {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }},
    start: e => onDragStart(cm, e),
    drop: operation(cm, onDrop),
    leave: e => {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }}
  }

  let inp = d.input.getField()
  on(inp, "keyup", e => onKeyUp.call(cm, e))
  on(inp, "keydown", operation(cm, onKeyDown))
  on(inp, "keypress", operation(cm, onKeyPress))
  on(inp, "focus", e => onFocus(cm, e))
  on(inp, "blur", e => onBlur(cm, e))
}

let initHooks = []
CodeMirror.defineInitHook = f => initHooks.push(f)
<commit_msg>Don't autofocus until the editor has a .state property<commit_after>import { Display } from "../display/Display"
import { onFocus, onBlur } from "../display/focus"
import { setGuttersForLineNumbers, updateGutters } from "../display/gutters"
import { maybeUpdateLineNumberWidth } from "../display/line_numbers"
import { endOperation, operation, startOperation } from "../display/operations"
import { initScrollbars } from "../display/scrollbars"
import { onScrollWheel, setScrollLeft, setScrollTop } from "../display/scroll_events"
import { clipPos, Pos } from "../line/pos"
import { posFromMouse } from "../measurement/position_measurement"
import { eventInWidget } from "../measurement/widgets"
import Doc from "../model/Doc"
import { attachDoc } from "../model/document_data"
import { Range } from "../model/selection"
import { extendSelection } from "../model/selection_updates"
import { captureRightClick, ie, ie_version, mobile, webkit } from "../util/browser"
import { e_preventDefault, e_stop, on, signal, signalDOMEvent } from "../util/event"
import { bind, copyObj, Delayed } from "../util/misc"

import { clearDragCursor, onDragOver, onDragStart, onDrop } from "./drop_events"
import { ensureGlobalHandlers } from "./global_events"
import { onKeyDown, onKeyPress, onKeyUp } from "./key_events"
import { clickInGutter, onContextMenu, onMouseDown } from "./mouse_events"
import { themeChanged } from "./utils"
import { defaults, optionHandlers, Init } from "./options"

// A CodeMirror instance represents an editor. This is the object
// that user code is usually dealing with.

export function CodeMirror(place, options) {
  if (!(this instanceof CodeMirror)) return new CodeMirror(place, options)

  this.options = options = options ? copyObj(options) : {}
  // Determine effective options based on given values and defaults.
  copyObj(defaults, options, false)
  setGuttersForLineNumbers(options)

  let doc = options.value
  if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator)
  this.doc = doc

  let input = new CodeMirror.inputStyles[options.inputStyle](this)
  let display = this.display = new Display(place, doc, input)
  display.wrapper.CodeMirror = this
  updateGutters(this)
  themeChanged(this)
  if (options.lineWrapping)
    this.display.wrapper.className += " CodeMirror-wrap"
  initScrollbars(this)

  this.state = {
    keyMaps: [],  // stores maps added by addKeyMap
    overlays: [], // highlighting overlays, as added by addOverlay
    modeGen: 0,   // bumped when mode/overlay changes, used to invalidate highlighting info
    overwrite: false,
    delayingBlurEvent: false,
    focused: false,
    suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
    pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
    selectingText: false,
    draggingText: false,
    highlight: new Delayed(), // stores highlight worker timeout
    keySeq: null,  // Unfinished key sequence
    specialChars: null
  }

  if (options.autofocus && !mobile) display.input.focus()

  // Override magic textarea content restore that IE sometimes does
  // on our hidden textarea on reload
  if (ie && ie_version < 11) setTimeout(() => this.display.input.reset(true), 20)

  registerEventHandlers(this)
  ensureGlobalHandlers()

  startOperation(this)
  this.curOp.forceUpdate = true
  attachDoc(this, doc)

  if ((options.autofocus && !mobile) || this.hasFocus())
    setTimeout(bind(onFocus, this), 20)
  else
    onBlur(this)

  for (let opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt))
    optionHandlers[opt](this, options[opt], Init)
  maybeUpdateLineNumberWidth(this)
  if (options.finishInit) options.finishInit(this)
  for (let i = 0; i < initHooks.length; ++i) initHooks[i](this)
  endOperation(this)
  // Suppress optimizelegibility in Webkit, since it breaks text
  // measuring on line wrapping boundaries.
  if (webkit && options.lineWrapping &&
      getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
    display.lineDiv.style.textRendering = "auto"
}

// The default configuration options.
CodeMirror.defaults = defaults
// Functions to run when options are changed.
CodeMirror.optionHandlers = optionHandlers

export default CodeMirror

// Attach the necessary event handlers when initializing the editor
function registerEventHandlers(cm) {
  let d = cm.display
  on(d.scroller, "mousedown", operation(cm, onMouseDown))
  // Older IE's will not fire a second mousedown for a double click
  if (ie && ie_version < 11)
    on(d.scroller, "dblclick", operation(cm, e => {
      if (signalDOMEvent(cm, e)) return
      let pos = posFromMouse(cm, e)
      if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return
      e_preventDefault(e)
      let word = cm.findWordAt(pos)
      extendSelection(cm.doc, word.anchor, word.head)
    }))
  else
    on(d.scroller, "dblclick", e => signalDOMEvent(cm, e) || e_preventDefault(e))
  // Some browsers fire contextmenu *after* opening the menu, at
  // which point we can't mess with it anymore. Context menu is
  // handled in onMouseDown for these browsers.
  if (!captureRightClick) on(d.scroller, "contextmenu", e => onContextMenu(cm, e))

  // Used to suppress mouse event handling when a touch happens
  let touchFinished, prevTouch = {end: 0}
  function finishTouch() {
    if (d.activeTouch) {
      touchFinished = setTimeout(() => d.activeTouch = null, 1000)
      prevTouch = d.activeTouch
      prevTouch.end = +new Date
    }
  }
  function isMouseLikeTouchEvent(e) {
    if (e.touches.length != 1) return false
    let touch = e.touches[0]
    return touch.radiusX <= 1 && touch.radiusY <= 1
  }
  function farAway(touch, other) {
    if (other.left == null) return true
    let dx = other.left - touch.left, dy = other.top - touch.top
    return dx * dx + dy * dy > 20 * 20
  }
  on(d.scroller, "touchstart", e => {
    if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
      d.input.ensurePolled()
      clearTimeout(touchFinished)
      let now = +new Date
      d.activeTouch = {start: now, moved: false,
                       prev: now - prevTouch.end <= 300 ? prevTouch : null}
      if (e.touches.length == 1) {
        d.activeTouch.left = e.touches[0].pageX
        d.activeTouch.top = e.touches[0].pageY
      }
    }
  })
  on(d.scroller, "touchmove", () => {
    if (d.activeTouch) d.activeTouch.moved = true
  })
  on(d.scroller, "touchend", e => {
    let touch = d.activeTouch
    if (touch && !eventInWidget(d, e) && touch.left != null &&
        !touch.moved && new Date - touch.start < 300) {
      let pos = cm.coordsChar(d.activeTouch, "page"), range
      if (!touch.prev || farAway(touch, touch.prev)) // Single tap
        range = new Range(pos, pos)
      else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
        range = cm.findWordAt(pos)
      else // Triple tap
        range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0)))
      cm.setSelection(range.anchor, range.head)
      cm.focus()
      e_preventDefault(e)
    }
    finishTouch()
  })
  on(d.scroller, "touchcancel", finishTouch)

  // Sync scrolling between fake scrollbars and real scrollable
  // area, ensure viewport is updated when scrolling.
  on(d.scroller, "scroll", () => {
    if (d.scroller.clientHeight) {
      setScrollTop(cm, d.scroller.scrollTop)
      setScrollLeft(cm, d.scroller.scrollLeft, true)
      signal(cm, "scroll", cm)
    }
  })

  // Listen to wheel events in order to try and update the viewport on time.
  on(d.scroller, "mousewheel", e => onScrollWheel(cm, e))
  on(d.scroller, "DOMMouseScroll", e => onScrollWheel(cm, e))

  // Prevent wrapper from ever scrolling
  on(d.wrapper, "scroll", () => d.wrapper.scrollTop = d.wrapper.scrollLeft = 0)

  d.dragFunctions = {
    enter: e => {if (!signalDOMEvent(cm, e)) e_stop(e)},
    over: e => {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }},
    start: e => onDragStart(cm, e),
    drop: operation(cm, onDrop),
    leave: e => {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }}
  }

  let inp = d.input.getField()
  on(inp, "keyup", e => onKeyUp.call(cm, e))
  on(inp, "keydown", operation(cm, onKeyDown))
  on(inp, "keypress", operation(cm, onKeyPress))
  on(inp, "focus", e => onFocus(cm, e))
  on(inp, "blur", e => onBlur(cm, e))
}

let initHooks = []
CodeMirror.defineInitHook = f => initHooks.push(f)
<|endoftext|>


<commit_before>const R = require('ramda');
const VirtualAudioGraph = require('../dist/index.js');
const pingPongDelayParamsFactory = require('./tools/pingPongDelayParamsFactory');

describe('virtualAudioGraph.defineNode', function () {
  var audioContext;
  var virtualAudioGraph;

  beforeEach(function () {
    audioContext = new AudioContext();
    virtualAudioGraph = new VirtualAudioGraph({
      audioContext: audioContext,
      output: audioContext.destination,
    });
  });

  it('returns itself', function () {
    expect(virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay')).toBe(virtualAudioGraph);
  });

  it('throws if name provided is a standard node', function () {
    expect(function () {
      virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'gain');
    }).toThrow();
  });

  it('creates a custom node internally', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    expect(typeof virtualAudioGraph.customNodes.pingPongDelay).toBe('function');
  });

  it('creates a custom node which can be reused in virtualAudioGraph.update', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    expect(virtualAudioGraph.update(virtualNodeParams)).toBe(virtualAudioGraph);
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
  });

  it('can define a custom node built of other custom nodes', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const quietpingPongDelayParamsFactory = function () {
      return [
        {
          id: 0,
          node: 'gain',
          output: 'output',
        },
        {
          id: 1,
          node: 'pingPongDelay',
          output: 0,
        },
        {
          id: 2,
          node: 'oscillator',
          output: 1,
        },
      ];
    };

    virtualAudioGraph.defineNode(quietpingPongDelayParamsFactory, 'quietPingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'quietPingPongDelay',
        output: 0,
      },
      {
        id: 2,
        node: 'pingPongDelay',
        output: 1,
      },
      {
        id: 3,
        node: 'oscillator',
        output: 2,
      },
    ];

    expect(virtualAudioGraph.update(virtualNodeParams)).toBe(virtualAudioGraph);
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":1,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]}]})).toBe(true);
  });

  it('can define a custom node which can be updated', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    virtualAudioGraph.update(virtualNodeParams);

    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);

    virtualNodeParams[1].params.decay = 0.6;

    virtualAudioGraph.update(virtualNodeParams);

    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
  });

  it('can define a custom node which can be removed', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    virtualAudioGraph.update(virtualNodeParams);

    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);

    virtualNodeParams[1].params.decay = 0.6;

    virtualAudioGraph.update([
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        }
      }
    ]);

    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[]}]})).toBe(true);
  });
});
<commit_msg>meet linting rules<commit_after>const R = require('ramda');
const VirtualAudioGraph = require('../dist/index.js');
const pingPongDelayParamsFactory = require('./tools/pingPongDelayParamsFactory');

describe('virtualAudioGraph.defineNode', function () {
  var audioContext;
  var virtualAudioGraph;

  beforeEach(function () {
    audioContext = new AudioContext();
    virtualAudioGraph = new VirtualAudioGraph({
      audioContext: audioContext,
      output: audioContext.destination,
    });
  });

  it('returns itself', function () {
    expect(virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay')).toBe(virtualAudioGraph);
  });

  it('throws if name provided is a standard node', function () {
    expect(function () {
      virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'gain');
    }).toThrow();
  });

  it('creates a custom node internally', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    expect(typeof virtualAudioGraph.customNodes.pingPongDelay).toBe('function');
  });

  it('creates a custom node which can be reused in virtualAudioGraph.update', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    expect(virtualAudioGraph.update(virtualNodeParams)).toBe(virtualAudioGraph);
    /* eslint-disable */
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
    /* eslint-enable */
  });

  it('can define a custom node built of other custom nodes', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const quietpingPongDelayParamsFactory = function () {
      return [
        {
          id: 0,
          node: 'gain',
          output: 'output',
        },
        {
          id: 1,
          node: 'pingPongDelay',
          output: 0,
        },
        {
          id: 2,
          node: 'oscillator',
          output: 1,
        },
      ];
    };

    virtualAudioGraph.defineNode(quietpingPongDelayParamsFactory, 'quietPingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'quietPingPongDelay',
        output: 0,
      },
      {
        id: 2,
        node: 'pingPongDelay',
        output: 1,
      },
      {
        id: 3,
        node: 'oscillator',
        output: 2,
      },
    ];

    expect(virtualAudioGraph.update(virtualNodeParams)).toBe(virtualAudioGraph);
    /* eslint-disable */
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":1,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.3333333333333333,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.3333333333333333,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]}]})).toBe(true);
    /* eslint-enable */
  });

  it('can define a custom node which can be updated', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    virtualAudioGraph.update(virtualNodeParams);

    /* eslint-disable */
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
    /* eslint-enable */
    virtualNodeParams[1].params.decay = 0.6;

    virtualAudioGraph.update(virtualNodeParams);
    /* eslint-disable */
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.6,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
    /* eslint-enable */
  });

  it('can define a custom node which can be removed', function () {
    virtualAudioGraph.defineNode(pingPongDelayParamsFactory, 'pingPongDelay');

    const virtualNodeParams = [
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
      {
        id: 1,
        node: 'pingPongDelay',
        output: 0,
        params: {
          decay: 0.5,
          delayTime: 0.5,
          maxDelayTime: 0.5,
        },
      },
      {
        id: 2,
        node: 'oscillator',
        output: 1,
      },
    ];

    virtualAudioGraph.update(virtualNodeParams);

    /* eslint-disable */
    expect(R.equals(audioContext.toJSON(), {"name":"AudioDestinationNode","inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"StereoPannerNode","pan":{"value":-1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>"]}]},{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]},{"name":"StereoPannerNode","pan":{"value":1,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":[{"name":"DelayNode","delayTime":{"value":0.5,"inputs":[]},"inputs":[{"name":"GainNode","gain":{"value":0.5,"inputs":[]},"inputs":["<circular:DelayNode>",{"name":"OscillatorNode","type":"sine","frequency":{"value":440,"inputs":[]},"detune":{"value":0,"inputs":[]},"inputs":[]}]}]}]}]}]}]}]})).toBe(true);
    /* eslint-enable */
    virtualNodeParams[1].params.decay = 0.6;

    virtualAudioGraph.update([
      {
        id: 0,
        node: 'gain',
        output: 'output',
        params: {
          gain: 0.5,
        },
      },
    ]);

    expect(R.equals(audioContext.toJSON(), {
      name: 'AudioDestinationNode',
      inputs: [
        {
          name: 'GainNode',
          gain: {
            value: 0.5,
            inputs: [],
          },
          inputs: [],
        },
      ],
    })).toBe(true);
  });
});
<|endoftext|>


<commit_before>
//import EVENTS     from '../../constants/artifacts_events.constants';

/**
 * @desc wrapper around the $modal service
 * @url http://angular-ui.github.io/bootstrap/#/modal
 */
export class JFrogModal {

    constructor($modal, $rootScope, $injector, $q, $sce, $timeout, JFrogEventBus, JFrogUILibConfig, JFrogUIUtils) {
        this.modal = $modal;
        this.$rootScope = $rootScope;
        this.$q = $q;
        this.$timeout = $timeout;
        this.$sce = $sce;
        this.templatesBaseUrl = 'ui_components/jfrog_modal/templates/';
        this.JFrogUILibConfig = JFrogUILibConfig;
        this.JFrogEventBus = JFrogEventBus;
        this.JFrogUIUtils = JFrogUIUtils;
        this.$injector = $injector;
        this.EVENTS = JFrogEventBus.getEventsDefinition();

    }

    /**
     * build the path to the template location
     * and delegate to the $modal service
     * return the modal instance
     *
     * @param template
     * @param scope
     * @returns {{Modal instance}}
     */
    launchModal(template, scope, size, cancelable = true, options) {
        if (!size) size = 'lg';

        let customTemplate = true;
        if (template.startsWith('@')) {
            customTemplate = false;
            template = template.substr(1);
        }

        let customTemplatesBaseUrl = this.JFrogUILibConfig.getConfig().customModalTemplatesPath;
        if (customTemplatesBaseUrl && !customTemplatesBaseUrl.endsWith('/')) customTemplatesBaseUrl += '/';

        let templateUrl = (customTemplate ? customTemplatesBaseUrl : this.templatesBaseUrl) + template + '.html';

        let modalObj = {
            templateUrl: templateUrl,
            scope: scope,
            size: size
        };
        if (!cancelable) {
            modalObj.backdrop = 'static';
            modalObj.keyboard = false;
        }
        if (options && _.isObject(options)) _.extend(modalObj,options);

        let modalInstance =  this.modal.open(modalObj);
        this.JFrogEventBus.registerOnScope(this.$rootScope, this.EVENTS.CLOSE_MODAL, () => {
            modalInstance.dismiss();
        });

        if (typeof size == 'number') {
            this.$timeout(() => {
                $('.modal-dialog').css('max-width', size)
            });
        }
        this._calculateMaxHeight();

        if (modalInstance.result) {
            // Modal close event handler is registered as result.then(errorCallback)
            // In some cases the modal close event is caught by result.finally()
            modalInstance.result.then(()=>{}, ()=>{
                this.modalIsClosing = true;
            }).finally(()=>{
                this.modalIsClosing = true;
                $(window).off('resize', this._calculateMaxHeight());
            });
        }

        $(window).resize(() => {
            this._calculateMaxHeight();
        });

        return modalInstance;
    }

    /**
     * Calculate and set the max-height attribute of a modal's body
     * */
    _calculateMaxHeight(isWizardStep) {
        // return this.oldResize();
        if(this.modalIsClosing){
            this.modalIsClosing = false;
            return;
        }
        // Try to hide the wizard modal body in this digest cycle before calculating height in the next digest cycle.
        // This is very important for cases that the modal has more then one step - such as onboarding wizard (and
        // applies to every step but the first)
        if(isWizardStep) $('.modal-body').hide();

        // Calculate and set modal body height in the next digest cycle
        // After the resizing is done - the modal body is shown again.
        this.resizeModalBodyInNextCycle();
    }

    resizeModalBodyInNextCycle(){
        this.$timeout(() => {
            // Hide modal body before perfroming calculations
            let modal = $('.modal-content');
            let modalBody = modal.find('.modal-body');

            // Calculate and show content
            let wizardModalContainer = modal.find('.wizard-modal');
            if(wizardModalContainer.length > 0) {
                modalBody.hide();
                this.resizeWizardModalBody(modal,wizardModalContainer,modalBody);
                modalBody.show();
            }
            else {
                this.resizeAnyModalBody(modal,modalBody);
            }
        });
    }

    resizeAnyModalBody(modal,modalBody){
        let modalOffsetTop = 110,                                 //Modal offset top
            viewPortHeight = window.innerHeight,                 // View port height
            modalHeight = viewPortHeight - (2 * modalOffsetTop);
        this.setModalBodyMaxHeight(modal,modalBody,modalHeight);
    }

    resizeWizardModalBody(modal,wizardContainer,modalBody){
        let modalHeight = wizardContainer.height();
        this.setModalBodyMaxHeight(modal,modalBody,modalHeight);
    }

    setModalBodyMaxHeight(modal,modalBody,modalHeight){
        let headerHeight = modal.find('.modal-header').outerHeight() || 0,   // Header height
            footerHeight = modal.find('.modal-footer').outerHeight() || 0,  // Footer height
            maxHeight = modalHeight - headerHeight - footerHeight;
        modalBody.css('max-height', maxHeight);
    }

    oldResize(){
        this.$timeout(() => {
            if ($('.wizard-modal').length > 0) {

                // modal height - header - footer
                let MH = $('.wizard-modal').height(),               // Modal height
                    HH  = $('.modal-header').outerHeight() || 0,         // Header height
                    FH  = $('.modal-footer').outerHeight() || 0;    // Footer height

                let maxHeight = MH - HH - FH;
                $('.modal-body').css('max-height', maxHeight);
                return;
            }

            let VPH = window.innerHeight,                       // View port height
                MOT = 110,                                      //Modal offset top
                HH  = $('.modal-header').outerHeight() || 0,         // Header height
                FH  = $('.modal-footer').outerHeight() || 0;    // Footer height

            // Calculate: MPH - (MOT*2) - HH - FH = maxHeight
            let maxHeight = VPH - (MOT * 2) - HH - FH;

            $('.modal-body').css('max-height', maxHeight);
        }, 100)
    }

    /**
     * launch a modal that shows content in a codemirror container
     *
     * @param title - title of the modal
     * @param content - content for the code mirror container
     * @param mode - mode for code mirror editor options (usually {name: <mimetype>}
     * @param beforeMessage - message to insert before the codemirror element
     * @returns {{Modal instance}}
     */
    launchCodeModal(title, content, mode, beforeMessage = undefined,objectName = undefined) {

        let modalInstance;
        let modalScope = this.$rootScope.$new();
        modalScope.closeModal = () => modalInstance.close();
        modalScope.content = content;
        modalScope.mode = mode;
        modalScope.title = title;//this.$sce.trustAsHtml(title);
        modalScope.beforeMessage = beforeMessage;
        modalScope.objectName = objectName;
        return modalInstance = this.launchModal('@code_modal', modalScope);
    }

    /**
     * launch a modal that shows a confirmation box, and returns a promise
     *
     * @param title - title of the confirmation box
     * @param content - HTML content of the confirmation box
     * @param buttons - button text (Object(confirm: String, cancel: String))
     * @returns promise - resolved if the user confirmed, rejected otherwise
     */
    confirm(content, title, buttons, checkboxLabel, checkBoxChangeListener) {

        buttons = buttons || {};
        buttons.confirm = buttons.confirm || 'Confirm';
        buttons.cancel = buttons.cancel || 'Cancel';
        title = title || 'Are you sure?';

        let modalInstance;
        let modalScope = this.$rootScope.$new();

        modalScope.buttons = buttons;
        modalScope.content = content;//this.$sce.trustAsHtml(content);
        modalScope.title = title;//this.$sce.trustAsHtml(title);
        modalScope.checkboxLabel = checkboxLabel;
        modalScope.checkbox = {checked: false};
        modalScope.onCheckboxStateChange = (state) => {
            if (checkBoxChangeListener) checkBoxChangeListener(state,modalScope);
        };

        return this.launchModal('@confirm_modal', modalScope, 'sm').result;
    }

    launchWizard(wizardDefinitionObject) {

        let wizardModalScope = this.$rootScope.$new();

        wizardModalScope.$wizardDef = wizardDefinitionObject;
        WizardController.prototype.JFrogModal = this;
        wizardModalScope.$wizardCtrl = new WizardController(wizardDefinitionObject);

        wizardDefinitionObject.controller.prototype.$wizardCtrl = wizardModalScope.$wizardCtrl;

        let controllerInstance = this.$injector.instantiate(wizardDefinitionObject.controller);

        let controllerObject = {};
        controllerObject[wizardDefinitionObject.controllerAs || 'ctrl'] = controllerInstance;

        _.extend(wizardModalScope,controllerObject);

        wizardModalScope.$wizardCtrl.$userCtrl = controllerInstance;

        let modalInstance = this.launchModal('@wizard_modal', wizardModalScope, 'lg', wizardDefinitionObject.cancelable && wizardDefinitionObject.backdropCancelable, wizardDefinitionObject.modalOptions);

        wizardModalScope.$wizardCtrl.$modalInstance = modalInstance;

        modalInstance.result.catch((reason) => {
            if (reason) wizardModalScope.$wizardCtrl.cancel();
        })

        return modalInstance.result;
    }

}

class WizardController {
    constructor(wizardDefinitionObject, modalInstance) {
        this.currentStep = 1;
        this.wizardDefinitionObject = wizardDefinitionObject;
        this.totalSteps = wizardDefinitionObject.steps.length;
        if (this.wizardDefinitionObject.initialStep) {
            let index = _.findIndex(wizardDefinitionObject.steps,{id: this.wizardDefinitionObject.initialStep});
            this.currentStep = index + 1;
        }
    }

    cancel() {
        if (this.$userCtrl.onCancel) this.$userCtrl.onCancel();
        this.$modalInstance.dismiss();
    }

    titleInit() {
        if (this.$userCtrl.onWizardShow) this.$userCtrl.onWizardShow(this.wizardDefinitionObject.steps[this.currentStep-1]);
    }

    nextStep(skip) {
        if (this.$userCtrl.onStepChange) {
            let response = this.$userCtrl.onStepChange(this.wizardDefinitionObject.steps[this.currentStep], this.wizardDefinitionObject.steps[this.currentStep-1], skip ? 'skip' : 'next');
            if (response && response.then) {
                this.pending = true;
                response.then((pRes)=>{
                    if (pRes !== false) this.currentStep++
                    if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep-2], skip ? 'skip' : 'next');
                    this.pending = false;
                })
                    .catch(()=>{
                        this.pending = false;
                    });

            }
            else if (response !== false) {
                this.currentStep++;
                if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep-2], skip ? 'skip' : 'next');
            }
        }
        else {
            this.currentStep++;
        }
        this.JFrogModal._calculateMaxHeight(true);
    }

    prevStep() {
        if (this.$userCtrl.onStepChange) {
            let response = this.$userCtrl.onStepChange(this.wizardDefinitionObject.steps[this.currentStep-2], this.wizardDefinitionObject.steps[this.currentStep-1],'prev');
            if (response && response.then) {
                this.pending = true;
                response.then((pRes)=>{
                    if (pRes !== false) this.currentStep--;
                    if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep],  'prev');
                    this.pending = false;
                })
                    .catch(()=>{
                        this.pending = false;
                    });
            }
            else if (response !== false) {
                this.currentStep--;
                if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep], 'prev');
            }
        }
        else {
            this.currentStep--;
        }
        this.JFrogModal._calculateMaxHeight(true);
    }

    finish() {
        if (this.$userCtrl.onComplete) this.$userCtrl.onComplete();
        this.$modalInstance.close();
    }

    isFunction(val) {
        return _.isFunction(val);
    }
}<commit_msg>JFrogModal: Respond to ENTER press<commit_after>
//import EVENTS     from '../../constants/artifacts_events.constants';

/**
 * @desc wrapper around the $modal service
 * @url http://angular-ui.github.io/bootstrap/#/modal
 */
export class JFrogModal {

    constructor($modal, $rootScope, $injector, $q, $sce, $timeout, JFrogEventBus, JFrogUILibConfig, JFrogUIUtils) {
        this.modal = $modal;
        this.$rootScope = $rootScope;
        this.$q = $q;
        this.$timeout = $timeout;
        this.$sce = $sce;
        this.templatesBaseUrl = 'ui_components/jfrog_modal/templates/';
        this.JFrogUILibConfig = JFrogUILibConfig;
        this.JFrogEventBus = JFrogEventBus;
        this.JFrogUIUtils = JFrogUIUtils;
        this.$injector = $injector;
        this.EVENTS = JFrogEventBus.getEventsDefinition();

    }

    /**
     * build the path to the template location
     * and delegate to the $modal service
     * return the modal instance
     *
     * @param template
     * @param scope
     * @returns {{Modal instance}}
     */
    launchModal(template, scope, size, cancelable = true, options) {
        if (!size) size = 'lg';

        let customTemplate = true;
        if (template.startsWith('@')) {
            customTemplate = false;
            template = template.substr(1);
        }

        let customTemplatesBaseUrl = this.JFrogUILibConfig.getConfig().customModalTemplatesPath;
        if (customTemplatesBaseUrl && !customTemplatesBaseUrl.endsWith('/')) customTemplatesBaseUrl += '/';

        let templateUrl = (customTemplate ? customTemplatesBaseUrl : this.templatesBaseUrl) + template + '.html';

        let modalObj = {
            templateUrl: templateUrl,
            scope: scope,
            size: size
        };
        if (!cancelable) {
            modalObj.backdrop = 'static';
            modalObj.keyboard = false;
        }
        if (options && _.isObject(options)) _.extend(modalObj,options);

        let modalInstance =  this.modal.open(modalObj);
        this.JFrogEventBus.registerOnScope(this.$rootScope, this.EVENTS.CLOSE_MODAL, () => {
            modalInstance.dismiss();
        });

        if (typeof size == 'number') {
            this.$timeout(() => {
                $('.modal-dialog').css('max-width', size)
            });
        }
        this._calculateMaxHeight();

        let keyDownBinded = this._onKeyDown.bind(this);

        if (modalInstance.result) {
            // Modal close event handler is registered as result.then(errorCallback)
            // In some cases the modal close event is caught by result.finally()
            modalInstance.result.then(()=>{}, ()=>{
                this.modalIsClosing = true;
            }).finally(()=>{
                this.modalIsClosing = true;
                $(window).off('resize', this._calculateMaxHeight());
                $(document).off('keydown', keyDownBinded);
            });
        }

        $(window).resize(() => {
            this._calculateMaxHeight();
        });

        $(document).on('keydown', keyDownBinded);

        return modalInstance;
    }

    _onKeyDown(event) {
        let target = $(event.target);
        if (event.keyCode === 13) {
            if (target.attr('jf-enter-press') === undefined) {
                if ($('.wizard-modal').length) {
                    this._clickFirstFoundButton(['.wizard-modal button#wizard-popup-next', '.wizard-modal button#wizard-popup-next-custom', '.wizard-modal button#wizard-popup-finish'])
                }
                else {
                    this._clickFirstFoundButton(['.modal-dialog button.btn-primary'])
                }
                event.preventDefault();
            }
        }
    }

    _clickFirstFoundButton(selectorsArray) {
        for (let i in selectorsArray) {
            let selector = selectorsArray[i];
            if ($(selector).length) {
                $(selector).click();
                break;
            }
        }
    }

    /**
     * Calculate and set the max-height attribute of a modal's body
     * */
    _calculateMaxHeight(isWizardStep) {
        // return this.oldResize();
        if(this.modalIsClosing){
            this.modalIsClosing = false;
            return;
        }
        // Try to hide the wizard modal body in this digest cycle before calculating height in the next digest cycle.
        // This is very important for cases that the modal has more then one step - such as onboarding wizard (and
        // applies to every step but the first)
        if(isWizardStep) $('.modal-body').hide();

        // Calculate and set modal body height in the next digest cycle
        // After the resizing is done - the modal body is shown again.
        this.resizeModalBodyInNextCycle();
    }

    resizeModalBodyInNextCycle(){
        this.$timeout(() => {
            // Hide modal body before perfroming calculations
            let modal = $('.modal-content');
            let modalBody = modal.find('.modal-body');

            // Calculate and show content
            let wizardModalContainer = modal.find('.wizard-modal');
            if(wizardModalContainer.length > 0) {
                modalBody.hide();
                this.resizeWizardModalBody(modal,wizardModalContainer,modalBody);
                modalBody.show();
            }
            else {
                this.resizeAnyModalBody(modal,modalBody);
            }
        });
    }

    resizeAnyModalBody(modal,modalBody){
        let modalOffsetTop = 110,                                 //Modal offset top
            viewPortHeight = window.innerHeight,                 // View port height
            modalHeight = viewPortHeight - (2 * modalOffsetTop);
        this.setModalBodyMaxHeight(modal,modalBody,modalHeight);
    }

    resizeWizardModalBody(modal,wizardContainer,modalBody){
        let modalHeight = wizardContainer.height();
        this.setModalBodyMaxHeight(modal,modalBody,modalHeight);
    }

    setModalBodyMaxHeight(modal,modalBody,modalHeight){
        let headerHeight = modal.find('.modal-header').outerHeight() || 0,   // Header height
            footerHeight = modal.find('.modal-footer').outerHeight() || 0,  // Footer height
            maxHeight = modalHeight - headerHeight - footerHeight;
        modalBody.css('max-height', maxHeight);
    }

    oldResize(){
        this.$timeout(() => {
            if ($('.wizard-modal').length > 0) {

                // modal height - header - footer
                let MH = $('.wizard-modal').height(),               // Modal height
                    HH  = $('.modal-header').outerHeight() || 0,         // Header height
                    FH  = $('.modal-footer').outerHeight() || 0;    // Footer height

                let maxHeight = MH - HH - FH;
                $('.modal-body').css('max-height', maxHeight);
                return;
            }

            let VPH = window.innerHeight,                       // View port height
                MOT = 110,                                      //Modal offset top
                HH  = $('.modal-header').outerHeight() || 0,         // Header height
                FH  = $('.modal-footer').outerHeight() || 0;    // Footer height

            // Calculate: MPH - (MOT*2) - HH - FH = maxHeight
            let maxHeight = VPH - (MOT * 2) - HH - FH;

            $('.modal-body').css('max-height', maxHeight);
        }, 100)
    }

    /**
     * launch a modal that shows content in a codemirror container
     *
     * @param title - title of the modal
     * @param content - content for the code mirror container
     * @param mode - mode for code mirror editor options (usually {name: <mimetype>}
     * @param beforeMessage - message to insert before the codemirror element
     * @returns {{Modal instance}}
     */
    launchCodeModal(title, content, mode, beforeMessage = undefined,objectName = undefined) {

        let modalInstance;
        let modalScope = this.$rootScope.$new();
        modalScope.closeModal = () => modalInstance.close();
        modalScope.content = content;
        modalScope.mode = mode;
        modalScope.title = title;//this.$sce.trustAsHtml(title);
        modalScope.beforeMessage = beforeMessage;
        modalScope.objectName = objectName;
        return modalInstance = this.launchModal('@code_modal', modalScope);
    }

    /**
     * launch a modal that shows a confirmation box, and returns a promise
     *
     * @param title - title of the confirmation box
     * @param content - HTML content of the confirmation box
     * @param buttons - button text (Object(confirm: String, cancel: String))
     * @returns promise - resolved if the user confirmed, rejected otherwise
     */
    confirm(content, title, buttons, checkboxLabel, checkBoxChangeListener) {

        buttons = buttons || {};
        buttons.confirm = buttons.confirm || 'Confirm';
        buttons.cancel = buttons.cancel || 'Cancel';
        title = title || 'Are you sure?';

        let modalInstance;
        let modalScope = this.$rootScope.$new();

        modalScope.buttons = buttons;
        modalScope.content = content;//this.$sce.trustAsHtml(content);
        modalScope.title = title;//this.$sce.trustAsHtml(title);
        modalScope.checkboxLabel = checkboxLabel;
        modalScope.checkbox = {checked: false};
        modalScope.onCheckboxStateChange = (state) => {
            if (checkBoxChangeListener) checkBoxChangeListener(state,modalScope);
        };

        return this.launchModal('@confirm_modal', modalScope, 'sm').result;
    }

    launchWizard(wizardDefinitionObject) {

        let wizardModalScope = this.$rootScope.$new();

        wizardModalScope.$wizardDef = wizardDefinitionObject;
        WizardController.prototype.JFrogModal = this;
        wizardModalScope.$wizardCtrl = new WizardController(wizardDefinitionObject);

        wizardDefinitionObject.controller.prototype.$wizardCtrl = wizardModalScope.$wizardCtrl;

        let controllerInstance = this.$injector.instantiate(wizardDefinitionObject.controller);

        let controllerObject = {};
        controllerObject[wizardDefinitionObject.controllerAs || 'ctrl'] = controllerInstance;

        _.extend(wizardModalScope,controllerObject);

        wizardModalScope.$wizardCtrl.$userCtrl = controllerInstance;

        let modalInstance = this.launchModal('@wizard_modal', wizardModalScope, 'lg', wizardDefinitionObject.cancelable && wizardDefinitionObject.backdropCancelable, wizardDefinitionObject.modalOptions);

        wizardModalScope.$wizardCtrl.$modalInstance = modalInstance;

        modalInstance.result.catch((reason) => {
            if (reason) wizardModalScope.$wizardCtrl.cancel();
        })

        return modalInstance.result;
    }

}

class WizardController {
    constructor(wizardDefinitionObject, modalInstance) {
        this.currentStep = 1;
        this.wizardDefinitionObject = wizardDefinitionObject;
        this.totalSteps = wizardDefinitionObject.steps.length;
        if (this.wizardDefinitionObject.initialStep) {
            let index = _.findIndex(wizardDefinitionObject.steps,{id: this.wizardDefinitionObject.initialStep});
            this.currentStep = index + 1;
        }
    }

    cancel() {
        if (this.$userCtrl.onCancel) this.$userCtrl.onCancel();
        this.$modalInstance.dismiss();
    }

    titleInit() {
        if (this.$userCtrl.onWizardShow) this.$userCtrl.onWizardShow(this.wizardDefinitionObject.steps[this.currentStep-1]);
    }

    nextStep(skip) {
        if (this.$userCtrl.onStepChange) {
            let response = this.$userCtrl.onStepChange(this.wizardDefinitionObject.steps[this.currentStep], this.wizardDefinitionObject.steps[this.currentStep-1], skip ? 'skip' : 'next');
            if (response && response.then) {
                this.pending = true;
                response.then((pRes)=>{
                    if (pRes !== false) this.currentStep++
                    if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep-2], skip ? 'skip' : 'next');
                    this.pending = false;
                })
                    .catch(()=>{
                        this.pending = false;
                    });

            }
            else if (response !== false) {
                this.currentStep++;
                if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep-2], skip ? 'skip' : 'next');
            }
        }
        else {
            this.currentStep++;
        }
        this.JFrogModal._calculateMaxHeight(true);
    }

    prevStep() {
        if (this.$userCtrl.onStepChange) {
            let response = this.$userCtrl.onStepChange(this.wizardDefinitionObject.steps[this.currentStep-2], this.wizardDefinitionObject.steps[this.currentStep-1],'prev');
            if (response && response.then) {
                this.pending = true;
                response.then((pRes)=>{
                    if (pRes !== false) this.currentStep--;
                    if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep],  'prev');
                    this.pending = false;
                })
                    .catch(()=>{
                        this.pending = false;
                    });
            }
            else if (response !== false) {
                this.currentStep--;
                if (this.$userCtrl.afterStepChange) this.$userCtrl.afterStepChange(this.wizardDefinitionObject.steps[this.currentStep-1], this.wizardDefinitionObject.steps[this.currentStep], 'prev');
            }
        }
        else {
            this.currentStep--;
        }
        this.JFrogModal._calculateMaxHeight(true);
    }

    finish() {
        if (this.$userCtrl.onComplete) this.$userCtrl.onComplete();
        this.$modalInstance.close();
    }

    isFunction(val) {
        return _.isFunction(val);
    }
}<|endoftext|>


<commit_before>// define a adminapp namespace in jQuery and all related methodes
(function($){
    $.fn.adminapp = function(){};

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findList = function(str, fieldList, ignoreList) {
        ignoreList = (typeof(ignoreList) == "undefined") ? [] : ignoreList;
        var list = [];

        // get all el with id attr
        list = fieldList.filter("[id]");
        // find els with id containing searched str
        list = list.filter(function(index) {
            if (this.id.indexOf(str) > -1) {
                return this;
            }
        });
        // remove ignored els
        list = list.filter(function(index) {
            if (ignoreList.length > 0) {
                for (var j=0; j<ignoreList.length; j++) {
                    if (this.id.indexOf(ignoreList[j]) == -1) {
                        return this;
                    }
                }
            } else {
                return this;
            }
        });

        return list;
    };

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findField = function(str, ignoreList) {
        var result = this.findList(str, this.fieldList, ignoreList);
        if (result.length == 0) {
            result = this.findList(str, this.selectList, ignoreList);
        }
        return result;
    };

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findSelect = function(str, ignoreList) {
        return this.findList(str, this.selectList, ignoreList);
    };

    /**
     * attach toogleAddress event on the secondary address checkbox
     */
    $.fn.adminapp.bindEventOnAddress = function(el) {
        var chk = $('#' + el.id);
        chk.bind('click', function(event) {
            $.fn.adminapp.toogleAddress(event.target);
        });
    };

    /**
     * attach toogle restrictionarea event on the secondary "public" checkbox
     */
    $.fn.adminapp.bindEventOnLayer = function(pl, lt) {
        var chk = $('#' + pl.id);
        chk.bind('click', function(event) {
            $.fn.adminapp.toogleRestrictionAreas(event.target);
        });
        chk = $('#' + lt.id);
        chk.bind('change', function(event) {
            $.fn.adminapp.toogleLayerType(event.target);
        });
    };

    /**
     * attach toogle internal WMS on Base Layer.
     */
    $.fn.adminapp.bindEventOnLayerGroup = function(wmsi, bl) {
        wmsi.bind('change', function(event) {
            $.fn.adminapp.toogleBaseLayer(wmsi, bl);
        });
    };

    /**
     * show / hide secondary address input fields
     */
    $.fn.adminapp.toogleAddress = function(el) {
        var els = $.fn.adminapp.findField('b_', [el.id]);
        /* this code can be used to show/hide block instead of enabling/disabling inputs
        var d = 'block';
        */
        var state = false;
        if (!el.checked) {
            //d = 'none';
            state = true;
        }

        if (state) {
            $.fn.adminapp.resetField(els);
            els.addClass('disabledinput');
        } else {
            els.removeClass('disabledinput');
        }
        // reset value and set readonly
        els.attr('readOnly', state);
        els.attr('disabled', state);

        /*
        for (var i=0; i<els.length; i++) {
            var p = $.fn.adminapp.getParentBLock(els[i]);
            p.style.display = d;
            // can NOT use disabled as FA expect the field to be in request
            els[i].disabled = state;
        }*/
    };

    /**
     * show / hide restrictionArea input fields
     */
    $.fn.adminapp.toogleRestrictionAreas = function(el) {
        var els = $.fn.adminapp.findField('restrictionareas', [el.id]);
        var state = el.checked;
        if (state) {
            // reset value
            $.fn.adminapp.resetField(els);

            els.addClass('disabledinput');
        } else {
            els.removeClass('disabledinput');
        }
        // set readonly
        els.attr('readOnly', state);
        els.attr('disabled', state);
    };

    /**
     * show / hide unneeded fields
     */
    $.fn.adminapp.toogleLayerType = function(el) {
        var state = el.value;
        var fields = [];
        if (state == "internal WMS") {
            fields = ["style", "imageType", "legendRule", "imageType"];
        }
        else if (state == "external WMS") {
            fields = ["url", "style", "imageType", "legendRule", "isSingleTile", "imageType"];
        }
        else if (state == "WMTS") {
            fields = ["url", "style", "dimensions", "matrixSet", "wmsUrl", "wmsLayers"];
        }

        var change = function(field, fields) {
            var e = $.fn.adminapp.findField(field, [el.id]);
            var state = jQuery.inArray(field, fields) >= 0;
            if (state) {
                e.removeClass('disabledinput');
            }
            else {
                e.addClass('disabledinput');
            }
            e.attr('readOnly', !state);
            e.attr('disabled', !state);
        };

        change("url", fields);
        change("imageType", fields);
        change("style", fields);
        change("dimensions", fields);
        change("matrixSet", fields);
        change("wmsUrl", fields);
        change("wmsLayers", fields);
        change("isSingleTile", fields);
        change("legendRule", fields);
    };

    $.fn.adminapp.toogleBaseLayer = function(wmsi, bl) {
        var state = wmsi[0].checked;
        if (state) {
            // reset value
            $.fn.adminapp.resetField(bl);

            bl.addClass('disabledinput');
        } else {
            bl.removeClass('disabledinput');
        }
        // set readonly
        bl.attr('readOnly', state);
        bl.attr('disabled', state);
    };

    /**
     * get the parent div containing on input field
     */
    $.fn.adminapp.getParentBLock = function(el) {
        var p = el.parentNode;
        while (p.nodeName.toLowerCase() != 'div') {
            p = p.parentNode;
        }
        return p;
    };

    /**
     * reset input value or state
     */
    $.fn.adminapp.resetField = function(el) {
        for (var i = 0 ; i < el.length ; i++) {
            switch (el[i].type) {
              case 'checkbox':
                  el[i].checked = false;
                  break;
              case 'radio':
                  break;
              default:
                  el[i].value = '';
            }
        }
    };

    $.fn.adminapp.syncField = function(el) {
        var cbl = $.fn.adminapp.checkboxcorrespondance[el.target.id];
        for (var i = 0, len = cbl.length ; i < len ; i++) {
            cbl[i].checked = el.target.checked;
        }
    };

})(jQuery);

$(document).ready(function(){

    // store all fields
    $.fn.adminapp.fieldList = $("input");
    $.fn.adminapp.selectList = $("select");

    // attach event on User.b_company to show/hide secondary address fields (b_*)
    var f = $.fn.adminapp.findField('b_company');
    if (f.length > 0) {
        $.fn.adminapp.bindEventOnAddress(f[0]);
        // init state
        $.fn.adminapp.toogleAddress(f[0]);
    }

    // attach event on Layer.public to show/hide restrictionareas
    var pl = $.fn.adminapp.findField('public');
    var lt = $.fn.adminapp.findSelect('layerType');
    //Select('layerType');
    if (pl.length > 0 && lt.length > 0) {
        // restrictionareas
        $.fn.adminapp.bindEventOnLayer(pl[0], lt[0]);
        // init state
        $.fn.adminapp.toogleRestrictionAreas(pl[0]);
        $.fn.adminapp.toogleLayerType(lt[0]);
    }

    /**
     * When a layer(or group) is display more than one time
     * this will sync the state on all tree items.
     */

    // store field correspondence
    $.fn.adminapp.checkboxcorrespondance = {};
    var checkboxtrees = $(".checkboxtree");
    for (var i = 0, leni = checkboxtrees.length ; i < leni ; i++) {
        var checkboxlist = $("#" + checkboxtrees[i].id + " input");
        for (var j = 0, lenj = checkboxlist.length ; j < lenj ; j++) {
            if (checkboxlist[j].id) {
                var samenamecheckbox = $("input[value=" + checkboxlist[j].value + ']');
                if (samenamecheckbox.length > 1) {
                    $.fn.adminapp.checkboxcorrespondance[checkboxlist[j].id] = samenamecheckbox;
                    $("#" + checkboxlist[j].id).bind('change', $.fn.adminapp.syncField);
                }
            }
        }
    }

    var wmsi = $.fn.adminapp.findField('isInternalWMS')
    var bl = $.fn.adminapp.findField('isBaseLayer')
    if (wmsi.length > 0 && bl.length > 0) {
        $.fn.adminapp.bindEventOnLayerGroup(wmsi, bl);
        // init state
        $.fn.adminapp.toogleBaseLayer(wmsi, bl);
    }

});
<commit_msg>don't desable INPUT (FormAlchemy expect the field to be in request)<commit_after>// define a adminapp namespace in jQuery and all related methodes
(function($){
    $.fn.adminapp = function(){};

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findList = function(str, fieldList, ignoreList) {
        ignoreList = (typeof(ignoreList) == "undefined") ? [] : ignoreList;
        var list = [];

        // get all el with id attr
        list = fieldList.filter("[id]");
        // find els with id containing searched str
        list = list.filter(function(index) {
            if (this.id.indexOf(str) > -1) {
                return this;
            }
        });
        // remove ignored els
        list = list.filter(function(index) {
            if (ignoreList.length > 0) {
                for (var j=0; j<ignoreList.length; j++) {
                    if (this.id.indexOf(ignoreList[j]) == -1) {
                        return this;
                    }
                }
            } else {
                return this;
            }
        });

        return list;
    };

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findField = function(str, ignoreList) {
        var result = this.findList(str, this.fieldList, ignoreList);
        if (result.length == 0) {
            result = this.findList(str, this.selectList, ignoreList);
        }
        return result;
    };

    /**
     * find an element in the dom whose id match str and not contained in ignoreList
     */
    $.fn.adminapp.findSelect = function(str, ignoreList) {
        return this.findList(str, this.selectList, ignoreList);
    };

    /**
     * attach toogleAddress event on the secondary address checkbox
     */
    $.fn.adminapp.bindEventOnAddress = function(el) {
        var chk = $('#' + el.id);
        chk.bind('click', function(event) {
            $.fn.adminapp.toogleAddress(event.target);
        });
    };

    /**
     * attach toogle restrictionarea event on the secondary "public" checkbox
     */
    $.fn.adminapp.bindEventOnLayer = function(pl, lt) {
        var chk = $('#' + pl.id);
        chk.bind('click', function(event) {
            $.fn.adminapp.toogleRestrictionAreas(event.target);
        });
        chk = $('#' + lt.id);
        chk.bind('change', function(event) {
            $.fn.adminapp.toogleLayerType(event.target);
        });
    };

    /**
     * attach toogle internal WMS on Base Layer.
     */
    $.fn.adminapp.bindEventOnLayerGroup = function(wmsi, bl) {
        wmsi.bind('change', function(event) {
            $.fn.adminapp.toogleBaseLayer(wmsi, bl);
        });
    };

    /**
     * show / hide secondary address input fields
     */
    $.fn.adminapp.toogleAddress = function(el) {
        var els = $.fn.adminapp.findField('b_', [el.id]);
        /* this code can be used to show/hide block instead of enabling/disabling inputs
        var d = 'block';
        */
        var state = false;
        if (!el.checked) {
            //d = 'none';
            state = true;
        }

        if (state) {
            $.fn.adminapp.resetField(els);
            els.addClass('disabledinput');
        } else {
            els.removeClass('disabledinput');
        }
        // reset value and set readonly
        els.attr('readOnly', state);
        // can NOT use disabled as FA expect the field to be in request
        // els.attr('disabled', state);
    };

    /**
     * show / hide restrictionArea input fields
     */
    $.fn.adminapp.toogleRestrictionAreas = function(el) {
        var els = $.fn.adminapp.findField('restrictionareas', [el.id]);
        var state = el.checked;
        if (state) {
            // reset value
            $.fn.adminapp.resetField(els);

            els.addClass('disabledinput');
        } else {
            els.removeClass('disabledinput');
        }
        // set readonly
        els.attr('readOnly', state);
        els.attr('disabled', state);
    };

    /**
     * show / hide unneeded fields
     */
    $.fn.adminapp.toogleLayerType = function(el) {
        var state = el.value;
        var fields = [];
        if (state == "internal WMS") {
            fields = ["style", "imageType", "legendRule", "imageType"];
        }
        else if (state == "external WMS") {
            fields = ["url", "style", "imageType", "legendRule", "isSingleTile", "imageType"];
        }
        else if (state == "WMTS") {
            fields = ["url", "style", "dimensions", "matrixSet", "wmsUrl", "wmsLayers"];
        }

        var change = function(field, fields) {
            var e = $.fn.adminapp.findField(field, [el.id]);
            var state = jQuery.inArray(field, fields) >= 0;
            if (state) {
                e.removeClass('disabledinput');
            }
            else {
                e.addClass('disabledinput');
            }
            e.attr('readOnly', !state);
            if (e[0].tagName != "INPUT") {
                e.attr('disabled', !state);
            }
        };

        change("url", fields);
        change("imageType", fields);
        change("style", fields);
        change("dimensions", fields);
        change("matrixSet", fields);
        change("wmsUrl", fields);
        change("wmsLayers", fields);
        change("isSingleTile", fields);
        change("legendRule", fields);
    };

    $.fn.adminapp.toogleBaseLayer = function(wmsi, bl) {
        var state = wmsi[0].checked;
        if (state) {
            // reset value
            $.fn.adminapp.resetField(bl);

            bl.addClass('disabledinput');
        } else {
            bl.removeClass('disabledinput');
        }
        // set readonly
        bl.attr('readOnly', state);
        bl.attr('disabled', state);
    };

    /**
     * get the parent div containing on input field
     */
    $.fn.adminapp.getParentBLock = function(el) {
        var p = el.parentNode;
        while (p.nodeName.toLowerCase() != 'div') {
            p = p.parentNode;
        }
        return p;
    };

    /**
     * reset input value or state
     */
    $.fn.adminapp.resetField = function(el) {
        for (var i = 0 ; i < el.length ; i++) {
            switch (el[i].type) {
              case 'checkbox':
                  el[i].checked = false;
                  break;
              case 'radio':
                  break;
              default:
                  el[i].value = '';
            }
        }
    };

    $.fn.adminapp.syncField = function(el) {
        var cbl = $.fn.adminapp.checkboxcorrespondance[el.target.id];
        for (var i = 0, len = cbl.length ; i < len ; i++) {
            cbl[i].checked = el.target.checked;
        }
    };

})(jQuery);

$(document).ready(function(){

    // store all fields
    $.fn.adminapp.fieldList = $("input");
    $.fn.adminapp.selectList = $("select");

    // attach event on User.b_company to show/hide secondary address fields (b_*)
    var f = $.fn.adminapp.findField('b_company');
    if (f.length > 0) {
        $.fn.adminapp.bindEventOnAddress(f[0]);
        // init state
        $.fn.adminapp.toogleAddress(f[0]);
    }

    // attach event on Layer.public to show/hide restrictionareas
    var pl = $.fn.adminapp.findField('public');
    var lt = $.fn.adminapp.findSelect('layerType');
    //Select('layerType');
    if (pl.length > 0 && lt.length > 0) {
        // restrictionareas
        $.fn.adminapp.bindEventOnLayer(pl[0], lt[0]);
        // init state
        $.fn.adminapp.toogleRestrictionAreas(pl[0]);
        $.fn.adminapp.toogleLayerType(lt[0]);
    }

    /**
     * When a layer(or group) is display more than one time
     * this will sync the state on all tree items.
     */

    // store field correspondence
    $.fn.adminapp.checkboxcorrespondance = {};
    var checkboxtrees = $(".checkboxtree");
    for (var i = 0, leni = checkboxtrees.length ; i < leni ; i++) {
        var checkboxlist = $("#" + checkboxtrees[i].id + " input");
        for (var j = 0, lenj = checkboxlist.length ; j < lenj ; j++) {
            if (checkboxlist[j].id) {
                var samenamecheckbox = $("input[value=" + checkboxlist[j].value + ']');
                if (samenamecheckbox.length > 1) {
                    $.fn.adminapp.checkboxcorrespondance[checkboxlist[j].id] = samenamecheckbox;
                    $("#" + checkboxlist[j].id).bind('change', $.fn.adminapp.syncField);
                }
            }
        }
    }

    var wmsi = $.fn.adminapp.findField('isInternalWMS')
    var bl = $.fn.adminapp.findField('isBaseLayer')
    if (wmsi.length > 0 && bl.length > 0) {
        $.fn.adminapp.bindEventOnLayerGroup(wmsi, bl);
        // init state
        $.fn.adminapp.toogleBaseLayer(wmsi, bl);
    }

});
<|endoftext|>


<commit_before><commit_msg>Convenience method to get the center of an Entity<commit_after><|endoftext|>


<commit_before>import AutomationSDKIcon from './icon-automation-sdk.svg'
import CommunityIcon from './icon-community.svg'
import SocketRegistryIcon from './icon-socket-registry.svg'
import CloudOSIcon from './icon-cloud-os.svg'
import Hexagon from '../../../../components/ui/hexagon'
import Link from '../../../../components/ui/link'
import Grid from '../../../../components/ui/grid'

const Features = () => (

    <Hexagon width={32} fill='#05A5B4' position={{top: '20px', right: '-20px'}} />

At Syncano, we want to help you build technology that matters, faster

        Syncano’s Serverless Platform and SDKs automatically assemble and deploy your backend to the cloud instantaneously - all while you build your app.

      <Grid wrap>

            Use Syncano to experiment and test your product with real users on a live production platform until you achieve product/market fit. Get results faster than with any other solution. Adapt, tweak and deploy at blazing speed.

            Take the risk and friction out of application development.
            As you grow, Syncano grows with you - Syncano’s infrastructure will automatically scale to support your needs.

            <Link to='/features'>

                  <SocketRegistryIcon />

Syncano Registry

                  Don’t rebuild what has already been built. The registry is your toolbox of reusable backend code.

            </Link>

            <Link to='/features'>

                  <AutomationSDKIcon />

Syncano Automation SDK

                  Operate your backend directly from your local development environment. No, weird GUIs, no hassle, more efficiency!

            </Link>

            <Link to='/features'>

                  <CommunityIcon />

Syncano Community

                  Crowd + Cloud. Harness the power of our community, and give yourself more creative freedom. Share, build, collaborate.

            </Link>

            <Link to='/features'>

                  <CloudOSIcon />

Syncano Cloud OS

                  Throw any Socket from the Registry into the Syncano Cloud OS, and its functionality becomes immediately available.

            </Link>

      </Grid>

)

export default Features
<commit_msg>fix(view): features layout<commit_after>import AutomationSDKIcon from './icon-automation-sdk.svg'
import CommunityIcon from './icon-community.svg'
import SocketRegistryIcon from './icon-socket-registry.svg'
import CloudOSIcon from './icon-cloud-os.svg'
import Hexagon from '../../../../components/ui/hexagon'
import Link from '../../../../components/ui/link'
import Grid from '../../../../components/ui/grid'

const Features = () => (

    <Hexagon width={32} fill='#05A5B4' position={{top: '20px', right: '-20px'}} />

At Syncano, we want to help you build technology that matters, faster

        Syncano’s Serverless Platform and SDKs automatically assemble and deploy your backend to the cloud instantaneously - all while you build your app.

      <Grid wrap>

            Use Syncano to experiment and test your product with real users on a live production platform until you achieve product/market fit. Get results faster than with any other solution. Adapt, tweak and deploy at blazing speed.

            Take the risk and friction out of application development.
            As you grow, Syncano grows with you - Syncano’s infrastructure will automatically scale to support your needs.

            <Link to='/features'>

                  <SocketRegistryIcon />

Syncano Registry

                  Don’t rebuild what has already been built. The registry is your toolbox of reusable backend code.

            </Link>

            <Link to='/features'>

                  <AutomationSDKIcon />

Syncano Automation SDK

                  Operate your backend directly from your local development environment. No, weird GUIs, no hassle, more efficiency!

            </Link>

            <Link to='/features'>

                  <CommunityIcon />

Syncano Community

                  Crowd + Cloud. Harness the power of our community, and give yourself more creative freedom. Share, build, collaborate.

            </Link>

            <Link to='/features'>

                  <CloudOSIcon />

Syncano Cloud OS

                  Throw any Socket from the Registry into the Syncano Cloud OS, and its functionality becomes immediately available.

            </Link>

      </Grid>

)

export default Features
<|endoftext|>


<commit_before>module("event");

test("toggle(Function, Function) - add toggle event and fake a few clicks", function() {
	expect(1);
	var count = 0,
		fn1 = function(e) { count++; },
		fn2 = function(e) { count--; },
		preventDefault = function(e) { e.preventDefault() },
		link = $('#mark');
	if ( $.browser.msie || $.browser.opera || /konquerer/i.test(navigator.userAgent) )
		ok( false, "click() on link gets executed in IE/Opera/Konquerer, not intended behaviour!" );
	else
		link.click(preventDefault).click().toggle(fn1, fn2).click().click().click().click().click();
	ok( count == 1, "Check for toggle(fn, fn)" );
});

test("unbind(event)", function() {
	expect(6);
	var el = $("#firstp");
	el.click(function() {
		ok( true, "Fake normal bind" );
	});
	el.click(function(event) {
		el.unbind(event);
		ok( true, "Fake onebind" );
	});
	el.click().click();

	el.click(function() { return; });
	el.unbind('click');
	ok( !el[0].onclick, "Handler is removed" ); // Bug #964

	el.click(function() { return; });
	el.unbind('change',function(){ return; });
	ok( el[0].onclick, "Extra handlers weren't accidentally removed." );

	el.unbind('click');
	ok( !el[0].$events, "Removed the events expando after all handlers are unbound." );
});

test("trigger(event, [data]", function() {
	expect(3);
	var handler = function(event, a, b, c) {
		ok( a == 1, "check passed data" );
		ok( b == "2", "check passed data" );
		ok( c == "abc", "check passed data" );
	}
	$("#firstp").bind("click", handler).trigger("click", [1, "2", "abc"]);
});

test("bind() with data", function() {
	expect(2);
	var handler = function(event) {
		ok( event.data, "check passed data exists" );
		ok( event.data.foo == "bar", "Check value of passed data" );
	}
	$("#firstp").bind("click", {foo: "bar"}, handler).click();
});

test("bind() with data and trigger() with data", function() {
	expect(4);
	var handler = function(event, data) {
		ok( event.data, "check passed data exists" );
		ok( event.data.foo == "bar", "Check value of passed data" );
		ok( data, "Check trigger data" );
		ok( data.bar == "foo", "Check value of trigger data" );
	}
	$("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]);
});
<commit_msg>Added a not-yet-failing testcase for #1054<commit_after>module("event");

test("toggle(Function, Function) - add toggle event and fake a few clicks", function() {
	expect(1);
	var count = 0,
		fn1 = function(e) { count++; },
		fn2 = function(e) { count--; },
		preventDefault = function(e) { e.preventDefault() },
		link = $('#mark');
	if ( $.browser.msie || $.browser.opera || /konquerer/i.test(navigator.userAgent) )
		ok( false, "click() on link gets executed in IE/Opera/Konquerer, not intended behaviour!" );
	else
		link.click(preventDefault).click().toggle(fn1, fn2).click().click().click().click().click();
	ok( count == 1, "Check for toggle(fn, fn)" );
});

test("unbind(event)", function() {
	expect(6);
	var el = $("#firstp");
	el.click(function() {
		ok( true, "Fake normal bind" );
	});
	el.click(function(event) {
		el.unbind(event);
		ok( true, "Fake onebind" );
	});
	el.click().click();

	el.click(function() { return; });
	el.unbind('click');
	ok( !el[0].onclick, "Handler is removed" ); // Bug #964

	el.click(function() { return; });
	el.unbind('change',function(){ return; });
	ok( el[0].onclick, "Extra handlers weren't accidentally removed." );

	el.unbind('click');
	ok( !el[0].$events, "Removed the events expando after all handlers are unbound." );
});

test("trigger(event, [data]", function() {
	expect(3);
	var handler = function(event, a, b, c) {
		ok( a == 1, "check passed data" );
		ok( b == "2", "check passed data" );
		ok( c == "abc", "check passed data" );
	}
	$("#firstp").bind("click", handler).trigger("click", [1, "2", "abc"]);
});

test("bind() with data", function() {
	expect(2);
	var handler = function(event) {
		ok( event.data, "check passed data exists" );
		ok( event.data.foo == "bar", "Check value of passed data" );
	}
	$("#firstp").bind("click", {foo: "bar"}, handler).click();
});

test("bind() with data and trigger() with data", function() {
	expect(4);
	var handler = function(event, data) {
		ok( event.data, "check passed data exists" );
		ok( event.data.foo == "bar", "Check value of passed data" );
		ok( data, "Check trigger data" );
		ok( data.bar == "foo", "Check value of trigger data" );
	}
	$("#firstp").bind("click", {foo: "bar"}, handler).trigger("click", [{bar: "foo"}]);
});

test("toggle(Function,Function) assigned from within one('xxx'), see #1054", function() {
	expect(3);
	var first = 0;
	$("#simon1").one("change", function() {
		ok( true, "Execute event only once" );
		$(this).toggle(function() {
			ok( first++ == 0 );
		}, function() {
			ok( first == 1 );
		});
	}).trigger("change").trigger("change").click().click();
	ok( false, "Seems like this doesn't work (that is, it doesn't fail) when triggering the event programmatically" );
});<|endoftext|>


<commit_before>//this page connects to mysql

var mysql=require('mysql');

var connection = mysql.createConnection({
  host:"localhost",
  port:3306,
  user:"root",
  password:"",
  database: "safechat"
});

connection.connect(function(err){
  if(err) throw err;
  console.log("mysql is connected on port 3306");
});<commit_msg>fix connection<commit_after>//this page connects to mysql

var mysql=require('mysql');

var connection = mysql.createConnection({
  host:"localhost",
  port:3306,
  user:"root",
  password:"",
  database: "safechat"
});

connection.connect(function(err){
  if(err) throw err;
  console.log("mysql is connected on port 3306");
});

module.exports = connection;<|endoftext|>