<commit_before>import React, {Component} from "react";
import {
  StyleSheet,
  View,
  Text,
  Image,
  ScrollView
} from "react-native";
import Button from "react-native-button";
import ChatHeads from "./ChatHeads";

export default class EventDetail extends Component {
  constructor() {
    super();
    this.state = {
      signupEnabled: true
    };
  }

  signup() {
    this.setState({signupEnabled: false});
  }

  render() {
    return (
      <View style={{flex: 1}}>
        <ScrollView style={{flex: 1}}>
          <View style={styles.header}>
          {/* Header */}
            <Image source={this.props.image} style={styles.bannerImage} />
            <Text style={styles.title}>{this.props.title}</Text>
          </View>
          <View style={styles.body}>
            <View>
              <Text>{this.props.date}</Text>
              <Text>{this.props.location}</Text>
            </View>
            <View>
              {/* Event details */}
              <Text style={styles.eventDetail}>{this.props.description}</Text>
            </View>
            <View>
              {/* Organizer details */}
              <Text style={styles.organizerName}>{this.props.organizer.name}</Text>
              <Text>{this.props.organizer.bio}</Text>
            </View>
          </View>
        </ScrollView>
        {
        this.state.signupEnabled ?
          <View style={styles.buttonBar}>
            <Button
              containerStyle={styles.buttonContainer}
              style={styles.button}
              onPress={() => this.signup()}
            >
              Sign up
            </Button>
          </View>
        :
        <View style={styles.buttonBar}>
          <Text>Who's going:</Text>
          <ChatHeads people={this.props.people} />
        </View>
        }
      </View>
    );
  }
};

const styles = StyleSheet.create({
  header: {
    flexDirection: "column",
    height: 300,
    backgroundColor: "black"
  },
  body: {
    flex: 1,
    padding: 10,
    backgroundColor: "#f3efef"
  },
  bannerImage: {
    flex: 1,
    resizeMode: "cover"
  },
  title: {
    position: "absolute",
    bottom: 0,
    left: 0,
    right: 0,
    textAlign: "center",
    color: "white",
    fontSize: 30,
    padding: 5,
    backgroundColor: "#333c"
  },
  eventDetail: {
    fontSize: 18
  },
  organizerName: {
    paddingTop: 20,
    fontSize: 20
  },
  buttonBar: {
    elevation: 10,
    backgroundColor: "#4b4b4b"
  },
  buttonContainer: {
    margin: 10,
    padding: 10,
    height: 45,
    backgroundColor: "green"
  },
  button: {
    fontSize: 20,
    color: "white"
  }
});
<commit_msg>Added cancel functionality and removed state<commit_after>import React, {Component} from "react";
import {
  StyleSheet,
  View,
  Text,
  Image,
  ScrollView
} from "react-native";
import {Ionicons} from "@exponent/vector-icons";
import Button from "react-native-button";
import ChatHeads from "./ChatHeads";

export default class EventDetail extends Component {
  constructor(props) {
    super(props);
    this.toggleSignup = this.toggleSignup.bind(this);
  }

  toggleSignup() {
    this.props.onSignUpChange(!this.props.signedUp);
    console.log("toggle signup");
  }

  render() {
    /* The footer holds either the signup button or the chat heads. */
    var footer = null;
    if (this.props.signedUp) {
      footer = (
        <View style={styles.chatHeadsBar}>
          <ChatHeads style={styles.chatHeads} title="Who's going:" people={this.props.people} />
        </View>
      );
    } else {
      footer = (
        <View style={styles.buttonBar}>
          <Button
            containerStyle={styles.buttonContainer}
            style={styles.button}
            onPress={this.toggleSignup}
          >
            Sign up
          </Button>
        </View>
      );
    }

    var cancelView = null;
    if (this.props.signedUp) {
      cancelView = (
        <View style={styles.cancelView}>
          <Ionicons name="md-checkmark-circle-outline" style={styles.cancelViewText} />
          <Text style={styles.cancelViewText}>I'm going</Text>
          <Button
            onPress={this.toggleSignup}
          >
            Cancel
          </Button>
        </View>
      );
    }

    return (
      <View style={{flex: 1}}>
        <ScrollView style={{flex: 1}}>
          <View style={styles.header}>
            {/* Header */}
            <Image source={this.props.image} style={styles.bannerImage} />
            <Text style={styles.title}>{this.props.title}</Text>
          </View>
          <View style={styles.body}>
            <View style={styles.meta}>
              <Text style={[styles.metaText, styles.date]}>{this.props.date}</Text>
              <Text style={[styles.metaText, styles.location]}>{this.props.location}</Text>
            </View>
            {cancelView}
            <View>
              {/* Event details */}
              <Text style={styles.eventDetail}>{this.props.description}</Text>
            </View>
            <View>
              {/* Organizer details */}
              <Text style={styles.organizerName}>{this.props.organizer.name}</Text>
              <Text>{this.props.organizer.bio}</Text>
            </View>
          </View>
        </ScrollView>
        {footer}
      </View>
    );
  }
};

EventDetail.propTypes = {
  /* True when the user is signed up for this event and false otherwise */
  signedUp: React.PropTypes.bool,
  /* Called with new signup status when the user alters the signup */
  onSignUpChange: React.PropTypes.func.isRequired,
  /* Event title */
  title: React.PropTypes.string.isRequired,
  /* Event description */
  description: React.PropTypes.string.isRequired,
  /* Information about the event organizer */
  organizer: React.PropTypes.shape({
    /* The name of the organizer */
    name: React.PropTypes.string.isRequired,
    /* The biography or description of the organizer */
    bio: React.PropTypes.string.isRequired,
    /* `image` should be an image as returned by require("image-uri") */
    image: React.PropTypes.number
  }).isRequired,
  /* `image` should be an image as returned by require("image-uri") */
  image: React.PropTypes.number.isRequired,
  /* The human-formatted date string to be displayed for the event */
  date: React.PropTypes.string.isRequired,
  /* The human-formatted location string to be displayed for the event */
  location: React.PropTypes.string.isRequired,
  /* The attendees of the event */
  people: React.PropTypes.arrayOf(React.PropTypes.shape({
    name: React.PropTypes.string.isRequired,
    /* `image` should be an image as returned by require("image-uri") */
    image: React.PropTypes.number.isRequired
  })).isRequired
};

const styles = StyleSheet.create({
  header: {
    flexDirection: "column",
    height: 300,
    backgroundColor: "black"
  },
  body: {
    flex: 1,
    padding: 10,
    backgroundColor: "#f3efef"
  },
  bannerImage: {
    flex: 1,
    resizeMode: "cover"
  },
  title: {
    position: "absolute",
    bottom: 0,
    left: 0,
    right: 0,
    textAlign: "center",
    color: "white",
    fontSize: 30,
    padding: 5,
    backgroundColor: "#333c"
  },
  cancelView: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center"
  },
  cancelViewText: {
    fontSize: 20,
    padding: 5
  },
  eventDetail: {
    fontSize: 18
  },
  meta: {
    flex: 1,
    flexDirection: "row",
    padding: 5
  },
  metaText: {
    fontSize: 15
  },
  date: {
    flex: 1
  },
  location: {
    flex: 1,
    textAlign: "right"
  },
  organizerName: {
    paddingTop: 20,
    fontSize: 20
  },
  buttonBar: {
    elevation: 10,
    backgroundColor: "#4b4b4b"
  },
  buttonContainer: {
    margin: 10,
    padding: 10,
    height: 45,
    backgroundColor: "green"
  },
  button: {
    fontSize: 20,
    color: "white"
  },
  chatHeadsBar: {
    backgroundColor: "white",
    paddingTop: 5,
    paddingBottom: 5,
    elevation: 5
  }
});
<|endoftext|>


