<commit_before>/* @flow */

import LiveSet from 'live-set';
import type Scheduler from 'live-set/Scheduler';
import type { TagTree } from 'tag-tree';
import type { TagOptions, Finder } from '.';

import type { ElementContext } from './internalTypes';

export default function watcherFinderMerger(
  scheduler: Scheduler,
  tagTree: TagTree<HTMLElement>,
  tag: string,
  tagOptions: TagOptions,
  watcherSet: ?LiveSet<ElementContext>,
  finder: ?Finder,
  logError: (err: Error, el: ?HTMLElement) => void
): LiveSet<ElementContext> {
  return new LiveSet({
    scheduler,
    read() {
      throw new Error('Should not happen');
    },
    listen(setValues, controller) {
      const currentElements = new Set();
      const currentElementContexts = new Set();
      const watcherFoundElements = new Set();
      const watcherFoundElementsMissedByFinder = new Set();

      let sub = null;
      if (watcherSet) {
        sub = watcherSet.subscribe({
          start() {
            if (!watcherSet) throw new Error();
            const currentValues = watcherSet.values();
            setValues(currentValues);
            currentValues.forEach(ec => {
              watcherFoundElements.add(ec.el);
              currentElements.add(ec.el);
              currentElementContexts.add(ec);
            });
          },
          next(changes) {
            changes.forEach(change => {
              if (change.type === 'add') {
                const { el } = change.value;
                watcherFoundElements.add(el);
                if (currentElements.has(el)) {
                  logError(
                    new Error(
                      `PageParserTree(${tag}) watcher found element already found by finder`
                    ),
                    el
                  );
                } else {
                  currentElements.add(el);
                  currentElementContexts.add(change.value);
                  controller.add(change.value);
                }
              } else if (change.type === 'remove') {
                const { el } = change.value;
                watcherFoundElements.delete(el);
                watcherFoundElementsMissedByFinder.delete(el);
                if (currentElementContexts.has(change.value)) {
                  currentElements.delete(el);
                  currentElementContexts.delete(change.value);
                  controller.remove(change.value);
                } // else the ec was added by finder and it will deal with this
              }
            });
          },
          error(err) {
            controller.error(err);
          },
          complete() {
            controller.end();
          }
        });
      } else {
        setValues(new Set());
      }

      let finderSchedule = null;

      if (finder) {
        const { fn, interval } = finder;
        const ownedBy = tagOptions.ownedBy || [];

        const runFinder = () => {
          const finderRunFoundElements = new Set();
          const found = fn(tagTree.getValue());
          for (let i = 0, len = found.length; i < len; i++) {
            const el = found[i];
            finderRunFoundElements.add(el);
            if (!currentElements.has(el)) {
              currentElements.add(el);
              const ec = makeElementContext(el, tagTree, ownedBy);
              currentElementContexts.add(ec);
              controller.add(ec);
              if (watcherSet) {
                logError(
                  new Error(
                    `PageParserTree(${tag}) finder found element missed by watcher`
                  ),
                  el
                );
                if (sub) sub.pullChanges();
              }
            }
          }

          currentElementContexts.forEach(ec => {
            const { el } = ec;
            if (!finderRunFoundElements.has(el)) {
              if (watcherFoundElements.has(el)) {
                if (!watcherFoundElementsMissedByFinder.has(el)) {
                  watcherFoundElementsMissedByFinder.add(el);
                  logError(
                    new Error(
                      `PageParserTree(${tag}) watcher found element missed by finder`
                    ),
                    el
                  );
                }
              } else {
                currentElementContexts.delete(ec);
                currentElements.delete(el);
                controller.remove(ec);
                if (sub) sub.pullChanges();
              }
            }
          });

          scheduler.flush();
        };

        finderSchedule = scheduleRepeatingFinder(
          interval,
          currentElements,
          runFinder
        );
      }

      return {
        unsubscribe() {
          if (finderSchedule != null) finderSchedule.dispose();
          if (sub) sub.unsubscribe();
        },
        pullChanges() {
          if (sub) sub.pullChanges();
        }
      };
    }
  });
}

function scheduleRepeatingFinder(
  interval: $PropertyType<Finder, 'interval'>,
  currentElements: Set<any>,
  runFinder: () => void
): { dispose: () => void } {
  const finderStartedTimestamp = Date.now();

  let timeoutHandle = null;
  let idleHandle = null;

  const step = () => {
    runFinder();
    scheduleNextStep();
  };

  const scheduleNextStep = () => {
    let time;
    if (interval == null) {
      time = 5000 + Math.random() * 1000;
    } else if (typeof interval === 'number') {
      time = interval;
    } else if (typeof interval === 'function') {
      time = interval(
        currentElements.size,
        Date.now() - finderStartedTimestamp
      );
    } else {
      throw new Error(`interval has wrong type: ${typeof interval}`);
    }

    timeoutHandle = setTimeout(() => {
      if (global.requestIdleCallback && global.cancelIdleCallback) {
        // Wait up to `time` milliseconds again until there's an idle moment.
        idleHandle = global.requestIdleCallback(step, {
          timeout: time
        });
      } else {
        step();
      }
    }, time);
  };

  scheduleNextStep();

  return {
    dispose() {
      if (timeoutHandle != null) clearTimeout(timeoutHandle);
      if (idleHandle != null) global.cancelIdleCallback(idleHandle);
    }
  };
}

function makeElementContext(
  el: HTMLElement,
  tagTree: TagTree<HTMLElement>,
  ownedBy: string[]
): ElementContext {
  // Don't compute parents until it's read from.
  // This is important because nodes aren't added to the tag tree until
  // PageParserTree iterates over the results, and some of these nodes may be
  // owned by each other.
  let _cachedParents = null;
  return {
    el,
    get parents() {
      if (!_cachedParents) {
        const root = tagTree.getValue();
        const parents = [];

        let current = el.parentElement;
        while (current) {
          const tagTreeNodes = tagTree.getNodesForValue((current: any));
          for (let i = 0, len = tagTreeNodes.length; i < len; i++) {
            const node = tagTreeNodes[i];
            const tag = node.getTag();
            if (tag == null || ownedBy.indexOf(tag) >= 0) {
              parents.push({ tag, node });
              break;
            }
          }

          if (current === root) break;
          current = current.parentElement;
        }

        parents.reverse();

        _cachedParents = parents;
      }
      return _cachedParents;
    }
  };
}
<commit_msg>Clear timeoutHandle and idleHandle when they don't represent a current timer.<commit_after>/* @flow */

import LiveSet from 'live-set';
import type Scheduler from 'live-set/Scheduler';
import type { TagTree } from 'tag-tree';
import type { TagOptions, Finder } from '.';

import type { ElementContext } from './internalTypes';

export default function watcherFinderMerger(
  scheduler: Scheduler,
  tagTree: TagTree<HTMLElement>,
  tag: string,
  tagOptions: TagOptions,
  watcherSet: ?LiveSet<ElementContext>,
  finder: ?Finder,
  logError: (err: Error, el: ?HTMLElement) => void
): LiveSet<ElementContext> {
  return new LiveSet({
    scheduler,
    read() {
      throw new Error('Should not happen');
    },
    listen(setValues, controller) {
      const currentElements = new Set();
      const currentElementContexts = new Set();
      const watcherFoundElements = new Set();
      const watcherFoundElementsMissedByFinder = new Set();

      let sub = null;
      if (watcherSet) {
        sub = watcherSet.subscribe({
          start() {
            if (!watcherSet) throw new Error();
            const currentValues = watcherSet.values();
            setValues(currentValues);
            currentValues.forEach(ec => {
              watcherFoundElements.add(ec.el);
              currentElements.add(ec.el);
              currentElementContexts.add(ec);
            });
          },
          next(changes) {
            changes.forEach(change => {
              if (change.type === 'add') {
                const { el } = change.value;
                watcherFoundElements.add(el);
                if (currentElements.has(el)) {
                  logError(
                    new Error(
                      `PageParserTree(${tag}) watcher found element already found by finder`
                    ),
                    el
                  );
                } else {
                  currentElements.add(el);
                  currentElementContexts.add(change.value);
                  controller.add(change.value);
                }
              } else if (change.type === 'remove') {
                const { el } = change.value;
                watcherFoundElements.delete(el);
                watcherFoundElementsMissedByFinder.delete(el);
                if (currentElementContexts.has(change.value)) {
                  currentElements.delete(el);
                  currentElementContexts.delete(change.value);
                  controller.remove(change.value);
                } // else the ec was added by finder and it will deal with this
              }
            });
          },
          error(err) {
            controller.error(err);
          },
          complete() {
            controller.end();
          }
        });
      } else {
        setValues(new Set());
      }

      let finderSchedule = null;

      if (finder) {
        const { fn, interval } = finder;
        const ownedBy = tagOptions.ownedBy || [];

        const runFinder = () => {
          const finderRunFoundElements = new Set();
          const found = fn(tagTree.getValue());
          for (let i = 0, len = found.length; i < len; i++) {
            const el = found[i];
            finderRunFoundElements.add(el);
            if (!currentElements.has(el)) {
              currentElements.add(el);
              const ec = makeElementContext(el, tagTree, ownedBy);
              currentElementContexts.add(ec);
              controller.add(ec);
              if (watcherSet) {
                logError(
                  new Error(
                    `PageParserTree(${tag}) finder found element missed by watcher`
                  ),
                  el
                );
                if (sub) sub.pullChanges();
              }
            }
          }

          currentElementContexts.forEach(ec => {
            const { el } = ec;
            if (!finderRunFoundElements.has(el)) {
              if (watcherFoundElements.has(el)) {
                if (!watcherFoundElementsMissedByFinder.has(el)) {
                  watcherFoundElementsMissedByFinder.add(el);
                  logError(
                    new Error(
                      `PageParserTree(${tag}) watcher found element missed by finder`
                    ),
                    el
                  );
                }
              } else {
                currentElementContexts.delete(ec);
                currentElements.delete(el);
                controller.remove(ec);
                if (sub) sub.pullChanges();
              }
            }
          });

          scheduler.flush();
        };

        finderSchedule = scheduleRepeatingFinder(
          interval,
          currentElements,
          runFinder
        );
      }

      return {
        unsubscribe() {
          if (finderSchedule != null) finderSchedule.dispose();
          if (sub) sub.unsubscribe();
        },
        pullChanges() {
          if (sub) sub.pullChanges();
        }
      };
    }
  });
}

