(function(global) {
  'use strict';
  var app = global.app || {};
  var m = global.m;
  var util = global.util;

  var TimelineController = app.TimelineController;

  var camelCase = util.camelCase;
  var loadData = util.loadData;
  var saveData = util.saveData;
  var windowWidth = util.windowWidth;

  var ActionController = function(option) {
    this.headerController = m.prop(option.headerController);
    this.timeAxisController = m.prop(option.timeAxisController);
    this.timelineListController = m.prop(option.timelineListController);
  };

  ActionController.prototype.timelineControllers = function(value) {
    var headerController = this.headerController();

    // headerController's timelineController is used as a cache
    if (typeof value === 'undefined')
      return headerController.timelineControllers();

    var timelineListController = this.timelineListController();

    headerController.timelineControllers(value);
    timelineListController.timelineControllers(value);
  };

  ActionController.prototype.start = function() {
    var headerController = this.headerController();
    var timeAxisController = this.timeAxisController();
    var timelineListController = this.timelineListController();

    var daysAgo = loadData('days-ago', 183);
    var daysAfter = loadData('days-after', 183);
    var pixelsPerDay = loadData('pixels-per-day' ,8);

    loadDefaultTimelineControllers(this, {
      daysAgo: daysAgo,
      daysAfter: daysAfter,
      pixelsPerDay: pixelsPerDay
    });

    updateTimelineSettings(headerController, daysAgo, daysAfter, pixelsPerDay);
    updateTimelineSettings(timeAxisController, daysAgo, daysAfter, pixelsPerDay);
    updateTimelineSettings(timelineListController, daysAgo, daysAfter, pixelsPerDay);

    headerController.onchange = onChangeHeaderController.bind(this);
    headerController.ontoday = onTodayHeaderController.bind(this);
    headerController.ontimelineadd = onTimelineAddHeaderController.bind(this);
    headerController.ontimelineremove = onTimelineRemoveHeaderController.bind(this);
    headerController.ontimelinereorder = onTimelineReorderHeaderController.bind(this);
    timelineListController.oninit = onInitTimelineListController.bind(this);
    timelineListController.onscroll = onScrollTimelineListController.bind(this);
  };

  var updateTimelineSettings = function(ctrl, daysAgo, daysAfter, pixelsPerDay) {
    ctrl.daysAgo(daysAgo);
    ctrl.daysAfter(daysAfter);
    ctrl.pixelsPerDay(pixelsPerDay);
  };

  var loadDefaultTimelineControllers = function(ctrl, option) {
    var urls = loadTimelineUrls();
    var timelineControllers = urls.map(function(url) {
      return new TimelineController({
        url: url
      });
    });

    m.sync(timelineControllers.map(function(timelineController) {
      return timelineController.fetch();
    })).then(function(timelineControllers) {
      var timelineListController = ctrl.timelineListController();
      var daysAgo = option.daysAgo;
      var daysAfter = option.daysAfter;
      var pixelsPerDay = option.pixelsPerDay;

      ctrl.timelineControllers(timelineControllers);
      updateTimelineSettings(timelineListController, daysAgo, daysAfter, pixelsPerDay);
      m.redraw();

      // locate timeline title
      timelineControllers.forEach(function(timelineController) {
        timelineController.scrollLeft(timelineListController.scrollLeft());
      });
    }.bind(ctrl));
  };

  var updateScrollLeftPosition = function(ctrl, value) {
    var timelineListController = ctrl.timelineListController();

    // need only adjust timeline list scroll position
    // timeline list scroll event transferred to time axis
    timelineListController.scrollLeft(value);
  };

  var addTimelineController = function(ctrl, url) {
    var headerController = ctrl.headerController();
    var timelineListController = ctrl.timelineListController();
    var timelineControllers = ctrl.timelineControllers();

    var timelineController = new TimelineController({
      url: url
    });

    timelineControllers.push(timelineController);

    timelineController.fetch().then(function(timelineController) {
      var daysAgo = headerController.daysAgo();
      var daysAfter = headerController.daysAfter();
      var pixelsPerDay = headerController.pixelsPerDay();

      updateTimelineSettings(timelineController, daysAgo, daysAfter, pixelsPerDay);
      m.redraw(true);

      // locate timeline title
      timelineController.scrollLeft(timelineListController.scrollLeft());
    }.bind(ctrl));

    saveTimelineUrls(timelineControllers);
    m.redraw();
  };

  var removeTimelineController = function(ctrl, index) {
    var timelineControllers = ctrl.timelineControllers();
    timelineControllers.splice(index, 1);
    saveTimelineUrls(timelineControllers);
    m.redraw();
  };

  var reorderTimelineController = function(ctrl, indeces) {
    var timelineListController = ctrl.timelineListController();
    var timelineControllers = ctrl.timelineControllers();

    var scrollLeft = timelineListController.scrollLeft();
    var clone = timelineControllers.concat();

    for (var i = 0, len = timelineControllers.length; i < len; i++) {
      timelineControllers[i] = clone[indeces[i]];
    }

    saveTimelineUrls(timelineControllers);
    m.redraw();

    updateScrollLeftPosition(ctrl, scrollLeft);
  };

  var loadTimelineUrls = function() {
    return loadData('timeline-urls', []);
  };

  var saveTimelineUrls = function(timelineControllers) {
    saveData('timeline-urls', timelineControllers.map(function(timelineController) {
      return timelineController.url();
    }));
  };

  var onChangeHeaderController = function(event) {
    var timeAxisController = this.timeAxisController();
    var timelineListController = this.timelineListController();

    // get values before change
    var daysAgo = timeAxisController.daysAgo();
    var pixelsPerDay = timeAxisController.pixelsPerDay();
    var scrollLeft = timelineListController.scrollLeft();

    var name = event.name;
    var value = event.value;
    var methodName = camelCase(name);

    timeAxisController[methodName](value);
    timelineListController[methodName](value);

    saveData(name, value);
    m.redraw();

    // adjust scroll position after redraw
    if (name === 'days-ago') {
      scrollLeft += (value - daysAgo) * pixelsPerDay;
    } else if (name === 'pixels-per-day') {
      var scrollDays = (scrollLeft + windowWidth() / 2) / pixelsPerDay;
      scrollLeft += scrollDays * (value - pixelsPerDay);
    }

    updateScrollLeftPosition(this, scrollLeft);
  };

  var onTodayHeaderController = function() {
    var headerController = this.headerController();

    var daysAgo = headerController.daysAgo();
    var pixelsPerDay = headerController.pixelsPerDay();
    var scrollLeft = (daysAgo + 0.5) * pixelsPerDay - windowWidth() / 2;

    updateScrollLeftPosition(this, scrollLeft);
  };

  var onTimelineAddHeaderController = function(event) {
    var url = event.url;
    if (!url)
      return;
    addTimelineController(this, url);
  };

  var onTimelineRemoveHeaderController = function(event) {
    removeTimelineController(this, event.index);
  };

  var onTimelineReorderHeaderController = function(event) {
    reorderTimelineController(this, event.indeces);
  };

  var onInitTimelineListController = function() {
    onTodayHeaderController.call(this);
  };

  var onScrollTimelineListController = function(event) {
    var timeAxisController = this.timeAxisController();
    timeAxisController.scrollLeft(event.scrollLeft);
  };

  app.ActionController = ActionController;
  global.app = app;
})(this);
@@ -3228,200 +3228,45 @@
     
-// locate timeline title%0A      timelineControllers.forEach(function(timelineController) %7B%0A        timelineController.scrollLeft(timelineListController.scrollLeft());%0A      %7D);%0A    %7D.bind(ctrl)
+updateScrollLeftPosition(ctrl);%0A    %7D
 );%0A 
@@ -3388,24 +3388,148 @@
 troller();%0A%0A
+    // locate each timeline title%0A    if (typeof value === 'undefined')%0A      value = timelineListController.scrollLeft();%0A%0A
     // need 
@@ -4484,19 +4484,8 @@
    %7D
-.bind(ctrl)
 );%0A%0A
@@ -4851,169 +4851,46 @@
 line
-ListController = ctrl.timelineListController();%0A    var timelineControllers = ctrl.timelineControllers();%0A%0A    var scrollLeft = timelineListController.scrollLeft
+Controllers = ctrl.timelineControllers
 ();%0A
@@ -5156,28 +5156,16 @@
 ion(ctrl
-, scrollLeft
 );%0A  %7D;%0A

Refactor action-controller