<commit_before>chrome.extension.sendMessage({}, function(response) {

  var settings = {
    togglePlayAndPauseKeyCode: 80,  // default: P
    jumpToBeginningKeyCode:    72,  // defualt: H
    jumpToEndKeyCode:          69,  // default: E
    rewindTimeKeyCode:         65,  // default: A
    advanceTimeKeyCode:        83,  // default: S
    speedDownKeyCode:          68,  // default: D
    speedUpKeyCode:            85,  // default: U
    resetSpeedKeyCode:         82,  // default: R
    partialLoopKeyCode:        76,  // default: L
    skipTimeAmount:             5,  // default: 5
  };

  chrome.storage.sync.get(settings, function(storage) {
    settings.togglePlayAndPauseKeyCode = Number(storage.togglePlayAndPauseKeyCode);
    settings.jumpToBeginningKeyCode    = Number(storage.jumpToBeginningKeyCode);
    settings.jumpToEndKeyCode          = Number(storage.jumpToEndKeyCode);
    settings.rewindTimeKeyCode         = Number(storage.rewindTimeKeyCode);
    settings.advanceTimeKeyCode        = Number(storage.advanceTimeKeyCode);
    settings.speedDownKeyCode          = Number(storage.speedDownKeyCode);
    settings.speedUpKeyCode            = Number(storage.speedUpKeyCode);
    settings.resetSpeedKeyCode         = Number(storage.resetSpeedKeyCode);
    settings.partialLoopKeyCode        = Number(storage.partialLoopKeyCode);
    settings.skipTimeAmount            = Number(storage.skipTimeAmount);
  });

  // Global variable
  var loopStatus = 0;
  var loopStart;
  var loopEnd;
  var loopTimeoutID;
  var flag = 0;
  var removeStatusBoxTimeoutID;

  // キーが押されたかどうかを判定
  document.addEventListener('keydown', function(event) {

    // 入力フォームにフォーカスがあるときはショートカットを無効化
    if ((document.activeElement.nodeName === 'INPUT'
    || document.activeElement.nodeName === 'TEXTAREA'
    || document.activeElement.getAttribute('type') === 'text')
    || document.activeElement.isContentEditable === true) {
      return false;
    } else {
      activeBlur();
    }

    // cmd, shift, ctrl, alt をエスケープ
    if (event.metaKey || event.shiftKey || event.ctrlKey || event.altKey) {
      return false;
    }

    // ショートカットキーから関数を呼び出す
    switch (event.keyCode) {
      // オプションで変更可能なキーコード
      case settings.togglePlayAndPauseKeyCode: togglePlayAndPause(); break; // default: P
      case settings.jumpToBeginningKeyCode:    jumpToBeginning();    break; // default: H
      case settings.jumpToEndKeyCode:          jumpToEnd();          break; // default: E
      case settings.rewindTimeKeyCode:         rewindTime();         break; // default: A
      case settings.advanceTimeKeyCode:        advanceTime();        break; // default: S
      case settings.speedDownKeyCode:          speedDown();          break; // default: D
      case settings.speedUpKeyCode:            speedUp();            break; // default: U
      case settings.resetSpeedKeyCode:         resetSpeed();         break; // default: R

      // 固定のキーコード
      case 32: event.preventDefault(); togglePlayAndPause(); break; // space
      case 37:                         rewindTime();         break; // left-arrow
      case 39:                         advanceTime();        break; // right-arrow
      case 27:                         activeBlur();         break; // esc
    }

    // 数字のキーを押すとその数字に対応する割合まで動画を移動する
    // キーボードの 3 を押すと動画全体の 30% の位置に移動する
    // 固定のキーコード
    if (event.keyCode >= 48 && event.keyCode <= 57) {
      jumpToTimerRatio(event.keyCode);
    }

    // 部分ループ再生のステータスを記録
    // オプションで変更可能なキーコード
    // default: L
    if (event.keyCode == settings.partialLoopKeyCode) {
      if (loopStatus === undefined) {
        loopStatus = 0;
      }
      loopStatus++;
      partialLoop();
    }

  });

  // 再生/停止
  function togglePlayAndPause() {
    var player = document.getElementsByTagName('video')[0];
    if (player.paused === true)
      player.play();
    else
      player.pause();
    scrollToPlayer();
  };

  // 数秒巻き戻し
  function rewindTime() {
    document.getElementsByTagName('video')[0].currentTime -= settings.skipTimeAmount;
    scrollToPlayer();
  };

  // 数秒早送り
  function advanceTime() {
    document.getElementsByTagName('video')[0].currentTime += settings.skipTimeAmount;
    scrollToPlayer();
  };

  // 再生スピードダウン
  function speedDown() {
    var player = document.getElementsByTagName('video')[0];
    player.playbackRate = floorFormat((player.playbackRate - 0.09), 1);
    statusBox('playbackRate', player.playbackRate.toFixed(1));
    scrollToPlayer();
  }

  // 再生スピードアップ
  function speedUp() {
    var player = document.getElementsByTagName('video')[0];
    player.playbackRate = floorFormat((player.playbackRate + 0.11), 1);
    statusBox('playbackRate', player.playbackRate.toFixed(1));
    scrollToPlayer();
  }

  // 再生スピードリセット
  function resetSpeed() {
    var player = document.getElementsByTagName('video')[0];
    player.playbackRate = 1.0;
    statusBox('playbackRate', player.playbackRate.toFixed(1));
    scrollToPlayer();
  }

  // 動画の最初の位置に移動する
  function jumpToBeginning() {
    var player = document.getElementsByTagName('video')[0];
    player.currentTime = player.seekable.start(0);
    scrollToPlayer();
  };

  // 動画の最後の位置に移動する
  function jumpToEnd() {
    var player = document.getElementsByTagName('video')[0];
    player.currentTime = player.seekable.end(0);
    scrollToPlayer();
  };

  // 数字に対応する割合まで動画を移動する
  function jumpToTimerRatio(timerRatio) {
    var player = document.getElementsByTagName('video')[0];
    timerRatio = (timerRatio - 48) / 10;
    player.currentTime = player.seekable.end(0) * timerRatio;
    scrollToPlayer();
  };

  // 部分ループ再生
  function partialLoop() {
    var player = document.getElementsByTagName('video')[0];
    if (loopStatus === 1) {
      loopStart = player.currentTime;
      statusBox('set', 'Set');
    }
    else if (loopStatus === 2) {
      if (flag !== 1) {
        loopEnd = player.currentTime;
        flag = 1;
        statusBox('loop', 'Loop!');
      }
      loopTimeoutID = setTimeout(function() {
        if (player.currentTime >= loopEnd || player.currentTime < loopStart) {
          player.currentTime = loopStart;
        }
        if (loopStatus === 3) {
          clearTimeout(loopTimeoutID);
          loopStatus = 0;
          flag = 0;
          statusBox('restore', 'Restore');
          return false;
        }
        partialLoop();
      }, 100);
    }
  };

  // アクティブフォーカスを外す
  function activeBlur() {
    document.activeElement.blur();
  };

  // 小数点第(n+1)位を切り捨てて小数点第n位まで求める
  function floorFormat(number, n) {
    var _pow = Math.pow(10, n);
    return Math.floor(number * _pow) / _pow;
  };

  // 動画プレイヤーのある位置までスクロールする
  function scrollToPlayer() {
    var player = document.getElementsByTagName('video')[0];
    var rect = player.getBoundingClientRect();
    var positionY = rect.top;
    var dElm = document.documentElement;
    var dBody = document.body;
    var scrollY = dElm.scrollTop || dBody.scrollTop;
    var y = positionY + scrollY - 100;
    window.scrollTo(0, y);
  };

  // 部分ループ再生のステータスを表示する
  function statusBox(status, statusStr) {
    if (status === 'set') {
      var videoStatus = '' + statusStr + '';
    }
    else {
      var videoStatus = '' + statusStr + '';
    }

    $('.video-status').remove();
    if (status === 'loop') {
      $('.video-status-keep-showing').remove();
    }

    $(videoStatus).insertBefore('video');

    if ($('span').hasClass('video-status') && $('span').hasClass('video-status-keep-showing')) {
      $('.video-status-keep-showing').css('display', 'none');
      clearTimeout(removeStatusBoxTimeoutID);
      removeStatusBoxTimeoutID = setTimeout(function() {
        $('.video-status').remove();
        $('.video-status-keep-showing').css('display', 'inline-block');
      }, 1000);
    }
    else {
      $('.video-status').fadeOut(1000, function() {
        $(this).remove();
      });
    }

  };

});
<commit_msg>:sparkles: Validate play speed<commit_after>chrome.extension.sendMessage({}, function(response) {

  var settings = {
    togglePlayAndPauseKeyCode: 80,  // default: P
    jumpToBeginningKeyCode:    72,  // defualt: H
    jumpToEndKeyCode:          69,  // default: E
    rewindTimeKeyCode:         65,  // default: A
    advanceTimeKeyCode:        83,  // default: S
    speedDownKeyCode:          68,  // default: D
    speedUpKeyCode:            85,  // default: U
    resetSpeedKeyCode:         82,  // default: R
    partialLoopKeyCode:        76,  // default: L
    skipTimeAmount:             5,  // default: 5
  };

  chrome.storage.sync.get(settings, function(storage) {
    settings.togglePlayAndPauseKeyCode = Number(storage.togglePlayAndPauseKeyCode);
    settings.jumpToBeginningKeyCode    = Number(storage.jumpToBeginningKeyCode);
    settings.jumpToEndKeyCode          = Number(storage.jumpToEndKeyCode);
    settings.rewindTimeKeyCode         = Number(storage.rewindTimeKeyCode);
    settings.advanceTimeKeyCode        = Number(storage.advanceTimeKeyCode);
    settings.speedDownKeyCode          = Number(storage.speedDownKeyCode);
    settings.speedUpKeyCode            = Number(storage.speedUpKeyCode);
    settings.resetSpeedKeyCode         = Number(storage.resetSpeedKeyCode);
    settings.partialLoopKeyCode        = Number(storage.partialLoopKeyCode);
    settings.skipTimeAmount            = Number(storage.skipTimeAmount);
  });

  // グローバル変数
  var player = document.getElementsByTagName('video')[0];
  var loopStatus = 0;
  var loopStart;
  var loopEnd;
  var flag = 0;
  var loopTimeoutID;
  var removeStatusBoxTimeoutID;

  // キーが押されたかどうかを判定
  document.addEventListener('keydown', function(event) {

    // 入力フォームにフォーカスがあるときはショートカットを無効化
    if ((document.activeElement.nodeName === 'INPUT'
    || document.activeElement.nodeName === 'TEXTAREA'
    || document.activeElement.getAttribute('type') === 'text')
    || document.activeElement.isContentEditable === true) {
      return false;
    } else {
      activeBlur();
    }

    // cmd, shift, ctrl, alt をエスケープ
    if (event.metaKey || event.shiftKey || event.ctrlKey || event.altKey) {
      return false;
    }

    // ショートカットキーから関数を呼び出す
    switch (event.keyCode) {
      // オプションで変更可能なキーコード
      case settings.togglePlayAndPauseKeyCode: togglePlayAndPause(); break; // default: P
      case settings.jumpToBeginningKeyCode:    jumpToBeginning();    break; // default: H
      case settings.jumpToEndKeyCode:          jumpToEnd();          break; // default: E
      case settings.rewindTimeKeyCode:         rewindTime();         break; // default: A
      case settings.advanceTimeKeyCode:        advanceTime();        break; // default: S
      case settings.speedDownKeyCode:          speedDown();          break; // default: D
      case settings.speedUpKeyCode:            speedUp();            break; // default: U
      case settings.resetSpeedKeyCode:         resetSpeed();         break; // default: R

      // 固定のキーコード
      case 32: event.preventDefault(); togglePlayAndPause(); break; // space
      case 37:                         rewindTime();         break; // left-arrow
      case 39:                         advanceTime();        break; // right-arrow
      case 27:                         activeBlur();         break; // esc
    }

    // 数字のキーを押すとその数字に対応する割合まで動画を移動する
    // キーボードの 3 を押すと動画全体の 30% の位置に移動する
    // 固定のキーコード
    if (event.keyCode >= 48 && event.keyCode <= 57) {
      jumpToTimerRatio(event.keyCode);
    }

    // 部分ループ再生のステータスを記録
    // オプションで変更可能なキーコード
    // default: L
    if (event.keyCode == settings.partialLoopKeyCode) {
      if (loopStatus === undefined) {
        loopStatus = 0;
      }
      loopStatus++;
      partialLoop();
    }

  });

  // 再生スピードの変更を監視する
  player.onratechange = function() {
    observeSpeed(player.playbackRate);
  };

  // 再生/停止
  function togglePlayAndPause() {
    if (player.paused === true)
      player.play();
    else
      player.pause();
    scrollToPlayer();
  };

  // 数秒巻き戻し
  function rewindTime() {
    player.currentTime -= settings.skipTimeAmount;
    scrollToPlayer();
  };

  // 数秒早送り
  function advanceTime() {
    player.currentTime += settings.skipTimeAmount;
    scrollToPlayer();
  };

  // 再生スピードダウン
  function speedDown() {
    player.playbackRate = floorFormat((player.playbackRate - 0.09), 1);
    statusBox('playbackRate', adjustSpeedStatus(player.playbackRate));
    scrollToPlayer();
  }

  // 再生スピードアップ
  function speedUp() {
    player.playbackRate = floorFormat((player.playbackRate + 0.11), 1);
    statusBox('playbackRate', adjustSpeedStatus(player.playbackRate));
    scrollToPlayer();
  }

  // 再生スピードリセット
  function resetSpeed() {
    player.playbackRate = 1.0;
    statusBox('playbackRate', adjustSpeedStatus(player.playbackRate));
    scrollToPlayer();
  }

  // 動画の最初の位置に移動する
  function jumpToBeginning() {
    player.currentTime = player.seekable.start(0);
    scrollToPlayer();
  };

  // 動画の最後の位置に移動する
  function jumpToEnd() {
    player.currentTime = player.seekable.end(0);
    scrollToPlayer();
  };

  // 数字に対応する割合まで動画を移動する
  function jumpToTimerRatio(timerRatio) {
    timerRatio = (timerRatio - 48) / 10;
    player.currentTime = player.seekable.end(0) * timerRatio;
    scrollToPlayer();
  };

  // 部分ループ再生
  function partialLoop() {
    if (loopStatus === 1) {
      loopStart = player.currentTime;
      statusBox('set', 'Set');
    }
    else if (loopStatus === 2) {
      if (flag !== 1) {
        loopEnd = player.currentTime;
        flag = 1;
        statusBox('loop', 'Loop!');
      }
      loopTimeoutID = setTimeout(function() {
        if (player.currentTime >= loopEnd || player.currentTime < loopStart) {
          player.currentTime = loopStart;
        }
        if (loopStatus === 3) {
          clearTimeout(loopTimeoutID);
          loopStatus = 0;
          flag = 0;
          statusBox('restore', 'Restore');
          return false;
        }
        partialLoop();
      }, 100);
    }
  };

  // アクティブフォーカスを外す
  function activeBlur() {
    document.activeElement.blur();
  };

  // 小数点第(n+1)位を切り捨てて小数点第n位まで求める
  function floorFormat(number, n) {
    var _pow = Math.pow(10, n);
    return Math.floor(number * _pow) / _pow;
  };

  // 動画プレイヤーのある位置までスクロールする
  function scrollToPlayer() {
    var rect = player.getBoundingClientRect();
    var positionY = rect.top;
    var dElm = document.documentElement;
    var dBody = document.body;
    var scrollY = dElm.scrollTop || dBody.scrollTop;
    var y = positionY + scrollY - 100;
    window.scrollTo(0, y);
  };

  // 部分ループ再生のステータスを表示する
  function statusBox(status, statusStr) {
    if (status === 'set') {
      var videoStatus = '' + statusStr + '';
    }
    else {
      var videoStatus = '' + statusStr + '';
    }

    $('.video-status').remove();
    if (status === 'loop') {
      $('.video-status-keep-showing').remove();
    }

    $(videoStatus).insertBefore('video');

    if ($('span').hasClass('video-status') && $('span').hasClass('video-status-keep-showing')) {
      $('.video-status-keep-showing').css('display', 'none');
      clearTimeout(removeStatusBoxTimeoutID);
      removeStatusBoxTimeoutID = setTimeout(function() {
        $('.video-status').remove();
        $('.video-status-keep-showing').css('display', 'inline-block');
      }, 1000);
    }
    else {
      $('.video-status').fadeOut(1000, function() {
        $(this).remove();
      });
    }
  };

  // 再生スピードの上限と下限を設定する
  function observeSpeed(speedChecker) {
    if (speedChecker < 0.5) {
      player.playbackRate = 0.5;
    }
    else if (speedChecker > 4.0) {
      player.playbackRate = 4.0;
    }
  };

  // 表示される再生スピードを調整する
  function adjustSpeedStatus(speedStatus) {
    if (speedStatus < 0.5) {
      speedStatus = 0.5;
    }
    else if (speedStatus > 4.0) {
      speedStatus = 4.0;
    }
    return speedStatus.toFixed(1);
  };

});
<|endoftext|>