function scheduleRepeatingFinder(
  interval: $PropertyType<Finder, 'interval'>,
  currentElements: Set<any>,
  runFinder: () => void
): { dispose: () => void } {
  const finderStartedTimestamp = Date.now();

  let timeoutHandle = null;
  let idleHandle = null;

  const step = () => {
    idleHandle = null;
    runFinder();
    scheduleNextStep();
  };

  const scheduleNextStep = () => {
    let time;
    if (interval == null) {
      time = 5000 + Math.random() * 1000;
    } else if (typeof interval === 'number') {
      time = interval;
    } else if (typeof interval === 'function') {
      time = interval(
        currentElements.size,
        Date.now() - finderStartedTimestamp
      );
    } else {
      throw new Error(`interval has wrong type: ${typeof interval}`);
    }

    timeoutHandle = setTimeout(() => {
      timeoutHandle = null;
      if (global.requestIdleCallback && global.cancelIdleCallback) {
        // Wait up to `time` milliseconds again until there's an idle moment.
        idleHandle = global.requestIdleCallback(step, {
          timeout: time
        });
      } else {
        step();
      }
    }, time);
  };

  scheduleNextStep();

  return {
    dispose() {
      if (timeoutHandle != null) clearTimeout(timeoutHandle);
      if (idleHandle != null) global.cancelIdleCallback(idleHandle);
    }
  };
}

function makeElementContext(
  el: HTMLElement,
  tagTree: TagTree<HTMLElement>,
  ownedBy: string[]
): ElementContext {
  // Don't compute parents until it's read from.
  // This is important because nodes aren't added to the tag tree until
  // PageParserTree iterates over the results, and some of these nodes may be
  // owned by each other.
  let _cachedParents = null;
  return {
    el,
    get parents() {
      if (!_cachedParents) {
        const root = tagTree.getValue();
        const parents = [];

        let current = el.parentElement;
        while (current) {
          const tagTreeNodes = tagTree.getNodesForValue((current: any));
          for (let i = 0, len = tagTreeNodes.length; i < len; i++) {
            const node = tagTreeNodes[i];
            const tag = node.getTag();
            if (tag == null || ownedBy.indexOf(tag) >= 0) {
              parents.push({ tag, node });
              break;
            }
          }

          if (current === root) break;
          current = current.parentElement;
        }

        parents.reverse();

        _cachedParents = parents;
      }
      return _cachedParents;
    }
  };
}
<|endoftext|>


<commit_before>/*
 *
 */
"use strict";

goog.provide("Entry.Workspace");

goog.require("Entry.Model");
goog.require("Entry.FieldTrashcan");
goog.require("Entry.TextCodingUtil");

Entry.Workspace = function(options) {
    Entry.Model(this, false);

    this.dSetMode = Entry.Utils.debounce(this.setMode, 200);

    this.observe(this, "_handleChangeBoard", ["selectedBoard"], false);
    this.trashcan = new Entry.FieldTrashcan();

    var option = options.blockMenu;
    if (option) {
        this.blockMenu = new Entry.BlockMenu(
            option.dom,
            option.align,
            option.categoryData,
            option.scroll
        );
        this.blockMenu.workspace = this;
        this.blockMenu.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
    }

    option = options.board;
    if (option) {
        option.workspace = this;
        this.board = new Entry.Board(option);
        this.board.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
        this.set({selectedBoard:this.board});
    }

    option = options.vimBoard;
    if (option) {
        this.vimBoard = new Entry.Vim(option.dom);
        this.vimBoard.workspace = this;
    }

    if (this.board && this.vimBoard)
        this.vimBoard.hide();

    Entry.GlobalSvg.createDom();

    this.mode = Entry.Workspace.MODE_BOARD;

    if (Entry.keyPressed)
        Entry.keyPressed.attach(this, this._keyboardControl);

    // view state change event
    this.changeEvent = new Entry.Event(this);

    Entry.commander.setCurrentEditor("board", this.board);

    if (options.textType !== undefined)
        this.textType = options.textType;
    else this.textType = Entry.Vim.TEXT_TYPE_PY;

    this.oldMode = Entry.Workspace.MODE_BOARD;
    this.mode = Entry.Workspace.MODE_BOARD;
};

Entry.Workspace.MODE_BOARD = 0;
Entry.Workspace.MODE_VIMBOARD = 1;
Entry.Workspace.MODE_OVERLAYBOARD = 2;

