<commit_before>import {
  objectOrFunction,
  isFunction
} from './utils';

import asap from './asap';

function noop() {}

var PENDING   = void 0;
var FULFILLED = 1;
var REJECTED  = 2;

var GET_THEN_ERROR = new ErrorObject();

function selfFullfillment() {
  return new TypeError("You cannot resolve a promise with itself");
}

function cannotReturnOwn() {
  return new TypeError('A promises callback cannot return that same promise.');
}

function getThen(promise) {
  try {
    return promise.then;
  } catch(error) {
    GET_THEN_ERROR.error = error;
    return GET_THEN_ERROR;
  }
}

function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
  try {
    then.call(value, fulfillmentHandler, rejectionHandler);
  } catch(e) {
    return e;
  }
}

function handleForeignThenable(promise, thenable, then) {
   asap(function(promise) {
    var sealed = false;
    var error = tryThen(then, thenable, function(value) {
      if (sealed) { return; }
      sealed = true;
      if (thenable !== value) {
        resolve(promise, value);
      } else {
        fulfill(promise, value);
      }
    }, function(reason) {
      if (sealed) { return; }
      sealed = true;

      reject(promise, reason);
    }, 'Settle: ' + (promise._label || ' unknown promise'));

    if (!sealed && error) {
      sealed = true;
      reject(promise, error);
    }
  }, promise);
}

function handleOwnThenable(promise, thenable) {
  if (thenable._state === FULFILLED) {
    fulfill(promise, thenable._result);
  } else if (promise._state === REJECTED) {
    reject(promise, thenable._result);
  } else {
    subscribe(thenable, undefined, function(value) {
      resolve(promise, value);
    }, function(reason) {
      reject(promise, reason);
    });
  }
}

function handleMaybeThenable(promise, maybeThenable) {
  if (maybeThenable.constructor === promise.constructor) {
    handleOwnThenable(promise, maybeThenable);
  } else {
    var then = getThen(maybeThenable);

    if (then === GET_THEN_ERROR) {
      reject(promise, GET_THEN_ERROR.error);
    } else if (then === undefined) {
      fulfill(promise, maybeThenable);
    } else if (isFunction(then)) {
      handleForeignThenable(promise, maybeThenable, then);
    } else {
      fulfill(promise, maybeThenable);
    }
  }
}

function resolve(promise, value) {
  if (promise === value) {
    reject(promise, selfFullfillment());
  } else if (objectOrFunction(value)) {
    handleMaybeThenable(promise, value);
  } else {
    fulfill(promise, value);
  }
}

function publishRejection(promise) {
  if (promise._onerror) {
    promise._onerror(promise._result);
  }

  publish(promise);
}

function fulfill(promise, value) {
  if (promise._state !== PENDING) { return; }

  promise._result = value;
  promise._state = FULFILLED;

  if (promise._subscribers.length !== 0) {
    asap(publish, promise);
  }
}

function reject(promise, reason) {
  if (promise._state !== PENDING) { return; }
  promise._state = REJECTED;
  promise._result = reason;

  asap(publishRejection, promise);
}

function subscribe(parent, child, onFulfillment, onRejection) {
  var subscribers = parent._subscribers;
  var length = subscribers.length;

  parent._onerror = null;

  subscribers[length] = child;
  subscribers[length + FULFILLED] = onFulfillment;
  subscribers[length + REJECTED]  = onRejection;

  if (length === 0 && parent._state) {
    asap(publish, parent);
  }
}

function publish(promise) {
  var subscribers = promise._subscribers;
  var settled = promise._state;

  if (subscribers.length === 0) { return; }

  var child, callback, detail = promise._result;

  for (var i = 0; i < subscribers.length; i += 3) {
    child = subscribers[i];
    callback = subscribers[i + settled];

    if (child) {
      invokeCallback(settled, child, callback, detail);
    } else {
      callback(detail);
    }
  }

  promise._subscribers.length = 0;
}

function ErrorObject() {
  this.error = null;
}

var TRY_CATCH_ERROR = new ErrorObject();

function tryCatch(callback, detail) {
  try {
    return callback(detail);
  } catch(e) {
    TRY_CATCH_ERROR.error = e;
    return TRY_CATCH_ERROR;
  }
}

function invokeCallback(settled, promise, callback, detail) {
  var hasCallback = isFunction(callback),
      value, error, succeeded, failed;

  if (hasCallback) {
    value = tryCatch(callback, detail);

    if (value === TRY_CATCH_ERROR) {
      failed = true;
      error = value.error;
      value = null;
    } else {
      succeeded = true;
    }

    if (promise === value) {
      reject(promise, cannotReturnOwn());
      return;
    }

  } else {
    value = detail;
    succeeded = true;
  }

  if (promise._state !== PENDING) {
    // noop
  } else if (hasCallback && succeeded) {
    resolve(promise, value);
  } else if (failed) {
    reject(promise, error);
  } else if (settled === FULFILLED) {
    fulfill(promise, value);
  } else if (settled === REJECTED) {
    reject(promise, value);
  }
}

function initializePromise(promise, resolver) {
  try {
    resolver(function resolvePromise(value){
      resolve(promise, value);
    }, function rejectPromise(reason) {
      reject(promise, reason);
    });
  } catch(e) {
    reject(promise, e);
  }
}

export {
  noop,
  resolve,
  reject,
  fulfill,
  subscribe,
  publish,
  publishRejection,
  initializePromise,
  invokeCallback,
  FULFILLED,
  REJECTED,
  PENDING
};
<commit_msg>Follow thenable state not own state<commit_after>import {
  objectOrFunction,
  isFunction
} from './utils';

import asap from './asap';

function noop() {}

var PENDING   = void 0;
var FULFILLED = 1;
var REJECTED  = 2;

var GET_THEN_ERROR = new ErrorObject();

function selfFullfillment() {
  return new TypeError("You cannot resolve a promise with itself");
}

function cannotReturnOwn() {
  return new TypeError('A promises callback cannot return that same promise.');
}

function getThen(promise) {
  try {
    return promise.then;
  } catch(error) {
    GET_THEN_ERROR.error = error;
    return GET_THEN_ERROR;
  }
}

function tryThen(then, value, fulfillmentHandler, rejectionHandler) {
  try {
    then.call(value, fulfillmentHandler, rejectionHandler);
  } catch(e) {
    return e;
  }
}

function handleForeignThenable(promise, thenable, then) {
   asap(function(promise) {
    var sealed = false;
    var error = tryThen(then, thenable, function(value) {
      if (sealed) { return; }
      sealed = true;
      if (thenable !== value) {
        resolve(promise, value);
      } else {
        fulfill(promise, value);
      }
    }, function(reason) {
      if (sealed) { return; }
      sealed = true;

      reject(promise, reason);
    }, 'Settle: ' + (promise._label || ' unknown promise'));

    if (!sealed && error) {
      sealed = true;
      reject(promise, error);
    }
  }, promise);
}

function handleOwnThenable(promise, thenable) {
  if (thenable._state === FULFILLED) {
    fulfill(promise, thenable._result);
  } else if (thenable._state === REJECTED) {
    reject(promise, thenable._result);
  } else {
    subscribe(thenable, undefined, function(value) {
      resolve(promise, value);
    }, function(reason) {
      reject(promise, reason);
    });
  }
}

function handleMaybeThenable(promise, maybeThenable) {
  if (maybeThenable.constructor === promise.constructor) {
    handleOwnThenable(promise, maybeThenable);
  } else {
    var then = getThen(maybeThenable);

    if (then === GET_THEN_ERROR) {
      reject(promise, GET_THEN_ERROR.error);
    } else if (then === undefined) {
      fulfill(promise, maybeThenable);
    } else if (isFunction(then)) {
      handleForeignThenable(promise, maybeThenable, then);
    } else {
      fulfill(promise, maybeThenable);
    }
  }
}

function resolve(promise, value) {
  if (promise === value) {
    reject(promise, selfFullfillment());
  } else if (objectOrFunction(value)) {
    handleMaybeThenable(promise, value);
  } else {
    fulfill(promise, value);
  }
}

function publishRejection(promise) {
  if (promise._onerror) {
    promise._onerror(promise._result);
  }

  publish(promise);
}

function fulfill(promise, value) {
  if (promise._state !== PENDING) { return; }

  promise._result = value;
  promise._state = FULFILLED;

  if (promise._subscribers.length !== 0) {
    asap(publish, promise);
  }
}

function reject(promise, reason) {
  if (promise._state !== PENDING) { return; }
  promise._state = REJECTED;
  promise._result = reason;

  asap(publishRejection, promise);
}

function subscribe(parent, child, onFulfillment, onRejection) {
  var subscribers = parent._subscribers;
  var length = subscribers.length;

  parent._onerror = null;

  subscribers[length] = child;
  subscribers[length + FULFILLED] = onFulfillment;
  subscribers[length + REJECTED]  = onRejection;

  if (length === 0 && parent._state) {
    asap(publish, parent);
  }
}

function publish(promise) {
  var subscribers = promise._subscribers;
  var settled = promise._state;

  if (subscribers.length === 0) { return; }

  var child, callback, detail = promise._result;

  for (var i = 0; i < subscribers.length; i += 3) {
    child = subscribers[i];
    callback = subscribers[i + settled];

    if (child) {
      invokeCallback(settled, child, callback, detail);
    } else {
      callback(detail);
    }
  }

  promise._subscribers.length = 0;
}