<commit_before>BookShelf.TagListView = function(params) {

    var items = ko.observableArray();
    var selected = ko.observableArray();

    var id = ko.observable();
    var title = ko.observable();
    var editing = ko.observable();

    var viewModel = {

        items: items,
        selectionEnabled: params.selectionEnabled,
        scrollingEnabled: (params.scrollingEnabled === undefined) ? true : params.scrollingEnabled,
        editingEnabled: (params.editingEnabled === undefined) ? true : params.editingEnabled,
        selected: selected,

        editing: editing,

        tag: {
            id: id,
            title: title,
            invalid: ko.computed(function() {
                return !title();
            })
        },

        getTag: function() {
            return {
                id: id(),
                title: title()
            };
        },

        prepareTag: function(tag) {
            id(tag.id);
            title(tag.title);
        },

        resetTag: function() {
            editing(false);
            this.prepareTag({});
        },

        saveTag: function() {
            var tag = this.getTag();

            var currentSelected = selected();
            if(editing()) {
                BookShelf.db.tags.update(tag);
                items(BookShelf.db.tags.getAll().slice());
                BookShelf.app.bookListShowing.fire({ reloadTag: tag.id });
            } else {
                var newTag = BookShelf.db.tags.get(BookShelf.db.tags.add(tag));
                items.unshift(newTag);
                currentSelected.push(newTag);
            }
            selected(currentSelected);

            this.resetTag();
        },

        cancelEditTag: function() {
            this.resetTag();
        },

        editTag: function(args) {
            this.prepareTag(args.itemData);
            editing(true);

            setTimeout(function() {
                $(".tag-form-field").dxTextBox("focus");
            }, 400);
        },

        deleteTagConfirmation: function(args) {
            var booksByTag = BookShelf.db.books.getByTag(args.itemData.id);

            if(!booksByTag.length)
                return;

            return DevExpress.ui.dialog.confirm("Are you sure you want to delete category \"" + args.itemData.title + "\"? There are books associated with this category.", "Delete category");
        },

        deleteTag: function(args) {
            BookShelf.db.tags.remove(args.itemData.id);
            BookShelf.app.bookListShowing.fire({ reloadTag: args.itemData.id });
        },

        listTnit: function(args) {
            this.list = args.component;
        },

        onShowing: function() {
            this.resetTag();

            var currentSelected = selected();
            items(BookShelf.db.tags.getAll().slice().sort(function(a, b) { return b.title < a.title }));
            selected(currentSelected);
        },

        onShown: function() {
            this.list.element().off("dxactive.listBetterActiveState dxinactive.listBetterActiveState");
            if(params.selectionEnabled) {
                this.list.element()
                    .on("dxactive.listBetterActiveState", ".dx-list-item", { timeout: 30 }, function(e) {
                        $(e.currentTarget).addClass("dx-state-active");
                    })
                    .on("dxinactive.listBetterActiveState", ".dx-list-item", { timeout: 400 }, function(e) {
                        $(e.currentTarget).removeClass("dx-state-active");
                    });
            }
        }

    };

    return viewModel;
};<commit_msg>Views: Remove timeout for autofocus of tag edit field<commit_after>BookShelf.TagListView = function(params) {

    var items = ko.observableArray();
    var selected = ko.observableArray();

    var id = ko.observable();
    var title = ko.observable();
    var editing = ko.observable();

    var viewModel = {

        items: items,
        selectionEnabled: params.selectionEnabled,
        scrollingEnabled: (params.scrollingEnabled === undefined) ? true : params.scrollingEnabled,
        editingEnabled: (params.editingEnabled === undefined) ? true : params.editingEnabled,
        selected: selected,

        editing: editing,

        tag: {
            id: id,
            title: title,
            invalid: ko.computed(function() {
                return !title();
            })
        },

        getTag: function() {
            return {
                id: id(),
                title: title()
            };
        },

        prepareTag: function(tag) {
            id(tag.id);
            title(tag.title);
        },

        resetTag: function() {
            editing(false);
            this.prepareTag({});
        },

        saveTag: function() {
            var tag = this.getTag();

            var currentSelected = selected();
            if(editing()) {
                BookShelf.db.tags.update(tag);
                items(BookShelf.db.tags.getAll().slice());
                BookShelf.app.bookListShowing.fire({ reloadTag: tag.id });
            } else {
                var newTag = BookShelf.db.tags.get(BookShelf.db.tags.add(tag));
                items.unshift(newTag);
                currentSelected.push(newTag);
            }
            selected(currentSelected);

            this.resetTag();
        },

        cancelEditTag: function() {
            this.resetTag();
        },

        editTag: function(args) {
            this.prepareTag(args.itemData);
            editing(true);

            $(".tag-form-field").dxTextBox("focus");
        },

        deleteTagConfirmation: function(args) {
            var booksByTag = BookShelf.db.books.getByTag(args.itemData.id);

            if(!booksByTag.length)
                return;

            return DevExpress.ui.dialog.confirm("Are you sure you want to delete category \"" + args.itemData.title + "\"? There are books associated with this category.", "Delete category");
        },

        deleteTag: function(args) {
            BookShelf.db.tags.remove(args.itemData.id);
            BookShelf.app.bookListShowing.fire({ reloadTag: args.itemData.id });
        },

        listTnit: function(args) {
            this.list = args.component;
        },

        onShowing: function() {
            this.resetTag();

            var currentSelected = selected();
            items(BookShelf.db.tags.getAll().slice().sort(function(a, b) { return b.title < a.title }));
            selected(currentSelected);
        },

        onShown: function() {
            this.list.element().off("dxactive.listBetterActiveState dxinactive.listBetterActiveState");
            if(params.selectionEnabled) {
                this.list.element()
                    .on("dxactive.listBetterActiveState", ".dx-list-item", { timeout: 30 }, function(e) {
                        $(e.currentTarget).addClass("dx-state-active");
                    })
                    .on("dxinactive.listBetterActiveState", ".dx-list-item", { timeout: 400 }, function(e) {
                        $(e.currentTarget).removeClass("dx-state-active");
                    });
            }
        }

    };

    return viewModel;
};<|endoftext|>


