LoginSignup
25
25

More than 5 years have passed since last update.

ちょっとしたフロントエンドJavaScriptのサンプルで気軽にBabelを使いたい

Last updated at Posted at 2016-04-01

テンプレ

コンパイルに時間がかかるので実用性はほとんどありませんが,実はブラウザ上でコンパイルもできます!

Babel
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.0/babel.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.9.1/polyfill.min.js"></script>

<script type="text/babel">
  /* ここにコードを書く */
</script>
React+Redux+ReduxSaga
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.1/react-redux.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/redux-saga/0.14.0/redux-saga.min.js"></script>

<!DOCTYPE html>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Date Calculator</title>

<link href="https://cdn.muicss.com/mui-0.9.7/css/mui.min.css" rel="stylesheet" type="text/css">

<style>

html, body {
  background: #A9D0F5;
  height: 100%;
  min-height: 800px;
}
@media (min-width: 544px) {
  html, body {
    min-height: 580px;
  }
}

#main {
  background: white;
  width: 80%;
  height: 100%;
  margin: auto;
  padding-top: 20px;
  display: flex;
  align-items: center;
}

</style>

<!-- Compiler and Polyfills -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.0/babel.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.9.1/polyfill.min.js"></script>

<!-- React + Redux + ReduxSaga -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.1/react-redux.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/redux-saga/0.14.0/redux-saga.min.js"></script>

<!-- Other libraries -->
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/muicss/0.9.7/react/mui-react.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment-with-locales.min.js"></script>

<script type="text/babel">

/**
 * Initializations
 */

moment.locale('ja');


/**
 * Actions
 */

function createActionCreators(actions) {
  const creators = {};
  for (const [key, type] of Object.entries(actions)) {
    const name = key.toLowerCase().replace(/_(.)/g, (_, c) => c.toUpperCase());
    creators[name] = payload => ({ type, payload });
  }
  return creators;
}

const PREFIX = '@@example/';
const DATE_ADD_CHANGED    = PREFIX + 'DATE_ADD_CHANGED';
const DATE_ADD_CALCULATE  = PREFIX + 'DATE_ADD_CALCULATE';
const DATE_DIFF_CHANGED   = PREFIX + 'DATE_DIFF_CHANGED';
const DATE_DIFF_CALCULATE = PREFIX + 'DATE_DIFF_CALCULATE';

const {
  dateAddChanged, dateAddCalculate,
  dateDiffChanged, dateDiffCalculate,
} = createActionCreators({
  DATE_ADD_CHANGED, DATE_ADD_CALCULATE,
  DATE_DIFF_CHANGED, DATE_DIFF_CALCULATE,
});


/**
 * Reducers
 */

const { combineReducers } = Redux;

function dateAddControl(
  state = { from: '', span: '', answer: null },
  { type, payload }
) {
  switch (type) {
    case DATE_ADD_CHANGED:
      return { ...state, ...payload };
    case DATE_ADD_CALCULATE:
      const fromDate = moment(state.from);
      const number = parseInt(state.span, 10);
      const answer =
        fromDate.isValid() && !isNaN(number)
        ? fromDate.add(state.span, 'days').format('ll')
        : null;
      return { ...state, answer };
    default:
      return state;
  }
}

function dateDiffControl(
  state = { from: '', to: '', answer: null },
  { type, payload }
) {
  switch (type) {
    case DATE_DIFF_CHANGED:
      return { ...state, ...payload };
    case DATE_DIFF_CALCULATE:
      const fromDate = moment(state.from);
      const toDate = moment(state.to);
      const answer =
        fromDate.isValid() && toDate.isValid()
        ? toDate.diff(fromDate, 'days')
        : null;
      return { ...state, answer };
    default:
      return state;
  }
}

const rootReducer = combineReducers({ dateAddControl, dateDiffControl });


/**
 * Sagas
 */

const { delay } = ReduxSaga;
const { put, take, call, fork } = ReduxSaga.effects;

function createLazySaga(inputAction, ms, outputActionCreator) {
  return function* () {
    let task;
    while (true) {
      const { payload } = yield take(inputAction);
      if (task && task.isRunning()) {
        task.cancel();
      }
      task = yield fork(function* () {
        yield call(delay, ms);
        yield put(outputActionCreator(payload));
      });
    }
  };
}

function* rootSaga() {
  yield fork(createLazySaga(DATE_ADD_CHANGED, 250, dateAddCalculate));
  yield fork(createLazySaga(DATE_DIFF_CHANGED, 250, dateDiffCalculate));
}


/**
 * Components
 */

const { Container, Input, Panel, Form } = mui.react;

const PaddedInput = props => (
  <Input {...props} style={{ padding: '10px' }} />
);
const StaticForm = props => (
  <Form {...props} onSubmit={e => e.preventDefault()} />
);
const CenterBlock = ({ children, ...props }) => (
  <div {...props} style={{ display: 'table', width: '100%', height: '120px' }}>
    <div style={{ display: 'table-cell', textAlign: 'center', verticalAlign: 'middle' }}>
      { children }
    </div>
  </div>
);
const Large = props => (
  <span {...props} style={{ fontSize: '40px' }} />
);

const AddTool = ({ from, span, answer, dateAddChanged }) => (
  <Panel>
    <legend>N日後の日付を計算します</legend>
    <StaticForm inline={true}>
      <PaddedInput type="date" value={from} onChange={e => dateAddChanged({from: e.target.value})} />
      
      <PaddedInput type="number" value={span} onChange={e => dateAddChanged({span: e.target.value})} />
      日後は
      <CenterBlock>
        {answer ? <Large>{answer}</Large> : ''}
      </CenterBlock>
    </StaticForm>
  </Panel>
);

const DiffTool = ({ from, to, answer, dateDiffChanged }) => (
  <Panel>
    <StaticForm inline={true}>
      <legend>日付の差を計算します</legend>
      <PaddedInput type="date" value={from} onChange={e => dateDiffChanged({from: e.target.value})} />
      
      <PaddedInput type="date" value={to} onChange={e => dateDiffChanged({to: e.target.value})} />
      の差は
      <CenterBlock>
        {answer ? <Large>{answer}</Large> : ''}
      </CenterBlock>
    </StaticForm>
  </Panel>
);


/**
 * Containers
 */

const { bindActionCreators } = Redux;
const { connect } = ReactRedux;

const App = connect(
  state => state,
  dispatch => bindActionCreators({ dateAddChanged, dateDiffChanged }, dispatch),
)(
  ({ dateAddControl, dateDiffControl, dateAddChanged, dateDiffChanged }) => (
    <Container>
      <AddTool {...dateAddControl} dateAddChanged={dateAddChanged} />
      <DiffTool {...dateDiffControl} dateDiffChanged={dateDiffChanged} />
    </Container>
  )
);


/**
 * Executor
 */

const { createStore, applyMiddleware, compose } = Redux;
const { Provider } = ReactRedux;
const createSagaMiddleware = ReduxSaga.default;

const sagaMiddleware = createSagaMiddleware();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(sagaMiddleware)));

sagaMiddleware.run(rootSaga);
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('main'));

</script>

<div id="main">
  <div style="display: table; width: 100%; height: 120px;">
    <div style="display: table-cell; text-align: center; vertical-align: middle;">
      <span style="font-size: 40px;">Now Loading ...</span>
    </div>
  </div>
</div>
25
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
25