function ErrorObject() {
  this.error = null;
}

var TRY_CATCH_ERROR = new ErrorObject();

function tryCatch(callback, detail) {
  try {
    return callback(detail);
  } catch(e) {
    TRY_CATCH_ERROR.error = e;
    return TRY_CATCH_ERROR;
  }
}

function invokeCallback(settled, promise, callback, detail) {
  var hasCallback = isFunction(callback),
      value, error, succeeded, failed;

  if (hasCallback) {
    value = tryCatch(callback, detail);

    if (value === TRY_CATCH_ERROR) {
      failed = true;
      error = value.error;
      value = null;
    } else {
      succeeded = true;
    }

    if (promise === value) {
      reject(promise, cannotReturnOwn());
      return;
    }

  } else {
    value = detail;
    succeeded = true;
  }

  if (promise._state !== PENDING) {
    // noop
  } else if (hasCallback && succeeded) {
    resolve(promise, value);
  } else if (failed) {
    reject(promise, error);
  } else if (settled === FULFILLED) {
    fulfill(promise, value);
  } else if (settled === REJECTED) {
    reject(promise, value);
  }
}

function initializePromise(promise, resolver) {
  try {
    resolver(function resolvePromise(value){
      resolve(promise, value);
    }, function rejectPromise(reason) {
      reject(promise, reason);
    });
  } catch(e) {
    reject(promise, e);
  }
}

export {
  noop,
  resolve,
  reject,
  fulfill,
  subscribe,
  publish,
  publishRejection,
  initializePromise,
  invokeCallback,
  FULFILLED,
  REJECTED,
  PENDING
};
<|endoftext|>


<commit_before>import {keyName} from "w3c-keyname"

import {findTarget} from "./basic"

const dialogTemplate = ({id, classes, title, height, width, icon, buttons, zIndex, body, scroll, help, canClose, note}) =>
    `<div tabindex="-1" role="dialog"
        class="ui-dialog ui-corner-all ui-widget ui-widget-content ui-front ui-dialog-buttons"
        ${id ? `aria-describedby="${id}"` : ''} style="z-index: ${zIndex};">

        ${icon ? `<i class="fa fa-${icon}" aria-hidden="true"></i>` : ''}
        ${title}
        ${help ? `<button type="button" class="ui-button ui-corner-all ui-widget ui-button-icon-only ui-dialog-titlebar-help" title="${gettext('Help')}">

            ${gettext('Help')}
        </button>` : ''}
        ${canClose ? `<button type="button" class="ui-button ui-corner-all ui-widget ui-button-icon-only ui-dialog-titlebar-close" title="${gettext('Close')}">

            ${gettext('Close')}
        </button>` : ''}

    <div ${id ? `id="${id}"` : ''} class="ui-dialog-content ui-widget-content${classes ? ` ${classes}` : ''}${scroll ? ` ui-scrollable` : ''}" style="width: ${width}; height: ${height};">
        ${note.text ? `<div class="note-container">${noteTemplate(note)}</div>` : ''}
        ${body}

${buttonsTemplate({buttons})}

`

const noteTemplate = (note) => {
    return note.text ? `<p class="noteEl ${note.display ? `` : `hide`}">${note.text}
` : ``
}

const buttonsTemplate = ({buttons}) => buttons.map(button => buttonTemplate(button)).join('')

const buttonTemplate = ({text, classes, icon}) => `<button type="button" class="${classes ? classes : 'fw-light'} fw-button ui-button ui-corner-all ui-widget">
    ${icon ? `<i class="fa fa-${icon}" aria-hidden="true"></i>` : ''}
    ${text}
</button>`

const BUTTON_TYPES = {
    close: {
        text: gettext('Close'),
        classes: 'fw-orange',
        click: dialog => () => dialog.close()
    },
    cancel: {
        text: gettext('Cancel'),
        classes: 'fw-orange',
        click: dialog => () => dialog.close()
    },
    ok: {
        text: gettext('OK'),
        classes: 'fw-dark',
        click: dialog => () => dialog.close()
    }
}

export class Dialog {
    constructor(options) {
        this.id = options.id || false
        this.classes = options.classes || false
        this.title = options.title || ''
        this.body = options.body || ''
        this.height = options.height ? `${options.height}px` : 'auto'
        this.width = options.width ? `${options.width}px` : 'auto'
        this.canClose = 'canClose' in options ? options.canClose : true
        this.help = 'help' in options ? options.help : false
        this.note = 'note' in options ? options.note : {}
        this.buttons = []
        if (options.buttons) {
            this.setButtons(options.buttons)
        }
        this.beforeClose = options.beforeClose || false
        this.onClose = options.onClose || false
        this.icon = options.icon || false
        this.scroll = options.scroll || false
        this.canEscape = options.canEscape || false
        this.dialogEl = false
        this.backdropEl = false
        this.dragging = false
        this.hasBeenMoved = false
        this.listeners = {}
        this.fullScreen = options.fullScreen ? options.fullScreen : false
    }

    setButtons(buttons) {
        this.buttons = buttons.map(button => ({
            text: button.text ? button.text : button.type ? BUTTON_TYPES[button.type].text : '',
            classes: button.classes ? button.classes : button.type ? BUTTON_TYPES[button.type].classes : false,
            click: button.click ? button.click : button.type ? BUTTON_TYPES[button.type].click(this) : '',
            icon: button.icon ? button.icon : false
        }))
    }

    open() {
        if (this.dialogEl) {
            return
        }
        if (this.fullScreen) {
            this.height = "85vh"
        }

        document.body.insertAdjacentHTML(
            'beforeend',
            dialogTemplate({
                id: this.id,
                classes: this.classes,
                title: this.title,
                height: this.height,
                width: this.width,
                icon: this.icon,
                buttons: this.buttons,
                zIndex: this.getHighestDialogZIndex() + 2,
                body: this.body,
                scroll: this.scroll,
                canClose: this.canClose,
                help: this.help,
                note: this.note
            })
        )
        this.backdropEl = document.body.lastElementChild
        this.dialogEl = this.backdropEl.previousElementSibling
        if (this.fullScreen) {
            this.dialogEl.style.width = '98%'
            this.dialogEl.style.height = '100%'
            this.dialogEl.style.position = 'fixed'
            this.dialogEl.style.top = "0px"
        } else {
            this.centerDialog()
        }
        this.bind()
    }

    refreshButtons() {
        this.dialogEl.querySelector('.ui-dialog-buttonset').innerHTML = buttonsTemplate({buttons: this.buttons})
    }

    refreshNote() {
        this.dialogEl.querySelector(".note-container").innerHTML = noteTemplate(this.note)
    }

    centerDialog() {
        const totalWidth = window.innerWidth,
            totalHeight = window.innerHeight,
            dialogWidth = this.dialogEl.clientWidth,
            dialogHeight = this.dialogEl.clientHeight,
            scrollTopOffset = window.pageYOffset,
            scrollLeftOffset = window.pageXOffset

        this.dialogEl.style.top = `${(totalHeight - dialogHeight) / 2 + scrollTopOffset}px`
        this.dialogEl.style.left = `${(totalWidth - dialogWidth) / 2 + scrollLeftOffset}px`
    }

    adjustDialogToScroll() {
        this.dialogEl.style.top = `${
            Math.max(
                Math.min(
                    this.dialogEl.offsetTop,
                    this.backdropEl.scrollHeight - this.dialogEl.scrollHeight + window.pageYOffset
                ),
                window.pageYOffset
            )
        }px`
    }

    moveDialog(x, y) {
        this.dialogEl.style.top = `${
            Math.min(
                Math.max(y - this.dragging.y, 0),
                this.backdropEl.scrollHeight - this.dialogEl.scrollHeight + window.pageYOffset
            )
        }px`
        this.dialogEl.style.left = `${
            Math.min(
                Math.max(x - this.dragging.x, 0),
                document.body.scrollWidth - this.dialogEl.scrollWidth
            )
        }px`
        this.hasBeenMoved = true
    }

    onScroll(_event) {
        if (this.hasBeenMoved) {
            // The dialog has been moved manually. We just adjust the position to make it stay in the view.
            this.adjustDialogToScroll()
        } else {
            this.centerDialog()
        }
    }

    onKeydown(event) {
        let name = keyName(event)
        if (event.altKey) {
            name = "Alt-" + name
        }
        if (event.ctrlKey) {
            name = "Ctrl-" + name
        }
        if (event.metaKey) {
            name = "Meta-" + name
        }
        if (event.shiftKey) {
            name = "Shift-" + name
        }
        if (name === 'Escape' && this.canEscape) {
            this.close()
        }
    }