<commit_before>(function() {
	var treePromise = null;
	var defaultBaseUrl = "http://prismjs.com/"
	var getConfig = function() {
		try {
			var config = JSON.parse(localStorage["config"]);
			var repo = config.baseUrl.match("https://github.com/([^/]+)/([^/]+)/tree/([^/]+)(?:/|$)");
			if (repo) {
				config.baseUrl = "https://api.github.com/repos/"+repo[1]+"/"+repo[2]+"/git/trees/"+repo[3]+"?recursive=1";
			}
			config.isRepo = config.baseUrl.match("https://api.github.*recursive");
			if (config.isRepo) {
				treePromise = new Promise(function(resolve) {
					$u.xhr({
						url: config.baseUrl,
						callback: function(xhr) {
							if (xhr.status < 400) {
								resolve(JSON.parse(xhr.responseText).tree.reduce(function(dict,v) {
									dict[v.path] = v.url;
									return dict;
								}, {}));
							}
						}
					});
				});
			}

		} catch(error) {
			var config = {
				first: true,
				baseUrl: defaultBaseUrl,
				languages: {},
				language: undefined,
				plugins: {},
				themes: {},
				code: '

Some Heading
\n\t
\n\t\t
Hello World!
\n\t
\n
',
				attr: {
					"line-highlight": {
						"data-line": "1-2,4"
					},
					"line-numbers": {
						"class": "line-numbers"
					}
				}
			};
		}
		base.value = config.baseUrl;
		code.value = config.code;
		return config;
	};
	var saveConfig = function() {
		config.first = false;
		config.baseUrl = (base.value || defaultBaseUrl).replace(/\/+$/,"") + "/";
		["languages","plugins","themes"].forEach(function(category){
			$$("input[name='"+category+"']").forEach(function(input){
				config[category][input.value]=input.checked;
			})
		});
		config.language = langselect.value;
		config.code = code.value;
		localStorage["config"] = JSON.stringify(config);
	};

	var config = getConfig();

	var notMeta = function(v) { return v !== "meta"; }
	var iframe, promises = {}, timer = 0;

	var ping = function(func,what,err) {
		return function() {
			console.log(what, typeof err === "boolean" ? (err ? "failed" : "OK") : (err || "ok"));
			func(what);
		}
	};
	var opt = function(category, id, name) {
		return typeof components[category][id][name] !== "undefined"
			? components[category][id][name]
			: components[category].meta[name];
	};
	var loadLanguage = function(lang) {
		if (!promises[lang]) {
			promises[lang] = Promise.all(components.languages[lang].require.map(loadLanguage)).then(function() {
				var files = getFiles('languages', lang);
				files.css.map(loadAsset);
				return Promise.all(files.js.map(loadAsset));
			});
		}
		return promises[lang];
	};
	var pathOrContent = function(src) {
		if (config.isRepo) {
			return treePromise.then(function(paths) {
				if (paths[src]) {
					return new Promise(function(resolve, reject) {
						$u.xhr({
							url: paths[src],
							callback: function(xhr) {
								if (xhr.status < 400 && xhr.responseText) {
									resolve([atob(JSON.parse(xhr.responseText).content)]);
								} else {
									reject();
								}
							}
						});
					});
				}
				return Promise.reject(src);
			});
		}
		else {
			return Promise.resolve(src);
		}
	}
	var loadAsset = function(src, doc) {
		doc = doc || iframe.contentDocument || document;
		var xtn = (src.toLowerCase().match(/\.(css|js)$/)||[,''])[1];
		if (!xtn) return Promise.reject(src);

		return pathOrContent(src).then(function(result) {
			return new Promise(function(resolve,reject) {
				if (typeof result === "string") {
					if (xtn === "js") {
						var script = doc.createElement("script");
						script.src = src;
						script.onload = ping(resolve,src);
						script.onerror = ping(reject,src,true);
						doc.head.appendChild(script);
					}
					else if (xtn === "css") {
						var css = doc.createElement("link");
						css.rel = "stylesheet";
						css.href = src;
						doc.head.appendChild(css);
						Promise.resolve(src);
					}
				}
				else {
					if (xtn === "js") {
						$u.element.create("script",{inside:doc.head,contents:result[0]});
					}
					else if (xtn === "css") {
						$u.element.create("style",{inside:doc.head,contents:result[0]});
					}
					resolve(src);
				}
			});
		});
	};

	var getFiles = function(category, id) {
		var files = { js: [], css: [] };
		var template = opt(category, id, "path").replace(/\{id}/g, id);

		var m = template.match(/\.(css|js)$/);
		if (m) {
			files[m[1]].push(template);
		}
		else {
			if (!opt(category, id, "noJS")) {
				files.js.push(template.replace(/(\.js)?$/, ".js"));
			}
			if (!opt(category, id, "noCSS")) {
				files.css.push(template.replace(/(\.css)?$/, ".css"));
			}
			if (opt(category, id, "themedCSS")) {
				files.css.push(template.replace(/(\.css)?$/, "-" + config.theme + ".css"));
			}
		}
		return files;
	};

	var generateFileList = function() {
		promises = {};
		var themeName = $("input[name='themes']:checked").value;
		config.theme = themeName.replace(/^prism-?/, "") || "default";

		var langwas = langselect.value || localStorage["language"];
		while(langselect.options.length)
			langselect.options[0].remove();

		if (iframe != null) {
			iframe.remove();
		}
		if (timer) {
			clearTimeout(timer);
		}

		iframe = $u.element.create("iframe",{inside:output,className:"wide"});

		timer = setTimeout(function() {
			if (!config.isRepo) {
				$u.element.create("base",{
					inside:iframe.contentDocument.head,
					prop:{href:config.baseUrl}
				});
			}

			// general theme CSS must be loaded before any plugin CSS
			getFiles("themes", themeName).css.map(loadAsset);

			loadAsset("components/prism-core.js", iframe.contentDocument).then(function() {
				return Promise.all($$("input[name='languages']:checked").reduce(function(p, input){
					$u.element.create("option",{
						inside:langselect,
						contents:input.value,
						prop:{
							value:input.value,
							selected: input.value === langwas
						}});
					p.push(loadLanguage(input.value));
					return p;
				}, []));
			}).then(function() {
				return Promise.all($$("input[name='plugins']:checked").reduce(function(p, input){
					var files = getFiles(input.name, input.value);
					files.css.map(loadAsset)
					return p.concat(files.js.map(loadAsset));
				}, []));
			}).then(updateCode)
		}, 10);
	}

	var updateCode = function() {
		var body = $("body", iframe.contentDocument);
		while (body.childNodes.length)
			body.childNodes[0].remove();

		var container = $u.element.create("div",{inside:body});
		var pre = $u.element.create("pre", {
			inside: container,
			className: "language-" + langselect.value
		});

		$u.element.create("code", { inside: pre, contents: code.value });

		$$("input[name='plugins']:checked")
			.map(function(v) { return config.attr[v.value] || {} })
			.forEach(function(attr) {
				Object.keys(attr).forEach(function(k) {
					if (k === "class") {
						pre.classList.add(attr.class)
					}
					else {
						pre.setAttribute(k, attr[k]);
					}
				})
			});
		saveConfig();

		iframe.contentWindow.Prism.highlightAll();
	}

	var createListItem = function(list, def, category, id, type) {
		var item = $u.element.create("li", {inside:list});
		var title = typeof def[id] === "string" ? def[id] : (def[id].title || id);
		var label = $u.element.create("label",{
			inside:item
		});
		var cb = $u.element.create("input",{
			prop: {
				type: type,
				name: category,
				value: id,
				checked: config[category][id]
			},
			inside:label
		});
		$u.element.create({contents:title,inside:label})
		return item;
	};

	var checkDeps = function(lang, enabled) {
		config.languages[lang] = enabled;
		var deps = enabled
			? components.languages[lang].require
			: components.languages[lang].children;
		deps.forEach(function(dep) {
			var input = $("input[name='languages'][value='"+dep+"']");
			if (input.checked != enabled) {
				input.checked = enabled;
				checkDeps(dep, enabled);
			}
		})
	};

	loadAsset((config.isRepo ? "" : config.baseUrl) + "components.js", document).then(function() {
		Object.keys(components.languages).filter(notMeta).forEach(function(lang) {
			components.languages[lang].children = components.languages[lang].children || [];
			components.languages[lang].require = [].concat(components.languages[lang].require || []);
		});
		Object.keys(components.languages).filter(notMeta).forEach(function(lang) {
			components.languages[lang].require.forEach(function(parent) {
				components.languages[parent].children.push(lang);
			})
		});

		["languages", "plugins", "themes"].forEach(function(category){
			var list = $u.element.create("ul",{inside:configuration});
			Object.keys(components[category]).filter(notMeta).forEach(function(id) {
				if (config.first) {
					config[category][id] = components[category][id].option === "default";
				}
				createListItem(list, components[category], category, id, components[category].meta.exclusive ? "radio" : "checkbox");
			});
		});

		generateFileList();

		configuration.addEventListener("change", function(e) {
			var target = e.target;
			if (target.name === "languages") {
				checkDeps(target.value, target.checked);
			}
			config[target.name][target.value] = target.checked;
			generateFileList();
		});

		langselect.addEventListener("change", function() {
			localStorage["language"] = langselect.value;
			var code = $("code", iframe.contentDocument);
			var pre = $("pre", iframe.contentDocument);
			[code,pre].forEach(function(v) {
				v.className = v.className.replace(/\blang(uage)-\w+\b/g, "")
			});
			code.classList.add("language-"+langselect.value);
			iframe.contentWindow.Prism.highlightAll();
		})

		input.addEventListener("input", updateCode);
	}).catch(function(what) {
		alert("Something went wrong loading " + (what || "... something :("));
		if (what && what.match("components")) {
			base.value = defaultBaseUrl;
			saveConfig();
			location.reload();
		}
	});

	// always make this available
	base.addEventListener("change", function() {
		saveConfig();
		location.reload();
	})
})();<commit_msg>I should feel worse about this hack, but I do not. Not at all.<commit_after>(function() {
	var treePromise = null;
	var defaultBaseUrl = "http://prismjs.com/"
	var getConfig = function() {
		try {
			var config = JSON.parse(localStorage["config"]);
			var repo = config.baseUrl.match("https://github.com/([^/]+)/([^/]+)/tree/([^/]+)(?:/|$)");
			if (repo) {
				config.baseUrl = "https://api.github.com/repos/"+repo[1]+"/"+repo[2]+"/git/trees/"+repo[3]+"?recursive=1";
			}
			config.isRepo = config.baseUrl.match("https://api.github.*recursive");
			if (config.isRepo) {
				treePromise = new Promise(function(resolve) {
					$u.xhr({
						url: config.baseUrl,
						callback: function(xhr) {
							if (xhr.status < 400) {
								resolve(JSON.parse(xhr.responseText).tree.reduce(function(dict,v) {
									dict[v.path] = v.url;
									return dict;
								}, {}));
							}
						}
					});
				});
			}

		} catch(error) {
			var config = {
				first: true,
				baseUrl: defaultBaseUrl,
				languages: {},
				language: undefined,
				plugins: {},
				themes: {},
				code: '

Some Heading
\n\t
\n\t\t
Hello World!
\n\t
\n
',
				attr: {
					"line-highlight": {
						"data-line": "1-2,4"
					},
					"line-numbers": {
						"class": "line-numbers"
					}
				}
			};
		}
		base.value = config.baseUrl;
		code.value = config.code;
		return config;
	};
	var saveConfig = function() {
		config.first = false;
		config.baseUrl = (base.value || defaultBaseUrl).replace(/\/+$/,"") + "/";
		["languages","plugins","themes"].forEach(function(category){
			$$("input[name='"+category+"']").forEach(function(input){
				config[category][input.value]=input.checked;
			})
		});
		config.language = langselect.value;
		config.code = code.value;
		localStorage["config"] = JSON.stringify(config);
	};

	var config = getConfig();

	var notMeta = function(v) { return v !== "meta"; }
	var iframe, promises = {}, timer = 0;

	var ping = function(func,what,err) {
		return function() {
			console.log(what, typeof err === "boolean" ? (err ? "failed" : "OK") : (err || "ok"));
			func(what);
		}
	};
	var opt = function(category, id, name) {
		return typeof components[category][id][name] !== "undefined"
			? components[category][id][name]
			: components[category].meta[name];
	};
	var loadLanguage = function(lang) {
		if (!promises[lang]) {
			promises[lang] = Promise.all(components.languages[lang].require.map(loadLanguage)).then(function() {
				var files = getFiles('languages', lang);
				files.css.map(loadAsset);
				return Promise.all(files.js.map(loadAsset));
			});
		}
		return promises[lang];
	};
	var pathOrContent = function(src) {
		if (config.isRepo) {
			return treePromise.then(function(paths) {
				if (paths[src]) {
					return new Promise(function(resolve, reject) {
						$u.xhr({
							url: paths[src],
							callback: function(xhr) {
								if (xhr.status < 400 && xhr.responseText) {
									resolve([atob(JSON.parse(xhr.responseText).content)]);
								} else {
									reject();
								}
							}
						});
					});
				}
				return Promise.reject(src);
			});
		}
		else {
			return Promise.resolve(src);
		}
	}
	var loadAsset = function(src, doc) {
		// oh the hacks! Array.map(loadAsset) means doc will be an index, so just ignore
		doc = (typeof doc === "number" ? 0 : doc) || iframe.contentDocument || document;
		var xtn = (src.toLowerCase().match(/\.(css|js)$/)||[,''])[1];
		if (!xtn) return Promise.reject(src);

		return pathOrContent(src).then(function(result) {
			return new Promise(function(resolve,reject) {
				if (typeof result === "string") {
					if (xtn === "js") {
						var script = doc.createElement("script");
						script.src = src;
						script.onload = ping(resolve,src);
						script.onerror = ping(reject,src,true);
						doc.head.appendChild(script);
					}
					else if (xtn === "css") {
						var css = doc.createElement("link");
						css.rel = "stylesheet";
						css.href = src;
						doc.head.appendChild(css);
						Promise.resolve(src);
					}
				}
				else {
					if (xtn === "js") {
						$u.element.create("script",{inside:doc.head,contents:result[0]});
					}
					else if (xtn === "css") {
						$u.element.create("style",{inside:doc.head,contents:result[0]});
					}
					resolve(src);
				}
			});
		});
	};

	var getFiles = function(category, id) {
		var files = { js: [], css: [] };
		var template = opt(category, id, "path").replace(/\{id}/g, id);

		var m = template.match(/\.(css|js)$/);
		if (m) {
			files[m[1]].push(template);
		}
		else {
			if (!opt(category, id, "noJS")) {
				files.js.push(template.replace(/(\.js)?$/, ".js"));
			}
			if (!opt(category, id, "noCSS")) {
				files.css.push(template.replace(/(\.css)?$/, ".css"));
			}
			if (opt(category, id, "themedCSS")) {
				files.css.push(template.replace(/(\.css)?$/, "-" + config.theme + ".css"));
			}
		}
		return files;
	};

	var generateFileList = function() {
		promises = {};
		var themeName = $("input[name='themes']:checked").value;
		config.theme = themeName.replace(/^prism-?/, "") || "default";

		var langwas = langselect.value || localStorage["language"];
		while(langselect.options.length)
			langselect.options[0].remove();

		if (iframe != null) {
			iframe.remove();
		}
		if (timer) {
			clearTimeout(timer);
		}

		iframe = $u.element.create("iframe",{inside:output,className:"wide"});

		timer = setTimeout(function() {
			if (!config.isRepo) {
				$u.element.create("base",{
					inside:iframe.contentDocument.head,
					prop:{href:config.baseUrl}
				});
			}

			// general theme CSS must be loaded before any plugin CSS
			getFiles("themes", themeName).css.map(loadAsset);

			loadAsset("components/prism-core.js").then(function() {
				return Promise.all($$("input[name='languages']:checked").reduce(function(p, input){
					$u.element.create("option",{
						inside:langselect,
						contents:input.value,
						prop:{
							value:input.value,
							selected: input.value === langwas
						}});
					p.push(loadLanguage(input.value));
					return p;
				}, []));
			}).then(function() {
				return Promise.all($$("input[name='plugins']:checked").reduce(function(p, input){
					var files = getFiles(input.name, input.value);
					files.css.map(loadAsset)
					return p.concat(files.js.map(loadAsset));
				}, []));
			}).then(updateCode)
		}, 10);
	}

	var updateCode = function() {
		var body = $("body", iframe.contentDocument);
		while (body.childNodes.length)
			body.childNodes[0].remove();

		var container = $u.element.create("div",{inside:body});
		var pre = $u.element.create("pre", {
			inside: container,
			className: "language-" + langselect.value
		});

		$u.element.create("code", { inside: pre, contents: code.value });

		$$("input[name='plugins']:checked")
			.map(function(v) { return config.attr[v.value] || {} })
			.forEach(function(attr) {
				Object.keys(attr).forEach(function(k) {
					if (k === "class") {
						pre.classList.add(attr.class)
					}
					else {
						pre.setAttribute(k, attr[k]);
					}
				})
			});
		saveConfig();

		iframe.contentWindow.Prism.highlightAll();
	}

	var createListItem = function(list, def, category, id, type) {
		var item = $u.element.create("li", {inside:list});
		var title = typeof def[id] === "string" ? def[id] : (def[id].title || id);
		var label = $u.element.create("label",{
			inside:item
		});
		var cb = $u.element.create("input",{
			prop: {
				type: type,
				name: category,
				value: id,
				checked: config[category][id]
			},
			inside:label
		});
		$u.element.create({contents:title,inside:label})
		return item;
	};

	var checkDeps = function(lang, enabled) {
		config.languages[lang] = enabled;
		var deps = enabled
			? components.languages[lang].require
			: components.languages[lang].children;
		deps.forEach(function(dep) {
			var input = $("input[name='languages'][value='"+dep+"']");
			if (input.checked != enabled) {
				input.checked = enabled;
				checkDeps(dep, enabled);
			}
		})
	};

	loadAsset((config.isRepo ? "" : config.baseUrl) + "components.js", document).then(function() {
		Object.keys(components.languages).filter(notMeta).forEach(function(lang) {
			components.languages[lang].children = components.languages[lang].children || [];
			components.languages[lang].require = [].concat(components.languages[lang].require || []);
		});
		Object.keys(components.languages).filter(notMeta).forEach(function(lang) {
			components.languages[lang].require.forEach(function(parent) {
				components.languages[parent].children.push(lang);
			})
		});

		["languages", "plugins", "themes"].forEach(function(category){
			var list = $u.element.create("ul",{inside:configuration});
			Object.keys(components[category]).filter(notMeta).forEach(function(id) {
				if (config.first) {
					config[category][id] = components[category][id].option === "default";
				}
				createListItem(list, components[category], category, id, components[category].meta.exclusive ? "radio" : "checkbox");
			});
		});

		generateFileList();

		configuration.addEventListener("change", function(e) {
			var target = e.target;
			if (target.name === "languages") {
				checkDeps(target.value, target.checked);
			}
			config[target.name][target.value] = target.checked;
			generateFileList();
		});

		langselect.addEventListener("change", function() {
			localStorage["language"] = langselect.value;
			var code = $("code", iframe.contentDocument);
			var pre = $("pre", iframe.contentDocument);
			[code,pre].forEach(function(v) {
				v.className = v.className.replace(/\blang(uage)-\w+\b/g, "")
			});
			code.classList.add("language-"+langselect.value);
			iframe.contentWindow.Prism.highlightAll();
		})

		input.addEventListener("input", updateCode);
	}).catch(function(what) {
		alert("Something went wrong loading " + (what || "... something :("));
		if (what && what.match("components")) {
			base.value = defaultBaseUrl;
			saveConfig();
			location.reload();
		}
	});

	// always make this available
	base.addEventListener("change", function() {
		saveConfig();
		location.reload();
	})
})();<|endoftext|>