(function(p) {
    p.schema = {
        selectedBlockView: null,
        selectedBoard: null
    };

    p.getBoard = function(){return this.board;};

    p.getSelectedBoard = function(){return this.selectedBoard;};

    p.getBlockMenu = function(){return this.blockMenu;};

    p.getVimBoard = function(){return this.vimBoard;};

    p.getMode = function() {return this.mode;};

    p.setMode = function(mode, message) {
        if (!isNaN(mode)) this.mode = mode;
        else {
            this.mode = mode.boardType;
            this.runType = mode.runType;
            this.textType = mode.textType;
        }

        this.mode = Number(this.mode);
        if (this.oldMode === this.mode)
            return;

        var VIM = Entry.Vim,
            WORKSPACE = Entry.Workspace,
            blockMenu = this.blockMenu;

        switch (this.mode) {
            case WORKSPACE.MODE_VIMBOARD:
                    if(alert_message = Entry.TextCodingUtil.isNamesIncludeSpace()) {
                        alert(alert_message);
                        var mode = {};
                        mode.boardType = WORKSPACE.MODE_BOARD;
                        mode.textType = -1;
                        Entry.getMainWS().setMode(mode);
                        break;
                    }
                    if (this.board) this.board.hide();
                    if (this.overlayBoard) this.overlayBoard.hide();
                    blockMenu.banClass('functionInit');
                    this.set({selectedBoard:this.vimBoard});
                    this.vimBoard.show();
                    this.initDeclaration();
                    this.codeToText(this.board.code, mode);
                    blockMenu.renderText();
                    this.board.clear();
                    this.oldTextType = this.textType;
                    //destroy view because of performance
                break;
            case WORKSPACE.MODE_BOARD:
                try {
                    this.board.show();
                    blockMenu.unbanClass('functionInit');
                    this.set({selectedBoard:this.board});
                    this.textToCode(this.oldMode, this.oldTextType);
                    if (this.overlayBoard)
                        this.overlayBoard.hide();
                    blockMenu.renderBlock();
                    this.oldTextType = this.textType;
                    this.vimBoard && this.vimBoard.hide();
                    this.vimBoard._parser._isError = false;
                } catch(e) {
                    this.vimBoard._parser._isError = true;
                    if(this.board && this.board.code)
                        this.board.code.clear();
                    if (this.board) this.board.hide();
                    this.set({selectedBoard:this.vimBoard});
                    blockMenu.banClass('functionInit');
                    this.mode = WORKSPACE.MODE_VIMBOARD;

                    //console.log(("this.oldTextType", this.oldTextType);

                    if(this.oldTextType == VIM.TEXT_TYPE_JS) {
                        mode.boardType = WORKSPACE.MODE_VIMBOARD;
                        mode.textType = VIM.TEXT_TYPE_JS;
                        mode.runType = VIM.MAZE_MODE;
                        this.oldTextType = VIM.TEXT_TYPE_JS;
                    } else if(this.oldTextType == VIM.TEXT_TYPE_PY) {
                        mode.boardType = WORKSPACE.MODE_VIMBOARD;
                        mode.textType = VIM.TEXT_TYPE_PY;
                        mode.runType = VIM.WORKSPACE_MODE;
                        this.oldTextType = VIM.TEXT_TYPE_PY;
                        //console.log(("mode", mode);
                    }
                    Entry.getMainWS().setMode(mode);

                    //throw e;
                }
                Entry.commander.setCurrentEditor("board", this.board);
                break;

            case WORKSPACE.MODE_OVERLAYBOARD:
                if (!this.overlayBoard)
                    this.initOverlayBoard();
                this.overlayBoard.show();
                this.set({selectedBoard:this.overlayBoard});
                Entry.commander.setCurrentEditor("board", this.overlayBoard);
                break;
        }

        this.oldMode = this.mode;

        Entry.dispatchEvent('workspaceChangeMode');
        this.changeEvent.notify(message);
    };

    p.changeBoardCode = function(code, cb) {
        this._syncTextCode();
        var isVim = this.mode === Entry.Workspace.MODE_VIMBOARD;
        this.board.changeCode(code, isVim, cb);
        if (isVim) {
            var mode = {};
            mode.textType = this.textType;
            mode.boardType = this.boardType;
            mode.runType = this.runType;
            this.codeToText(this.board.code, mode);
        }
    };

    p.changeOverlayBoardCode = function(code) {
        if (this.overlayBoard)
            this.overlayBoard.changeCode(code);
    };

    p.changeBlockMenuCode = function(code) {
        this.blockMenu.changeCode(code);
    };

    p.textToCode = function(mode, oldTextType) {
        if (!this.vimBoard || mode !== Entry.Workspace.MODE_VIMBOARD)
            return;

        var changedCode = this.vimBoard.textToCode(oldTextType);

        var board = this.board;
        var code = board.code;
        code.load(changedCode);
        this.changeBoardCode(code);
        setTimeout(function() {
            if (code.view) {
                code.view.reDraw();
                this.board.alignThreads();
            }
        }.bind(this), 0);
    };

    p.loadCodeFromText = function(mode) {
        if (!this.vimBoard || mode != Entry.Workspace.MODE_VIMBOARD)
            return;
        var changedCode = this.vimBoard.textToCode(this.textType);
        var board = this.board;
        var code = board.code;
        code.load(changedCode);
    };

    p.codeToText = function(code, mode) {
        if (!this.vimBoard)
            return;
        this.initDeclaration();
        return this.vimBoard.codeToText(code, mode);

    };

    p.getCodeToText = function(code) {
        if (!this.vimBoard) return;

        return this.vimBoard.getCodeToText(code);
    };

    p._setSelectedBlockView = function() {
        var view = 'selectedBlockView';
        var blockView = this.board[view] ||
            this.blockMenu[view] ||
            (this.overlayBoard ? this.overlayBoard[view] : null);
        this.set({selectedBlockView:blockView});
    };

    p.initOverlayBoard = function() {
        this.overlayBoard = new Entry.Board({
            dom: this.board.view,
            workspace: this,
            isOverlay: true
        });
        this.overlayBoard.changeCode(new Entry.Code([]));
        this.overlayBoard.workspace = this;
        this.overlayBoard.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
    };

    p._keyboardControl = function(e, isForce) {
        var keyCode = e.keyCode || e.which,
            ctrlKey = e.ctrlKey, shiftKey = e.shiftKey, altKey = e.altKey;
        var playground = Entry.playground;

        if (Entry.Utils.isInInput(e) && !isForce)
            return;

        var isVimMode = this._isVimMode();

        var blockView = this.selectedBlockView;

        if (ctrlKey) {
            switch (keyCode) {
                case 86:  //paste
                    var board = this.selectedBoard;
                    if (board && board instanceof Entry.Board && Entry.clipboard)
                        Entry.do('addThread', Entry.clipboard).value
                            .getFirstBlock().copyToClipboard();
                    break;
                case 219: //setMode(block) for textcoding
                    if (playground && !playground.object) {
                        if (isVimMode) {
                            var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                            alert(message);
                            return;
                        }
                    }

                    var oldMode = Entry.getMainWS().oldMode;
                    if(oldMode == Entry.Workspace.MODE_OVERLAYBOARD)
                        return;

                    var message = Entry.TextCodingUtil.isNamesIncludeSpace()
                    if(message) {
                        alert(message);
                        return;
                    }

                    this.dSetMode({
                        boardType : Entry.Workspace.MODE_BOARD,
                        textType : -1
                    });
                    e.preventDefault();
                    break;
                case 221: //setMode(python) for textcoding
                    if (playground && !playground.object) {
                        if (this.oldMode === Entry.Workspace.MODE_BOARD) {
                            var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                            alert(message);
                            return;
                        }
                    }

                    var message;
                    message = Entry.TextCodingUtil.canConvertTextModeForOverlayMode(Entry.Workspace.MODE_VIMBOARD);
                    if(message) {
                        alert(message);
                        return;
                    }

                    var message = Entry.TextCodingUtil.isNamesIncludeSpace()
                    if(message) {
                        alert(message);
                        return;
                    }

                    this.dSetMode({
                        boardType : Entry.Workspace.MODE_VIMBOARD,
                        textType : Entry.Vim.TEXT_TYPE_PY,
                        runType : Entry.Vim.WORKSPACE_MODE
                    });
                    e.preventDefault();
                    break;
                case 67:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        blockView.block.copyToClipboard();
                    }
                    break;
                case 88:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        (function(block) {
                            block.copyToClipboard();
                            block.destroy(true, true);
                            blockView.getBoard().setSelectedBlock(null);
                        })(blockView.block);
                    }
                    break;
            }
        } else if (altKey) {
            if (playground && !playground.object) {
                var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                alert(message);
                return;
            }

            switch (keyCode) {
                case 49:
                    playground.changeViewMode('code');
                    e.preventDefault();
                    break;
                case 50:
                    playground.changeViewMode('picture');
                    e.preventDefault();
                    break;
                case 51:
                    playground.changeViewMode('sound');
                    e.preventDefault();
                    break;
                case 52:
                    playground.toggleOnVariableView();
                    playground.changeViewMode('variable');
                    e.preventDefault();
                    break;
                case 219:
                    if (Entry.container) {
                        e.preventDefault();
                        Entry.container.selectNeighborObject('prev');
                    }
                    break;
                case 221:
                    if (Entry.container) {
                        e.preventDefault();
                        Entry.container.selectNeighborObject('next');
                    }
                    break;
            }
        } else if (shiftKey) {
            switch (keyCode) {
                case 9:
                    if (isVimMode) {
                        CodeMirror.commands.indentLess(this.vimBoard.codeMirror);
                        e.preventDefault();
                    }
                    break;
            }
        } else {
            switch (keyCode) {
                case 9:
                    if (isVimMode) {
                        CodeMirror.commands.indentMore(this.vimBoard.codeMirror);
                        e.preventDefault();
                    }
                    break;
                case 8:
                case 46:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        Entry.do("destroyBlock", blockView.block);
                        e.preventDefault();
                    }
                    break;
            }
        }

        //delay for fields value applied
        setTimeout(function() {
            Entry.disposeEvent && Entry.disposeEvent.notify(e);
        }, 0);
    };

    p._handleChangeBoard = function() {
        var board = this.selectedBoard;
        if (!board) return;
        if (board.constructor === Entry.Board)
            this.trashcan.setBoard(board);
    };

    p._syncTextCode = function() {
        if (this.mode !== Entry.Workspace.MODE_VIMBOARD)
            return;

        var changedCode = this.vimBoard.textToCode(this.textType);
        var board = this.board;
        var code = board.code;
        if (code) code.load(changedCode);
    };

    p.addVimBoard = function(dom) {
        if (this.vimBoard) return;
        this.vimBoard = new Entry.Vim(dom);
        this.vimBoard.workspace = this;
        this.vimBoard.hide();
    };

    p.getParserType = function() {
        return this.vimBoard._parserType;
    };

    p.getBlockViewRenderMode = function() {
        switch (this.mode) {
            case Entry.Workspace.MODE_BOARD:
            case Entry.Workspace.MODE_OVERLAYBOARD:
                return Entry.BlockView.RENDER_MODE_BLOCK;
            case Entry.Workspace.MODE_VIMBOARD:
                return Entry.BlockView.RENDER_MODE_TEXT;
        }
    };

    p._isVimMode = function() {
        return this.oldMode === Entry.Workspace.MODE_VIMBOARD;
    };

    p.initDeclaration = function() {
        if(this.vimBoard && this.vimBoard._parser) {
            var parser = this.vimBoard._parser;
            parser.py_variableDeclaration = null;
            parser.py_listDeclaration = null;
            parser.py_funcDeclaration = null;
        }
    }

})(Entry.Workspace.prototype);
<commit_msg>doing something<commit_after>/*
 *
 */
"use strict";

goog.provide("Entry.Workspace");

goog.require("Entry.Model");
goog.require("Entry.FieldTrashcan");
goog.require("Entry.TextCodingUtil");

Entry.Workspace = function(options) {
    Entry.Model(this, false);

    this.dSetMode = Entry.Utils.debounce(this.setMode, 200);

    this.observe(this, "_handleChangeBoard", ["selectedBoard"], false);
    this.trashcan = new Entry.FieldTrashcan();

    var option = options.blockMenu;
    if (option) {
        this.blockMenu = new Entry.BlockMenu(
            option.dom,
            option.align,
            option.categoryData,
            option.scroll
        );
        this.blockMenu.workspace = this;
        this.blockMenu.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
    }

    option = options.board;
    if (option) {
        option.workspace = this;
        this.board = new Entry.Board(option);
        this.board.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
        this.set({selectedBoard:this.board});
    }

    option = options.vimBoard;
    if (option) {
        this.vimBoard = new Entry.Vim(option.dom);
        this.vimBoard.workspace = this;
    }

    if (this.board && this.vimBoard)
        this.vimBoard.hide();

    Entry.GlobalSvg.createDom();

    this.mode = Entry.Workspace.MODE_BOARD;

    if (Entry.keyPressed)
        Entry.keyPressed.attach(this, this._keyboardControl);

    // view state change event
    this.changeEvent = new Entry.Event(this);

    Entry.commander.setCurrentEditor("board", this.board);

    if (options.textType !== undefined)
        this.textType = options.textType;
    else this.textType = Entry.Vim.TEXT_TYPE_PY;

    this.oldMode = Entry.Workspace.MODE_BOARD;
    this.mode = Entry.Workspace.MODE_BOARD;
};

Entry.Workspace.MODE_BOARD = 0;
Entry.Workspace.MODE_VIMBOARD = 1;
Entry.Workspace.MODE_OVERLAYBOARD = 2;