    bind() {
        this.listeners.onKeydown = event => this.onKeydown(event)
        document.body.addEventListener('keydown', this.listeners.onKeydown)
        this.dialogEl.addEventListener('click', event => {
            const el = {}
            switch (true) {
            case findTarget(event, '.ui-dialog-buttonpane button', el): {
                event.preventDefault()
                let buttonNumber = 0
                let seekItem = el.target
                while (seekItem.previousElementSibling) {
                    buttonNumber++
                    seekItem = seekItem.previousElementSibling
                }
                this.buttons[buttonNumber].click()
                break
            }
            case findTarget(event, '.ui-dialog-titlebar-close', el):
                event.preventDefault()
                this.close()
                break
            case findTarget(event, '.ui-dialog-titlebar-help', el):
                event.preventDefault()
                this.help()
                break
            default:
                break
            }
        })
        if (!this.fullScreen) {
            this.listeners.onScroll = event => this.onScroll(event)
            window.addEventListener('scroll', this.listeners.onScroll, false)
            this.dialogEl.addEventListener('mousedown', event => {
                const el = {}
                switch (true) {
                case findTarget(event, '.ui-dialog-titlebar', el):
                    this.dragging = {
                        x: event.clientX - this.dialogEl.offsetLeft,
                        y: event.clientY - this.dialogEl.offsetTop
                    }
                    break
                default:
                    break
                }
            })
            this.dialogEl.addEventListener('mouseup', event => {
                const el = {}
                switch (true) {
                case findTarget(event, '.ui-dialog-titlebar', el):
                    this.dragging = false
                    break
                default:
                    break
                }
            })
            this.dialogEl.addEventListener('mousemove', event => {
                if (!this.dragging) {
                    return
                }
                this.moveDialog(event.clientX, event.clientY)
            })
        }

    }

    getHighestDialogZIndex() {
        let zIndex = 100
        document.querySelectorAll('div.ui-dialog').forEach(dialogEl => zIndex = Math.max(zIndex, dialogEl.style.zIndex))
        return zIndex
    }

    close() {
        if (!this.dialogEl) {
            return
        }
        if (!this.fullScreen) {
            window.removeEventListener("scroll",  this.listeners.onScroll, false)
        }
        document.body.removeEventListener("keydown", this.listeners.onKeydown)
        if (this.beforeClose) {
            this.beforeClose()
        }
        this.dialogEl.parentElement.removeChild(this.dialogEl)
        this.backdropEl.parentElement.removeChild(this.backdropEl)
        if (this.onClose) {
            this.onClose()
        }
    }
}
<commit_msg>allow dropdown from dialog buttons<commit_after>import {keyName} from "w3c-keyname"

import {findTarget} from "./basic"

const dialogTemplate = ({id, classes, title, height, width, icon, buttons, zIndex, body, scroll, help, canClose, note}) =>
    `<div tabindex="-1" role="dialog"
        class="ui-dialog ui-corner-all ui-widget ui-widget-content ui-front ui-dialog-buttons"
        ${id ? `aria-describedby="${id}"` : ''} style="z-index: ${zIndex};">

        ${icon ? `<i class="fa fa-${icon}" aria-hidden="true"></i>` : ''}
        ${title}
        ${help ? `<button type="button" class="ui-button ui-corner-all ui-widget ui-button-icon-only ui-dialog-titlebar-help" title="${gettext('Help')}">

            ${gettext('Help')}
        </button>` : ''}
        ${canClose ? `<button type="button" class="ui-button ui-corner-all ui-widget ui-button-icon-only ui-dialog-titlebar-close" title="${gettext('Close')}">

            ${gettext('Close')}
        </button>` : ''}

    <div ${id ? `id="${id}"` : ''} class="ui-dialog-content ui-widget-content${classes ? ` ${classes}` : ''}${scroll ? ` ui-scrollable` : ''}" style="width: ${width}; height: ${height};">
        ${note.text ? `<div class="note-container">${noteTemplate(note)}</div>` : ''}
        ${body}

${buttonsTemplate({buttons})}

`

const noteTemplate = (note) => {
    return note.text ? `<p class="noteEl ${note.display ? `` : `hide`}">${note.text}
` : ``
}

const buttonsTemplate = ({buttons}) => buttons.map(button => buttonTemplate(button)).join('')

const buttonTemplate = ({text, classes, icon, dropdown}) => `<button type="button" class="${classes ? classes : 'fw-light'} fw-button ui-button ui-corner-all ui-widget">
    ${icon ? `<i class="fa fa-${icon}" aria-hidden="true"></i>` : ''}
    ${text}
    ${dropdown ? `<i class="fa fa-caret-down" aria-hidden="true"></i>` : ''}
</button>`

const BUTTON_TYPES = {
    close: {
        text: gettext('Close'),
        classes: 'fw-orange',
        click: dialog => () => dialog.close()
    },
    cancel: {
        text: gettext('Cancel'),
        classes: 'fw-orange',
        click: dialog => () => dialog.close()
    },
    ok: {
        text: gettext('OK'),
        classes: 'fw-dark',
        click: dialog => () => dialog.close()
    }
}

export class Dialog {
    constructor(options) {
        this.id = options.id || false
        this.classes = options.classes || false
        this.title = options.title || ''
        this.body = options.body || ''
        this.height = options.height ? `${options.height}px` : 'auto'
        this.width = options.width ? `${options.width}px` : 'auto'
        this.canClose = 'canClose' in options ? options.canClose : true
        this.help = 'help' in options ? options.help : false
        this.note = 'note' in options ? options.note : {}
        this.buttons = []
        if (options.buttons) {
            this.setButtons(options.buttons)
        }
        this.beforeClose = options.beforeClose || false
        this.onClose = options.onClose || false
        this.icon = options.icon || false
        this.scroll = options.scroll || false
        this.canEscape = options.canEscape || false
        this.dialogEl = false
        this.backdropEl = false
        this.dragging = false
        this.hasBeenMoved = false
        this.listeners = {}
        this.fullScreen = options.fullScreen ? options.fullScreen : false
    }

    setButtons(buttons) {
        this.buttons = buttons.map(button => ({
            text: button.text ? button.text : button.type ? BUTTON_TYPES[button.type].text : '',
            classes: button.classes ? button.classes : button.type ? BUTTON_TYPES[button.type].classes : false,
            click: button.click ? button.click : button.type ? BUTTON_TYPES[button.type].click(this) : '',
            icon: button.icon ? button.icon : false,
            dropdown: button.dropdown? true : false
        }))
    }

    open() {
        if (this.dialogEl) {
            return
        }
        if (this.fullScreen) {
            this.height = "85vh"
        }

        document.body.insertAdjacentHTML(
            'beforeend',
            dialogTemplate({
                id: this.id,
                classes: this.classes,
                title: this.title,
                height: this.height,
                width: this.width,
                icon: this.icon,
                buttons: this.buttons,
                zIndex: this.getHighestDialogZIndex() + 2,
                body: this.body,
                scroll: this.scroll,
                canClose: this.canClose,
                help: this.help,
                note: this.note
            })
        )
        this.backdropEl = document.body.lastElementChild
        this.dialogEl = this.backdropEl.previousElementSibling
        if (this.fullScreen) {
            this.dialogEl.style.width = '98%'
            this.dialogEl.style.height = '100%'
            this.dialogEl.style.position = 'fixed'
            this.dialogEl.style.top = "0px"
        } else {
            this.centerDialog()
        }
        this.bind()
    }

    refreshButtons() {
        this.dialogEl.querySelector('.ui-dialog-buttonset').innerHTML = buttonsTemplate({buttons: this.buttons})
    }

    refreshNote() {
        this.dialogEl.querySelector(".note-container").innerHTML = noteTemplate(this.note)
    }

    centerDialog() {
        const totalWidth = window.innerWidth,
            totalHeight = window.innerHeight,
            dialogWidth = this.dialogEl.clientWidth,
            dialogHeight = this.dialogEl.clientHeight,
            scrollTopOffset = window.pageYOffset,
            scrollLeftOffset = window.pageXOffset

        this.dialogEl.style.top = `${(totalHeight - dialogHeight) / 2 + scrollTopOffset}px`
        this.dialogEl.style.left = `${(totalWidth - dialogWidth) / 2 + scrollLeftOffset}px`
    }

    adjustDialogToScroll() {
        this.dialogEl.style.top = `${
            Math.max(
                Math.min(
                    this.dialogEl.offsetTop,
                    this.backdropEl.scrollHeight - this.dialogEl.scrollHeight + window.pageYOffset
                ),
                window.pageYOffset
            )
        }px`
    }

    moveDialog(x, y) {
        this.dialogEl.style.top = `${
            Math.min(
                Math.max(y - this.dragging.y, 0),
                this.backdropEl.scrollHeight - this.dialogEl.scrollHeight + window.pageYOffset
            )
        }px`
        this.dialogEl.style.left = `${
            Math.min(
                Math.max(x - this.dragging.x, 0),
                document.body.scrollWidth - this.dialogEl.scrollWidth
            )
        }px`
        this.hasBeenMoved = true
    }

    onScroll(_event) {
        if (this.hasBeenMoved) {
            // The dialog has been moved manually. We just adjust the position to make it stay in the view.
            this.adjustDialogToScroll()
        } else {
            this.centerDialog()
        }
    }

    onKeydown(event) {
        let name = keyName(event)
        if (event.altKey) {
            name = "Alt-" + name
        }
        if (event.ctrlKey) {
            name = "Ctrl-" + name
        }
        if (event.metaKey) {
            name = "Meta-" + name
        }
        if (event.shiftKey) {
            name = "Shift-" + name
        }
        if (name === 'Escape' && this.canEscape) {
            this.close()
        }
    }