<commit_before>var protocol = require('../protocol.js');
var _ = require('underscore');

var clientGamePackets = {};

//-----------------------------------------------//
// Game server client packets                   //
//-----------------------------------------------//

clientGamePackets.RequestTargetCancel = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readH();
    p.unselect = p._data[0];
    return p;
}

clientGamePackets.RequestStartPledgeWar = function (buffer) {
    var p = new protocol.ClientPacket(buffer);

    p.readS();
    p.pledgeName = p._data[0];

    return p;
}

clientGamePackets.ExSendClientINI = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readC(); // 0x04
    p.readC(); // 0x01
    p.readC(); // partNumber
    p.readH(); // size

    p.packetId2 = p._data[0];
    p.packetId3 = p._data[1];
    p.partNumber = p._data[2];
    p.size = p._data[3];

    p.readB(p.size);
    p.content = p._data[4];

    return p;
}

clientGamePackets.CharacterCreate = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readS();

    p.readD();
    p.readD();
    p.readD();

    p.readD(); // INT
    p.readD(); // STR
    p.readD(); // CON
    p.readD(); // MEN
    p.readD(); // DEX
    p.readD(); // WIT

    p.readD();
    p.readD();
    p.readD();

    p.Name = p._data[0];
    p.Race = p._data[1];
    p.Sex = p._data[2];
    p.ClassId = p._data[3];

    p.HairStyle = p._data[10];
    p.HairColor = p._data[11];
    p.Face = p._data[12];

    return p;
};

clientGamePackets.RequestAction = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readC();
    p.ObjectId = p._data[0];
    p.X = p._data[1];
    p.Y = p._data[2];
    p.Z = p._data[3];
    p.Action = p._data[4];
    return p;
};

clientGamePackets.ValidatePosition = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.X = p._data[0];
    p.Y = p._data[1];
    p.Z = p._data[2];
    p.Heading = p._data[3];
    return p;
};

clientGamePackets.Say2 = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    try {
        if (buffer.length >= 12) {
            p.readS();
            p.readD();

            p.text = p._data[0];
            p.type = p._data[1];

            if (p.type < 0 || p.type > 23) {
                p.type = 0;
            }

            if (p.type == 2) { // CHAT_TELL
                p.readS();
                p.target = p._data[2];
            }

            p.real = true;
        }
    } catch (ex) {
        console.log(ex); // TODO: exception Say2 packet on Create Character.   0_o
        p.real = false;
    }

    return p;

    /*
	    public static final int ALL = 0;
	    public static final int SHOUT = 1; // !
	    public static final int TELL = 2;
	    public static final int PARTY = 3; // #
	    public static final int CLAN = 4; // @
	    public static final int GM = 5;
	    public static final int PETITION_PLAYER = 6; // used for petition
	    public static final int PETITION_GM = 7; // * used for petition
	    public static final int TRADE = 8; // +
	    public static final int ALLIANCE = 9; // $
	    public static final int ANNOUNCEMENT = 10;
	    public static final int BOAT = 11;
	    public static final int L2FRIEND = 12;
	    public static final int MSNCHAT = 13;
	    public static final int PARTYMATCH_ROOM = 14;
	    public static final int PARTYROOM_COMMANDER = 15; // (Yellow)
	    public static final int PARTYROOM_ALL = 16; // (Red)
	    public static final int HERO_VOICE = 17;
	    public static final int CRITICAL_ANNOUNCE = 18;
	    public static final int SCREEN_ANNOUNCE = 19;
	    public static final int BATTLEFIELD = 20;
	    public static final int MPCC_ROOM = 21;
	    public static final int NPC_ALL = 22;
	    public static final int NPC_SHOUT = 23;
    */
}

clientGamePackets.MoveBackwardToLocation = function (buffer) {
    var p = new protocol.ClientPacket(buffer);

    console.log(p._buffer.toString('hex'));

    if ((p._buffer[7] + p._buffer[23] == 255) && p._buffer[6] == 0 && p._buffer[2] == 255) {
        p._buffer[7] = 0;
        p._buffer[23] = 255;
    }

    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();

    console.log(p._buffer.toString('hex'));

    p.toX = p._data[0];
    p.toY = p._data[1];
    p.toZ = p._data[2];

    p.origX = p._data[3];
    p.origY = p._data[4];
    p.origZ = p._data[5];

    p.mouse = p._data[6];  // is 0 if cursor keys are used 1 if mouse is used

    return p;
}

clientGamePackets.ProtocolVersion = function(buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.protocolVersion = p._data[0];
    return p;
}

clientGamePackets.CharacterSelected = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.charIndex = p._data[0];
    return p;
}

clientGamePackets.AuthLogin = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readS()
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.login = p._data[0].toLowerCase();
    p.session2_2 = p._data[1];
    p.session2_1 = p._data[2];
    p.session1_1 = p._data[3];
    p.session1_2 = p._data[4];
    return p;
}

module.exports = clientGamePackets;<commit_msg>MBTL packet - 16<commit_after>var protocol = require('../protocol.js');
var _ = require('underscore');

var clientGamePackets = {};

//-----------------------------------------------//
// Game server client packets                   //
//-----------------------------------------------//

clientGamePackets.RequestTargetCancel = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readH();
    p.unselect = p._data[0];
    return p;
}

clientGamePackets.RequestStartPledgeWar = function (buffer) {
    var p = new protocol.ClientPacket(buffer);

    p.readS();
    p.pledgeName = p._data[0];

    return p;
}

clientGamePackets.ExSendClientINI = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readC(); // 0x04
    p.readC(); // 0x01
    p.readC(); // partNumber
    p.readH(); // size

    p.packetId2 = p._data[0];
    p.packetId3 = p._data[1];
    p.partNumber = p._data[2];
    p.size = p._data[3];

    p.readB(p.size);
    p.content = p._data[4];

    return p;
}

clientGamePackets.CharacterCreate = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readS();

    p.readD();
    p.readD();
    p.readD();

    p.readD(); // INT
    p.readD(); // STR
    p.readD(); // CON
    p.readD(); // MEN
    p.readD(); // DEX
    p.readD(); // WIT

    p.readD();
    p.readD();
    p.readD();

    p.Name = p._data[0];
    p.Race = p._data[1];
    p.Sex = p._data[2];
    p.ClassId = p._data[3];

    p.HairStyle = p._data[10];
    p.HairColor = p._data[11];
    p.Face = p._data[12];

    return p;
};