(function(p) {
    p.schema = {
        selectedBlockView: null,
        selectedBoard: null
    };

    p.getBoard = function(){return this.board;};

    p.getSelectedBoard = function(){return this.selectedBoard;};

    p.getBlockMenu = function(){return this.blockMenu;};

    p.getVimBoard = function(){return this.vimBoard;};

    p.getMode = function() {return this.mode;};

    p.setMode = function(mode, message) {
        if (!isNaN(mode)) this.mode = mode;
        else {
            this.mode = mode.boardType;
            this.runType = mode.runType;
            this.textType = mode.textType;
        }

        this.mode = Number(this.mode);
        if (this.oldMode === this.mode)
            return;

        var VIM = Entry.Vim,
            WORKSPACE = Entry.Workspace,
            blockMenu = this.blockMenu;

        switch (this.mode) {
            case WORKSPACE.MODE_VIMBOARD:
                    if(alert_message = Entry.TextCodingUtil.isNamesIncludeSpace()) {
                        alert(alert_message);
                        var mode = {};
                        mode.boardType = WORKSPACE.MODE_BOARD;
                        mode.textType = -1;
                        Entry.getMainWS().setMode(mode);
                        break;
                    }
                    if (this.board) this.board.hide();
                    if (this.overlayBoard) this.overlayBoard.hide();
                    blockMenu.banClass('functionInit');
                    this.set({selectedBoard:this.vimBoard});
                    this.vimBoard.show();
                    this.initDeclaration();
                    this.codeToText(this.board.code, mode);
                    blockMenu.renderText();
                    this.board.clear();
                    this.oldTextType = this.textType;
                    //destroy view because of performance
                break;
            case WORKSPACE.MODE_BOARD:
                try {
                    this.board.show();
                    blockMenu.unbanClass('functionInit');
                    this.set({selectedBoard:this.board});
                    this.textToCode(this.oldMode, this.oldTextType);
                    if (this.overlayBoard)
                        this.overlayBoard.hide();
                    blockMenu.renderBlock();
                    this.oldTextType = this.textType;
                    this.vimBoard && this.vimBoard.hide();
                    this.vimBoard._parser._isError = false;
                } catch(e) {
                    this.vimBoard._parser._isError = true;
                    if(this.board && this.board.code)
                        this.board.code.clear();
                    if (this.board) this.board.hide();
                    this.set({selectedBoard:this.vimBoard});
                    blockMenu.banClass('functionInit');
                    this.mode = WORKSPACE.MODE_VIMBOARD;

                    //console.log(("this.oldTextType", this.oldTextType);

                    if(this.oldTextType == VIM.TEXT_TYPE_JS) {
                        mode.boardType = WORKSPACE.MODE_VIMBOARD;
                        mode.textType = VIM.TEXT_TYPE_JS;
                        mode.runType = VIM.MAZE_MODE;
                        this.oldTextType = VIM.TEXT_TYPE_JS;
                    } else if(this.oldTextType == VIM.TEXT_TYPE_PY) {
                        mode.boardType = WORKSPACE.MODE_VIMBOARD;
                        mode.textType = VIM.TEXT_TYPE_PY;
                        mode.runType = VIM.WORKSPACE_MODE;
                        this.oldTextType = VIM.TEXT_TYPE_PY;
                        //console.log(("mode", mode);
                    }
                    Entry.getMainWS().setMode(mode);

                    //throw e;
                }
                Entry.commander.setCurrentEditor("board", this.board);
                break;

            case WORKSPACE.MODE_OVERLAYBOARD:
                if (!this.overlayBoard)
                    this.initOverlayBoard();
                this.overlayBoard.show();
                this.set({selectedBoard:this.overlayBoard});
                Entry.commander.setCurrentEditor("board", this.overlayBoard);
                break;
        }

        this.oldMode = this.mode;

        Entry.dispatchEvent('workspaceChangeMode');
        this.changeEvent.notify(message);
    };

    p.changeBoardCode = function(code, cb) {
        this._syncTextCode();
        var isVim = this.mode === Entry.Workspace.MODE_VIMBOARD;
        this.board.changeCode(code, isVim, cb);
        if (isVim) {
            var mode = {};
            mode.textType = this.textType;
            mode.boardType = this.boardType;
            mode.runType = this.runType;
            this.codeToText(this.board.code, mode);
        }
    };

    p.changeOverlayBoardCode = function(code) {
        if (this.overlayBoard)
            this.overlayBoard.changeCode(code);
    };

    p.changeBlockMenuCode = function(code) {
        this.blockMenu.changeCode(code);
    };

    p.textToCode = function(mode, oldTextType) {
        if (!this.vimBoard || mode !== Entry.Workspace.MODE_VIMBOARD)
            return;

        var changedCode = this.vimBoard.textToCode(oldTextType);

        var board = this.board;
        var code = board.code;
        code.load(changedCode);
        this.changeBoardCode(code);
        setTimeout(function() {
            if (code.view) {
                code.view.reDraw();
                this.board.alignThreads();
            }
        }.bind(this), 0);
    };

    /*p.loadCodeFromText = function(mode) {
        if (!this.vimBoard || mode != Entry.Workspace.MODE_VIMBOARD)
            return;
        var changedCode = this.vimBoard.(this.textType);
        var board = this.board;
        var code = board.code;
        code.load(changedCode);
    };*/

    p.codeToText = function(code, mode) {
        if (!this.vimBoard)
            return;
        this.initDeclaration();
        return this.vimBoard.codeToText(code, mode);

    };

    p.getCodeToText = function(code) {
        if (!this.vimBoard) return;

        return this.vimBoard.getCodeToText(code);
    };

    p._setSelectedBlockView = function() {
        var view = 'selectedBlockView';
        var blockView = this.board[view] ||
            this.blockMenu[view] ||
            (this.overlayBoard ? this.overlayBoard[view] : null);
        this.set({selectedBlockView:blockView});
    };

    p.initOverlayBoard = function() {
        this.overlayBoard = new Entry.Board({
            dom: this.board.view,
            workspace: this,
            isOverlay: true
        });
        this.overlayBoard.changeCode(new Entry.Code([]));
        this.overlayBoard.workspace = this;
        this.overlayBoard.observe(this, "_setSelectedBlockView", ["selectedBlockView"], false);
    };

    p._keyboardControl = function(e, isForce) {
        var keyCode = e.keyCode || e.which,
            ctrlKey = e.ctrlKey, shiftKey = e.shiftKey, altKey = e.altKey;
        var playground = Entry.playground;

        if (Entry.Utils.isInInput(e) && !isForce)
            return;

        var isVimMode = this._isVimMode();

        var blockView = this.selectedBlockView;

        if (ctrlKey) {
            switch (keyCode) {
                case 86:  //paste
                    var board = this.selectedBoard;
                    if (board && board instanceof Entry.Board && Entry.clipboard)
                        Entry.do('addThread', Entry.clipboard).value
                            .getFirstBlock().copyToClipboard();
                    break;
                case 219: //setMode(block) for textcoding
                    if (playground && !playground.object) {
                        if (isVimMode) {
                            var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                            alert(message);
                            return;
                        }
                    }

                    var oldMode = Entry.getMainWS().oldMode;
                    if(oldMode == Entry.Workspace.MODE_OVERLAYBOARD)
                        return;

                    var message = Entry.TextCodingUtil.isNamesIncludeSpace()
                    if(message) {
                        alert(message);
                        return;
                    }

                    this.dSetMode({
                        boardType : Entry.Workspace.MODE_BOARD,
                        textType : -1
                    });
                    e.preventDefault();
                    break;
                case 221: //setMode(python) for textcoding
                    if (playground && !playground.object) {
                        if (this.oldMode === Entry.Workspace.MODE_BOARD) {
                            var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                            alert(message);
                            return;
                        }
                    }

                    var message;
                    message = Entry.TextCodingUtil.canConvertTextModeForOverlayMode(Entry.Workspace.MODE_VIMBOARD);
                    if(message) {
                        alert(message);
                        return;
                    }

                    var message = Entry.TextCodingUtil.isNamesIncludeSpace()
                    if(message) {
                        alert(message);
                        return;
                    }

                    this.dSetMode({
                        boardType : Entry.Workspace.MODE_VIMBOARD,
                        textType : Entry.Vim.TEXT_TYPE_PY,
                        runType : Entry.Vim.WORKSPACE_MODE
                    });
                    e.preventDefault();
                    break;
                case 67:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        blockView.block.copyToClipboard();
                    }
                    break;
                case 88:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        (function(block) {
                            block.copyToClipboard();
                            block.destroy(true, true);
                            blockView.getBoard().setSelectedBlock(null);
                        })(blockView.block);
                    }
                    break;
            }
        } else if (altKey) {
            if (playground && !playground.object) {
                var message = "오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.";
                alert(message);
                return;
            }

            switch (keyCode) {
                case 49:
                    playground.changeViewMode('code');
                    e.preventDefault();
                    break;
                case 50:
                    playground.changeViewMode('picture');
                    e.preventDefault();
                    break;
                case 51:
                    playground.changeViewMode('sound');
                    e.preventDefault();
                    break;
                case 52:
                    playground.toggleOnVariableView();
                    playground.changeViewMode('variable');
                    e.preventDefault();
                    break;
                case 219:
                    if (Entry.container) {
                        e.preventDefault();
                        Entry.container.selectNeighborObject('prev');
                    }
                    break;
                case 221:
                    if (Entry.container) {
                        e.preventDefault();
                        Entry.container.selectNeighborObject('next');
                    }
                    break;
            }
        } else if (shiftKey) {
            switch (keyCode) {
                case 9:
                    if (isVimMode) {
                        CodeMirror.commands.indentLess(this.vimBoard.codeMirror);
                        e.preventDefault();
                    }
                    break;
            }
        } else {
            switch (keyCode) {
                case 9:
                    if (isVimMode) {
                        CodeMirror.commands.indentMore(this.vimBoard.codeMirror);
                        e.preventDefault();
                    }
                    break;
                case 8:
                case 46:
                    if (blockView && !blockView.isInBlockMenu && blockView.block.isDeletable()) {
                        Entry.do("destroyBlock", blockView.block);
                        e.preventDefault();
                    }
                    break;
            }
        }

        //delay for fields value applied
        setTimeout(function() {
            Entry.disposeEvent && Entry.disposeEvent.notify(e);
        }, 0);
    };

    p._handleChangeBoard = function() {
        var board = this.selectedBoard;
        if (!board) return;
        if (board.constructor === Entry.Board)
            this.trashcan.setBoard(board);
    };

    p._syncTextCode = function() {
        if (this.mode !== Entry.Workspace.MODE_VIMBOARD)
            return;

        var changedCode = this.vimBoard.textToCode(this.textType);
        var board = this.board;
        var code = board.code;
        if (code) code.load(changedCode);
    };

    p.addVimBoard = function(dom) {
        if (this.vimBoard) return;
        this.vimBoard = new Entry.Vim(dom);
        this.vimBoard.workspace = this;
        this.vimBoard.hide();
    };

    p.getParserType = function() {
        return this.vimBoard._parserType;
    };

    p.getBlockViewRenderMode = function() {
        switch (this.mode) {
            case Entry.Workspace.MODE_BOARD:
            case Entry.Workspace.MODE_OVERLAYBOARD:
                return Entry.BlockView.RENDER_MODE_BLOCK;
            case Entry.Workspace.MODE_VIMBOARD:
                return Entry.BlockView.RENDER_MODE_TEXT;
        }
    };

    p._isVimMode = function() {
        return this.oldMode === Entry.Workspace.MODE_VIMBOARD;
    };

    p.initDeclaration = function() {
        if(this.vimBoard && this.vimBoard._parser) {
            var parser = this.vimBoard._parser;
            parser.py_variableDeclaration = null;
            parser.py_listDeclaration = null;
            parser.py_funcDeclaration = null;
        }
    }

})(Entry.Workspace.prototype);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict';

require.config({
  shim: {
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: [
        'underscore',
        'jquery'
      ],
      exports: 'Backbone'
    }
  },
  paths: {
    jquery: '../bower_components/jquery/dist/jquery',
    backbone: '../bower_components/backbone/backbone',
    underscore: '../bower_components/underscore/underscore',
    text: '../bower_components/requirejs-text/text',
    mustache: '../bower_components/mustache/mustache',
    stache: '../bower_components/requirejs-mustache/stache'
  }
});