    bind() {
        this.listeners.onKeydown = event => this.onKeydown(event)
        document.body.addEventListener('keydown', this.listeners.onKeydown)
        this.dialogEl.addEventListener('click', event => {
            const el = {}
            switch (true) {
            case findTarget(event, '.ui-dialog-buttonpane button', el): {
                event.preventDefault()
                let buttonNumber = 0
                let seekItem = el.target
                while (seekItem.previousElementSibling) {
                    buttonNumber++
                    seekItem = seekItem.previousElementSibling
                }
                this.buttons[buttonNumber].click(event)
                break
            }
            case findTarget(event, '.ui-dialog-titlebar-close', el):
                event.preventDefault()
                this.close()
                break
            case findTarget(event, '.ui-dialog-titlebar-help', el):
                event.preventDefault()
                this.help()
                break
            default:
                break
            }
        })
        if (!this.fullScreen) {
            this.listeners.onScroll = event => this.onScroll(event)
            window.addEventListener('scroll', this.listeners.onScroll, false)
            this.dialogEl.addEventListener('mousedown', event => {
                const el = {}
                switch (true) {
                case findTarget(event, '.ui-dialog-titlebar', el):
                    this.dragging = {
                        x: event.clientX - this.dialogEl.offsetLeft,
                        y: event.clientY - this.dialogEl.offsetTop
                    }
                    break
                default:
                    break
                }
            })
            this.dialogEl.addEventListener('mouseup', event => {
                const el = {}
                switch (true) {
                case findTarget(event, '.ui-dialog-titlebar', el):
                    this.dragging = false
                    break
                default:
                    break
                }
            })
            this.dialogEl.addEventListener('mousemove', event => {
                if (!this.dragging) {
                    return
                }
                this.moveDialog(event.clientX, event.clientY)
            })
        }

    }

    getHighestDialogZIndex() {
        let zIndex = 100
        document.querySelectorAll('div.ui-dialog').forEach(dialogEl => zIndex = Math.max(zIndex, dialogEl.style.zIndex))
        return zIndex
    }

    close() {
        if (!this.dialogEl) {
            return
        }
        if (!this.fullScreen) {
            window.removeEventListener("scroll",  this.listeners.onScroll, false)
        }
        document.body.removeEventListener("keydown", this.listeners.onKeydown)
        if (this.beforeClose) {
            this.beforeClose()
        }
        this.dialogEl.parentElement.removeChild(this.dialogEl)
        this.backdropEl.parentElement.removeChild(this.backdropEl)
        if (this.onClose) {
            this.onClose()
        }
    }
}
<|endoftext|>


<commit_before>var hijackResponse = require('hijackresponse');

var HtmlParser = require('htmlparser2-papandreou').Parser;

var RangeOmittingStream = require('./RangeOmittingStream');