clientGamePackets.RequestAction = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readC();
    p.ObjectId = p._data[0];
    p.X = p._data[1];
    p.Y = p._data[2];
    p.Z = p._data[3];
    p.Action = p._data[4];
    return p;
};

clientGamePackets.ValidatePosition = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.X = p._data[0];
    p.Y = p._data[1];
    p.Z = p._data[2];
    p.Heading = p._data[3];
    return p;
};

clientGamePackets.Say2 = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    try {
        if (buffer.length >= 12) {
            p.readS();
            p.readD();

            p.text = p._data[0];
            p.type = p._data[1];

            if (p.type < 0 || p.type > 23) {
                p.type = 0;
            }

            if (p.type == 2) { // CHAT_TELL
                p.readS();
                p.target = p._data[2];
            }

            p.real = true;
        }
    } catch (ex) {
        console.log(ex); // TODO: exception Say2 packet on Create Character.   0_o
        p.real = false;
    }

    return p;

    /*
	    public static final int ALL = 0;
	    public static final int SHOUT = 1; // !
	    public static final int TELL = 2;
	    public static final int PARTY = 3; // #
	    public static final int CLAN = 4; // @
	    public static final int GM = 5;
	    public static final int PETITION_PLAYER = 6; // used for petition
	    public static final int PETITION_GM = 7; // * used for petition
	    public static final int TRADE = 8; // +
	    public static final int ALLIANCE = 9; // $
	    public static final int ANNOUNCEMENT = 10;
	    public static final int BOAT = 11;
	    public static final int L2FRIEND = 12;
	    public static final int MSNCHAT = 13;
	    public static final int PARTYMATCH_ROOM = 14;
	    public static final int PARTYROOM_COMMANDER = 15; // (Yellow)
	    public static final int PARTYROOM_ALL = 16; // (Red)
	    public static final int HERO_VOICE = 17;
	    public static final int CRITICAL_ANNOUNCE = 18;
	    public static final int SCREEN_ANNOUNCE = 19;
	    public static final int BATTLEFIELD = 20;
	    public static final int MPCC_ROOM = 21;
	    public static final int NPC_ALL = 22;
	    public static final int NPC_SHOUT = 23;
    */
}

clientGamePackets.MoveBackwardToLocation = function (buffer) {
    var p = new protocol.ClientPacket(buffer);

    console.log(p._buffer.toString('hex'));
    console.log(p._buffer[7].toString('hex') + ' ' + p._buffer[23]);

    if ((p._buffer[7] + p._buffer[23] == 255) && p._buffer[6] == 0 && p._buffer[2] == 255) {
        p._buffer[7] = 0;
        p._buffer[23] = 255;
    }

    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.readD();

    console.log(p._buffer.toString('hex'));

    p.toX = p._data[0];
    p.toY = p._data[1];
    p.toZ = p._data[2];

    p.origX = p._data[3];
    p.origY = p._data[4];
    p.origZ = p._data[5];

    p.mouse = p._data[6];  // is 0 if cursor keys are used 1 if mouse is used

    return p;
}

clientGamePackets.ProtocolVersion = function(buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.protocolVersion = p._data[0];
    return p;
}

clientGamePackets.CharacterSelected = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readD();
    p.charIndex = p._data[0];
    return p;
}

clientGamePackets.AuthLogin = function (buffer) {
    var p = new protocol.ClientPacket(buffer);
    p.readS()
    p.readD();
    p.readD();
    p.readD();
    p.readD();
    p.login = p._data[0].toLowerCase();
    p.session2_2 = p._data[1];
    p.session2_1 = p._data[2];
    p.session1_1 = p._data[3];
    p.session1_2 = p._data[4];
    return p;
}

module.exports = clientGamePackets;<|endoftext|>


<commit_before>$(function () {

    $(".cartNavInner").each(function () {
        appendDiscontinued(this);
    });

    $(".stockOpen").each(function () {
        var stockLink = "http://www.yodobashi.com/" + $(this).attr('rel');
        getStock(stockLink, this);
    });
});

function getStock(stockUrl, target) {
    var myStoreName = "";
    chrome.runtime.sendMessage({action: "getLocalStorage"}, function (response) {
        if (response["store_name"]) {
            myStoreName = response["store_name"];
        }
    });

    $.ajax({
        url: stockUrl,
    }).done(function (data) {
        var stock = "在庫なし";
        $(data).find(".storeInfoUnit").each(function () {
            var storeName = $(this).find(".storeName").text();
            if (storeName == myStoreName) {
                stock = $(this).find(".uiIconTxtS").text();
            }
        });
        $(target).html(myStoreName + ":" + stock);
    }).fail(function (data) {
    });
}

function appendDiscontinued(target) {
    var newInput = $(target).html() + "<input type='hidden' name='discontinued' value='false'>";
    $(target).html(newInput);
}
<commit_msg>Set default store<commit_after>$(function () {

    $(".cartNavInner").each(function () {
        appendDiscontinued(this);
    });

    $(".stockOpen").each(function () {
        var stockLink = "http://www.yodobashi.com/" + $(this).attr('rel');
        getStock(stockLink, this);
    });
});

function getStock(stockUrl, target) {
    var myStoreName = "ヨドバシ・ドット・コム";
    chrome.runtime.sendMessage({action: "getLocalStorage"}, function (response) {
        if (response["store_name"]) {
            myStoreName = response["store_name"];
        }
    });

    $.ajax({
        url: stockUrl,
    }).done(function (data) {
        var stock = "在庫なし";
        $(data).find(".storeInfoUnit").each(function () {
            var storeName = $(this).find(".storeName").text();
            if (storeName == myStoreName) {
                stock = $(this).find(".uiIconTxtS").text();
            }
        });
        $(target).html(myStoreName + ":" + stock);
    }).fail(function (data) {
    });
}

function appendDiscontinued(target) {
    var newInput = $(target).html() + "<input type='hidden' name='discontinued' value='false'>";
    $(target).html(newInput);
}
<|endoftext|>


<commit_before>export { ScaleArray };

/**
 * Describe an array of scale (i.e. multiplier) values.
 *
 * @member {number[]} scales
 *   The scale (i.e. multiplier) values.
 */
class ScaleArray {

  constructor( length ) {
    this.scales = new Array( length );
  }

  clone() {
    let result = new ScaleArray( this.scales.length );
    result.set_all_byScaleArray( this );
    return result;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} N          Set ( this.scales[ thisIndex ] ) by ( N ). Default are ( N = 1 ) (i.e. no scale).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byN( thisIndex, N = 1 ) {
    this.scales[ thisIndex ] = N;
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number[]} Ns       Set ( this.scales[ thisIndex ] ) by ( Ns[ aIndex ] ).
   * @param {number} aIndex     The array index of Ns[].
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byNs( thisIndex, Ns, aIndex ) {
    return this.set_one_byN( thisIndex, Ns[ aIndex ] );
  }

  /**
   * Set this.scales[ thisIndex ] to a scale value which could let source bounds [ fromLower, fromUpper ] completely insides destination
   * bounds [ toLower, toUpper ].
   *
   * Note: this.scales[ thisIndex ] may become Number.NaN, if it is impossible to let source bounds completely insides destination
   * bounds.
   *
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} fromLower  The source bounds [ fromLower, fromUpper ]
   * @param {number} fromUpper  The source bounds [ fromLower, fromUpper ]
   * @param {number} toLower    The destination bounds [ toLower, toUpper ]
   * @param {number} toUpper    The destination bounds [ toLower, toUpper ]
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_by_fromLowerUpper_toLowerUpper( thisIndex, fromLower, fromUpper, toLower, toUpper ) {
    let aScale = ScaleArray.calc_scale_by_fromLowerUpper_toLowerUpper( fromLower, fromUpper, toLower, toUpper );
    this.scales[ thisIndex ] = aScale;
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} N          Set ( this.scales[ thisIndex ] ) by ( 1 / N ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byUndo_N( thisIndex, N ) {
    this.scales[ thisIndex ] = ( 1 / N );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number[]} Ns       Set ( this.scales[ thisIndex ] ) by ( 1 / Ns[ aIndex ] ).
   * @param {number} aIndex     The array index of Ns[].
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byUndo_Ns( thisIndex, Ns, aIndex ) {
    this.scales[ thisIndex ] = ( 1 / Ns[ aIndex ] );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    return this;
  }

  /**
   * @param {number} N  Set all ( this.scales[] ) by ( N ). Default are ( N = 1 ) (i.e. no scale).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byN( N = 1 ) {
    this.scales.fill( N );
    return this;
  }

  /**
   * @param {number[]} Ns  Set all ( this.scales[] ) by ( Ns[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byNs( Ns ) {
    for ( let i = 0; i < this.scales.length; ++i ) {
      this.scales[ i ] = Ns[ i ];
    }
    return this;
  }

  /**
   * @param {ScaleArray} aScaleArray  Set all ( this.scales[] ) by ( aScaleArray.scales[] ).
   *
   * @return {ScaleArray} Return this (modified) object whose values are copied from aScaleArray.
   */
  set_all_byScaleArray( aScaleArray ) {
    return this.set_all_byNs( aScaleArray.scales );
  }

  /**
   * @param {number[]} Ns  Set all ( this.scales[] ) by ( 1 / Ns[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byUndo_Ns( Ns ) {
    for ( let i = 0; i < this.scales.length; ++i ) {
      this.scales[ i ] = ( 1 / Ns[ i ] );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    }
    return this;
  }

  /**
   * @param {ScaleArray} aScaleArray  Set all ( this.scales[] ) by ( 1 / aScaleArray.scales[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byUndo_ScaleArray( aScaleArray ) {
    return this.set_all_byUndo_Ns( aScaleArray.scales );
  }

  /**
   *
   * @param {number} fromLower  The source bounds [ fromLower, fromUpper ]
   * @param {number} fromUpper  The source bounds [ fromLower, fromUpper ]
   * @param {number} toLower    The destination bounds [ toLower, toUpper ]
   * @param {number} toUpper    The destination bounds [ toLower, toUpper ]
   *
   * @return {number}
   *   Return a scale value which could let source bounds [ fromLower, fromUpper ] completely insides destination bounds [ toLower, toUpper ].
   * Return Number.NaN, if it is impossible to do that.
   */
  static calc_scale_by_fromLowerUpper_toLowerUpper( fromLower, fromUpper, toLower, toUpper ) {
    let srcLower = Math.min( fromLower, fromUpper ); // Confirm ( lower <= upper ).
    let srcUpper = Math.max( fromLower, fromUpper );
    let dstLower = Math.min( toLower, toUpper );
    let dstUpper = Math.max( toLower, toUpper );

    let scale;

    // 1. Try lower bound.
    //
    // Note:
    //  ( x / +Infinity ) == +0
    //  ( x / -Infinity ) == -0
    //  (  0 / x ) = 0
    //  ( -1 / 0 ) = -Infinity
    //  ( +1 / 0 ) = +Infinity
    //  (  0 / 0 ) = NaN
    //  ( +-Infinity / +-Infinity ) == NaN
    //
    scale = dstLower / srcLower;

//!!! (2022/01/06 Remarked)
//     if ( ( srcLower == 0 ) || ( dstLower == 0 ) ) {
//       scale = 0; // Avoid -Infinity, +Infinity, NaN.
//     } else {
//       scale = dstLower / srcLower;
//     }

    // 1.2 Verification.
    //   - If scale is zero or -Infinity or +Infinity or NaN, it is always failed.
    //   - If scaled source upper bound is out of destination range, it is also failed.
    let adjustedUpper = srcUpper * scale;
    if ( ( scale == 0 ) || ( !Number.isFinite( scale ) ) || ( adjustedUpper < dstLower ) || ( adjustedUpper > dstUpper ) ) {

      // 2. Try upperer bound, since it is failed to fit [ srcLower, srcUpper ] into [ dstLower, dstUpper ] by scale according to lower bound.
      scale = dstUpper / srcUpper;

//!!! (2022/01/06 Remarked)
//       if ( ( srcUpper == 0 ) || ( dstUpper == 0 ) ) {
//         scale = 0; // Avoid -Infinity, +Infinity, NaN.
//       } else {
//         scale = dstUpper / srcUpper;
//       }

      // 2.2 Verification. If scale is zero, it is always failed. Otherwise, check it by lower side.
      //   - If scale is zero or -Infinity or +Infinity or NaN, it is always failed.
      //   - If scaled source lower bound is out of destination range, it is also failed.
      let adjustedLower = srcLower * scale;
      if ( ( scale == 0 ) || ( !Number.isFinite( scale ) ) || ( adjustedLower < dstLower ) || ( adjustedLower > dstUpper ) ) {
        // 3. It is impossible to fit [ srcLower, srcUpper ] into [ dstLower, dstUpper ] only by scale because all cases are tried and failed.
        scale = Number.NaN;
      }
    }

    return scale;
  }

}