require([
  'jquery',
  'backbone',
  'router',
  'collections/devices'
], function ($, Backbone, Router, Devices) {
  // Bring on the globals
  window.devices = new Devices();

  // Fetch devices from the server
  window.devices.fetch().then(function () {
    // Now that we have devices we can start
    Backbone.history.start();
  });

  // Temporary logout handing
  $(document).on('click', 'a.signout', function (event) {
    event.preventDefault();

    document.cookie = 'user=;expires=Thu, 01 Jan 1970 00:00:00 GMT';
    document.location = '/';
  });
});
<commit_msg>Removed click handler for signout.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

'use strict';

require.config({
  shim: {
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: [
        'underscore',
        'jquery'
      ],
      exports: 'Backbone'
    }
  },
  paths: {
    jquery: '../bower_components/jquery/dist/jquery',
    backbone: '../bower_components/backbone/backbone',
    underscore: '../bower_components/underscore/underscore',
    text: '../bower_components/requirejs-text/text',
    mustache: '../bower_components/mustache/mustache',
    stache: '../bower_components/requirejs-mustache/stache'
  }
});

require([
  'jquery',
  'backbone',
  'router',
  'collections/devices'
], function ($, Backbone, Router, Devices) {
  // Bring on the globals
  window.devices = new Devices();

  // Fetch devices from the server
  window.devices.fetch().then(function () {
    // Now that we have devices we can start
    Backbone.history.start();
  });
});
<|endoftext|>


<commit_before>const EventEmitter = require('events');
const util = require('util');
const log = require("../common/log.js");
const ZwaveLib = require('openzwave-shared');

function Zwave(config) {
	log.debug("zwave config: " + JSON.stringify(config));
	EventEmitter.call(this);
	var self = this;
	this.config = config;
	this.connected = false;
	this.zwave = new ZwaveLib({
		ConsoleOutput: false,
		Logging: false,
		SaveConfiguration: false,
		DriverMaxAttempts: 3,
		PollInterval: 500,
		SuppressValueRefresh: true
	});
	this.zwave.connect(this.config.device);

	this.zwave.on('driver ready', function(homeid) {
		log.debug("zwave driver ready");
		self.id = homeid.toString(16);
                self.emit("connected", self, self.id);
	});

	this.zwave.on('driver failed', function() {
                log.debug("zwave driver failed");
		self.connected = false;
		self.zwave.disconnect();
		self.emit("disconnected", self);
	});

	this.zwave.on('scan complete', function() {
                log.debug("zwave scan complete");
                self.connected = true;
	});

        this.zwave.on('node added', function(nodeid) {
                log.debug("zwave node added: " + nodeid);
		self.emit("node added", self, nodeid, {});
        });

        this.zwave.on('node removed', function(nodeid) {
                log.debug("zwave node removeed: " + nodeid);
		self.emit("node removed", self, nodeid);
        });

        this.zwave.on('node naming', function(nodeid, nodeinfo) {
                log.debug("zwave node naming: " + nodeid + ": " + JSON.stringify(nodeinfo));
        });

        this.zwave.on('node available', function(nodeid, nodeinfo) {
                log.debug("zwave node available: " + nodeid + ": " + JSON.stringify(nodeinfo));
        });

	this.zwave.on('node ready', function(nodeid, nodeinfo){
		log.debug("zwave node ready: " + nodeid + ": " + JSON.stringify(nodeinfo));
	});

	this.zwave.on('node event', function(nodeid, data) {
		log.debug("zwave node event: " + nodeid + ": " + JSON.stringify(data));
	});

	this.zwave.on('value added', function(nodeid, commandclass, valueId) {
		log.debug("zwave value added: " + nodeid + " / " + commandclass + " / " + JSON.stringify(valueId));
		self.emit("parameter added", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index);
                self.emit("parameter value", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index, valueId.value, valueId);
	});

        this.zwave.on('value changed', function(nodeid, commandclass, valueId) {
                log.debug("zwave value changed: " + nodeid + " / " + commandclass + " / " + JSON.stringify(valueId));
                self.emit("parameter value", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index, valueId.value, valueId);
        });

        this.zwave.on('value removed', function(nodeid, commandclass, instance, index) {
                log.debug("zwave value removed: " + nodeid + " / " + commandclass + " / " + instance + "/" + index);
		self.emit("parameter removed", self, nodeid, commandclass + "_" + instance + "_" + index);
        });

	this.zwave.on('controller command', function(nodeid, ctrlState, ctrlError, helpmsg){
                log.debug("zwave controller command: " + nodeid + ": " + ctrlState + " / " + ctrlError + " / " + helpmsg);
	});
};

util.inherits(Zwave, EventEmitter)

Zwave.prototype.adapter = function(command, message) {
	switch (command) {
		case "learn":
			this.zwave.addNode(this.id, true);
			break;
	}
};

Zwave.prototype.node = function(nodeid, command, message) {
}

Zwave.prototype.parameter = function(nodeid, parameterid, command, message) {
	switch (command) {
		case "set":
			var paramParts = parameterid.split('_');
			this.zwave.setValue({
				node_id: nodeid,
				class_id: paramParts[0],
				instance: paramParts[1],
				index: paramParts[2]
			}, message.val);
			break;
	}
}

module.exports = Zwave;
<commit_msg>minor tweak<commit_after>const EventEmitter = require('events');
const util = require('util');
const log = require("../common/log.js");
const ZwaveLib = require('openzwave-shared');

function Zwave(config) {
	log.debug("zwave config: " + JSON.stringify(config));
	EventEmitter.call(this);
	var self = this;
	this.config = config;
	this.connected = false;
	this.zwave = new ZwaveLib({
		ConsoleOutput: false,
		Logging: false,
		SaveConfiguration: false,
		DriverMaxAttempts: 3,
		PollInterval: 500,
		SuppressValueRefresh: true
	});
	this.zwave.connect(this.config.device);

	this.zwave.on('driver ready', function(homeid) {
		log.debug("zwave driver ready");
		self.id = homeid.toString(16);
                self.emit("connected", self, self.id);
	});

	this.zwave.on('driver failed', function() {
                log.debug("zwave driver failed");
		self.connected = false;
		self.zwave.disconnect();
		self.emit("disconnected", self);
	});

	this.zwave.on('scan complete', function() {
                log.debug("zwave scan complete");
                self.connected = true;
	});

        this.zwave.on('node added', function(nodeid) {
                log.debug("zwave node added: " + nodeid);
		self.emit("node added", self, nodeid, {});
        });

        this.zwave.on('node removed', function(nodeid) {
                log.debug("zwave node removeed: " + nodeid);
		self.emit("node removed", self, nodeid);
        });

        this.zwave.on('node naming', function(nodeid, nodeinfo) {
                log.debug("zwave node naming: " + nodeid + ": " + JSON.stringify(nodeinfo));
        });

        this.zwave.on('node available', function(nodeid, nodeinfo) {
                log.debug("zwave node available: " + nodeid + ": " + JSON.stringify(nodeinfo));
        });

	this.zwave.on('node ready', function(nodeid, nodeinfo){
		log.debug("zwave node ready: " + nodeid + ": " + JSON.stringify(nodeinfo));
	});

	this.zwave.on('node event', function(nodeid, data) {
		log.debug("zwave node event: " + nodeid + ": " + JSON.stringify(data));
	});

	this.zwave.on('value added', function(nodeid, commandclass, valueId) {
		log.debug("zwave value added: " + nodeid + " / " + commandclass + " / " + JSON.stringify(valueId));
		self.emit("parameter added", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index);
                self.emit("parameter value", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index, valueId.value, valueId);
	});

        this.zwave.on('value changed', function(nodeid, commandclass, valueId) {
                log.debug("zwave value changed: " + nodeid + " / " + commandclass + " / " + JSON.stringify(valueId));
                self.emit("parameter value", self, nodeid, commandclass + "_" + valueId.instance + "_" + valueId.index, valueId.value, valueId);
        });

        this.zwave.on('value removed', function(nodeid, commandclass, instance, index) {
                log.debug("zwave value removed: " + nodeid + " / " + commandclass + " / " + instance + "/" + index);
		self.emit("parameter removed", self, nodeid, commandclass + "_" + instance + "_" + index);
        });

	this.zwave.on('controller command', function(nodeid, ctrlState, ctrlError, helpmsg){
                log.debug("zwave controller command: " + nodeid + ": " + ctrlState + " / " + ctrlError + " / " + helpmsg);
	});
};

util.inherits(Zwave, EventEmitter)

Zwave.prototype.adapter = function(command, message) {
	switch (command) {
		case "scan":
			this.zwave.addNode(this.id, true);
			break;
	}
};

Zwave.prototype.node = function(nodeid, command, message) {
}

Zwave.prototype.parameter = function(nodeid, parameterid, command, message) {
	switch (command) {
		case "set":
			var paramParts = parameterid.split('_');
			this.zwave.setValue({
				node_id: nodeid,
				class_id: paramParts[0],
				instance: paramParts[1],
				index: paramParts[2]
			}, message.val);
			break;
	}
}

module.exports = Zwave;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule PickerAndroid
 * @flow
 */

'use strict';

var ColorPropType = require('ColorPropType');
var React = require('React');
var ReactChildren = require('react/lib/ReactChildren');
var ReactPropTypes = require('react/lib/ReactPropTypes');
var StyleSheet = require('StyleSheet');
var StyleSheetPropType = require('StyleSheetPropType');
var View = require('View');
var ViewStylePropTypes = require('ViewStylePropTypes');

var processColor = require('processColor');
var requireNativeComponent = require('requireNativeComponent');

var REF_PICKER = 'picker';
var MODE_DIALOG = 'dialog';
var MODE_DROPDOWN = 'dropdown';

var pickerStyleType = StyleSheetPropType({
  ...ViewStylePropTypes,
  color: ColorPropType,
});

type Event = Object;

/**
 * Not exposed as a public API - use <Picker> instead.
 */