module.exports = function (config) {
    config = config || {};

    var memoize = config.memoize;
    var previousResultByUrl = {};

    return function expressExtractHeaders(req, res, next) {
        var previousResult = previousResultByUrl[req.url];
        var isHead = req.method === 'HEAD';
        if (previousResult && memoize && (previousResult.omitRanges.length === 0 || isHead)) {
            res.set(previousResult.headers);
            next();
        } else {
            if (isHead) {
                // Rewrite to GET so we can retrieve the response from the upstream middleware and
                // still get the correct previousHeaders:
                req.method = 'GET';
            }
            delete req.headers.range;
            delete req.headers['if-range'];
            hijackResponse(res, function (err, res) {
                if (err) {
                    res.unhijack();
                    return next(err);
                } else if (previousResult && previousResult.headers.etag && previousResult.headers.etag === res.getHeader('ETag') && (previousResult.omitRanges.length === 0 || !/^W\//.test(previousResult.headers.etag))) {
                    res.set(previousResult.headers);
                    if (previousResult.omitRanges.length > 0) {
                        return res.pipe(new RangeOmittingStream(previousResult.omitRanges)).pipe(res);
                    } else {
                        return res.unhijack();
                    }
                }

                if (/^text\/html(?:;|\s|$)/i.test(res.getHeader('Content-Type'))) {
                    var headers = {};
                    var omitRanges = [];
                    var stillParsing = true;
                    var htmlParser = new HtmlParser({
                        onopentag: function (name, attribs) {
                            if (stillParsing && name === 'meta') {
                                var httpEquiv = attribs['http-equiv'];
                                if (typeof httpEquiv === 'string') {
                                    headers[httpEquiv] = attribs.content || '';
                                    if (/^(?:X-Frame-Options|Content-Security-Policy(?:-Report-Only)?)$/i.test(httpEquiv)) {
                                        omitRanges.push([htmlParser.startIndex, htmlParser.endIndex + 1]);
                                    }
                                }
                            }
                        },
                        onclosetag: function (name) {
                            if (name === 'head') {
                                stopParsingAndSendResponse();
                            }
                        }
                    });
                    var chunks = [];

                    res.on('data', function (chunk) {
                        if (stillParsing) {
                            if (!isHead) {
                                chunks.push(chunk);
                            }
                            htmlParser.write(chunk);
                        } else if (!isHead) {
                            res.write(chunk);
                        }
                    }).on('end', function () {
                        stopParsingAndSendResponse();
                        res.end();
                    });

                    var stopParsingAndSendResponse = function () {
                        if (stillParsing) {
                            stillParsing = false;
                            res.set(headers);
                            headers.etag = res.getHeader('ETag');
                            previousResultByUrl[req.url] = {
                                headers: headers,
                                omitRanges: omitRanges
                            };

                            var rangeOmittingStream = new RangeOmittingStream(omitRanges);
                            rangeOmittingStream.pipe(res);
                            chunks.forEach(function (chunk) {
                                rangeOmittingStream.write(chunk);
                            });
                        }
                    };
                } else {
                    res.unhijack();
                }
            });
            next();
        }
    };
};
<commit_msg>Don't run the response through a RangeOmittingStream when there are no ranges to omit.<commit_after>var hijackResponse = require('hijackresponse');

var HtmlParser = require('htmlparser2-papandreou').Parser;

var RangeOmittingStream = require('./RangeOmittingStream');

module.exports = function (config) {
    config = config || {};

    var memoize = config.memoize;
    var previousResultByUrl = {};

    return function expressExtractHeaders(req, res, next) {
        var previousResult = previousResultByUrl[req.url];
        var isHead = req.method === 'HEAD';
        if (previousResult && memoize && (previousResult.omitRanges.length === 0 || isHead)) {
            res.set(previousResult.headers);
            next();
        } else {
            if (isHead) {
                // Rewrite to GET so we can retrieve the response from the upstream middleware and
                // still get the correct previousHeaders:
                req.method = 'GET';
            }
            delete req.headers.range;
            delete req.headers['if-range'];
            hijackResponse(res, function (err, res) {
                if (err) {
                    res.unhijack();
                    return next(err);
                } else if (previousResult && previousResult.headers.etag && previousResult.headers.etag === res.getHeader('ETag') && (previousResult.omitRanges.length === 0 || !/^W\//.test(previousResult.headers.etag))) {
                    res.set(previousResult.headers);
                    if (previousResult.omitRanges.length > 0) {
                        return res.pipe(new RangeOmittingStream(previousResult.omitRanges)).pipe(res);
                    } else {
                        return res.unhijack();
                    }
                }

                if (/^text\/html(?:;|\s|$)/i.test(res.getHeader('Content-Type'))) {
                    var headers = {};
                    var omitRanges = [];
                    var stillParsing = true;
                    var htmlParser = new HtmlParser({
                        onopentag: function (name, attribs) {
                            if (stillParsing && name === 'meta') {
                                var httpEquiv = attribs['http-equiv'];
                                if (typeof httpEquiv === 'string') {
                                    headers[httpEquiv] = attribs.content || '';
                                    if (/^(?:X-Frame-Options|Content-Security-Policy(?:-Report-Only)?)$/i.test(httpEquiv)) {
                                        omitRanges.push([htmlParser.startIndex, htmlParser.endIndex + 1]);
                                    }
                                }
                            }
                        },
                        onclosetag: function (name) {
                            if (name === 'head') {
                                stopParsingAndSendResponse();
                            }
                        }
                    });
                    var chunks = [];

                    res.on('data', function (chunk) {
                        if (stillParsing) {
                            if (!isHead) {
                                chunks.push(chunk);
                            }
                            htmlParser.write(chunk);
                        } else if (!isHead) {
                            res.write(chunk);
                        }
                    }).on('end', function () {
                        stopParsingAndSendResponse();
                        res.end();
                    });

                    var stopParsingAndSendResponse = function () {
                        if (stillParsing) {
                            stillParsing = false;
                            res.set(headers);
                            headers.etag = res.getHeader('ETag');
                            previousResultByUrl[req.url] = {
                                headers: headers,
                                omitRanges: omitRanges
                            };
                            if (omitRanges.length > 0) {
                                var rangeOmittingStream = new RangeOmittingStream(omitRanges);
                                rangeOmittingStream.pipe(res);
                                chunks.forEach(function (chunk) {
                                    rangeOmittingStream.write(chunk);
                                });
                            } else {
                                chunks.forEach(function (chunk) {
                                    res.write(chunk);
                                });
                            }
                        }
                    };
                } else {
                    res.unhijack();
                }
            });
            next();
        }
    };
};
<|endoftext|>


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

module.exports = {
  'Confirm selecting database via typeahead redirects properly': function (client) {
    var waitTime = client.globals.maxWaitTime,
        newDatabaseName = client.globals.testDatabaseName;

    client
      .createDatabase(newDatabaseName)
      .loginToGUI()

      // wait for the DB name typeahead field to appear in the header
      .waitForElementPresent('#jump-to-db .search-autocomplete', waitTime, false)
      .setValue('#jump-to-db .search-autocomplete', [newDatabaseName, client.Keys.ENTER])
      .waitForElementPresent('.index-pagination', waitTime, false)

      // now check we've redirected and the URL ends with /_all_docs
      .url(function (result) {
        var endsWithAllDocs = /all_docs$/.test(result.value);
        this.assert.ok(endsWithAllDocs, 'Redirected properly');
      })
      .end();
  }
};
<commit_msg>Fix for switchDatabase.js test<commit_after>// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

module.exports = {
  'Confirm selecting database via typeahead redirects properly': function (client) {
    var waitTime = client.globals.maxWaitTime,
        newDatabaseName = client.globals.testDatabaseName;

    client
      .createDatabase(newDatabaseName)
      .loginToGUI()

      // wait for the DB name typeahead field to appear in the header
      .waitForElementPresent('#jump-to-db .search-autocomplete', waitTime, false)
      .waitForElementPresent('#dashboard-content table.databases', waitTime, false)
      .setValue('#jump-to-db .search-autocomplete', [newDatabaseName, client.Keys.ENTER])
      .waitForElementPresent('.index-pagination', waitTime, false)
      // now check we've redirected and the URL ends with /_all_docs
      .url(function (result) {
        var endsWithAllDocs = /all_docs$/.test(result.value);
        this.assert.ok(endsWithAllDocs, 'Redirected properly');
      })
      .end();
  }
};
<|endoftext|>


<commit_before>/**
 * Created by will on 4/6/16.
 */
var MOL = {};

MOL.units = {};  //holds all the units
MOL.unit = function(id) {
    this.id = id;
    this.instructions = {};
    this.cache = {};
    this.data = {};
    this.data_limit = 5;
    this.gates = {};

    this.add_ins = function(ins) {
        if (!this.instructions[ins.signal]) {
            this.instructions[ins.signal] = [];
        }
        this.instructions[ins.signal].push(ins);
    }

};

MOL.gate = function(id,unit_id,direction,namespace,power) {
    this.id = id;
    this.unit_id = unit_id;
    this.direction = direction;
    this.namespace = namespace;
    this.power = power;
    this.hookup = nil;
};

MOL.instruction = function(id,signal,op,oprand1,oprand2,result) {
    this.id = id;
    this.signal = signal;
    this.op = op;
    this.oprand1 = oprand1;
    this.oprand2 = oprand2;
    this.result = result;
};

MOL.out_gates = {};
MOL.in_gates = {};
MOL.ins_next = {};
MOL.active_hookups = [];

/*
Steps each cycle:
empty all out_gates,in_gates

NOTE: after all ins for a single signal is run, delete the key to the cache for that signal

1) for each unit in MOL get all out_gates g that are on and put their namespace (the namespace they are looking for)
        as a key into out_gates with a ref to the gate as the value
        MOL.out_gates[g.namespace] = g

2) for each unit in MOL get all in_gates go that are on and put their NS into the hash
        MOL.in_gates[go.namespace] = go

3) match all outgates to ingates, multiple hookups for one gate is okay. For each pair found,
    make a hash {in_unit: go.unit_id, in_gate:go.id, out_unit:go.unit_id,out_gate:g.id} //avoid cycle ref
     and set each gate's hookup to this, and add to MOL.active_hookups

 4) get each gate's unit, and add any instruction whose state is 'GS' + gate.id for that gate's unit, to the MOL.ins_next

 5) ADD to each unit's cache the key , 'GS' + gate.id and set it to 1 unit.cache['GS' + gate.id] = 1

 6) EXECUTE all instructions in MOL.ins_next (remove ins from ins_next as we execute them)

 7) If any of these ins move data through a gate (D1 ++ , result GO#)
        if the target unit, that is at the end of the gate hookup, has an ins for GS#,
            add to that unit   unit.cache[GD#] = data moved (overrite if already set)
            add the ins to ins_next

 7) If any of these ins change data in their own unit (D1 + D2. result D2)
     if the unit has an ins for DD2
     add to that unit   unit.cache['DD2'] = index of data changed (overrite if already set)
     add all ins for this DD2 to ins_next

 8) EXECUTE ALL ins_next (removing each of the ins as we do it)

 9) Go through all MOL.hookups and see if any of the pair of gates is now off, if so see if each gate's unit
        has a detach signal (GX#), if so unit.cache[GX#] = 1 (create or overrite), remove any cache keys for incoming data
        ; delete unit.cache[GD#].remove hookup info from both gates and the hookup array
 */

$(function() {
    MOL.units[0] = new MOL.unit(0);
    MOL.units[0].gates[0] = new MOL.gate(0,0);
    MOL.units[0].add_ins( new MOL.instruction(2,'GS3','+','D1','GS4','GU5'));
    var g = MOL.units[0].gates[0];
    var mm = MOL.units[g.unit_id];

    makeBrick('first');
    makeBrick('second');
    makeBrick('third');

    $('.first .gate_house').css("background-color",'blue');
});

//create the brick on screen given an x and y
function makeBrick(parent_class) {
    $("<div/>",{
        "class" : "gate_house",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        },
        "click" : function(){
            alert("you just clicked me!!");
        },
        "data" : {
            "foo" : "bar"
        }
    }).appendTo("."+parent_class);

    for(var i=0;i<4;i++) {
        $("<div/>",{
            "class" : "gate",
            // .. you can go on and add properties
            "css" : {
                "color" : "black"
            }
        }).appendTo("."+parent_class + ' .gate_house');
    }

    $("<div/>",{
        "class" : "cpu",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        }
    }).appendTo("."+parent_class);

    $("<div/>",{
        "class" : "storage",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        }
    }).appendTo("."+parent_class);
}<commit_msg>Added some explanation of instructions<commit_after>/**
 * Created by will on 4/6/16.
 */
var MOL = {};

MOL.units = {};  //holds all the units
MOL.unit = function(id) {
    this.id = id;
    this.instructions = {};
    this.cache = {};
    this.data = {};
    this.data_limit = 5;
    this.gates = {};

    this.add_ins = function(ins) {
        if (!this.instructions[ins.signal]) {
            this.instructions[ins.signal] = [];
        }
        this.instructions[ins.signal].push(ins);
    }

};

MOL.gate = function(id,unit_id,direction,namespace,power) {
    this.id = id;
    this.unit_id = unit_id;
    this.direction = direction;
    this.namespace = namespace;
    this.power = power;
    this.hookup = nil;
};

MOL.instruction = function(id,signal,op,oprand1,oprand2,result) {
    this.id = id;
    this.signal = signal;
    this.op = op;
    this.oprand1 = oprand1;
    this.oprand2 = oprand2;
    this.result = result;
};

MOL.out_gates = {};
MOL.in_gates = {};
MOL.ins_next = {};
MOL.active_hookups = [];

/*
Steps each cycle:
empty all out_gates,in_gates

1) for each unit in MOL get all out_gates g that are on and put their namespace (the namespace they are looking for)
        as a key into out_gates with a ref to the gate as the value
        MOL.out_gates[g.namespace] = g

2) for each unit in MOL get all in_gates go that are on and put their NS into the hash
        MOL.in_gates[go.namespace] = go

3) match all outgates to ingates, multiple hookups for one gate is okay. For each pair found,
    make a hash {in_unit: go.unit_id, in_gate:go.id, out_unit:go.unit_id,out_gate:g.id} //avoid cycle ref
     and set each gate's hookup to this, and add to MOL.active_hookups

 4) get each gate's unit, and add any instruction whose state is 'GS' + gate.id for that gate's unit, to the MOL.ins_next

 5) ADD to each unit's cache the key , 'GS' + gate.id and set it to 1 unit.cache['GS' + gate.id] = 1

 6) EXECUTE all instructions in MOL.ins_next (remove ins from ins_next as we execute them)

 7) If any of these ins move data through a gate (D1 ++ , result GO#)
        if the target unit, that is at the end of the gate hookup, has an ins for GS#,
            add to that unit   unit.cache[GD#] = data moved (overrite if already set)
            add the ins to ins_next

 7) If any of these ins change data in their own unit (D1 + D2. result D2)
     if the unit has an ins for DD2 and DD2 has changed value
     add to that unit   unit.cache['DD2'] = index of data changed (overrite if already set)
     add all ins for this DD2 to ins_next

 8) EXECUTE ALL ins_next (removing each of the ins as we do it)

 9) Go through all MOL.hookups and see if any of the pair of gates is now off, if so see if each gate's unit
        has a detach signal (GX#), if so unit.cache[GX#] = 1 (create or overrite), remove any cache keys for incoming data
        ; delete unit.cache[GD#].remove hookup info from both gates and the hookup array
        ; delete GS# from cache

 ------------------------
 instruction works by : waits on signal : does an operation with up to two registers and then write to a register
 signals are:
 Gate Start: GS: when a gate connects
 Gate Data: GD :when there is data incoming through a gate
 Gate End: GX : when a gate detaches
 Data Delta DD : when a data slot changes value

 if there is no DG GS GX or DD in an instructions two operands, then that instruction does not affect or write anything

 instruction notation State,p1 p2 op, result
 p2 can be missing

 operations:
   math: + - * / --  %
   action_logic: AND OR NOT XOR > < >= <= <> ==
                            -- if logic is false no result is written to, if logic is true result has a 1
   logic: same as action logic           -- but result is always 0 or 1
   bitwise: & | ^ ~
   GateOff#  -- turns Gate# off
   GateOn#   -- turns Gate# on

 */