<commit_msg>Update ScaleArray.js<commit_after>export { ScaleArray };

/**
 * Describe an array of scale (i.e. multiplier) values.
 *
 * @member {number[]} scales
 *   The scale (i.e. multiplier) values.
 */
class ScaleArray {

  constructor( length ) {
    this.scales = new Array( length );
  }

  /**
   * @return {ScaleArray} Return a newly created ScaleArray which copies this object.
   */
  clone() {
    let result = new ScaleArray( this.scales.length );
    result.set_all_byScaleArray( this );
    return result;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} N          Set ( this.scales[ thisIndex ] ) by ( N ). Default are ( N = 1 ) (i.e. no scale).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byN( thisIndex, N = 1 ) {
    this.scales[ thisIndex ] = N;
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number[]} Ns       Set ( this.scales[ thisIndex ] ) by ( Ns[ aIndex ] ).
   * @param {number} aIndex     The array index of Ns[].
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byNs( thisIndex, Ns, aIndex ) {
    return this.set_one_byN( thisIndex, Ns[ aIndex ] );
  }

  /**
   * Set this.scales[ thisIndex ] to a scale value which could let source bounds [ fromLower, fromUpper ] completely insides destination
   * bounds [ toLower, toUpper ].
   *
   * Note: this.scales[ thisIndex ] may become Number.NaN, if it is impossible to let source bounds completely insides destination
   * bounds.
   *
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} fromLower  The source bounds [ fromLower, fromUpper ]
   * @param {number} fromUpper  The source bounds [ fromLower, fromUpper ]
   * @param {number} toLower    The destination bounds [ toLower, toUpper ]
   * @param {number} toUpper    The destination bounds [ toLower, toUpper ]
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_by_fromLowerUpper_toLowerUpper( thisIndex, fromLower, fromUpper, toLower, toUpper ) {
    let aScale = ScaleArray.calc_scale_by_fromLowerUpper_toLowerUpper( fromLower, fromUpper, toLower, toUpper );
    this.scales[ thisIndex ] = aScale;
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number} N          Set ( this.scales[ thisIndex ] ) by ( 1 / N ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byUndo_N( thisIndex, N ) {
    this.scales[ thisIndex ] = ( 1 / N );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    return this;
  }

  /**
   * @param {number} thisIndex  The array index of this.scales[].
   * @param {number[]} Ns       Set ( this.scales[ thisIndex ] ) by ( 1 / Ns[ aIndex ] ).
   * @param {number} aIndex     The array index of Ns[].
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_one_byUndo_Ns( thisIndex, Ns, aIndex ) {
    this.scales[ thisIndex ] = ( 1 / Ns[ aIndex ] );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    return this;
  }

  /**
   * @param {number} N  Set all ( this.scales[] ) by ( N ). Default are ( N = 1 ) (i.e. no scale).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byN( N = 1 ) {
    this.scales.fill( N );
    return this;
  }

  /**
   * @param {number[]} Ns  Set all ( this.scales[] ) by ( Ns[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byNs( Ns ) {
    for ( let i = 0; i < this.scales.length; ++i ) {
      this.scales[ i ] = Ns[ i ];
    }
    return this;
  }

  /**
   * @param {ScaleArray} aScaleArray  Set all ( this.scales[] ) by ( aScaleArray.scales[] ).
   *
   * @return {ScaleArray} Return this (modified) object whose values are copied from aScaleArray.
   */
  set_all_byScaleArray( aScaleArray ) {
    return this.set_all_byNs( aScaleArray.scales );
  }

  /**
   * @param {number[]} Ns  Set all ( this.scales[] ) by ( 1 / Ns[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byUndo_Ns( Ns ) {
    for ( let i = 0; i < this.scales.length; ++i ) {
      this.scales[ i ] = ( 1 / Ns[ i ] );  // Reciprocal will undo the scale. (Note: Not work for zero.)
    }
    return this;
  }

  /**
   * @param {ScaleArray} aScaleArray  Set all ( this.scales[] ) by ( 1 / aScaleArray.scales[] ).
   *
   * @return {ScaleArray} Return this (modified) object.
   */
  set_all_byUndo_ScaleArray( aScaleArray ) {
    return this.set_all_byUndo_Ns( aScaleArray.scales );
  }

  /**
   *
   * @param {number} fromLower  The source bounds [ fromLower, fromUpper ]
   * @param {number} fromUpper  The source bounds [ fromLower, fromUpper ]
   * @param {number} toLower    The destination bounds [ toLower, toUpper ]
   * @param {number} toUpper    The destination bounds [ toLower, toUpper ]
   *
   * @return {number}
   *   Return a scale value which could let source bounds [ fromLower, fromUpper ] completely insides destination bounds [ toLower, toUpper ].
   * Return Number.NaN, if it is impossible to do that.
   */
  static calc_scale_by_fromLowerUpper_toLowerUpper( fromLower, fromUpper, toLower, toUpper ) {
    let srcLower = Math.min( fromLower, fromUpper ); // Confirm ( lower <= upper ).
    let srcUpper = Math.max( fromLower, fromUpper );
    let dstLower = Math.min( toLower, toUpper );
    let dstUpper = Math.max( toLower, toUpper );

    let scale;

    // 1. Try lower bound.
    //
    // Note:
    //  ( x / +Infinity ) == +0
    //  ( x / -Infinity ) == -0
    //  (  0 / x ) = 0
    //  ( -1 / 0 ) = -Infinity
    //  ( +1 / 0 ) = +Infinity
    //  (  0 / 0 ) = NaN
    //  ( +-Infinity / +-Infinity ) == NaN
    //
    scale = dstLower / srcLower;

//!!! (2022/01/06 Remarked)
//     if ( ( srcLower == 0 ) || ( dstLower == 0 ) ) {
//       scale = 0; // Avoid -Infinity, +Infinity, NaN.
//     } else {
//       scale = dstLower / srcLower;
//     }

    // 1.2 Verification.
    //   - If scale is zero or -Infinity or +Infinity or NaN, it is always failed.
    //   - If scaled source upper bound is out of destination range, it is also failed.
    let adjustedUpper = srcUpper * scale;
    if ( ( scale == 0 ) || ( !Number.isFinite( scale ) ) || ( adjustedUpper < dstLower ) || ( adjustedUpper > dstUpper ) ) {

      // 2. Try upperer bound, since it is failed to fit [ srcLower, srcUpper ] into [ dstLower, dstUpper ] by scale according to lower bound.
      scale = dstUpper / srcUpper;

//!!! (2022/01/06 Remarked)
//       if ( ( srcUpper == 0 ) || ( dstUpper == 0 ) ) {
//         scale = 0; // Avoid -Infinity, +Infinity, NaN.
//       } else {
//         scale = dstUpper / srcUpper;
//       }

      // 2.2 Verification. If scale is zero, it is always failed. Otherwise, check it by lower side.
      //   - If scale is zero or -Infinity or +Infinity or NaN, it is always failed.
      //   - If scaled source lower bound is out of destination range, it is also failed.
      let adjustedLower = srcLower * scale;
      if ( ( scale == 0 ) || ( !Number.isFinite( scale ) ) || ( adjustedLower < dstLower ) || ( adjustedLower > dstUpper ) ) {
        // 3. It is impossible to fit [ srcLower, srcUpper ] into [ dstLower, dstUpper ] only by scale because all cases are tried and failed.
        scale = Number.NaN;
      }
    }

    return scale;
  }

}

<|endoftext|>


<commit_before>import React from 'react';
import {countries} from 'country-data';

import {
  Page,
  ProgressCircular
} from 'react-onsenui';

import NavBar from './NavBar';
import WeatherIcon from './WeatherIcon';

const WeatherPage = ({navigator, name, temperature, humidity, country, icon, isFetching, isInvalid}) => {
  let content;

  if (isInvalid) {
    content = (

Unable to fetch data!

    );
  } else if (isFetching) {
    content = (
      <ProgressCircular style={{width: '100px', height: '100px'}} indeterminate />
    );
  } else {
    content = (

          {name}

          {countries[country.toUpperCase()].name}

          <WeatherIcon icon={icon} />

          {temperature}°C

          {humidity}%

    );
  }

  return (
    <Page renderToolbar={() => <NavBar backButton={true} title={`Weather in ${name}`} navigator={navigator} />}>

      {content}

    </Page>
  );
};

export default WeatherPage;
<commit_msg>Remove unused file<commit_after><|endoftext|>