class PickerAndroid extends React.Component {
  props: {
    style?: $FlowFixMe,
    selectedValue?: any,
    enabled?: boolean,
    mode?: 'dialog' | 'dropdown',
    onValueChange?: Function,
    prompt?: string,
    testID?: string,
  };

  state: *;

  static propTypes = {
    ...View.propTypes,
    style: pickerStyleType,
    selectedValue: React.PropTypes.any,
    enabled: ReactPropTypes.bool,
    mode: ReactPropTypes.oneOf(['dialog', 'dropdown']),
    onValueChange: ReactPropTypes.func,
    prompt: ReactPropTypes.string,
    testID: ReactPropTypes.string,
  };

  constructor(props, context) {
    super(props, context);
    var state = this._stateFromProps(props);

    this.state = {
      ...state,
      initialSelectedIndex: state.selectedIndex,
    };
  }

  componentWillReceiveProps(nextProps) {
    this.setState(this._stateFromProps(nextProps));
  }

  // Translate prop and children into stuff that the native picker understands.
  _stateFromProps = (props) => {
    var selectedIndex = 0;
    const items = ReactChildren.map(props.children, (child, index) => {
      if (child.props.value === props.selectedValue) {
        selectedIndex = index;
      }
      const childProps = {
        value: child.props.value,
        label: child.props.label,
      };
      if (child.props.color) {
        childProps.color = processColor(child.props.color);
      }
      return childProps;
    });
    return {selectedIndex, items};
  };

  render() {
    var Picker = this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;

    var nativeProps = {
      enabled: this.props.enabled,
      items: this.state.items,
      mode: this.props.mode,
      onSelect: this._onChange,
      prompt: this.props.prompt,
      selected: this.state.initialSelectedIndex,
      testID: this.props.testID,
      style: [styles.pickerAndroid, this.props.style],
    };

    return <Picker ref={REF_PICKER} {...nativeProps} />;
  }

  _onChange = (event: Event) => {
    if (this.props.onValueChange) {
      var position = event.nativeEvent.position;
      if (position >= 0) {
        var value = this.props.children[position].props.value;
        this.props.onValueChange(value, position);
      } else {
        this.props.onValueChange(null, position);
      }
    }
    this._lastNativePosition = event.nativeEvent.position;
    this.forceUpdate();
  };

  componentDidMount() {
    this._lastNativePosition = this.state.initialSelectedIndex;
  }

  componentDidUpdate() {
    // The picker is a controlled component. This means we expect the
    // on*Change handlers to be in charge of updating our
    // `selectedValue` prop. That way they can also
    // disallow/undo/mutate the selection of certain values. In other
    // words, the embedder of this component should be the source of
    // truth, not the native component.
    if (this.refs[REF_PICKER] && this.state.selectedIndex !== this._lastNativePosition) {
      this.refs[REF_PICKER].setNativeProps({selected: this.state.selectedIndex});
      this._lastNativePosition = this.state.selectedIndex;
    }
  }
}

var styles = StyleSheet.create({
  pickerAndroid: {
    // The picker will conform to whatever width is given, but we do
    // have to set the component's height explicitly on the
    // surrounding view to ensure it gets rendered.
    // TODO would be better to export a native constant for this,
    // like in iOS the RCTDatePickerManager.m
    height: 50,
  },
});

var cfg = {
  nativeOnly: {
    items: true,
    selected: true,
  }
};

var DropdownPicker = requireNativeComponent('AndroidDropdownPicker', PickerAndroid, cfg);
var DialogPicker = requireNativeComponent('AndroidDialogPicker', PickerAndroid, cfg);

module.exports = PickerAndroid;
<commit_msg>Brings accessibilityLabel into PickerAndroid<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule PickerAndroid
 * @flow
 */

'use strict';

var ColorPropType = require('ColorPropType');
var React = require('React');
var ReactChildren = require('react/lib/ReactChildren');
var ReactPropTypes = require('react/lib/ReactPropTypes');
var StyleSheet = require('StyleSheet');
var StyleSheetPropType = require('StyleSheetPropType');
var View = require('View');
var ViewStylePropTypes = require('ViewStylePropTypes');

var processColor = require('processColor');
var requireNativeComponent = require('requireNativeComponent');

var REF_PICKER = 'picker';
var MODE_DIALOG = 'dialog';
var MODE_DROPDOWN = 'dropdown';

var pickerStyleType = StyleSheetPropType({
  ...ViewStylePropTypes,
  color: ColorPropType,
});

type Event = Object;

/**
 * Not exposed as a public API - use <Picker> instead.
 */
class PickerAndroid extends React.Component {
  props: {
    style?: $FlowFixMe,
    selectedValue?: any,
    enabled?: boolean,
    mode?: 'dialog' | 'dropdown',
    onValueChange?: Function,
    prompt?: string,
    testID?: string,
  };

  state: *;

  static propTypes = {
    ...View.propTypes,
    style: pickerStyleType,
    selectedValue: React.PropTypes.any,
    enabled: ReactPropTypes.bool,
    mode: ReactPropTypes.oneOf(['dialog', 'dropdown']),
    onValueChange: ReactPropTypes.func,
    prompt: ReactPropTypes.string,
    testID: ReactPropTypes.string,
  };

  constructor(props, context) {
    super(props, context);
    var state = this._stateFromProps(props);

    this.state = {
      ...state,
      initialSelectedIndex: state.selectedIndex,
    };
  }

  componentWillReceiveProps(nextProps) {
    this.setState(this._stateFromProps(nextProps));
  }

  // Translate prop and children into stuff that the native picker understands.
  _stateFromProps = (props) => {
    var selectedIndex = 0;
    const items = ReactChildren.map(props.children, (child, index) => {
      if (child.props.value === props.selectedValue) {
        selectedIndex = index;
      }
      const childProps = {
        value: child.props.value,
        label: child.props.label,
      };
      if (child.props.color) {
        childProps.color = processColor(child.props.color);
      }
      return childProps;
    });
    return {selectedIndex, items};
  };

  render() {
    var Picker = this.props.mode === MODE_DROPDOWN ? DropdownPicker : DialogPicker;

    var nativeProps = {
      enabled: this.props.enabled,
      items: this.state.items,
      mode: this.props.mode,
      onSelect: this._onChange,
      prompt: this.props.prompt,
      selected: this.state.initialSelectedIndex,
      testID: this.props.testID,
      style: [styles.pickerAndroid, this.props.style],
      accessibilityLabel: this.props.accessibilityLabel,
    };

    return <Picker ref={REF_PICKER} {...nativeProps} />;
  }

  _onChange = (event: Event) => {
    if (this.props.onValueChange) {
      var position = event.nativeEvent.position;
      if (position >= 0) {
        var value = this.props.children[position].props.value;
        this.props.onValueChange(value, position);
      } else {
        this.props.onValueChange(null, position);
      }
    }
    this._lastNativePosition = event.nativeEvent.position;
    this.forceUpdate();
  };

  componentDidMount() {
    this._lastNativePosition = this.state.initialSelectedIndex;
  }

  componentDidUpdate() {
    // The picker is a controlled component. This means we expect the
    // on*Change handlers to be in charge of updating our
    // `selectedValue` prop. That way they can also
    // disallow/undo/mutate the selection of certain values. In other
    // words, the embedder of this component should be the source of
    // truth, not the native component.
    if (this.refs[REF_PICKER] && this.state.selectedIndex !== this._lastNativePosition) {
      this.refs[REF_PICKER].setNativeProps({selected: this.state.selectedIndex});
      this._lastNativePosition = this.state.selectedIndex;
    }
  }
}

var styles = StyleSheet.create({
  pickerAndroid: {
    // The picker will conform to whatever width is given, but we do
    // have to set the component's height explicitly on the
    // surrounding view to ensure it gets rendered.
    // TODO would be better to export a native constant for this,
    // like in iOS the RCTDatePickerManager.m
    height: 50,
  },
});

var cfg = {
  nativeOnly: {
    items: true,
    selected: true,
  }
};

var DropdownPicker = requireNativeComponent('AndroidDropdownPicker', PickerAndroid, cfg);
var DialogPicker = requireNativeComponent('AndroidDialogPicker', PickerAndroid, cfg);

module.exports = PickerAndroid;
<|endoftext|>


<commit_before>var feature_flags = (function () {

var exports = {};

exports.mark_read_at_bottom = true;
exports.summarize_read_while_narrowed = true;

exports.twenty_four_hour_time = _.contains([],
                                  page_params.email);
exports.dropbox_integration = page_params.staging || _.contains(['dropbox.com'], page_params.domain);

exports.mandatory_topics = _.contains([
    'customer7.invalid'
    ],
    page_params.domain
);

exports.collapsible = page_params.staging;

exports.propagate_topic_edits = page_params.staging ||
  _.contains(['customer7.invalid'], page_params.domain);

var customer4_realms = [
  'customer4.invalid',
  'users.customer4.invalid'
];
var is_customer4 = _.contains(customer4_realms, page_params.domain);

exports.fade_users_when_composing = page_params.staging || is_customer4;

exports.alert_words =
  _.contains(['reddit.com', 'mit.edu', 'zulip.com'], page_params.domain);

var zulip_mit_emails = [];

var is_zulip_mit_user = _.contains(zulip_mit_emails, page_params.email);

exports.muting = page_params.staging || is_zulip_mit_user;

exports.left_side_userlist = page_params.staging ||
  _.contains(['customer7.invalid'], page_params.domain);

return exports;

}());
<commit_msg>Turn on 24-hour time for customer8.invalid (Iceland).<commit_after>var feature_flags = (function () {

var exports = {};

exports.mark_read_at_bottom = true;
exports.summarize_read_while_narrowed = true;

var internal_24_hour_people= _.contains([],
    page_params.email);

var iceland = page_params.domain === 'customer8.invalid';

exports.twenty_four_hour_time = internal_24_hour_people || iceland;

exports.dropbox_integration = page_params.staging || _.contains(['dropbox.com'], page_params.domain);

exports.mandatory_topics = _.contains([
    'customer7.invalid'
    ],
    page_params.domain
);

exports.collapsible = page_params.staging;

exports.propagate_topic_edits = page_params.staging ||
  _.contains(['customer7.invalid'], page_params.domain);

var customer4_realms = [
  'customer4.invalid',
  'users.customer4.invalid'
];
var is_customer4 = _.contains(customer4_realms, page_params.domain);

exports.fade_users_when_composing = page_params.staging || is_customer4;

exports.alert_words =
  _.contains(['reddit.com', 'mit.edu', 'zulip.com'], page_params.domain);

var zulip_mit_emails = [];

var is_zulip_mit_user = _.contains(zulip_mit_emails, page_params.email);

exports.muting = page_params.staging || is_zulip_mit_user;

exports.left_side_userlist = page_params.staging ||
  _.contains(['customer7.invalid'], page_params.domain);

return exports;

}());
<|endoftext|>