$(function() {
    MOL.units[0] = new MOL.unit(0);
    MOL.units[0].gates[0] = new MOL.gate(0,0);
    MOL.units[0].add_ins( new MOL.instruction(2,'GS3','+','D1','GS4','GU5'));
    var g = MOL.units[0].gates[0];
    var mm = MOL.units[g.unit_id];

    makeBrick('first');
    makeBrick('second');
    makeBrick('third');

    $('.first .gate_house').css("background-color",'blue');
});

//create the brick on screen given an x and y
function makeBrick(parent_class) {
    $("<div/>",{
        "class" : "gate_house",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        },
        "click" : function(){
            alert("you just clicked me!!");
        },
        "data" : {
            "foo" : "bar"
        }
    }).appendTo("."+parent_class);

    for(var i=0;i<4;i++) {
        $("<div/>",{
            "class" : "gate",
            // .. you can go on and add properties
            "css" : {
                "color" : "black"
            }
        }).appendTo("."+parent_class + ' .gate_house');
    }

    $("<div/>",{
        "class" : "cpu",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        }
    }).appendTo("."+parent_class);

    $("<div/>",{
        "class" : "storage",
        // .. you can go on and add properties
        "css" : {
            "color" : "black"
        }
    }).appendTo("."+parent_class);
}<|endoftext|>


<commit_before>App.addChild('Contribution', {
  el: '#new-contribution',

  events: {
    'click .radio label' : 'clickReward',
    'click .submit-form' : 'submitForm',
    'click .user-reward-value' : 'clearOnFocus',
    'input #contribution_value' : 'restrictChars'
  },

  restrictChars: function(event){
    var $target = $(event.target);
    $target.val($target.val().replace(/[^\d,]/, ''));
  },

  submitForm: function(event){
    var $target_row = $(event.target).parents('.back-reward-money'),
        user_value = this.$('.selected').find('.user-reward-value').val().replace(/\./g,'');
    if(user_value === ''){
      this.$value.val(this.minimumValue());
    }else{
      this.$value.val(user_value);
    }
    if(parseInt(user_value) < parseInt(this.minimumValue())){
      $target_row.find('.user-reward-value').addClass('error');
      $target_row.find('.text-error').slideDown();
    }else{
      this.$('form').submit();
    }

    return false;
  },

  activate: function(){
    this.$('.user-reward-value').mask('000.000.000,00', {reverse: true});
    this.$value = this.$('#contribution_value');
    this.$minimum = this.$('#minimum-value');
    this.clickReward({currentTarget: this.$('input[type=radio]:checked').parent()});
    this.isOnAutoScroll = false;
    this.activateFloattingHeader();
  },

  activateFloattingHeader: function(){
    var that = this,
        top,
        top_title = $('#new-contribution'),
        faq_top = $("#faq-box").offset().top;
    $(window).scroll(function() {
        if(!that.isOnAutoScroll && !app.isMobile()){
            top = $(top_title).offset().top,
            $(window).scrollTop() > top ? $(".reward-floating").addClass("reward-floating-display") : $(".reward-floating").removeClass("reward-floating-display");
            var t = $("#faq-box");
            $(window).scrollTop() > faq_top-130 ? $(t).hasClass("faq-card-fixed") || $(t).addClass("faq-card-fixed") : $(t).hasClass("faq-card-fixed") && $(t).removeClass("faq-card-fixed");
        }
    });
  },

  clearOnFocus: function(event){
    this.$(event.target).val("");
    this.$('.error').removeClass('error');
    this.$('.text-error').slideUp();
    return false;
  },

  customValidation: function(event){
    if(parseInt(this.$value.val()) < this.minimumValue()){
      this.selectReward(this.$('.radio label'));
    }
  },

  minimumValue: function(){
    return this.$('.selected').find('label[data-minimum-value]').data('minimum-value');
  },

  resetSelected: function(){
    this.$('.w-radio').removeClass('selected');
  },

  selectReward: function(reward){
    this.resetSelected();
    reward.find('input[type=radio]').prop('checked', true);
    this.$('.back-reward-money').hide();
    reward.find('.back-reward-money').show();
    reward.parents('.back-reward-radio-reward').addClass('selected');
  },

  clickReward: function(event){
    var $el = $(event.currentTarget);
    var elOffset = $el.offset().top;
    var elHeight = $el.height();
    var windowHeight = $(window).height();
    var isOnAutoScroll = this.isOnAutoScroll;
    var offset;
    if (elHeight < windowHeight) {
      offset = elOffset - ((windowHeight / 2) - ((elHeight * 2) / 3));
    } else {
      offset = elOffset;
    }
    $.smoothScroll({
      speed: 600,
      offset: -60,
      callback: function(){
        isOnAutoScroll = false;
      }
    }, offset);
    this.selectReward($el);
    var minimum = this.minimumValue();
    var reward_value = $el.find('.user-reward-value');
    if(reward_value.val() === ''){
      reward_value.val('10,00');
    }
  }
});

App.addChild('FaqBox', {
  el: '#faq-box',

  events: {
    'click li.list-question' : 'clickQuestion'
  },

  clickQuestion: function(event){
    var $question = $(event.currentTarget);
    var $answer = $question.next();
    $question.toggleClass('open').toggleClass('alt-link');
    $answer.slideToggle('slow');
  },

  activate: function(){
    this.$('li.list-answer').hide();
  }
});
<commit_msg>fix min value<commit_after>App.addChild('Contribution', {
  el: '#new-contribution',

  events: {
    'click .radio label' : 'clickReward',
    'click .submit-form' : 'submitForm',
    'click .user-reward-value' : 'clearOnFocus',
    'input #contribution_value' : 'restrictChars'
  },

  restrictChars: function(event){
    var $target = $(event.target);
    $target.val($target.val().replace(/[^\d,]/, ''));
  },

  submitForm: function(event){
    var $target_row = $(event.target).parents('.back-reward-money'),
        user_value = this.$('.selected').find('.user-reward-value').val().replace(/\./g,'');
    if(user_value === ''){
      this.$value.val(this.minimumValue());
    }else{
      this.$value.val(user_value);
    }
    if(parseInt(user_value) < parseInt(this.minimumValue())){
      $target_row.find('.user-reward-value').addClass('error');
      $target_row.find('.text-error').slideDown();
    }else{
      this.$('form').submit();
    }

    return false;
  },

  activate: function(){
    this.$('.user-reward-value').mask('000.000.000,00', {reverse: true});
    this.$value = this.$('#contribution_value');
    this.$minimum = this.$('#minimum-value');
    this.clickReward({currentTarget: this.$('input[type=radio]:checked').parent()});
    this.isOnAutoScroll = false;
    this.activateFloattingHeader();
  },

  activateFloattingHeader: function(){
    var that = this,
        top,
        top_title = $('#new-contribution'),
        faq_top = $("#faq-box").offset().top;
    $(window).scroll(function() {
        if(!that.isOnAutoScroll && !app.isMobile()){
            top = $(top_title).offset().top,
            $(window).scrollTop() > top ? $(".reward-floating").addClass("reward-floating-display") : $(".reward-floating").removeClass("reward-floating-display");
            var t = $("#faq-box");
            $(window).scrollTop() > faq_top-130 ? $(t).hasClass("faq-card-fixed") || $(t).addClass("faq-card-fixed") : $(t).hasClass("faq-card-fixed") && $(t).removeClass("faq-card-fixed");
        }
    });
  },

  clearOnFocus: function(event){
    this.$(event.target).val("");
    this.$('.error').removeClass('error');
    this.$('.text-error').slideUp();
    return false;
  },

  customValidation: function(event){
    if(parseInt(this.$value.val()) < this.minimumValue()){
      this.selectReward(this.$('.radio label'));
    }
  },

  minimumValue: function(){
    return this.$('.selected').find('label[data-minimum-value]').data('minimum-value');
  },

  resetSelected: function(){
    this.$('.w-radio').removeClass('selected');
  },

  selectReward: function(reward){
    this.resetSelected();
    reward.find('input[type=radio]').prop('checked', true);
    this.$('.back-reward-money').hide();
    reward.find('.back-reward-money').show();
    reward.parents('.back-reward-radio-reward').addClass('selected');
  },

  clickReward: function(event){
    var $el = $(event.currentTarget);
    var elOffset = $el.offset().top;
    var elHeight = $el.height();
    var windowHeight = $(window).height();
    var isOnAutoScroll = this.isOnAutoScroll;
    var offset;
    if (elHeight < windowHeight) {
      offset = elOffset - ((windowHeight / 2) - ((elHeight * 2) / 3));
    } else {
      offset = elOffset;
    }
    $.smoothScroll({
      speed: 600,
      offset: -60,
      callback: function(){
        isOnAutoScroll = false;
      }
    }, offset);
    this.selectReward($el);
    var minimum = this.minimumValue();
    var reward_value = $el.find('.user-reward-value');
    if(reward_value.val() === ''){
      reward_value.val(minimum);
    }
  }
});