<commit_before>document.addEventListener("DOMContentLoaded", function(){
    var shiftOut = function(value) {
        if (value.length > 9) {
            return (value.substr(value.length-9,9));
	}
	else {
	    return (value);
	}
    };
    var number = "";
    var newnumber = "";
    var operator = "";
    var totaldiv = document.getElementById('total');
    var shiftKey = false;
    var myTimer;
    var myKeyPressed = null;
    totaldiv.textContent = '0';
    var keysList = document.getElementsByClassName('ckey');
    keyPress = function(thisKey, thisEvent) {
	myKeyPressed = thisKey;
	myTimer = setTimeout(function(){
	    shiftKey = !shiftKey;
	    window.navigator.vibrate(20);
	}, 500);
	window.navigator.vibrate(30);
	thisEvent.preventDefault();
    }
    keyLeave = function(thisKey, thisEvent) {
	clearTimeout(myTimer);
	thisEvent.preventDefault();
    }
    keyRelease = function(thisKey, thisEvent) {
	clearTimeout(myTimer);
	if (thisKey === myKeyPressed) {
	    var value = totaldiv.textContent;
	    value += thisKey.textContent;
	    if (shiftKey) { value += "x"; }
	    shiftKey = false;
	    totaldiv.textContent = shiftOut(value);
	}
	thisEvent.preventDefault();
    }
    for (var i = 0; i < keysList.length; i++) {
	var key = keysList[i];
	key.addEventListener("pointerdown", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("pointerleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("pointerup", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
	key.addEventListener("touchstart", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("touchleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("touchend", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
	key.addEventListener("mousedown", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("mouseleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("mouseup", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
    }
});
/*    $("#operators a").not("#equals").click(function(){
	operator = $(this).text();
	newnumber = number;
	number = "";
	totaldiv.text("0");
    });
    $("#clear,#clearall").click(function(){
	number = "";
	totaldiv.text("0");
	if ($(this).attr("id") === "clearall") {
	    newnumber = "";
	}
    }); */
/*    $("#equals").click(function(){
	if (operator === "+"){
	    number = (parseInt(number, 10) + parseInt(newnumber,10)).toString(10);
	} else if (operator === "-"){
	    number = (parseInt(newnumber, 10) - parseInt(number,10)).toString(10);
	} else if (operator === "/"){
	    number = (parseInt(newnumber, 10) / parseInt(number,10)).toString(10);
	} else if (operator === "*"){
	    number = (parseInt(newnumber, 10) * parseInt(number,10)).toString(10);
	}
	totaldiv.text(number);
	testNumLength(number);
	number = "";
	newnumber = "";
    });
*/

<commit_msg>make the times a little longer, clear key on leave<commit_after>document.addEventListener("DOMContentLoaded", function(){
    var shiftOut = function(value) {
        if (value.length > 9) {
            return (value.substr(value.length-9,9));
	}
	else {
	    return (value);
	}
    };
    var number = "";
    var newnumber = "";
    var operator = "";
    var totaldiv = document.getElementById('total');
    var shiftKey = false;
    var myTimer;
    var myKeyPressed = null;
    totaldiv.textContent = '0';
    var keysList = document.getElementsByClassName('ckey');
    keyPress = function(thisKey, thisEvent) {
	myKeyPressed = thisKey;
	myTimer = setTimeout(function(){
	    shiftKey = !shiftKey;
	    window.navigator.vibrate(30);
	}, 750);
	window.navigator.vibrate(40);
	thisEvent.preventDefault();
    }
    keyLeave = function(thisKey, thisEvent) {
	myKeyPressed = null;
	clearTimeout(myTimer);
	thisEvent.preventDefault();
    }
    keyRelease = function(thisKey, thisEvent) {
	clearTimeout(myTimer);
	if (thisKey === myKeyPressed) {
	    var value = totaldiv.textContent;
	    value += thisKey.textContent;
	    if (shiftKey) { value += "x"; }
	    shiftKey = false;
	    totaldiv.textContent = shiftOut(value);
	}
	thisEvent.preventDefault();
    }
    for (var i = 0; i < keysList.length; i++) {
	var key = keysList[i];
	key.addEventListener("pointerdown", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("pointerleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("pointerup", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
	key.addEventListener("touchstart", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("touchleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("touchend", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
	key.addEventListener("mousedown", function(thisEvent){
	    keyPress(this, thisEvent);
	});
	key.addEventListener("mouseleave", function(thisEvent){
	    keyLeave(this, thisEvent);
	});
	key.addEventListener("mouseup", function(thisEvent){
	    keyRelease(this, thisEvent);
	});
    }
});
/*    $("#operators a").not("#equals").click(function(){
	operator = $(this).text();
	newnumber = number;
	number = "";
	totaldiv.text("0");
    });
    $("#clear,#clearall").click(function(){
	number = "";
	totaldiv.text("0");
	if ($(this).attr("id") === "clearall") {
	    newnumber = "";
	}
    }); */
/*    $("#equals").click(function(){
	if (operator === "+"){
	    number = (parseInt(number, 10) + parseInt(newnumber,10)).toString(10);
	} else if (operator === "-"){
	    number = (parseInt(newnumber, 10) - parseInt(number,10)).toString(10);
	} else if (operator === "/"){
	    number = (parseInt(newnumber, 10) / parseInt(number,10)).toString(10);
	} else if (operator === "*"){
	    number = (parseInt(newnumber, 10) * parseInt(number,10)).toString(10);
	}
	totaldiv.text(number);
	testNumLength(number);
	number = "";
	newnumber = "";
    });
*/

<|endoftext|>


<commit_before>
/* global Vue, global document, global location*/

'use strict';

var publicDomain;

var vm = new Vue({

  el: '#addInstance',

  ready : function () {

    var self = this;

    self.$http.get('/-/v3/config.js').then(function (result) {
      self.$set('publicDomain', result.data.publicDomain);
      publicDomain = result.data.publicDomain;
    }, console.error);
  },

  methods : {

    displayFormAddInstance : function (event) {
      document.getElementById('modal-add-instance').style.display = 'block';
    },

    cancelAddInstance : function (event) {
      document.getElementById('modal-add-instance').style.display = 'none';
    },

    addInstance : function (event) {
      this.longName = document.getElementById('inputLongName').value;
      this.project = document.getElementById('inputProject').value;
      this.study = document.getElementById('inputStudy').value;
      this.version = document.getElementById('inputVersion').value;

      document.getElementById('save').style.display = 'none';
      document.getElementById('close_modal').style.display = 'none';
      document.getElementById('loader').style.display = 'block';

      if (this.longName == '') { this.longName = 'Free comment of '+this.technicalName; }

      var data = {
        'longName' : this.longName,
        'project' : this.project,
        'version' : this.version,
        'study': this.study,
        'technicalName' :  this.technicalName,
        'app' : document.getElementById('app').value
      };
      this.$http.post('/-/v1/instances', data).then(function (result) {
        if (result.status == 200) { location.reload(); }
      }, function (error) {
        if (error.status == 400) {
          this.codeErrorPull = error.status;
          this.messageErrorPull = error.data;
          document.getElementById('loader').style.display = 'none';
          document.getElementById('errorLoader').style.display = 'block';
        }
      });
    },

    tryAgain : function (event) {
      location.reload();
    }
  },
  data : {
    longName : '',
    project: '',
    version : '',
    study : '',
    technicalName : '',
    urlPreview : '',
    messageErrorPull : '',
    codeErrorPull : ''
  }

});

module.exports = vm;

// The 3 first vm.$watch manage field color changes in the addInstance form.

vm.$watch('longName', function(longName) {

  // The longName parameter contains the longName field value.

  if (longName == '')
    document.getElementById('inputLongName').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputLongName').style.backgroundColor='#C5E1A5';

});

vm.$watch('study', function(study) {

  // The study parameter contains the study field value.

  if (/^[a-z0-9]+$/.test(study)==false || study == '')
    document.getElementById('inputStudy').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputStudy').style.backgroundColor='#C5E1A5';

});

vm.$watch('project', function(project) {

  // The project parameter contains the project field value.

  if (/^[a-z0-9]+$/.test(project)==false || project == '')
    document.getElementById('inputProject').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputProject').style.backgroundColor='#C5E1A5';

});

vm.$watch('project', function(project) {

  // The project parameter contains the project field value.

  this.project = project;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  verif(this.technicalName);

});

vm.$watch('study', function (study) {

  // The study parameter contains the study field value.

  this.study = study;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  verif(this.technicalName);

});

vm.$watch('version', function (version) {

  // The version parameter contains the version field value.

  this.version = version;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  verif(this.technicalName);

});

function verif (tn) {

  var data = {
    'technicalName' : tn
  };

  vm.$http.get('/-/v1/instances/verif', data).then(function (result) {

    if (result.status == 200) {
      document.getElementById('technicalNameExists').style.display = 'none';
      document.getElementById('save').style.display = 'block';
      document.getElementById('saveTechnicalExists').style.display = 'none';
    }

  }, function (error) {

    if (error.status == 409) {
      document.getElementById('technicalNameExists').style.display = 'block';
      document.getElementById('save').style.display = 'none';
      document.getElementById('saveTechnicalExists').style.display = 'block';
    }

  });

}<commit_msg>Minor changes.<commit_after>
/* global Vue, global document, global location*/

'use strict';

var publicDomain;

var vm = new Vue({

  el: '#addInstance',

  ready : function () {

    var self = this;

    self.$http.get('/-/v3/config.js').then(function (result) {
      self.$set('publicDomain', result.data.publicDomain);
      publicDomain = result.data.publicDomain;
    }, console.error);
  },

  methods : {

    verif : function (technicalName) {

      var data = {
        'technicalName' : technicalName
      };

      vm.$http.get('/-/v1/instances/verif', data).then(function (result) {

        if (result.status == 200) {
          document.getElementById('technicalNameExists').style.display = 'none';
          document.getElementById('save').style.display = 'block';
          document.getElementById('saveTechnicalExists').style.display = 'none';
        }

      }, function (error) {

        if (error.status == 409) {
          document.getElementById('technicalNameExists').style.display = 'block';
          document.getElementById('save').style.display = 'none';
          document.getElementById('saveTechnicalExists').style.display = 'block';
        }

      });

    },

    displayFormAddInstance : function (event) {
      document.getElementById('modal-add-instance').style.display = 'block';
    },

    cancelAddInstance : function (event) {
      document.getElementById('modal-add-instance').style.display = 'none';
    },

    addInstance : function (event) {
      this.longName = document.getElementById('inputLongName').value;
      this.project = document.getElementById('inputProject').value;
      this.study = document.getElementById('inputStudy').value;
      this.version = document.getElementById('inputVersion').value;

      document.getElementById('save').style.display = 'none';
      document.getElementById('close_modal').style.display = 'none';
      document.getElementById('loader').style.display = 'block';

      if (this.longName == '') { this.longName = 'Free comment of '+this.technicalName; }

      var data = {
        'longName' : this.longName,
        'project' : this.project,
        'version' : this.version,
        'study': this.study,
        'technicalName' :  this.technicalName,
        'app' : document.getElementById('app').value
      };
      this.$http.post('/-/v1/instances', data).then(function (result) {
        if (result.status == 200) { location.reload(); }
      }, function (error) {
        if (error.status == 400) {
          this.codeErrorPull = error.status;
          this.messageErrorPull = error.data;
          document.getElementById('loader').style.display = 'none';
          document.getElementById('errorLoader').style.display = 'block';
        }
      });
    },

    tryAgain : function (event) {
      location.reload();
    }
  },
  data : {
    longName : '',
    project: '',
    version : '',
    study : '',
    technicalName : '',
    urlPreview : '',
    messageErrorPull : '',
    codeErrorPull : ''
  }

});

module.exports = vm;

// The 3 first vm.$watch manage field color changes in the addInstance form.

vm.$watch('longName', function(longName) {

  // The longName parameter contains the longName field value.

  if (longName == '')
    document.getElementById('inputLongName').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputLongName').style.backgroundColor='#C5E1A5';

});

vm.$watch('study', function(study) {

  // The study parameter contains the study field value.

  if (/^[a-z0-9]+$/.test(study)==false || study == '')
    document.getElementById('inputStudy').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputStudy').style.backgroundColor='#C5E1A5';

});

vm.$watch('project', function(project) {

  // The project parameter contains the project field value.

  if (/^[a-z0-9]+$/.test(project)==false || project == '')
    document.getElementById('inputProject').style.backgroundColor='#FFCDD2';
  else
    document.getElementById('inputProject').style.backgroundColor='#C5E1A5';

});

vm.$watch('project', function(project) {

  // The project parameter contains the project field value.

  this.project = project;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  this.verif(this.technicalName);

});

vm.$watch('study', function (study) {

  // The study parameter contains the study field value.

  this.study = study;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  this.verif(this.technicalName);

});

vm.$watch('version', function (version) {

  // The version parameter contains the version field value.

  this.version = version;

  if (this.version == '') { this.technicalName = this.project + '-' + this.study; }
  else { this.technicalName = this.project + '-' + this.study + '-' + this.version; }

  this.urlPreview = 'http://'+this.technicalName+'.'+publicDomain;
  this.verif(this.technicalName);

});<|endoftext|>