<commit_before>!function ($) {
  "use strict";

  $.fn.switch = function (method) {
    var methods = {
      init:function () {
        this.each(function () {
            var $element = $(this)
              , $div
              , $switchLeft
              , $switchRight
              , $label
              , myClasses = ""
              , classes = $element.attr('class')
              , color
              , moving
              , onLabel = "ON"
              , offLabel = "OFF";

            $.each(['switch-mini', 'switch-small', 'switch-large'], function (i, el) {
              if (classes.indexOf(el) >= 0)
                myClasses = el;
            });

            if ($element.data('on') !== undefined)
              color = "switch-" + $element.data('on');

            if ($element.data('on-label') !== undefined)
              onLabel = $element.data('on-label');

            if ($element.data('off-label') !== undefined)
              offLabel = $element.data('off-label');

            $switchLeft = $('<span>')
              .addClass("switch-left")
              .addClass(myClasses)
              .addClass(color)
              .text(onLabel);

            if ($element.data('off') !== undefined)
              color = "switch-" + $element.data('off');

            $switchRight = $('<span>')
              .addClass("switch-right")
              .addClass(myClasses)
              .addClass(color)
              .text(offLabel);

            $label = $('<label>')
              .html(" ")
              .addClass(myClasses)
              .attr('for', $element.find('input').attr('id'));

            $div = $element.find('input').wrap($('<div>')).parent().data('animated', false);

            if ($element.data('animated') !== false)
              $div.addClass('switch-animate').data('animated', true);

            $div.append($switchLeft);
            $div.append($label);
            $div.append($switchRight);

            $element.find('>div').addClass(
              $element.find('input').is(':checked') ? 'switch-on' : 'switch-off'
            );

            if ($element.find('input').is(':disabled'))
              $(this).addClass('deactivate');

            var changeStatus = function ($this) {
              $this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');
            };

            $switchLeft.on('click', function (e) {
              changeStatus($(this));
            });
            $switchRight.on('click', function (e) {
              changeStatus($(this));
            });

            $element.find('input').on('change', function (e) {
              var $element = $(this).parent();

              e.preventDefault();
              e.stopImmediatePropagation();

              $element.css('left', '');

              if ($(this).is(':checked'))
                $element.removeClass('switch-off').addClass('switch-on');
              else $element.removeClass('switch-on').addClass('switch-off');

              if ($element.data('animated') !== false)
                $element.addClass("switch-animate");

              $element.parent().trigger('switch-change', {'el':$(this), 'value':$(this).is(':checked')})
            });

            $element.find('label').on('mousedown touchstart', function (e) {
              var $this = $(this);
              moving = false;

              e.preventDefault();
              e.stopImmediatePropagation();

              $this.closest('div').removeClass('switch-animate');

              if ($this.closest('.switch').is('.deactivate'))
                $this.unbind('click');
              else {
                $this.on('mousemove touchmove', function (e) {
                  var $element = $(this).closest('.switch')
                    , relativeX = (e.pageX || e.originalEvent.targetTouches[0].pageX) - $element.offset().left
                    , percent = (relativeX / $element.width()) * 100
                    , left = 25
                    , right = 75;

                  moving = true;

                  if (percent < left)
                    percent = left;
                  else if (percent > right)
                    percent = right;

                  $element.find('>div').css('left', (percent - right) + "%")
                });

                $this.on('click touchend', function (e) {
                  var $this = $(this)
                    , $target = $(e.target)
                    , $myCheckBox = $target.siblings('input');

                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $this.unbind('mouseleave');

                  if (moving)
                    $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25));
                  else $myCheckBox.prop("checked", !$myCheckBox.is(":checked"));

                  moving = false;
                  $myCheckBox.trigger('change');
                });

                $this.on('mouseleave', function (e) {
                  var $this = $(this)
                    , $myCheckBox = $this.siblings('input');

                  e.preventDefault();
                  e.stopImmediatePropagation();

                  $this.unbind('mouseleave');
                  $this.trigger('mouseup');

                  $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25)).trigger('change');
                });

                $this.on('mouseup', function (e) {
                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $(this).unbind('mousemove');
                });
              }
            });
          }
        );
      },
      toggleActivation:function () {
        $(this).toggleClass('deactivate');
      },
      toggleState:function (skipOnChange) {
        var $input = $(this).find('input:checkbox');
        $input.prop('checked', !$input.is(':checked')).trigger('change', skipOnChange);
      },
      setState:function (value, skipOnChange) {
        $(this).find('input:checkbox').prop('checked', value).trigger('change', skipOnChange);
      },
      status:function () {
        return $(this).find('input:checkbox').is(':checked');
      },
      destroy:function () {
        var $div = $(this).find('div')
          , $checkbox;

        $div.find(':not(input:checkbox)').remove();

        $checkbox = $div.children();
        $checkbox.unwrap().unwrap();

        $checkbox.unbind('change');

        return $checkbox;
      }
    };

    if (methods[method])
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    else if (typeof method === 'object' || !method)
      return methods.init.apply(this, arguments);
    else
      $.error('Method ' + method + ' does not exist!');
  };
}(jQuery);

$(function () {
  $('.switch').switch();
});
<commit_msg>ie8 fix<commit_after>!function ($) {
  "use strict";

  $.fn['switch'] = function (method) {
    var methods = {
      init:function () {
        this.each(function () {
            var $element = $(this)
              , $div
              , $switchLeft
              , $switchRight
              , $label
              , myClasses = ""
              , classes = $element.attr('class')
              , color
              , moving
              , onLabel = "ON"
              , offLabel = "OFF";

            $.each(['switch-mini', 'switch-small', 'switch-large'], function (i, el) {
              if (classes.indexOf(el) >= 0)
                myClasses = el;
            });

            if ($element.data('on') !== undefined)
              color = "switch-" + $element.data('on');

            if ($element.data('on-label') !== undefined)
              onLabel = $element.data('on-label');

            if ($element.data('off-label') !== undefined)
              offLabel = $element.data('off-label');

            $switchLeft = $('<span>')
              .addClass("switch-left")
              .addClass(myClasses)
              .addClass(color)
              .text(onLabel);

            if ($element.data('off') !== undefined)
              color = "switch-" + $element.data('off');

            $switchRight = $('<span>')
              .addClass("switch-right")
              .addClass(myClasses)
              .addClass(color)
              .text(offLabel);

            $label = $('<label>')
              .html(" ")
              .addClass(myClasses)
              .attr('for', $element.find('input').attr('id'));

            $div = $element.find('input').wrap($('<div>')).parent().data('animated', false);

            if ($element.data('animated') !== false)
              $div.addClass('switch-animate').data('animated', true);

            $div.append($switchLeft);
            $div.append($label);
            $div.append($switchRight);

            $element.find('>div').addClass(
              $element.find('input').is(':checked') ? 'switch-on' : 'switch-off'
            );

            if ($element.find('input').is(':disabled'))
              $(this).addClass('deactivate');

            var changeStatus = function ($this) {
              $this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');
            };

            $switchLeft.on('click', function (e) {
              changeStatus($(this));
            });
            $switchRight.on('click', function (e) {
              changeStatus($(this));
            });

            $element.find('input').on('change', function (e) {
              var $element = $(this).parent();

              e.preventDefault();
              e.stopImmediatePropagation();

              $element.css('left', '');

              if ($(this).is(':checked'))
                $element.removeClass('switch-off').addClass('switch-on');
              else $element.removeClass('switch-on').addClass('switch-off');

              if ($element.data('animated') !== false)
                $element.addClass("switch-animate");

              $element.parent().trigger('switch-change', {'el':$(this), 'value':$(this).is(':checked')})
            });

            $element.find('label').on('mousedown touchstart', function (e) {
              var $this = $(this);
              moving = false;

              e.preventDefault();
              e.stopImmediatePropagation();

              $this.closest('div').removeClass('switch-animate');

              if ($this.closest('.switch').is('.deactivate'))
                $this.unbind('click');
              else {
                $this.on('mousemove touchmove', function (e) {
                  var $element = $(this).closest('.switch')
                    , relativeX = (e.pageX || e.originalEvent.targetTouches[0].pageX) - $element.offset().left
                    , percent = (relativeX / $element.width()) * 100
                    , left = 25
                    , right = 75;

                  moving = true;

                  if (percent < left)
                    percent = left;
                  else if (percent > right)
                    percent = right;

                  $element.find('>div').css('left', (percent - right) + "%")
                });

                $this.on('click touchend', function (e) {
                  var $this = $(this)
                    , $target = $(e.target)
                    , $myCheckBox = $target.siblings('input');

                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $this.unbind('mouseleave');

                  if (moving)
                    $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25));
                  else $myCheckBox.prop("checked", !$myCheckBox.is(":checked"));

                  moving = false;
                  $myCheckBox.trigger('change');
                });

                $this.on('mouseleave', function (e) {
                  var $this = $(this)
                    , $myCheckBox = $this.siblings('input');

                  e.preventDefault();
                  e.stopImmediatePropagation();

                  $this.unbind('mouseleave');
                  $this.trigger('mouseup');

                  $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25)).trigger('change');
                });

                $this.on('mouseup', function (e) {
                  e.stopImmediatePropagation();
                  e.preventDefault();

                  $(this).unbind('mousemove');
                });
              }
            });
          }
        );
      },
      toggleActivation:function () {
        $(this).toggleClass('deactivate');
      },
      toggleState:function (skipOnChange) {
        var $input = $(this).find('input:checkbox');
        $input.prop('checked', !$input.is(':checked')).trigger('change', skipOnChange);
      },
      setState:function (value, skipOnChange) {
        $(this).find('input:checkbox').prop('checked', value).trigger('change', skipOnChange);
      },
      status:function () {
        return $(this).find('input:checkbox').is(':checked');
      },
      destroy:function () {
        var $div = $(this).find('div')
          , $checkbox;

        $div.find(':not(input:checkbox)').remove();

        $checkbox = $div.children();
        $checkbox.unwrap().unwrap();

        $checkbox.unbind('change');

        return $checkbox;
      }
    };

    if (methods[method])
      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
    else if (typeof method === 'object' || !method)
      return methods.init.apply(this, arguments);
    else
      $.error('Method ' + method + ' does not exist!');
  };
}(jQuery);