App.addChild('FaqBox', {
  el: '#faq-box',

  events: {
    'click li.list-question' : 'clickQuestion'
  },

  clickQuestion: function(event){
    var $question = $(event.currentTarget);
    var $answer = $question.next();
    $question.toggleClass('open').toggleClass('alt-link');
    $answer.slideToggle('slow');
  },

  activate: function(){
    this.$('li.list-answer').hide();
  }
});
<|endoftext|>


<commit_before>
/*
 *
 * poloniex-unofficial
 * https://git.io/polonode
 *
 * Yet another unofficial Node.js wrapper for the Poloniex cryptocurrency
 * exchange APIs.
 *
 * Copyright (c) 2016 Tyler Filla
 *
 * This software may be modified and distributed under the terms of the MIT
 * license. See the LICENSE file for details.
 *
 */

/*
 * NOTICE: This file needs documentation revisions.
 */

// Localize wrappers
var PushWrapper = module.parent.exports.PushWrapper;
var PublicWrapper = module.parent.exports.PublicWrapper;

// Do not continue without these wrappers
if (!PushWrapper || !PublicWrapper) {
    throw "Failed to localize wrappers (OrderBook.js should not be require()'d externally)";
}

/*
 * Order book utility constructor.
 */
function OrderBook(currencyPair) {
    this._currencyPair = currencyPair;

    this._wrapperPush = null;
    this._wrapperPublic = null;

    this._callbackSetStart = new Array();
    this._callbackSetStop = new Array();
    this._callbackSetSync = new Array();
    this._callbackSetLoseSync = new Array();
}

/*
 *
 * function getWrapperPush()
 *
 * Get the push wrapper instance.
 *
 */
OrderBook.prototype.getWrapperPush = function() {
    return this._wrapperPush;
};

/*
 *
 * function setWrapperPush(wrapperPush)
 *
 * Set the push wrapper instance.
 *
 */
OrderBook.prototype.setWrapperPush = function(wrapperPush) {
    // Sanity check
    if (!(wrapperPush instanceof PushWrapper)) {
        throw new TypeError("wrapperPush is not an instance of PushWrapper");
    }

    this._wrapperPush = wrapperPush;
};

/*
 *
 * function getWrapperPublic()
 *
 * Get the public wrapper instance.
 *
 */
OrderBook.prototype.getWrapperPublic = function() {
    return this._wrapperPublic;
};

/*
 *
 * function setWrapperPublic(wrapperPublic)
 *
 * Set the public wrapper instance.
 *
 */
OrderBook.prototype.setWrapperPublic = function(wrapperPublic) {
    // Sanity check
    if (!(wrapperPublic instanceof PublicWrapper)) {
        throw new TypeError("wrapperPublic is not an instance of PublicWrapper");
    }

    this._wrapperPublic = wrapperPublic;
};

/*
 *
 * function getCurrencyPair()
 *
 * Get the target currency pair.
 *
 */
OrderBook.prototype.getCurrencyPair = function(currencyPair) {
    return this._currencyPair;
};

/*
 *
 * function setCurrencyPair(currencyPair)
 *
 * Set the target currency pair.
 *
 */
OrderBook.prototype.setCurrencyPair = function(currencyPair) {
    this._currencyPair = currencyPair;
};

/*
 *
 * function useDefaultWrappers()
 *
 * Create new push and public wrappers and use them.
 *
 */
OrderBook.prototype.useDefaultWrappers = function() {
    this.setWrapperPush(new PushWrapper());
    this.setWrapperPublic(new PublicWrapper());
};

/*
 *
 * function start()
 *
 * Start tracking the target currency pair's order book.
 *
 */
OrderBook.prototype.start = function() {
};

/*
 *
 * function start()
 *
 * Stop tracking the target currency pair's order book.
 *
 */
OrderBook.prototype.stop = function() {
};

/*
 *
 * function onStart(callback)
 *
 * Register a callback to receive start events.
 *
 */