$(function () {
  $('.switch')['switch']();
});
<|endoftext|>


<commit_before>ControlWidget =
{
  update_url: "http://" + location.host + "/state",
  root_elem: $("#control_form fieldset"),
  components: [],

  init: function()
  {
    console.log("init ControlWidget");

    var self = this;

    $( "#load" ).click(function()
    {
      console.log("load settings");
      $.get("/load");
      self.get_state_and_update();
    });
    $( "#save" ).click(function()
    {
      console.log("save settings");
      $.get("/save");
      self.get_state_and_update();
    });
    $( "#snapshot" ).click(function()
    {
      console.log("generate snapshot");
      $("#snapshot_img").attr("src","/snapshot");
      $("#snapshot_img").show();
    });
    $("#snapshot_img").hide();
  },

  update_ui_with_component: function(the_component)
  {
    var field_set = $("<fieldset></fieldset>").hide();
    var legend = $("<legend/>").html(the_component.name);
    $("#control_form").empty();
    $("#control_form").append($("", {
                                click: function(){ field_set.slideToggle();}
                              }).append(legend));
    $("#control_form").append(field_set);

    var self = this;
    $.each(the_component.properties, function(key, prop)
    {
      self.add_control_for_property(the_component.name, prop, field_set);
    });
  },

  get_state_and_update: function()
  {
    this.set_loading(true);
    var self = this;

    $.getJSON(this.update_url, function(data)
    {
      self.components = data;
      for(var i = 0; i < data.length; i++)
      {
        self.update_ui_with_component(data[i]);
        self.set_loading(false);
      }
    });
  },

  set_loading: function(the_bool)
  {
    //TODO: implement
  },

  add_control_for_property: function(the_component_name, the_property, root_elem)
  {
    var self = this;
    var input_elem = undefined;
    var stripped_name = the_property.name.trim().replace(/ /g,'_');

    var group = $( "
", {
      "class": "form-group"
    });

    var label = $( "", {
      "class": "col-md-4 control-label",
      "for": stripped_name,
      "html": the_property.name
    });

    group.append(label);

    input_elem = $( "<input/>", {
        "id": stripped_name,
        "name": stripped_name,
        "type": "text",
        "class": "form-control input-md",
        "value": the_property.value
    });
    input_col = $("
").append(input_elem);

    switch(the_property.type)
    {
      case "string":
        input_elem.attr("type", "text");
        break;

      case "int":
      case "uint":
      case "float":
      case "double":
        input_elem.attr("type", "number");
        input_elem.val(Number(input_elem.val()));
        break;

      case "bool":
        input_elem.attr("type", "checkbox");
        input_elem.removeAttr('value');
        input_elem.prop('checked', the_property.value);
        break;

      case "vec4":
        input_elem.attr("type", "color");
        break;

      default:
        break;
    }

    if(input_elem != undefined)
    {
      // add change event
      input_elem.on("change", function()
      {
        var changed_prop = the_property;
        changed_prop.value = input_elem.val();

        switch(the_property.type)
        {
          case "bool":
          changed_prop.value = input_elem.prop('checked');
          break;

          case "int":
          case "uint":
          case "float":
          case "double":
            changed_prop.value = Number(changed_prop.value);
            break;

          case "vec2":
          case "vec3":
          case "mat3":
          case "mat4":

            // split comma separated values, form array
            var ret_array = [];
            var tmp = changed_prop.value.split(",");
            $.each(tmp, function(index, elem){ ret_array.push(Number(elem)); });
            changed_prop.value = ret_array;
            break;

          case "vec4":
            if(typeof changed_prop.value == 'string' ||
               changed_prop.value instanceof String)
            {
              // transform color-string (e.g. #FF23AB) to vec4 with values in range [0, 1]
              var ret_array = [];
              var tmp = [];
              for(var i = 1; i < 6; i += 2){ tmp.push(changed_prop.value.substring(i, i + 2)); }
              $.each(tmp, function(index, elem){ ret_array.push(parseInt(elem, 16) / 255.0); });
              changed_prop.value = ret_array;
            }
            break;

          default:
            break;
        }
        //input_elem.attr("name");

        self.on_change(the_component_name, changed_prop);
      });

      group.append(input_col);

      var root = root_elem == undefined ? this.root_elem : root_elem;
      root.append(group);
    }
  },

  on_change: function(the_component_name, the_json_obj)
  {
    console.log(the_json_obj);
    var component_obj = [{"name" : the_component_name, "properties": [the_json_obj]}]
    //$.post(this.update_url, JSON.stringify(component_obj), null, "json");

    $.ajax({
    type: "POST",
    url: this.update_url,
    data: JSON.stringify(component_obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: null,
    failure: null});
  }
};

$(document).ready(function(){
  ControlWidget.init();
  ControlWidget.get_state_and_update();
});
<commit_msg>removed a bug, that prevented diplaying of mutiple components<commit_after>ControlWidget =
{
  update_url: "http://" + location.host + "/state",
  root_elem: $("#control_form fieldset"),
  components: [],

  init: function()
  {
    console.log("init ControlWidget");

    var self = this;

    $( "#load" ).click(function()
    {
      console.log("load settings");
      $.get("/load");
      self.get_state_and_update();
    });
    $( "#save" ).click(function()
    {
      console.log("save settings");
      $.get("/save");
      self.get_state_and_update();
    });
    $( "#snapshot" ).click(function()
    {
      console.log("generate snapshot");
      $("#snapshot_img").attr("src","/snapshot");
      $("#snapshot_img").show();
    });
    $("#snapshot_img").hide();
  },

  update_ui_with_component: function(the_component)
  {
    var field_set = $("<fieldset></fieldset>").hide();
    var legend = $("<legend/>").html(the_component.name);
    $("#control_form").append($("", {
                                click: function(){ field_set.slideToggle();}
                              }).append(legend));
    $("#control_form").append(field_set);

    var self = this;
    $.each(the_component.properties, function(key, prop)
    {
      self.add_control_for_property(the_component.name, prop, field_set);
    });
  },

  get_state_and_update: function()
  {
    $("#control_form").empty();
    this.set_loading(true);
    var self = this;

    $.getJSON(this.update_url, function(data)
    {
      self.components = data;
      for(var i = 0; i < data.length; i++)
      {
        self.update_ui_with_component(data[i]);
        self.set_loading(false);
      }
    });
  },

  set_loading: function(the_bool)
  {
    //TODO: implement
  },

  add_control_for_property: function(the_component_name, the_property, root_elem)
  {
    var self = this;
    var input_elem = undefined;
    var stripped_name = the_property.name.trim().replace(/ /g,'_');

    var group = $( "
", {
      "class": "form-group"
    });

    var label = $( "", {
      "class": "col-md-4 control-label",
      "for": stripped_name,
      "html": the_property.name
    });

    group.append(label);

    input_elem = $( "<input/>", {
        "id": stripped_name,
        "name": stripped_name,
        "type": "text",
        "class": "form-control input-md",
        "value": the_property.value
    });
    input_col = $("
").append(input_elem);

    switch(the_property.type)
    {
      case "string":
        input_elem.attr("type", "text");
        break;

      case "int":
      case "uint":
      case "float":
      case "double":
        input_elem.attr("type", "number");
        input_elem.val(Number(input_elem.val()));
        break;

      case "bool":
        input_elem.attr("type", "checkbox");
        input_elem.removeAttr('value');
        input_elem.prop('checked', the_property.value);
        break;

      case "vec4":
        input_elem.attr("type", "color");
        break;

      default:
        break;
    }

    if(input_elem != undefined)
    {
      // add change event
      input_elem.on("change", function()
      {
        var changed_prop = the_property;
        changed_prop.value = input_elem.val();

        switch(the_property.type)
        {
          case "bool":
          changed_prop.value = input_elem.prop('checked');
          break;

          case "int":
          case "uint":
          case "float":
          case "double":
            changed_prop.value = Number(changed_prop.value);
            break;

          case "vec2":
          case "vec3":
          case "mat3":
          case "mat4":

            // split comma separated values, form array
            var ret_array = [];
            var tmp = changed_prop.value.split(",");
            $.each(tmp, function(index, elem){ ret_array.push(Number(elem)); });
            changed_prop.value = ret_array;
            break;

          case "vec4":
            if(typeof changed_prop.value == 'string' ||
               changed_prop.value instanceof String)
            {
              // transform color-string (e.g. #FF23AB) to vec4 with values in range [0, 1]
              var ret_array = [];
              var tmp = [];
              for(var i = 1; i < 6; i += 2){ tmp.push(changed_prop.value.substring(i, i + 2)); }
              $.each(tmp, function(index, elem){ ret_array.push(parseInt(elem, 16) / 255.0); });
              changed_prop.value = ret_array;
            }
            break;

          default:
            break;
        }
        //input_elem.attr("name");

        self.on_change(the_component_name, changed_prop);
      });

      group.append(input_col);

      var root = root_elem == undefined ? this.root_elem : root_elem;
      root.append(group);
    }
  },

  on_change: function(the_component_name, the_json_obj)
  {
    console.log(the_json_obj);
    var component_obj = [{"name" : the_component_name, "properties": [the_json_obj]}]
    //$.post(this.update_url, JSON.stringify(component_obj), null, "json");

    $.ajax({
    type: "POST",
    url: this.update_url,
    data: JSON.stringify(component_obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: null,
    failure: null});
  }
};

$(document).ready(function(){
  ControlWidget.init();
  ControlWidget.get_state_and_update();
});
<|endoftext|>