OrderBook.prototype.onStart = function(callback) {
    // Push to start callback set
    this._callbackSetStart.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from start callback set
            this._callbackSetStart.splice(this._callbackSetStart.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onStop(callback)
 *
 * Register a callback to receive stop events.
 *
 */
OrderBook.prototype.onStop = function(callback) {
    // Push to stop callback set
    this._callbackSetStop.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from stop callback set
            this._callbackSetStop.splice(this._callbackSetStop.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onSync(callback)
 *
 * Register a callback to receive sync events.
 *
 */
OrderBook.prototype.onSync = function(callback) {
    // Push to sync callback set
    this._callbackSetSync.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from sync callback set
            this._callbackSetSync.splice(this._callbackSetSync.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onLoseSync(callback)
 *
 * Register a callback to receive lose sync events.
 *
 */
OrderBook.prototype.onLoseSync = function(callback) {
    // Push to lose sync callback set
    this._callbackSetLoseSync.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from lose sync callback set
            this._callbackSetLoseSync.splice(this._callbackSetLoseSync.indexOf(callback), 1);
        }
    };
};

module.exports = OrderBook;
<commit_msg>Add running flag<commit_after>
/*
 *
 * poloniex-unofficial
 * https://git.io/polonode
 *
 * Yet another unofficial Node.js wrapper for the Poloniex cryptocurrency
 * exchange APIs.
 *
 * Copyright (c) 2016 Tyler Filla
 *
 * This software may be modified and distributed under the terms of the MIT
 * license. See the LICENSE file for details.
 *
 */

/*
 * NOTICE: This file needs documentation revisions.
 */

// Localize wrappers
var PushWrapper = module.parent.exports.PushWrapper;
var PublicWrapper = module.parent.exports.PublicWrapper;

// Do not continue without these wrappers
if (!PushWrapper || !PublicWrapper) {
    throw "Failed to localize wrappers (OrderBook.js should not be require()'d externally)";
}

/*
 * Order book utility constructor.
 */
function OrderBook(currencyPair) {
    this._currencyPair = currencyPair;

    this._wrapperPush = null;
    this._wrapperPublic = null;

    this._running = false;

    this._callbackSetStart = new Array();
    this._callbackSetStop = new Array();
    this._callbackSetSync = new Array();
    this._callbackSetLoseSync = new Array();
}

/*
 *
 * function getWrapperPush()
 *
 * Get the push wrapper instance.
 *
 */
OrderBook.prototype.getWrapperPush = function() {
    return this._wrapperPush;
};

/*
 *
 * function setWrapperPush(wrapperPush)
 *
 * Set the push wrapper instance.
 *
 */
OrderBook.prototype.setWrapperPush = function(wrapperPush) {
    // Sanity check
    if (!(wrapperPush instanceof PushWrapper)) {
        throw new TypeError("wrapperPush is not an instance of PushWrapper");
    }

    this._wrapperPush = wrapperPush;
};

/*
 *
 * function getWrapperPublic()
 *
 * Get the public wrapper instance.
 *
 */
OrderBook.prototype.getWrapperPublic = function() {
    return this._wrapperPublic;
};

/*
 *
 * function setWrapperPublic(wrapperPublic)
 *
 * Set the public wrapper instance.
 *
 */
OrderBook.prototype.setWrapperPublic = function(wrapperPublic) {
    // Sanity check
    if (!(wrapperPublic instanceof PublicWrapper)) {
        throw new TypeError("wrapperPublic is not an instance of PublicWrapper");
    }

    this._wrapperPublic = wrapperPublic;
};

/*
 *
 * function getCurrencyPair()
 *
 * Get the target currency pair.
 *
 */
OrderBook.prototype.getCurrencyPair = function(currencyPair) {
    return this._currencyPair;
};

/*
 *
 * function setCurrencyPair(currencyPair)
 *
 * Set the target currency pair.
 *
 */
OrderBook.prototype.setCurrencyPair = function(currencyPair) {
    this._currencyPair = currencyPair;
};

/*
 *
 * function useDefaultWrappers()
 *
 * Create new push and public wrappers and use them.
 *
 */
OrderBook.prototype.useDefaultWrappers = function() {
    this.setWrapperPush(new PushWrapper());
    this.setWrapperPublic(new PublicWrapper());
};

/*
 *
 * function start()
 *
 * Start tracking the target currency pair's order book.
 *
 */
OrderBook.prototype.start = function() {
    // Sanity check
    if (this._running) {
        throw "Attempt to start, but already running";
    }

    // TODO: Start tracker

    // Set running flag
    this._running = true;
};

/*
 *
 * function start()
 *
 * Stop tracking the target currency pair's order book.
 *
 */
OrderBook.prototype.stop = function() {
    // Sanity check
    if (this._running) {
        throw "Attempt to stop, but not running";
    }

    // TODO: Stop tracker

    // Clear running flag
    this._running = false;
};

/*
 *
 * function onStart(callback)
 *
 * Register a callback to receive start events.
 *
 */
OrderBook.prototype.onStart = function(callback) {
    // Push to start callback set
    this._callbackSetStart.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from start callback set
            this._callbackSetStart.splice(this._callbackSetStart.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onStop(callback)
 *
 * Register a callback to receive stop events.
 *
 */
OrderBook.prototype.onStop = function(callback) {
    // Push to stop callback set
    this._callbackSetStop.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from stop callback set
            this._callbackSetStop.splice(this._callbackSetStop.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onSync(callback)
 *
 * Register a callback to receive sync events.
 *
 */
OrderBook.prototype.onSync = function(callback) {
    // Push to sync callback set
    this._callbackSetSync.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from sync callback set
            this._callbackSetSync.splice(this._callbackSetSync.indexOf(callback), 1);
        }
    };
};

/*
 *
 * function onLoseSync(callback)
 *
 * Register a callback to receive lose sync events.
 *
 */
OrderBook.prototype.onLoseSync = function(callback) {
    // Push to lose sync callback set
    this._callbackSetLoseSync.push(callback);

    // Give user the option to remove it
    return {
        "remove": () => {
            // Remove from lose sync callback set
            this._callbackSetLoseSync.splice(this._callbackSetLoseSync.indexOf(callback), 1);
        }
    };
};

module.exports = OrderBook;
<|endoftext|>


<commit_before>
var lob = require('lob-enc');
var hashname = require('hashname');

module.exports = {
  bootstrap : handshake_bootstrap,
  validate  : handshake_validate,
  from      : handshake_from,
  types     : handshake_types
};

// cache incoming handshakes to aggregate them
var hcache = {};
setInterval(function hcachet(){hcache={}},60*1000);

function handshake_bootstrap(handshake){
  // default an at for bare key handshakes if not given
  if(typeof handshake.json.at === 'undefined')
    handshake.json.at = Date.now();

  // verify at
  if(typeof handshake.json.at != 'number' || handshake.json.at <= 0)
  {
    log.debug('invalid handshake at',handshake.json);
    return false;
  }

  // default the handshake type
  if(typeof handshake.json.type != 'string')
    handshake.json.type = 'link';

  // upvert deprecated key to link type
  if(handshake.json.type == 'key')
  {
    // map only csid keys into attachment header
    var json = {};
    hashname.ids(handshake.json).forEach(function(csid){
      if(handshake.json[csid] === true)
        handshake.json.csid = csid; // cruft
      json[csid] = handshake.json[csid];
    });

    if(message)
      json[message.head.toString('hex')] = true;

    var attach = lob.encode(json, handshake.body);
    handshake.json.type = 'link';
    handshake.body = attach;
  }

  return handshake
}

function handshake_validate(id,handshake, message, mesh){
  if(handshake.json.type == 'link')
  {
    // if it came from an encrypted message
    if(message)
    {
      // make sure the link csid matches the message csid
      handshake.json.csid = message.head.toString('hex');
      // stash inside the handshake, can be used later to create the exchange immediately
      handshake._message = message;
    }

    var attach = lob.decode(handshake.body);
    if(!attach)
    {
      log.debug('invalid link handshake attachment',handshake.body);
      return false;
    }

    // make sure key info is at least correct
    var keys = {};
    keys[handshake.json.csid] = attach.body;
    var csid = hashname.match(mesh.keys, keys, null, attach.json);
    if(handshake.json.csid != csid)
    {
      log.debug('invalid key handshake, unsupported csid',attach.json, keys);
      return false;
    }
    handshake.json.hashname = hashname.fromKeys(keys, attach.json);
    if(!handshake.json.hashname)
    {
      log.debug('invalid key handshake, no hashname',attach.json, keys);
      return false;
    }

    // hashname is valid now, so stash key bytes in handshake
    handshake.body = attach.body;
  }

  // add it to the cache

  hcache[id] = (hcache[id] || [] ).concat([handshake]);

  return true;

}

function handshake_types (handshake, id){
  var types = {}
  hcache[id].forEach(function(hs){
    if(hs.json.at === handshake.json.at)
      types[hs.json.type] = hs;
  });
  return types;
}

function handshake_from (handshake, pipe, link){
  return {
    paths    : (pipe.path) ? [pipe.path] : [],
    hashname : link.json.hashname,
    csid     : link.json.csid,
    key      : link.body
  };
}
<commit_msg>add handshake.receive as util<commit_after>var crypto = require('crypto');
var lob = require('lob-enc');
var hashname = require('hashname');

module.exports = {
  bootstrap : handshake_bootstrap,
  validate  : handshake_validate,
  from      : handshake_from,
  types     : handshake_types,
  receive   : handshake_receive,
  Log       : importlog
};
var log = {}
function importlog(l){
  log = l;
}

// cache incoming handshakes to aggregate them
var hcache = {};
setInterval(function hcachet(){hcache={}},60*1000);

function handshake_receive(mesh, packet, pipe){
  var inner = mesh.self.decrypt(packet);
  if(!inner)
  {
    log.debug('message decryption failed',this.self);
    return;
  }
  log.debug('inner',inner.json,inner.body)

  // process the handshake info to find a link
  var token = crypto.createHash('sha256').update(packet.body.slice(0,16)).digest().slice(0,16);
  var link = mesh.handshake(token.toString('hex'), inner, pipe, packet);

  if(!link || !link.x)
    return; // can't respond w/o an exchange

  var atOld = link.x.at();
  var sync = link.x.sync(packet, inner);
  var atNew = link.x.at();
  log.debug('handshake sync',sync,atOld,atNew);

  // always send handshake back if not in sync
  if(!sync) link.x.sending(link.handshake(),pipe);

  // new outgoing sync
  if(atNew > atOld)
  {
    log.debug('new outgoing sync');
    link.syncedAt = Date.now();
  }

  // when in sync or we sent a newer at, trust pipe
  if(atNew >= atOld) link.addPipe(pipe, true);

  // if the senders token changed, we need to reset
  if(link.x.session && link.sid != link.x.session.token.toString('hex'))
  {
    link.sid = link.x.session.token.toString('hex');
    log.debug('new session',link.sid);
    link.x.flush(); // any existing channels can resend
    link.setStatus(); // we're up
  }

}

function handshake_bootstrap(handshake){
  // default an at for bare key handshakes if not given
  if(typeof handshake.json.at === 'undefined')
    handshake.json.at = Date.now();

  // verify at
  if(typeof handshake.json.at != 'number' || handshake.json.at <= 0)
  {
    log.debug('invalid handshake at',handshake.json);
    return false;
  }

  // default the handshake type
  if(typeof handshake.json.type != 'string')
    handshake.json.type = 'link';

  // upvert deprecated key to link type
  if(handshake.json.type == 'key')
  {
    // map only csid keys into attachment header
    var json = {};
    hashname.ids(handshake.json).forEach(function(csid){
      if(handshake.json[csid] === true)
        handshake.json.csid = csid; // cruft
      json[csid] = handshake.json[csid];
    });

    if(message)
      json[message.head.toString('hex')] = true;

    var attach = lob.encode(json, handshake.body);
    handshake.json.type = 'link';
    handshake.body = attach;
  }

  return handshake
}

function handshake_validate(id,handshake, message, mesh){
  if(handshake.json.type == 'link')
  {
    // if it came from an encrypted message
    if(message)
    {
      // make sure the link csid matches the message csid
      handshake.json.csid = message.head.toString('hex');
      // stash inside the handshake, can be used later to create the exchange immediately
      handshake._message = message;
    }

    var attach = lob.decode(handshake.body);
    if(!attach)
    {
      log.debug('invalid link handshake attachment',handshake.body);
      return false;
    }

    // make sure key info is at least correct
    var keys = {};
    keys[handshake.json.csid] = attach.body;
    var csid = hashname.match(mesh.keys, keys, null, attach.json);
    if(handshake.json.csid != csid)
    {
      log.debug('invalid key handshake, unsupported csid',attach.json, keys);
      return false;
    }
    handshake.json.hashname = hashname.fromKeys(keys, attach.json);
    if(!handshake.json.hashname)
    {
      log.debug('invalid key handshake, no hashname',attach.json, keys);
      return false;
    }

    // hashname is valid now, so stash key bytes in handshake
    handshake.body = attach.body;
  }

  // add it to the cache

  hcache[id] = (hcache[id] || [] ).concat([handshake]);

  return true;

}

function handshake_types (handshake, id){
  var types = {}
  hcache[id].forEach(function(hs){
    if(hs.json.at === handshake.json.at)
      types[hs.json.type] = hs;
  });
  return types;
}

function handshake_from (handshake, pipe, link){
  return {
    paths    : (pipe.path) ? [pipe.path] : [],
    hashname : link.json.hashname,
    csid     : link.json.csid,
    key      : link.body
  };
}
<|endoftext|>