<commit_before>const MOE_VERSION = "20141222";

var Config = window.C;
var Storage = (function (Config) {
    var localStorage = (window.localStorage && window.JSON ? window.localStorage : null);
    var prefix = "moe_" + MOE_VERSION + "_" + Config.event_slug + "_";
    return {
        get: function (key) {
            var data = (localStorage ? localStorage[prefix + key] : null);
            try {
                return (data !== null ? JSON.parse(data) : null);
            } catch (e) {
                return null;
            }
        },
        set: function (key, value) {
            if (localStorage) localStorage[prefix + key] = JSON.stringify(value);
        }
    };
}(Config));

var Stars = (function () {
    var serverStarred = {};
    var locallyStarred = m.prop(Storage.get("starred") || {});

    function loadStarred() {
        if(!Config.starred_url) return;
        ajax({
            method: "GET",
            url: Config.starred_url,
            success: function (data) {
                data = JSON.parse(data);
                data.starred.forEach(function (identifier) {
                    serverStarred[identifier] = true;
                });
                m.redraw();
            }
        });
    }

    function getStarredness(program) {
        var localStar = locallyStarred()[program.identifier];
        if (localStar === true || localStar === false) return !!localStar;
        return !!serverStarred[program.identifier];
    }

    function setStarredness(programId, newStarredness) {
        var stars = locallyStarred();
        stars[programId] = !!newStarredness;
        locallyStarred(stars);
        Storage.set("starred", stars);
        if (!!Config.logged_in) {
            const url = (newStarredness ? Config.star_url : Config.unstar_url);
            if(!url) return;
            ajax({
                method: "POST",
                url: url + "?event=" + Config.event_slug + "&program_id=" + programId,
                data: "true"
            });
        }
    }

    return {
        load: loadStarred,
        get: getStarredness,
        set: setStarredness
    }
}());

var scheduleData = m.prop([]);
var showPast = m.prop(!!Storage.get("showPast"));
var search = m.prop(Storage.get("search") || "");
var filterLocation = m.prop("-");
var filterKindDisplay = m.prop("-");
var expandedProgram = m.prop(null);

function preprocessProgram(program) {
    if (!program._cached) {
        program.start_ts = Date.parse(program.start_time);
        program.end_ts = Date.parse(program.end_time);
        program.start = new Date(program.start_ts);
        program.end = new Date(program.end_ts);
        program.weekday = Kit.getWeekday(program.start);
        program.startTimeStr = Kit.formatTime(program.start);
        program.endTimeStr = Kit.formatTime(program.end);
        program._cached = true;
    }
    return program;
}

function preprocessScheduleData(data) {
    data.forEach(preprocessProgram);
    return data.sort(
        (ea, eb) => Kit.cmp(ea.start_time, eb.start_time) || Kit.cmp(ea.location, eb.location)
    );
}

function getScheduleData() {
    var data;
    var now = (+new Date()) / 1000;
    if (data = Storage.get("data")) {
        let fetchTime = 0 | Storage.get("dataMtime");
        let age = (now - fetchTime);
        if (age < 60 * 15) {
            data = preprocessScheduleData(data);
            scheduleData(data);
            m.redraw();
            return scheduleData;
        }
    }

    ajax({
        method: "GET",
        url: Config.schedule_url,
        success: function (data) {
            data = JSON.parse(data);
            data = preprocessScheduleData(data);
            Storage.set("data", data);
            Storage.set("dataMtime", now);
            scheduleData(data);
            m.redraw();
        }
    });
    return scheduleData;
}

function controller() {
    if (!scheduleData().length) getScheduleData();
    Stars.load();
    setInterval(function () {
        m.redraw();
    }, 60000);
}

function getSearchFilterPredicate(searchString) {
    var searchBits = (searchString || "")
        .split(/\s+/)
        .filter((bit) => bit.length > 0)
        .map((bit) => new RegExp(Kit.escapeRegExp(bit), "i"));
    if (!searchBits.length) return null;
    return function (str) {
        for (let i = 0; i < searchBits.length; i++) {
            if (!searchBits[i].test(str)) return false;
        }
        return true;
    };
}

function getFilterPredicate() {
    const nowTs = +new Date();
    const searchFilter = getSearchFilterPredicate(search());
    const doShowPast = !!(showPast());
    const filterLocationValue = filterLocation();
    const filterKindValue = filterKindDisplay();
    const location = (filterLocationValue && filterLocationValue !== "-" ? filterLocationValue : null);
    const kind = (filterKindValue && filterKindValue !== "-" ? filterKindValue : null);
    return function (program) {
        if (!doShowPast && (nowTs > program.end_ts)) return false;
        if (searchFilter && !(searchFilter(program.title) || searchFilter(program.presenter))) return false;
        if (location && program.location != location) return false;
        if (kind && program.kind_display != kind) return false;
        return true;
    };
};

function buildFilterBox(label, property, prop) {
    var facets = Kit.uniq(Kit.pluck(scheduleData(), property));
    return m("select.filter",
        {
            onchange: m.withAttr("value", prop),
            value: prop
        },
        [m("option", {value: "-"}, label)].concat(facets.map((facet) => m("option", {value: facet}, facet)))
    );
}

function uiSetStarredness(event) {
    Stars.set(event.target.id.replace(/^star-/, ""), !!event.target.checked);
}

function fixup(string) {
    if (string === "Puuseppä") return "Puu\u00ADseppä";
    if (string === "Metsähalli") return "Metsä\u00ADhalli";
    return string;
}

function setOrClearExpanded(programIdentifier) {
    if(expandedProgram() === programIdentifier) {
        expandedProgram(null);
    } else {
        expandedProgram(programIdentifier);
    }
}

function getProgramTableContent(programs) {
    const out = [];
    var lastWeekday = null;
    programs.forEach(function (program) {
        if (program.weekday !== lastWeekday) {
            lastWeekday = program.weekday;
            out.push(m("tr.weekday-divider", [m("td[colspan=4])", program.weekday)]));
        }
        out.push(m("tr", {className: "prog " + program.klass}, [
            m("td.times", [program.startTimeStr + " \u2013 " + program.endTimeStr]),
            m("td", [
                m("div.title",
                    m("a", {
                        href: "#p-" + program.identifier,
                        onclick: function(event) {
                            setOrClearExpanded(program.identifier);
                            event.stopPropagation();
                            return false;
                        }
                    }, program.title)
                ),
                m("div.meta", [
                    (program.kind_display ? m("span.kind." + program.kind, program.kind_display) : null),
                    (program.presenter ? m("span.pres", program.presenter) : null),
                    (program.hashtag ? m("span.hashtag", "#" + program.hashtag) : null)
                ])
            ]),
            m("td.loc", [fixup(program.location)]),
            m("td.star", m("label", [
                m("input.star-cb[type=checkbox]", {
                    checked: Stars.get(program),
                    id: "star-" + program.identifier,
                    onchange: uiSetStarredness
                }),
                "\u2605"
            ]))
        ]));
        if(expandedProgram() === program.identifier) {
            out.push(m("tr", [
                m("td", {colspan: 4}, m("div.description", program.description.replace(/<.+?>/g, ' ')))
            ]))
        }
    });

    return out;
}

function view() {
    var programs = scheduleData().filter(getFilterPredicate());

    var now = +new Date();
    programs.forEach(function (program) {
        var klass = "";
        if (program.start_ts <= now && now <= program.end_ts) klass = "current";
        else if (now > program.end_ts) klass = "past";
        program.klass = klass + (Stars.get(program) ? " starred" : "");
    });

    Storage.set("search", search());
    Storage.set("showPast", showPast());

    return m("div", [
        m("div#controls", [
            m("label", [
                m("input#search[placeholder=Etsi nimestä ja esittäjästä...]", {
                    onchange: m.withAttr("value", search),
                    oninput: m.withAttr("value", search),
                    value: search()
                })
            ]),
            m("label", [buildFilterBox("Sijainti...", "location", filterLocation)]),
            m("label", [buildFilterBox("Laji...", "kind_display", filterKindDisplay)]),
            m("label", [
                m("input[type=checkbox]", {
                    checked: showPast(),
                    onchange: m.withAttr("checked", showPast)
                }),
                "Menneet myös"
            ])
        ]),
        m("div#wrap", [
            (programs.length ? m("table", {id: "schedule"}, getProgramTableContent(programs)) : m("div.no-results", "Ei tuloksia :("))
        ])
    ]);
}

window.addEventListener("load", function () {
    m.module(window.document.body, {controller: controller, view: view});
}, false);
<commit_msg>Cache facet lists to speed up draw()s<commit_after>const MOE_VERSION = "20141222";

var Config = window.C;
var Storage = (function (Config) {
    var localStorage = (window.localStorage && window.JSON ? window.localStorage : null);
    var prefix = "moe_" + MOE_VERSION + "_" + Config.event_slug + "_";
    return {
        get: function (key) {
            var data = (localStorage ? localStorage[prefix + key] : null);
            try {
                return (data !== null ? JSON.parse(data) : null);
            } catch (e) {
                return null;
            }
        },
        set: function (key, value) {
            if (localStorage) localStorage[prefix + key] = JSON.stringify(value);
        }
    };
}(Config));

var Stars = (function () {
    var serverStarred = {};
    var locallyStarred = m.prop(Storage.get("starred") || {});

    function loadStarred() {
        if(!Config.starred_url) return;
        ajax({
            method: "GET",
            url: Config.starred_url,
            success: function (data) {
                data = JSON.parse(data);
                data.starred.forEach(function (identifier) {
                    serverStarred[identifier] = true;
                });
                m.redraw();
            }
        });
    }

    function getStarredness(program) {
        var localStar = locallyStarred()[program.identifier];
        if (localStar === true || localStar === false) return !!localStar;
        return !!serverStarred[program.identifier];
    }

    function setStarredness(programId, newStarredness) {
        var stars = locallyStarred();
        stars[programId] = !!newStarredness;
        locallyStarred(stars);
        Storage.set("starred", stars);
        if (!!Config.logged_in) {
            const url = (newStarredness ? Config.star_url : Config.unstar_url);
            if(!url) return;
            ajax({
                method: "POST",
                url: url + "?event=" + Config.event_slug + "&program_id=" + programId,
                data: "true"
            });
        }
    }

    return {
        load: loadStarred,
        get: getStarredness,
        set: setStarredness
    }
}());

var scheduleData = m.prop([]);
var showPast = m.prop(!!Storage.get("showPast"));
var search = m.prop(Storage.get("search") || "");
var filterLocation = m.prop("-");
var filterKindDisplay = m.prop("-");
var expandedProgram = m.prop(null);
var facetCache = {};

function preprocessProgram(program) {
    if (!program._cached) {
        program.start_ts = Date.parse(program.start_time);
        program.end_ts = Date.parse(program.end_time);
        program.start = new Date(program.start_ts);
        program.end = new Date(program.end_ts);
        program.weekday = Kit.getWeekday(program.start);
        program.startTimeStr = Kit.formatTime(program.start);
        program.endTimeStr = Kit.formatTime(program.end);
        program._cached = true;
    }
    return program;
}

function preprocessScheduleData(data) {
    facetCache = {}; // clear facet cache when we're (re)loading data
    data.forEach(preprocessProgram);
    return data.sort(
        (ea, eb) => Kit.cmp(ea.start_time, eb.start_time) || Kit.cmp(ea.location, eb.location)
    );
}

function getScheduleData() {
    var data;
    var now = (+new Date()) / 1000;
    if (data = Storage.get("data")) {
        let fetchTime = 0 | Storage.get("dataMtime");
        let age = (now - fetchTime);
        if (age < 60 * 15) {
            data = preprocessScheduleData(data);
            scheduleData(data);
            m.redraw();
            return scheduleData;
        }
    }

    ajax({
        method: "GET",
        url: Config.schedule_url,
        success: function (data) {
            data = JSON.parse(data);
            data = preprocessScheduleData(data);
            Storage.set("data", data);
            Storage.set("dataMtime", now);
            scheduleData(data);
            m.redraw();
        }
    });
    return scheduleData;
}

function controller() {
    if (!scheduleData().length) getScheduleData();
    Stars.load();
    setInterval(function () {
        m.redraw();
    }, 60000);
}

function getSearchFilterPredicate(searchString) {
    var searchBits = (searchString || "")
        .split(/\s+/)
        .filter((bit) => bit.length > 0)
        .map((bit) => new RegExp(Kit.escapeRegExp(bit), "i"));
    if (!searchBits.length) return null;
    return function (str) {
        for (let i = 0; i < searchBits.length; i++) {
            if (!searchBits[i].test(str)) return false;
        }
        return true;
    };
}

function getFilterPredicate() {
    const nowTs = +new Date();
    const searchFilter = getSearchFilterPredicate(search());
    const doShowPast = !!(showPast());
    const filterLocationValue = filterLocation();
    const filterKindValue = filterKindDisplay();
    const location = (filterLocationValue && filterLocationValue !== "-" ? filterLocationValue : null);
    const kind = (filterKindValue && filterKindValue !== "-" ? filterKindValue : null);
    return function (program) {
        if (!doShowPast && (nowTs > program.end_ts)) return false;
        if (searchFilter && !(searchFilter(program.title) || searchFilter(program.presenter))) return false;
        if (location && program.location != location) return false;
        if (kind && program.kind_display != kind) return false;
        return true;
    };
};

function buildFilterBox(label, property, prop) {
    var facets = facetCache[property];
    if(facets === undefined) {
        facetCache[property] = facets = Kit.uniq(Kit.pluck(scheduleData(), property));
    }
    return m("select.filter",
        {
            onchange: m.withAttr("value", prop),
            value: prop
        },
        [m("option", {value: "-"}, label)].concat(facets.map((facet) => m("option", {value: facet}, facet)))
    );
}

function uiSetStarredness(event) {
    Stars.set(event.target.id.replace(/^star-/, ""), !!event.target.checked);
}

function fixup(string) {
    if (string === "Puuseppä") return "Puu\u00ADseppä";
    if (string === "Metsähalli") return "Metsä\u00ADhalli";
    return string;
}

function setOrClearExpanded(programIdentifier) {
    if(expandedProgram() === programIdentifier) {
        expandedProgram(null);
    } else {
        expandedProgram(programIdentifier);
    }
}

function getProgramTableContent(programs) {
    const out = [];
    var lastWeekday = null;
    programs.forEach(function (program) {
        if (program.weekday !== lastWeekday) {
            lastWeekday = program.weekday;
            out.push(m("tr.weekday-divider", [m("td[colspan=4])", program.weekday)]));
        }
        out.push(m("tr", {className: "prog " + program.klass}, [
            m("td.times", [program.startTimeStr + " \u2013 " + program.endTimeStr]),
            m("td", [
                m("div.title",
                    m("a", {
                        href: "#p-" + program.identifier,
                        onclick: function(event) {
                            setOrClearExpanded(program.identifier);
                            event.stopPropagation();
                            return false;
                        }
                    }, program.title)
                ),
                m("div.meta", [
                    (program.kind_display ? m("span.kind." + program.kind, program.kind_display) : null),
                    (program.presenter ? m("span.pres", program.presenter) : null),
                    (program.hashtag ? m("span.hashtag", "#" + program.hashtag) : null)
                ])
            ]),
            m("td.loc", [fixup(program.location)]),
            m("td.star", m("label", [
                m("input.star-cb[type=checkbox]", {
                    checked: Stars.get(program),
                    id: "star-" + program.identifier,
                    onchange: uiSetStarredness
                }),
                "\u2605"
            ]))
        ]));
        if(expandedProgram() === program.identifier) {
            out.push(m("tr", [
                m("td", {colspan: 4}, m("div.description", program.description.replace(/<.+?>/g, ' ')))
            ]))
        }
    });

    return out;
}

function view() {
    var programs = scheduleData().filter(getFilterPredicate());

    var now = +new Date();
    programs.forEach(function (program) {
        var klass = "";
        if (program.start_ts <= now && now <= program.end_ts) klass = "current";
        else if (now > program.end_ts) klass = "past";
        program.klass = klass + (Stars.get(program) ? " starred" : "");
    });

    Storage.set("search", search());
    Storage.set("showPast", showPast());

    return m("div", [
        m("div#controls", [
            m("label", [
                m("input#search[placeholder=Etsi nimestä ja esittäjästä...]", {
                    onchange: m.withAttr("value", search),
                    oninput: m.withAttr("value", search),
                    value: search()
                })
            ]),
            m("label", [buildFilterBox("Sijainti...", "location", filterLocation)]),
            m("label", [buildFilterBox("Laji...", "kind_display", filterKindDisplay)]),
            m("label", [
                m("input[type=checkbox]", {
                    checked: showPast(),
                    onchange: m.withAttr("checked", showPast)
                }),
                "Menneet myös"
            ])
        ]),
        m("div#wrap", [
            (programs.length ? m("table", {id: "schedule"}, getProgramTableContent(programs)) : m("div.no-results", "Ei tuloksia :("))
        ])
    ]);
}

window.addEventListener("load", function () {
    m.module(window.document.body, {controller: controller, view: view});
}, false);
<|endoftext|>


<commit_before>var util = require("./util")
  , connect = require("connect")
  , File = require("./file")
  , WebResource = require("./resource")

function RoilApp(conf) {
  this._conf = conf
  this.server = connect.createServer()
  this._resourceRules = []
  this._resources = {}
}

util.def(RoilApp.prototype, {
  run: function() {
    this.server.listen(this._conf.port)
  }
, shutdown: function() {
    this.server.close()
  }
, loadPlugin: function(plugin) {
    plugin.call(null, this)
  }
, addResource: function(r) {
    if (r in this._resources) return
    if (this._conf.debug) console.log("ADD", r.path)
    this._resources[r] = r
    this._resourceRules.forEach(function(rule) {
      RoilApp._applyRule(rule, r)
    }, this)
  }
, matchResource: function(klass) {
    var cb = arguments[arguments.length - 1]
      , newRule = {
          klass: klass
        , cb: cb
        }
    this._resourceRules.push(newRule)
    for (var i in this._resources) {
      RoilApp._applyRule(newRule, this._resources[i])
    }
  }
, resource: {
    File: File
  , WebResource: WebResource
  }
, attachWorkspace: function(ws) {
    ws.on("BC:resource", function(r) {
      this.addResource(r)
    }.bind(this))
  }
})

RoilApp._applyRule = function(rule, resource) {
  if (!(resource instanceof rule.klass)) return
  (rule.cb)(resource)
}

module.exports = RoilApp
<commit_msg>Remove kludge<commit_after>var util = require("./util")
  , connect = require("connect")
  , File = require("./file")
  , WebResource = require("./resource")

function RoilApp(conf) {
  this._conf = conf
  this.server = connect.createServer()
  this._resourceRules = []
  this._resources = {}
}

util.def(RoilApp.prototype, {
  run: function() {
    this.server.listen(this._conf.port)
  }
, shutdown: function() {
    this.server.close()
  }
, loadPlugin: function(plugin) {
    plugin.call(null, this)
  }
, addResource: function(r) {
    if (r in this._resources) return
    if (this._conf.debug) console.log("ADD", r.path)
    this._resources[r] = r
    this._resourceRules.forEach(function(rule) {
      RoilApp._applyRule(rule, r)
    })
  }
, matchResource: function(klass) {
    var cb = arguments[arguments.length - 1]
      , newRule = {
          klass: klass
        , cb: cb
        }
    this._resourceRules.push(newRule)
    for (var i in this._resources) {
      RoilApp._applyRule(newRule, this._resources[i])
    }
  }
, resource: {
    File: File
  , WebResource: WebResource
  }
, attachWorkspace: function(ws) {
    ws.on("BC:resource", function(r) {
      this.addResource(r)
    }.bind(this))
  }
})

RoilApp._applyRule = function(rule, resource) {
  if (!(resource instanceof rule.klass)) return
  (rule.cb)(resource)
}

module.exports = RoilApp
<|endoftext|>


<commit_before>"use strict";

var app = angular.module('js110', []);

app.controller('controller', ['$scope', function($scope) {
  var synth = { };

  $scope.playing = false;
  $scope.amplitude = 0.5;
  $scope.tempo = 100;
  $scope.loop = true;
  $scope.downloadFileName = "js-110";

  $scope.instruments = [{
                          waveform:           'sawtooth',
                          lfoWaveform:        'sine',
                          lfoFrequency:       5,
                          lfoAmplitude:       0,
                          filterCutoff:       1000,
                          filterResonance:    0,
                          filterLFOWaveform:  'sine',
                          filterLFOFrequency: 5,
                          filterLFOAmplitude: 0,
                          envelopeAttack:     0.0,
                          envelopeDecay:      0.0,
                          envelopeSustain:    1.0,
                          envelopeRelease:    0.0,
                       },];

  $scope.tracks = [{
                     muted: false,
                     notes: [{name: 'C3'},
                             {name: ''},
                             {name: 'Eb3'},
                             {name: 'F3'},
                             {name: 'G3'},
                             {name: 'Bb4'},
                             {name: 'F3'},
                             {name: 'Bb4'},
                             {name: 'C3'},
                             {name: ''},
                             {name: 'Eb3'},
                             {name: 'F3'},
                             {name: 'D3'},
                             {name: 'Eb3'},
                             {name: 'D3'},
                             {name: 'Bb3'},],
                   },
                   {
                     muted: false,
                     notes: [{name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},],
                   },
                   {
                     muted: false,
                     notes: [{name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},],
                   },];

  var Serializer = function() {
    var serializer = {};

    var serializeInstrument = function() {
      var filterCutoff = parseInt($scope.instruments[0].filterCutoff, 10);

      return {
        waveform:  $scope.instruments[0].waveform,
        lfo: {
          waveform:  $scope.instruments[0].lfoWaveform,
          frequency: parseFloat($scope.instruments[0].lfoFrequency),
          amplitude: parseInt($scope.instruments[0].lfoAmplitude, 10),
        },
        filter: {
          cutoff:    filterCutoff,
          resonance: parseInt($scope.instruments[0].filterResonance, 10),
          lfo: {
            waveform:  $scope.instruments[0].filterLFOWaveform,
            frequency: parseFloat($scope.instruments[0].filterLFOFrequency),
            amplitude: parseFloat($scope.instruments[0].filterLFOAmplitude) * filterCutoff,
          },
        },
        envelope: {
          attack:  parseFloat($scope.instruments[0].envelopeAttack),
          decay:   parseFloat($scope.instruments[0].envelopeDecay),
          sustain: parseFloat($scope.instruments[0].envelopeSustain),
          release: parseFloat($scope.instruments[0].envelopeRelease),
        },
      };
    };

    var serializeTrackNotesIntoSequence = function(track) {
      var rawNotes = [];

      track.notes.forEach(function(note, index) {
        rawNotes[index] = note.name;
      });

      return rawNotes.join(' ');
    };

    serializer.serialize = function() {
      var instrument = new JSSynth.Instrument(serializeInstrument());

      var tracks = [];
      $scope.tracks.forEach(function(track) {
        var sequence = JSSynth.SequenceParser.parse(serializeTrackNotesIntoSequence(track));
        tracks.push(new JSSynth.Track(instrument, sequence, track.muted));
      });

      return tracks;
    };

    return serializer;
  };

  var stopCallback = function() {
    $scope.playing = false;
    $scope.$digest();
  };

  var exportCompleteCallback = function(blob) {
    var url  = window.URL.createObjectURL(blob);
    document.getElementById("downloaded-file").src = url;

    var hiddenDownloadLink = document.getElementById("hidden-download-link");
    hiddenDownloadLink.download = $scope.downloadFileName + ".wav";
    hiddenDownloadLink.href = url;
    hiddenDownloadLink.click();

    window.URL.revokeObjectURL(blob);
  };

  var syncPatternTracks = function(pattern) {
    var tracks = new Serializer().serialize();
    pattern.replaceTracks(tracks);
  };

  $scope.init = function() {
    synth.pattern = new JSSynth.Pattern();
    syncPatternTracks(synth.pattern);
    synth.transport = new JSSynth.Transport(synth.pattern, stopCallback);

    if (synth.transport) {
      synth.transport.setTempo(parseInt($scope.tempo, 10));
    }
    else {
      alert("Your browser doesn't appear to support WebAudio, and so won't be able to use the JS-110. Try a recent version of Chrome, Safari, or Firefox.");
      return;
    }
  };
  $scope.init();

  $scope.export = function() {
    var pattern = new JSSynth.Pattern();
    syncPatternTracks(pattern);

    var offlineTransport = new JSSynth.OfflineTransport(pattern, parseInt($scope.tempo, 10), parseFloat($scope.amplitude), exportCompleteCallback);
    offlineTransport.tick();
  };

  $scope.updateInstrument = function() {
    syncPatternTracks(synth.pattern);
  };

  $scope.updateNotes = function() {
    syncPatternTracks(synth.pattern);
  };

  $scope.addTrack = function() {
    var newTrack = {
                     muted: false,
                     notes: [{name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''}],
                   };
    $scope.tracks.push(newTrack);

    syncPatternTracks(synth.pattern);
  };

  $scope.removeTrack = function(index) {
    $scope.tracks.splice(index, 1);
    syncPatternTracks(synth.pattern);
  };

  $scope.updateTempo = function() {
    synth.transport.setTempo(parseInt($scope.tempo, 10));
  };

  $scope.updateAmplitude = function() {
    synth.transport.setAmplitude(parseFloat($scope.amplitude));
  };

  $scope.updateLoop = function() {
    synth.transport.loop = $scope.loop;
  };

  $scope.toggleTrackMute = function(index) {
    $scope.tracks[index].muted = !$scope.tracks[index].muted;
    syncPatternTracks(synth.pattern);
  };

  $scope.toggle = function() {
    synth.transport.toggle();
    $scope.playing = !$scope.playing;
  };
}]);

app.directive('noteInput', function () {
  return {
    require: 'ngModel',
    link: function (scope, element, attrs, ctrl) {
       if (!ctrl) return;

       var formatNoteValue = function(rawValue) {
         var formattedValue = rawValue;

         // Make first character uppercase (but not subsequent characters, to avoid
         // making a 'b' uppercase, which will mess with ♭ replacement).
         var firstCharacter = formattedValue.substr(0, 1);
         formattedValue = firstCharacter.toUpperCase() + formattedValue.substr(1);

         formattedValue = formattedValue.replace("##", "𝄪");
         formattedValue = formattedValue.replace("#", "♯");
         formattedValue = formattedValue.replace("bb", "𝄫");
         formattedValue = formattedValue.replace("b", "♭");
         formattedValue = formattedValue.replace("-", "—");

         return formattedValue;
       };

       ctrl.$formatters.push(function (a) {
         return formatNoteValue(ctrl.$modelValue);
       });

       ctrl.$parsers.unshift(function (viewValue) {
         var parsedValue = viewValue;

         // Make first character uppercase (but not subsequent characters, to avoid
         // making a 'b' uppercase, which will mess with ♭ replacement).
         var firstCharacter = viewValue.substr(0, 1);
         parsedValue = firstCharacter.toUpperCase() + viewValue.substr(1);
         parsedValue = parsedValue.replace("♯", "#");
         parsedValue = parsedValue.replace("𝄪", "##");
         parsedValue = parsedValue.replace("♭", "b");
         parsedValue = parsedValue.replace("𝄫", "bb");

         if (/^$|^-$|(^[A-G](b|bb|#|##){0,1}[0-7]$)/.test(parsedValue)) {
           ctrl.$setValidity('noteInput', true);
           return parsedValue;
         }
         else {
           ctrl.$setValidity('noteInput', false);
           return '';
         }
       });

       element.bind('blur', function(e) {
         element.val(formatNoteValue(element.val()));
       });

       element.bind('keydown', function(e) {
         var changeCurrentlySelectedNote = function(element, config) {
           var trackIndex = parseInt(element[0].id.split("-")[1], 10);
           var noteIndex = parseInt(element[0].id.split("-")[3], 10);
           var nextNoteId = 'track-' + (trackIndex + config.trackIndexDelta) + '-note-' + (noteIndex + config.noteIndexDelta);

           document.getElementById(nextNoteId).focus();
         };

         if (e.keyCode === 32) {  // Space bar
           element.val('');
         }
         else if (e.keyCode === 37) {  // Left arrow key
           if (element[0].selectionStart === 0 && !(element.hasClass('firstNote'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 0, noteIndexDelta: -1 });
           }
         }
         else if (e.keyCode === 39) {  // Right arrow key
           if (element[0].selectionEnd === element.val().length && !(element.hasClass('lastNote'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 0, noteIndexDelta: 1 });
           }
         }
         else if (e.keyCode === 38) {  // Up arrow key
           if (!(element.hasClass('firstTrack'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: -1, noteIndexDelta: 0 });
           }
         }
         else if (e.keyCode === 40) {  // Down arrow key
           if (!(element.hasClass('lastTrack'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 1, noteIndexDelta: 0 });
           }
         }
       });

       element.bind('keyup', function(e) {
         if (e.keyCode === 32) {  // Space bar
           element.val('');
         }
       });
    }
  };
});
<commit_msg>Re-organizing order of controller function definitions<commit_after>"use strict";

var app = angular.module('js110', []);

app.controller('controller', ['$scope', function($scope) {
  var synth = { };

  $scope.playing = false;
  $scope.amplitude = 0.5;
  $scope.tempo = 100;
  $scope.loop = true;
  $scope.downloadFileName = "js-110";

  $scope.instruments = [{
                          waveform:           'sawtooth',
                          lfoWaveform:        'sine',
                          lfoFrequency:       5,
                          lfoAmplitude:       0,
                          filterCutoff:       1000,
                          filterResonance:    0,
                          filterLFOWaveform:  'sine',
                          filterLFOFrequency: 5,
                          filterLFOAmplitude: 0,
                          envelopeAttack:     0.0,
                          envelopeDecay:      0.0,
                          envelopeSustain:    1.0,
                          envelopeRelease:    0.0,
                       },];

  $scope.tracks = [{
                     muted: false,
                     notes: [{name: 'C3'},
                             {name: ''},
                             {name: 'Eb3'},
                             {name: 'F3'},
                             {name: 'G3'},
                             {name: 'Bb4'},
                             {name: 'F3'},
                             {name: 'Bb4'},
                             {name: 'C3'},
                             {name: ''},
                             {name: 'Eb3'},
                             {name: 'F3'},
                             {name: 'D3'},
                             {name: 'Eb3'},
                             {name: 'D3'},
                             {name: 'Bb3'},],
                   },
                   {
                     muted: false,
                     notes: [{name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},
                             {name: 'C2'},
                             {name: ''},],
                   },
                   {
                     muted: false,
                     notes: [{name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},
                             {name: 'Eb3'},
                             {name: '-'},
                             {name: '-'},
                             {name: '-'},],
                   },];

  var Serializer = function() {
    var serializer = {};

    var serializeInstrument = function() {
      var filterCutoff = parseInt($scope.instruments[0].filterCutoff, 10);

      return {
        waveform:  $scope.instruments[0].waveform,
        lfo: {
          waveform:  $scope.instruments[0].lfoWaveform,
          frequency: parseFloat($scope.instruments[0].lfoFrequency),
          amplitude: parseInt($scope.instruments[0].lfoAmplitude, 10),
        },
        filter: {
          cutoff:    filterCutoff,
          resonance: parseInt($scope.instruments[0].filterResonance, 10),
          lfo: {
            waveform:  $scope.instruments[0].filterLFOWaveform,
            frequency: parseFloat($scope.instruments[0].filterLFOFrequency),
            amplitude: parseFloat($scope.instruments[0].filterLFOAmplitude) * filterCutoff,
          },
        },
        envelope: {
          attack:  parseFloat($scope.instruments[0].envelopeAttack),
          decay:   parseFloat($scope.instruments[0].envelopeDecay),
          sustain: parseFloat($scope.instruments[0].envelopeSustain),
          release: parseFloat($scope.instruments[0].envelopeRelease),
        },
      };
    };

    var serializeTrackNotesIntoSequence = function(track) {
      var rawNotes = [];

      track.notes.forEach(function(note, index) {
        rawNotes[index] = note.name;
      });

      return rawNotes.join(' ');
    };

    serializer.serialize = function() {
      var instrument = new JSSynth.Instrument(serializeInstrument());

      var tracks = [];
      $scope.tracks.forEach(function(track) {
        var sequence = JSSynth.SequenceParser.parse(serializeTrackNotesIntoSequence(track));
        tracks.push(new JSSynth.Track(instrument, sequence, track.muted));
      });

      return tracks;
    };

    return serializer;
  };

  var syncPatternTracks = function(pattern) {
    var tracks = new Serializer().serialize();
    pattern.replaceTracks(tracks);
  };

  $scope.init = function() {
    var stopCallback = function() {
      $scope.playing = false;
      $scope.$digest();
    };

    synth.pattern = new JSSynth.Pattern();
    syncPatternTracks(synth.pattern);
    synth.transport = new JSSynth.Transport(synth.pattern, stopCallback);

    if (synth.transport) {
      synth.transport.setTempo(parseInt($scope.tempo, 10));
    }
    else {
      alert("Your browser doesn't appear to support WebAudio, and so won't be able to use the JS-110. Try a recent version of Chrome, Safari, or Firefox.");
      return;
    }
  };
  $scope.init();

  $scope.updateInstrument = function() {
    syncPatternTracks(synth.pattern);
  };

  $scope.addTrack = function() {
    var newTrack = {
                     muted: false,
                     notes: [{name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''},
                             {name: ''}],
                   };
    $scope.tracks.push(newTrack);

    syncPatternTracks(synth.pattern);
  };

  $scope.removeTrack = function(index) {
    $scope.tracks.splice(index, 1);
    syncPatternTracks(synth.pattern);
  };

  $scope.toggleTrackMute = function(index) {
    $scope.tracks[index].muted = !$scope.tracks[index].muted;
    syncPatternTracks(synth.pattern);
  };

  $scope.updateNotes = function() {
    syncPatternTracks(synth.pattern);
  };

  $scope.updateTempo = function() {
    synth.transport.setTempo(parseInt($scope.tempo, 10));
  };

  $scope.updateAmplitude = function() {
    synth.transport.setAmplitude(parseFloat($scope.amplitude));
  };

  $scope.toggle = function() {
    synth.transport.toggle();
    $scope.playing = !$scope.playing;
  };

  $scope.updateLoop = function() {
    synth.transport.loop = $scope.loop;
  };

  $scope.export = function() {
    var pattern = new JSSynth.Pattern();
    syncPatternTracks(pattern);

    var exportCompleteCallback = function(blob) {
      var url  = window.URL.createObjectURL(blob);
      document.getElementById("downloaded-file").src = url;

      var hiddenDownloadLink = document.getElementById("hidden-download-link");
      hiddenDownloadLink.download = $scope.downloadFileName + ".wav";
      hiddenDownloadLink.href = url;
      hiddenDownloadLink.click();

      window.URL.revokeObjectURL(blob);
    };

    var offlineTransport = new JSSynth.OfflineTransport(pattern, parseInt($scope.tempo, 10), parseFloat($scope.amplitude), exportCompleteCallback);
    offlineTransport.tick();
  };
}]);

app.directive('noteInput', function () {
  return {
    require: 'ngModel',
    link: function (scope, element, attrs, ctrl) {
       if (!ctrl) return;

       var formatNoteValue = function(rawValue) {
         var formattedValue = rawValue;

         // Make first character uppercase (but not subsequent characters, to avoid
         // making a 'b' uppercase, which will mess with ♭ replacement).
         var firstCharacter = formattedValue.substr(0, 1);
         formattedValue = firstCharacter.toUpperCase() + formattedValue.substr(1);

         formattedValue = formattedValue.replace("##", "𝄪");
         formattedValue = formattedValue.replace("#", "♯");
         formattedValue = formattedValue.replace("bb", "𝄫");
         formattedValue = formattedValue.replace("b", "♭");
         formattedValue = formattedValue.replace("-", "—");

         return formattedValue;
       };

       ctrl.$formatters.push(function (a) {
         return formatNoteValue(ctrl.$modelValue);
       });

       ctrl.$parsers.unshift(function (viewValue) {
         var parsedValue = viewValue;

         // Make first character uppercase (but not subsequent characters, to avoid
         // making a 'b' uppercase, which will mess with ♭ replacement).
         var firstCharacter = viewValue.substr(0, 1);
         parsedValue = firstCharacter.toUpperCase() + viewValue.substr(1);
         parsedValue = parsedValue.replace("♯", "#");
         parsedValue = parsedValue.replace("𝄪", "##");
         parsedValue = parsedValue.replace("♭", "b");
         parsedValue = parsedValue.replace("𝄫", "bb");

         if (/^$|^-$|(^[A-G](b|bb|#|##){0,1}[0-7]$)/.test(parsedValue)) {
           ctrl.$setValidity('noteInput', true);
           return parsedValue;
         }
         else {
           ctrl.$setValidity('noteInput', false);
           return '';
         }
       });

       element.bind('blur', function(e) {
         element.val(formatNoteValue(element.val()));
       });

       element.bind('keydown', function(e) {
         var changeCurrentlySelectedNote = function(element, config) {
           var trackIndex = parseInt(element[0].id.split("-")[1], 10);
           var noteIndex = parseInt(element[0].id.split("-")[3], 10);
           var nextNoteId = 'track-' + (trackIndex + config.trackIndexDelta) + '-note-' + (noteIndex + config.noteIndexDelta);

           document.getElementById(nextNoteId).focus();
         };

         if (e.keyCode === 32) {  // Space bar
           element.val('');
         }
         else if (e.keyCode === 37) {  // Left arrow key
           if (element[0].selectionStart === 0 && !(element.hasClass('firstNote'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 0, noteIndexDelta: -1 });
           }
         }
         else if (e.keyCode === 39) {  // Right arrow key
           if (element[0].selectionEnd === element.val().length && !(element.hasClass('lastNote'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 0, noteIndexDelta: 1 });
           }
         }
         else if (e.keyCode === 38) {  // Up arrow key
           if (!(element.hasClass('firstTrack'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: -1, noteIndexDelta: 0 });
           }
         }
         else if (e.keyCode === 40) {  // Down arrow key
           if (!(element.hasClass('lastTrack'))) {
             changeCurrentlySelectedNote(element, { trackIndexDelta: 1, noteIndexDelta: 0 });
           }
         }
       });

       element.bind('keyup', function(e) {
         if (e.keyCode === 32) {  // Space bar
           element.val('');
         }
       });
    }
  };
});
<|endoftext|>


<commit_before>/**
 * @URL https://github.com/csetea/magpieJS
 * @license MIT
 */
// TODO
// m-option-group ?
// DONE
// m-option disabled
// m-option prevent
// m-option default
// m-appearance-select
// m-appearance-no-select
// m-appearance-select-none
// m-appearance=["select"]
// m-appearance=["select-none"]
// m-appearance=["no-select"]
define([ 'magpie/log!magpie/html5/widget/select/m-select',
		'css!./m-select.css' ], //
function(log) {

	var IE = (function () {
	    "use strict";

	    var ret, isTheBrowser,
	        actualVersion,
	        jscriptMap, jscriptVersion;

	    isTheBrowser = false;
	    jscriptMap = {
	        "5.5": "5.5",
	        "5.6": "6",
	        "5.7": "7",
	        "5.8": "8",
	        "9": "9",
	        "10": "10"
	    };
	    jscriptVersion = new Function("/*@cc_on return @_jscript_version; @*/")();

	    if (jscriptVersion !== undefined) {
	        isTheBrowser = true;
	        actualVersion = jscriptMap[jscriptVersion];
	    }

	    ret = {
	        isTheBrowser: isTheBrowser,
	        actualVersion: actualVersion
	    };

	    return ret;
	}());

	var forEach = Array.prototype.forEach;

	var findOptionEl = function(rt){
		if (rt == null){
			return null;
		}else if (rt.localName && rt.localName == 'm-option'){
			return rt;
		}else{
			return findOptionEl(rt.parentNode);
		}
	};

	return {
		tag : 'm-select',

		_openCounter: 0,

		createdCallback : function() {
			var _this=this;
			this._displayEl = document.createElement('div');
			this._displayEl.setAttribute('class','display');
			this._placeholderEl = document.createElement('div');
			this._placeholderEl.innerHTML=this.hasAttribute('placeholder')?this.getAttribute('placeholder'):'empty';
			this._placeholderEl.setAttribute('placeholder','');
			this._placeholderEl.contentEditable=false;
			this._displayEl.appendChild(this._placeholderEl);

			this._displayResultEl = document.createElement('div');
			this._displayResultEl.setAttribute('result','');
			this._displayEl.appendChild(this._displayResultEl);

			var selectionEl=this.querySelector('m-select-selection');
			if (selectionEl){
				this._displayEl.appendChild(selectionEl);
			}

			this._adjustWidth = false;
			var mAppearance =this.getAttribute('m-appearance');
			if (mAppearance != "no-select"){
				this._adjustWidth = true;
				var fakeSelectEl = document.createElement('select');
				fakeSelectEl.setAttribute('class','fake-select');
				fakeSelectEl.contentEditable=false;
				this._displayEl.appendChild(fakeSelectEl);

				var fakeSelectOverlayoutEl = document.createElement('div');
				fakeSelectOverlayoutEl.contentEditable=false;
				fakeSelectOverlayoutEl.setAttribute('class','fake-select-overlayout');
				this._displayEl.appendChild(fakeSelectOverlayoutEl);

				fakeSelectEl.onmousedown = function(event){
					event.preventDefault();
				};
			}

			this._displayEl.contentEditable=false;

			this._listEl = document.createElement('div');
			this._listEl.childNodes=this.childNodes;
			this._listEl.setAttribute('class','list');
			this._listEl.contentEditable=true;

			this._listEl.onkeydown = function(event){
				 var target = event.target || event.srcElement;
				 if ( target == _this._listEl){
					 event.preventDefault();
				 }
			};

			this.onblur = function(){
				_this._listEl.blur();
			}
			this._listEl.onmousedown=function(event){
				var relatedTarget = event.target || event.srcElement;
				_this._sourceOptionEl = findOptionEl(relatedTarget);
			}

			this._listEl.onblur=function(event){
				var mOptionEl = _this._sourceOptionEl;
				if (mOptionEl && mOptionEl.hasAttribute('prevent')){
					setTimeout(function(){
						var focusedEl = _this.querySelector(':focus')
						if (!focusedEl){
							_this.close();
						}else{
							focusedEl.addEventListener('blur', function(event2){
								setTimeout(function(){
									if (!_this.querySelector(':focus')){
										_this.close();
									}
								},50)

							});
						}
					},50)
				}else{
					if (IE.isTheBrowser){
						setTimeout(function(){
							_this.close();
						},300)
					}else{
						_this.close();
					}
				}
			};

			this._displayEl.onclick = function(event){
				if (_this._openStateOnMousedown){
					if (_this._adjustWidth){
						_this.style.minWidth='';
					}
					if(event){
						event.stopImmediatePropagation();
					}
					_this.close();
				}else{
					//FIX width on open
					if (_this._adjustWidth){
						_this.style.minWidth=_this.offsetWidth+'px';
					}
					// open
					_this.open();
				}
			};

			this._displayEl.onmousedown = function(event){
				_this._sourceOptionEl=null;
				_this._openStateOnMousedown = _this.hasAttribute("opened");
			}

			this._listContainerEl = document.createElement('div');
			this._listContainerEl.setAttribute('class','list-container');
			this._listContainerEl.appendChild(this._listEl);
		},

		close: function(){
			this._listEl.blur();
			this._listEl.style.display="none";
			setTimeout(function(){if (this._listEl){this._listEl.style.display="inherit";}},5);

			this.removeAttribute("opened");
		},

		open: function(){
			var _this=this;
			if (_this._adjustWidth){
				this.style.minWidth=this.offsetWidth+'px';
			}
			if (this._openCounter == 0){
				[].forEach.call(this._listEl.childNodes, function(child){
					if (child instanceof HTMLElement){
						if (child != _this._FirefFoxContentEditableFixTrap){
							if (child.contentEditable !== true){
								child.contentEditable=false;

								//FIXME on by FireFox browser
								var _FirefFoxContentEditableFix = document.createElement('div');
								_FirefFoxContentEditableFix.setAttribute('class','moz-FF-cE-fix');
								_FirefFoxContentEditableFix.contentEditable=true;
								child.appendChild(_FirefFoxContentEditableFix);
							}
						}
					}
				});
			}

			this.openCounter++;
			this._listEl.style.display="inherit";
			this.setAttribute("opened","true");
			this._listEl.focus();
		},

		update: function(){
			var selection = this.selection();
			var selectionLength= selection.length;
			//FIX width on update ??
//			this.style.width='';

			var selectionChangedEvent = new CustomEvent('change');
 			this.dispatchEvent(selectionChangedEvent);

			if (selectionLength >0){

				this.setAttribute('selection',selectionLength);

				if (!this._resultTemplatePresent){
					if (this.hasAttribute('multiple')){
						this._displayResultEl.innerHTML =  selectionLength + ' / ' + this.querySelectorAll('m-option').length;
					}else{
						while (this._displayResultEl.firstChild) {
							this._displayResultEl.removeChild(this._displayResultEl.firstChild);
						}
						var _this=this;
						selection.forEach(function(el){
							var clone = el.cloneNode(true);
							clone.removeAttribute('selected');
							_this._displayResultEl.appendChild( clone);
						});
					}
				}

			}else{
				this.removeAttribute('selection');
			}
		},

		fire: function(event, stateObject){
			log.trace('fire:',stateObject);

			this.update();

			if (!this.hasAttribute('multiple')){
				log.warn('fire ',stateObject, ' to close')
				this.close();
			}

		},

		attachedCallback: function(){
			var _this=this;
			while (this.firstChild) {
				var child= this.removeChild(this.firstChild);
				if (child.hasAttribute && child.hasAttribute('placeholder')){
					_this._displayEl.replaceChild( child, _this._placeholderEl);
				}else if (child.hasAttribute && child.hasAttribute('result')){
					_this._displayEl.replaceChild( child, _this._displayResultEl);
				}else {
					// TODO XXX
					_this._listEl.appendChild(child);
				}

			}

			this._resultTemplatePresent = this._displayResultEl.querySelector('*');

			this.appendChild(_this._displayEl);
			this.appendChild(_this._listContainerEl);

			this.update();
		},

		selection: function(){
			var selection=[];

			var childs = this.querySelectorAll('m-option[selected]');
			forEach.call(childs, function( el ){
					selection.push(el);
			});

			if (selection.length === 0){
				var defaultEl= this.querySelector('m-option[default]');
				if (defaultEl){
					defaultEl.setAttribute('selected','true');
					selection.push(defaultEl);
				}
			}

			return selection;
		}

	};

});
<commit_msg>bugfix: do not reprocess child node if already initialized<commit_after>/**
 * @URL https://github.com/csetea/magpieJS
 * @license MIT
 */
// TODO
// m-option-group ?
// DONE
// m-option disabled
// m-option prevent
// m-option default
// m-appearance-select
// m-appearance-no-select
// m-appearance-select-none
// m-appearance=["select"]
// m-appearance=["select-none"]
// m-appearance=["no-select"]
define([ 'magpie/log!magpie/html5/widget/select/m-select',
		'css!./m-select.css' ], //
function(log) {

	var IE = (function () {
	    "use strict";

	    var ret, isTheBrowser,
	        actualVersion,
	        jscriptMap, jscriptVersion;

	    isTheBrowser = false;
	    jscriptMap = {
	        "5.5": "5.5",
	        "5.6": "6",
	        "5.7": "7",
	        "5.8": "8",
	        "9": "9",
	        "10": "10"
	    };
	    jscriptVersion = new Function("/*@cc_on return @_jscript_version; @*/")();

	    if (jscriptVersion !== undefined) {
	        isTheBrowser = true;
	        actualVersion = jscriptMap[jscriptVersion];
	    }

	    ret = {
	        isTheBrowser: isTheBrowser,
	        actualVersion: actualVersion
	    };

	    return ret;
	}());

	var forEach = Array.prototype.forEach;

	var findOptionEl = function(rt){
		if (rt == null){
			return null;
		}else if (rt.localName && rt.localName == 'm-option'){
			return rt;
		}else{
			return findOptionEl(rt.parentNode);
		}
	};

	return {
		tag : 'm-select',

		_openCounter: 0,

		createdCallback : function() {
			if (this.className == "select x"){
				log.warn('createdCallback')
			}

			var _this=this;
			this._displayEl = document.createElement('div');
			this._displayEl.setAttribute('class','display');
			this._placeholderEl = document.createElement('div');
			this._placeholderEl.innerHTML=this.hasAttribute('placeholder')?this.getAttribute('placeholder'):'empty';
			this._placeholderEl.setAttribute('placeholder','');
			this._placeholderEl.contentEditable=false;
			this._displayEl.appendChild(this._placeholderEl);

			this._displayResultEl = document.createElement('div');
			this._displayResultEl.setAttribute('result','');
			this._displayEl.appendChild(this._displayResultEl);

			var selectionEl=this.querySelector('m-select-selection');
			if (selectionEl){
				this._displayEl.appendChild(selectionEl);
			}

			this._adjustWidth = false;
			var mAppearance =this.getAttribute('m-appearance');
			if (mAppearance != "no-select"){
				this._adjustWidth = true;
				var fakeSelectEl = document.createElement('select');
				fakeSelectEl.setAttribute('class','fake-select');
				fakeSelectEl.contentEditable=false;
				this._displayEl.appendChild(fakeSelectEl);

				var fakeSelectOverlayoutEl = document.createElement('div');
				fakeSelectOverlayoutEl.contentEditable=false;
				fakeSelectOverlayoutEl.setAttribute('class','fake-select-overlayout');
				this._displayEl.appendChild(fakeSelectOverlayoutEl);

				fakeSelectEl.onmousedown = function(event){
					event.preventDefault();
				};
			}

			this._displayEl.contentEditable=false;

			this._listEl = document.createElement('div');
			this._listEl.childNodes=this.childNodes;
			this._listEl.setAttribute('class','list');
			this._listEl.contentEditable=true;

			this._listEl.onkeydown = function(event){
				 var target = event.target || event.srcElement;
				 if ( target == _this._listEl){
					 event.preventDefault();
				 }
			};

			this.onblur = function(){
				_this.querySelector('.list-container>.list').blur();
			}

			this._listContainerEl = document.createElement('div');
			this._listContainerEl.setAttribute('class','list-container');
			this._listContainerEl.appendChild(this._listEl);
		},

		close: function(){
			this._listEl.blur();
			this._listEl.style.display="none";
			setTimeout(function(){if (this._listEl){this._listEl.style.display="inherit";}},5);

			this.removeAttribute("opened");
		},

		open: function(){
			var _this=this;
			if (_this._adjustWidth){
				this.style.minWidth=this.offsetWidth+'px';
			}
			if (this._openCounter == 0){
				[].forEach.call(this._listEl.childNodes, function(child){
					if (child instanceof HTMLElement){
						if (child != _this._FirefFoxContentEditableFixTrap){
							if (child.contentEditable !== true){
								child.contentEditable=false;

								//FIXME on by FireFox browser
								var _FirefFoxContentEditableFix = document.createElement('div');
								_FirefFoxContentEditableFix.setAttribute('class','moz-FF-cE-fix');
								_FirefFoxContentEditableFix.contentEditable=true;
								child.appendChild(_FirefFoxContentEditableFix);
							}
						}
					}
				});
			}

			this.openCounter++;
			this._listEl.style.display="inherit";
			this.setAttribute("opened","true");
			this._listEl.focus();
		},

		update: function(){
			var selection = this.selection();
			var selectionLength= selection.length;
			//FIX width on update ??
//			this.style.width='';

			var selectionChangedEvent = new CustomEvent('change');
 			this.dispatchEvent(selectionChangedEvent);

			if (selectionLength >0){

				this.setAttribute('selection',selectionLength);

				if (!this._resultTemplatePresent){
					if (this.hasAttribute('multiple')){
						this._displayResultEl.innerHTML =  selectionLength + ' / ' + this.querySelectorAll('m-option').length;
					}else{
						while (this._displayResultEl.firstChild) {
							this._displayResultEl.removeChild(this._displayResultEl.firstChild);
						}
						var _this=this;
						selection.forEach(function(el){
							var clone = el.cloneNode(true);
							clone.removeAttribute('selected');
							_this._displayResultEl.appendChild( clone);
						});
					}
				}

			}else{
				this.removeAttribute('selection');
			}
		},

		fire: function(event, stateObject){
			log.trace('fire:',stateObject);

			this.update();

			if (!this.hasAttribute('multiple')){
				log.warn('fire ',stateObject, ' to close')
				this.close();
			}

		},

		attachedCallback: function(){
			var _this=this;
			if (this.className == "select x"){
				log.warn('attachedCallback', this.getAttribute("inited"))

			}

			if (this.getAttribute("inited") != "true"){
				while (this.firstChild) {
					var child= this.removeChild(this.firstChild);
					if (child.hasAttribute && child.hasAttribute('placeholder')){
						if (this.className == "select x"){
							log.warn('attachedCallback placeholder',child)
						}

						_this._displayEl.replaceChild( child, _this._placeholderEl);
					}else if (child.hasAttribute && child.hasAttribute('result')){
						_this._displayEl.replaceChild( child, _this._displayResultEl);
					}else {
						// TODO XXX
						_this._listEl.appendChild(child);
					}

				}

				this._resultTemplatePresent = this._displayResultEl.querySelector('*');

				this.appendChild(_this._displayEl);
				this.appendChild(_this._listContainerEl);
				this.setAttribute("inited","true")
			}

			this._displayEl = this.querySelector('.display');
			this._displayEl.onclick = function(event){
				if (_this._openStateOnMousedown){
					if (_this._adjustWidth){
						_this.style.minWidth='';
					}
					if(event){
						event.stopImmediatePropagation();
					}
					_this.close();
				}else{
					//FIX width on open
					if (_this._adjustWidth){
						_this.style.minWidth=_this.offsetWidth+'px';
					}
					// open
					_this.open();
				}
			};

			this._displayEl.onmousedown = function(event){
				_this._sourceOptionEl=null;
				_this._openStateOnMousedown = _this.hasAttribute("opened");
			}

			this._listEl = _this.querySelector('.list-container>.list');
			this._listEl.onmousedown=function(event){
			var relatedTarget = event.target || event.srcElement;
				_this._sourceOptionEl = findOptionEl(relatedTarget);
			}

			this._listEl.onblur=function(event){
			var mOptionEl = _this._sourceOptionEl;
			if (mOptionEl && mOptionEl.hasAttribute('prevent')){
				setTimeout(function(){
					var focusedEl = _this.querySelector(':focus')
					if (!focusedEl){
						_this.close();
					}else{
						focusedEl.addEventListener('blur', function(event2){
							setTimeout(function(){
								if (!_this.querySelector(':focus')){
									_this.close();
								}
							},50)

						});
					}
				},50)
			}else{
				if (IE.isTheBrowser){
					setTimeout(function(){
						_this.close();
					},300)
				}else{
					_this.close();
				}
			}
			};

			this.update();
		},

		selection: function(){
			var selection=[];

			var childs = this.querySelectorAll('m-option[selected]');
			forEach.call(childs, function( el ){
					selection.push(el);
			});

			if (selection.length === 0){
				var defaultEl= this.querySelector('m-option[default]');
				if (defaultEl){
					defaultEl.setAttribute('selected','true');
					selection.push(defaultEl);
				}
			}

			return selection;
		}

	};

});
<|endoftext|>


<commit_before>import Ember from 'ember';
import DS from 'ember-data';

import {
  extractDeleteRecord
} from 'ember-pouch/utils';

const {
  run: {
    bind
  },
  on,
  String: {
    pluralize,
    camelize,
    classify
  }
} = Ember;

export default DS.RESTAdapter.extend({
  coalesceFindRequests: true,

  // The change listener ensures that individual records are kept up to date
  // when the data in the database changes. This makes ember-data 2.0's record
  // reloading redundant.
  shouldReloadRecord: function () { return false; },
  shouldBackgroundReloadRecord: function () { return false; },

  _startChangesToStoreListener: on('init', function () {
    this.changes = this.db.changes({
      since: 'now',
      live: true,
      returnDocs: false
    }).on('change', bind(this, 'onChange'));
  }),

  onChange: function (change) {
    // If relational_pouch isn't initialized yet, there can't be any records
    // in the store to update.
    if (!this.db.rel) { return; }

    var obj = this.db.rel.parseDocID(change.id);
    // skip changes for non-relational_pouch docs. E.g., design docs.
    if (!obj.type || !obj.id || obj.type === '') { return; }

    var store = this.container.lookup('store:main');

    try {
      store.modelFor(obj.type);
    } catch (e) {
      // The record refers to a model which this version of the application
      // does not have.
      return;
    }

    var recordInStore = store.getById(obj.type, obj.id);
    if (!recordInStore) {
      // The record hasn't been loaded into the store; no need to reload its data.
      return;
    }
    if (!recordInStore.get('isLoaded') || recordInStore.get('isDirty')) {
      // The record either hasn't loaded yet or has unpersisted local changes.
      // In either case, we don't want to refresh it in the store
      // (and for some substates, attempting to do so will result in an error).
      return;
    }

    if (change.deleted) {
      store.unloadRecord(recordInStore);
    } else {
      recordInStore.reload();
    }
  },

  willDestroy: function() {
    if (this.changes) {
      this.changes.cancel();
    }
  },

  _init: function (store, type) {
    var self = this,
        recordTypeName = this.getRecordTypeName(type);
    if (!this.db || typeof this.db !== 'object') {
      throw new Error('Please set the `db` property on the adapter.');
    }

    if (!Ember.get(type, 'attributes').has('rev')) {
      var modelName = classify(recordTypeName);
      throw new Error('Please add a `rev` attribute of type `string`' +
        ' on the ' + modelName + ' model.');
    }

    this._schema = this._schema || [];

    var singular = recordTypeName;
    var plural = pluralize(recordTypeName);

    // check that we haven't already registered this model
    for (var i = 0, len = this._schema.length; i < len; i++) {
      var currentSchemaDef = this._schema[i];
      if (currentSchemaDef.singular === singular) {
        return;
      }
    }

    var schemaDef = {
      singular: singular,
      plural: plural
    };

    if (type.documentType) {
      schemaDef['documentType'] = type.documentType;
    }

    // else it's new, so update
    this._schema.push(schemaDef);

    // check all the subtypes
    // We check the type of `rel.type`because with ember-data beta 19
    // `rel.type` switched from DS.Model to string
    type.eachRelationship(function (_, rel) {
      if (rel.kind !== 'belongsTo' && rel.kind !== 'hasMany') {
        // TODO: support inverse as well
        return; // skip
      }
      var relDef = {},
          relModel = (typeof rel.type === 'string' ? store.modelFor(rel.type) : rel.type);
      if (relModel) {
        relDef[rel.kind] = {
          type: self.getRecordTypeName(relModel),
          options: rel.options
        };
        if (!schemaDef.relations) {
          schemaDef.relations = {};
        }
        schemaDef.relations[rel.key] = relDef;
        self._init(store, relModel);
      }
    });

    this.db.setSchema(this._schema);
  },

  _recordToData: function (store, type, record) {
    var data = {};
    // Though it would work to use the default recordTypeName for modelName &
    // serializerKey here, these uses are conceptually distinct and may vary
    // independently.
    var modelName = type.modelName || type.typeKey;
    var serializerKey = camelize(modelName);
    var serializer = store.serializerFor(modelName);

    var recordToStore = record;
    // In Ember-Data beta.15, we need to take a snapshot. See issue #45.
    if (
      typeof record.record === 'undefined' &&
      typeof record._createSnapshot === 'function'
    ) {
      recordToStore = record._createSnapshot();
    }

    serializer.serializeIntoHash(
      data,
      type,
      recordToStore,
      {includeId: true}
    );

    data = data[serializerKey];

    // ember sets it to null automatically. don't need it.
    if (data.rev === null) {
      delete data.rev;
    }

    return data;
  },

  /**
   * Returns the string to use for the model name part of the PouchDB document
   * ID for records of the given ember-data type.
   *
   * This method uses the camelized version of the model name in order to
   * preserve data compatibility with older versions of ember-pouch. See
   * nolanlawson/ember-pouch#63 for a discussion.
   *
   * You can override this to change the behavior. If you do, be aware that you
   * need to execute a data migration to ensure that any existing records are
   * moved to the new IDs.
   */
  getRecordTypeName(type) {
    if (type.modelName) {
      return camelize(type.modelName);
    } else {
      // This branch can be removed when the library drops support for
      // ember-data 1.0-beta17 and earlier.
      return type.typeKey;
    }
  },

  findAll: function(store, type /*, sinceToken */) {
    // TODO: use sinceToken
    this._init(store, type);
    return this.db.rel.find(this.getRecordTypeName(type));
  },

  findMany: function(store, type, ids) {
    this._init(store, type);
    return this.db.rel.find(this.getRecordTypeName(type), ids);
  },

  findQuery: function(/* store, type, query */) {
    throw new Error(
      "findQuery not yet supported by ember-pouch. " +
      "See https://github.com/nolanlawson/ember-pouch/issues/7.");
  },

  /**
   * `find` has been deprecated in ED 1.13 and is replaced by 'new store
   * methods', see: https://github.com/emberjs/data/pull/3306
   * We keep the method for backward compatibility and forward calls to
   * `findRecord`. This can be removed when the library drops support
   * for deprecated methods.
  */
  find: function (store, type, id) {
    return this.findRecord(store, type, id);
  },

  findRecord: function (store, type, id) {
    this._init(store, type);
    var recordTypeName = this.getRecordTypeName(type);
    return this.db.rel.find(recordTypeName, id).then(function (payload) {
      // Ember Data chokes on empty payload, this function throws
      // an error when the requested data is not found
      if (typeof payload === 'object' && payload !== null) {
        var singular = recordTypeName;
        var plural = pluralize(recordTypeName);

        var results = payload[singular] || payload[plural];
        if (results && results.length > 0) {
          return payload;
        }
      }
      throw new Error('Not found: type "' + recordTypeName +
        '" with id "' + id + '"');
    });
  },

  createRecord: function(store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.db.rel.save(this.getRecordTypeName(type), data);
  },

  updateRecord: function (store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.db.rel.save(this.getRecordTypeName(type), data);
  },

  deleteRecord: function (store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.db.rel.del(this.getRecordTypeName(type), data)
      .then(extractDeleteRecord);
  }
});
<commit_msg>Changed access to db property to use Ember.get so that db can be injected<commit_after>import Ember from 'ember';
import DS from 'ember-data';

import {
  extractDeleteRecord
} from 'ember-pouch/utils';

const {
  run: {
    bind
  },
  on,
  String: {
    pluralize,
    camelize,
    classify
  }
} = Ember;

export default DS.RESTAdapter.extend({
  coalesceFindRequests: true,

  // The change listener ensures that individual records are kept up to date
  // when the data in the database changes. This makes ember-data 2.0's record
  // reloading redundant.
  shouldReloadRecord: function () { return false; },
  shouldBackgroundReloadRecord: function () { return false; },

  _startChangesToStoreListener: on('init', function () {
    this.changes = this.get('db').changes({
      since: 'now',
      live: true,
      returnDocs: false
    }).on('change', bind(this, 'onChange'));
  }),

  onChange: function (change) {
    // If relational_pouch isn't initialized yet, there can't be any records
    // in the store to update.
    if (!this.get('db').rel) { return; }

    var obj = this.get('db').rel.parseDocID(change.id);
    // skip changes for non-relational_pouch docs. E.g., design docs.
    if (!obj.type || !obj.id || obj.type === '') { return; }

    var store = this.container.lookup('store:main');

    try {
      store.modelFor(obj.type);
    } catch (e) {
      // The record refers to a model which this version of the application
      // does not have.
      return;
    }

    var recordInStore = store.getById(obj.type, obj.id);
    if (!recordInStore) {
      // The record hasn't been loaded into the store; no need to reload its data.
      return;
    }
    if (!recordInStore.get('isLoaded') || recordInStore.get('isDirty')) {
      // The record either hasn't loaded yet or has unpersisted local changes.
      // In either case, we don't want to refresh it in the store
      // (and for some substates, attempting to do so will result in an error).
      return;
    }

    if (change.deleted) {
      store.unloadRecord(recordInStore);
    } else {
      recordInStore.reload();
    }
  },

  willDestroy: function() {
    if (this.changes) {
      this.changes.cancel();
    }
  },

  _init: function (store, type) {
    var self = this,
        recordTypeName = this.getRecordTypeName(type);
    if (!this.get('db') || typeof this.get('db') !== 'object') {
      throw new Error('Please set the `db` property on the adapter.');
    }

    if (!Ember.get(type, 'attributes').has('rev')) {
      var modelName = classify(recordTypeName);
      throw new Error('Please add a `rev` attribute of type `string`' +
        ' on the ' + modelName + ' model.');
    }

    this._schema = this._schema || [];

    var singular = recordTypeName;
    var plural = pluralize(recordTypeName);

    // check that we haven't already registered this model
    for (var i = 0, len = this._schema.length; i < len; i++) {
      var currentSchemaDef = this._schema[i];
      if (currentSchemaDef.singular === singular) {
        return;
      }
    }

    var schemaDef = {
      singular: singular,
      plural: plural
    };

    if (type.documentType) {
      schemaDef['documentType'] = type.documentType;
    }

    // else it's new, so update
    this._schema.push(schemaDef);

    // check all the subtypes
    // We check the type of `rel.type`because with ember-data beta 19
    // `rel.type` switched from DS.Model to string
    type.eachRelationship(function (_, rel) {
      if (rel.kind !== 'belongsTo' && rel.kind !== 'hasMany') {
        // TODO: support inverse as well
        return; // skip
      }
      var relDef = {},
          relModel = (typeof rel.type === 'string' ? store.modelFor(rel.type) : rel.type);
      if (relModel) {
        relDef[rel.kind] = {
          type: self.getRecordTypeName(relModel),
          options: rel.options
        };
        if (!schemaDef.relations) {
          schemaDef.relations = {};
        }
        schemaDef.relations[rel.key] = relDef;
        self._init(store, relModel);
      }
    });

    this.get('db').setSchema(this._schema);
  },

  _recordToData: function (store, type, record) {
    var data = {};
    // Though it would work to use the default recordTypeName for modelName &
    // serializerKey here, these uses are conceptually distinct and may vary
    // independently.
    var modelName = type.modelName || type.typeKey;
    var serializerKey = camelize(modelName);
    var serializer = store.serializerFor(modelName);

    var recordToStore = record;
    // In Ember-Data beta.15, we need to take a snapshot. See issue #45.
    if (
      typeof record.record === 'undefined' &&
      typeof record._createSnapshot === 'function'
    ) {
      recordToStore = record._createSnapshot();
    }

    serializer.serializeIntoHash(
      data,
      type,
      recordToStore,
      {includeId: true}
    );

    data = data[serializerKey];

    // ember sets it to null automatically. don't need it.
    if (data.rev === null) {
      delete data.rev;
    }

    return data;
  },

  /**
   * Returns the string to use for the model name part of the PouchDB document
   * ID for records of the given ember-data type.
   *
   * This method uses the camelized version of the model name in order to
   * preserve data compatibility with older versions of ember-pouch. See
   * nolanlawson/ember-pouch#63 for a discussion.
   *
   * You can override this to change the behavior. If you do, be aware that you
   * need to execute a data migration to ensure that any existing records are
   * moved to the new IDs.
   */
  getRecordTypeName(type) {
    if (type.modelName) {
      return camelize(type.modelName);
    } else {
      // This branch can be removed when the library drops support for
      // ember-data 1.0-beta17 and earlier.
      return type.typeKey;
    }
  },

  findAll: function(store, type /*, sinceToken */) {
    // TODO: use sinceToken
    this._init(store, type);
    return this.get('db').rel.find(this.getRecordTypeName(type));
  },

  findMany: function(store, type, ids) {
    this._init(store, type);
    return this.get('db').rel.find(this.getRecordTypeName(type), ids);
  },

  findQuery: function(/* store, type, query */) {
    throw new Error(
      "findQuery not yet supported by ember-pouch. " +
      "See https://github.com/nolanlawson/ember-pouch/issues/7.");
  },

  /**
   * `find` has been deprecated in ED 1.13 and is replaced by 'new store
   * methods', see: https://github.com/emberjs/data/pull/3306
   * We keep the method for backward compatibility and forward calls to
   * `findRecord`. This can be removed when the library drops support
   * for deprecated methods.
  */
  find: function (store, type, id) {
    return this.findRecord(store, type, id);
  },

  findRecord: function (store, type, id) {
    this._init(store, type);
    var recordTypeName = this.getRecordTypeName(type);
    return this.get('db').rel.find(recordTypeName, id).then(function (payload) {
      // Ember Data chokes on empty payload, this function throws
      // an error when the requested data is not found
      if (typeof payload === 'object' && payload !== null) {
        var singular = recordTypeName;
        var plural = pluralize(recordTypeName);

        var results = payload[singular] || payload[plural];
        if (results && results.length > 0) {
          return payload;
        }
      }
      throw new Error('Not found: type "' + recordTypeName +
        '" with id "' + id + '"');
    });
  },

  createRecord: function(store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.get('db').rel.save(this.getRecordTypeName(type), data);
  },

  updateRecord: function (store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.get('db').rel.save(this.getRecordTypeName(type), data);
  },

  deleteRecord: function (store, type, record) {
    this._init(store, type);
    var data = this._recordToData(store, type, record);
    return this.get('db').rel.del(this.getRecordTypeName(type), data)
      .then(extractDeleteRecord);
  }
});
<|endoftext|>


<commit_before>// @flow

import React from 'react';
import ExampleWrapper from '../../ExampleWrapper';
import md from '../../markdown/renderer';
import {
  AsyncCallbacks,
  AsyncPromises,
  AnimatedMulti,
  BasicSingle,
  BasicGrouped,
  BasicMulti,
  CreatableSingle,
  Experimental,
  StyledMulti,
  StyledSingle,
} from '../../examples';

export default function Home() {
  return md`
  # Welcome

  TODO needs content!

  ## Quick Start

  Start by installing \`react-select\`

  ~~~bash
  yarn add react-select
  ~~~

  Import the default export and render in your component:

  ~~~jsx
  import React, { Component } from 'react'
  import Select from 'react-select'

  const options = [
    { value: 'chocolate', label: 'Chocolate' },
    { value: 'strawberry', label: 'Strawberry' },
    { value: 'vanilla', label: 'Vanilla' }
  ]

  const MyComponent = () => (
    <Select options={options} />
  )
  ~~~

  ${(
    <ExampleWrapper
      label="Single"
      urlPath="docs/examples/BasicSingle.js"
      raw={require('!!raw-loader!../../examples/BasicSingle.js')}
    >
      <BasicSingle />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Grouped"
      urlPath="docs/examples/BasicGrouped.js"
      raw={require('!!raw-loader!../../examples/BasicGrouped.js')}
    >
      <BasicGrouped />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Multi"
      urlPath="docs/examples/BasicMulti.js"
      raw={require('!!raw-loader!../../examples/BasicMulti.js')}
    >
      <BasicMulti />
    </ExampleWrapper>
  )}

  ## Animated Components

  React-Select comes with Animated variants that wrap the built-in
  components.

  Remove the values below to see them in action.

  ${(
    <ExampleWrapper
      label="Animation"
      urlPath="docs/examples/AnimatedMulti.js"
      raw={require('!!raw-loader!../../examples/AnimatedMulti.js')}

    >
      <AnimatedMulti />
    </ExampleWrapper>
  )}

  ## Custom Styles

  Style individual components with custom css using the \`styles\` prop.

  ${(
    <ExampleWrapper
      label="Single"
      urlPath="docs/examples/StyledSingle.js"
      raw={require('!!raw-loader!../../examples/StyledSingle.js')}
    >
      <StyledSingle />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Multi Select"
      urlPath="docs/examples/StyledMulti.js"
      raw={require('!!raw-loader!../../examples/StyledMulti.js')}
    >
      <StyledMulti />
    </ExampleWrapper>
  )}

  # Async
  Use the Async component to load options from a remote source as the user types.

  ~~~jsx
  import Async from 'react-select/lib/Async';
  ~~~

  ${(
    <ExampleWrapper
      label="Callbacks"
      urlPath="docs/examples/AsyncCallbacks.js"
      raw={require('!!raw-loader!../../examples/AsyncCallbacks.js')}
    >
      <AsyncCallbacks />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Promises"
      urlPath="docs/examples/AsyncPromises.js"
      raw={require('!!raw-loader!../../examples/AsyncPromises.js')}
    >
      <AsyncPromises />
    </ExampleWrapper>
  )}

  # Creatable

  ~~~jsx
  import Creatable from 'react-select/lib/Creatable';
  ~~~

  ${(
    <ExampleWrapper
      label="Creatable Example"
      urlPath="docs/home/examples/CreatableSingle.js"
      raw={require('!!raw-loader!../../examples/CreatableSingle.js')}
    >
      <CreatableSingle />
    </ExampleWrapper>
  )}

  ## Experimental

  Wild experiments with react-select v2

  ${(
    <ExampleWrapper
      isEditable={false}
      label="Date Picker"
      urlPath="docs/examples/Experimental.js"
      raw={require('!!raw-loader!../../examples/Experimental.js')}
    >
      <Experimental />
    </ExampleWrapper>
  )}

  > This example uses a combination of custom components and functions to make react-select behave like a date picker.

  > Type a date like "25/8/18", "tomorrow", "next monday", or "6 weeks from now" into the field to get date suggestions.
`;
}
<commit_msg>Fixing homepage content<commit_after>// @flow

import React from 'react';
import ExampleWrapper from '../../ExampleWrapper';
import md from '../../markdown/renderer';
import {
  AsyncCallbacks,
  AsyncPromises,
  AnimatedMulti,
  BasicSingle,
  BasicGrouped,
  BasicMulti,
  CreatableSingle,
  StyledMulti,
  StyledSingle,
} from '../../examples';

export default function Home() {
  return md`
  # Welcome

  React Select v2 is nearly ready, and we'd love your feedback.

  View the [source code](https://github.com/JedWatson/react-select/tree/v2) and
  [Pull Request on github](https://github.com/JedWatson/react-select/pull/2289).

  ## Getting Started

  Start by installing \`react-select\` (use the next tag to install the alpha)

  ~~~bash
  yarn add react-select@next
  ~~~

  Import the default export and render in your component:

  ~~~jsx
  import React, { Component } from 'react'
  import Select from 'react-select'

  const options = [
    { value: 'chocolate', label: 'Chocolate' },
    { value: 'strawberry', label: 'Strawberry' },
    { value: 'vanilla', label: 'Vanilla' }
  ]

  const MyComponent = () => (
    <Select options={options} />
  )
  ~~~

  ${(
    <ExampleWrapper
      label="Single"
      urlPath="docs/examples/BasicSingle.js"
      raw={require('!!raw-loader!../../examples/BasicSingle.js')}
    >
      <BasicSingle />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Grouped"
      urlPath="docs/examples/BasicGrouped.js"
      raw={require('!!raw-loader!../../examples/BasicGrouped.js')}
    >
      <BasicGrouped />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Multi"
      urlPath="docs/examples/BasicMulti.js"
      raw={require('!!raw-loader!../../examples/BasicMulti.js')}
    >
      <BasicMulti />
    </ExampleWrapper>
  )}

  ## Animated Components

  React-Select comes with Animated variants that wrap the built-in
  components.

  Remove the values below to see them in action.

  ${(
    <ExampleWrapper
      label="Animation"
      urlPath="docs/examples/AnimatedMulti.js"
      raw={require('!!raw-loader!../../examples/AnimatedMulti.js')}
    >
      <AnimatedMulti />
    </ExampleWrapper>
  )}

  ## Custom Styles

  Style individual components with custom css using the \`styles\` prop.

  ${(
    <ExampleWrapper
      label="Single"
      urlPath="docs/examples/StyledSingle.js"
      raw={require('!!raw-loader!../../examples/StyledSingle.js')}
    >
      <StyledSingle />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Multi Select"
      urlPath="docs/examples/StyledMulti.js"
      raw={require('!!raw-loader!../../examples/StyledMulti.js')}
    >
      <StyledMulti />
    </ExampleWrapper>
  )}

  # Async
  Use the Async component to load options from a remote source as the user types.

  ~~~jsx
  import Async from 'react-select/lib/Async';
  ~~~

  ${(
    <ExampleWrapper
      label="Callbacks"
      urlPath="docs/examples/AsyncCallbacks.js"
      raw={require('!!raw-loader!../../examples/AsyncCallbacks.js')}
    >
      <AsyncCallbacks />
    </ExampleWrapper>
  )}

  ${(
    <ExampleWrapper
      label="Promises"
      urlPath="docs/examples/AsyncPromises.js"
      raw={require('!!raw-loader!../../examples/AsyncPromises.js')}
    >
      <AsyncPromises />
    </ExampleWrapper>
  )}

  # Creatable

  ~~~jsx
  import Creatable from 'react-select/lib/Creatable';
  ~~~

  ${(
    <ExampleWrapper
      label="Creatable Example"
      urlPath="docs/home/examples/CreatableSingle.js"
      raw={require('!!raw-loader!../../examples/CreatableSingle.js')}
    >
      <CreatableSingle />
    </ExampleWrapper>
  )}
`;
}
<|endoftext|>


<commit_before>import DS from 'ember-data';
import { recordKey } from 'ember-gdrive/lib/util';

function serializeId(record, relationship) {
  if (!record) {
    return null;
  }
  if (relationship.options.polymorphic) {
    return {
      id: record.get('id'),
      type: recordKey(record)
    };
  }
  else {
    return record.get('id');
  }
}

var Serializer = DS.JSONSerializer.extend({

  serializeHasMany: function(record, json, relationship) {
    if(relationship.options.serialize === false) {
      return;
    }
    var key = relationship.key;
    var rel = record.get(key);

    if(relationship.options.async && rel){
      rel = record._relationships[key].manyArray.toArray();
    }

    if (rel){
      json[key] = rel.map(function(record) {
        return serializeId(record, relationship);
      });
    }
  },

  serializeBelongsTo: function(record, json, relationship) {
    if(relationship.options.serialize === false) {
      return;
    }
    if (relationship.options && relationship.options.async){
      var key = relationship.key;
      var belongsTo = record._relationships[key].inverseRecord;
      json[key] = serializeId(belongsTo, relationship);
    } else {
      this._super(record, json, relationship);
    }
  },

  normalizePayload: function(payload) {
    return JSON.parse(JSON.stringify(payload));
  }
});

export default Serializer;<commit_msg>Remove superfluous fix in favor of the remaining better one<commit_after>import DS from 'ember-data';
import { recordKey } from 'ember-gdrive/lib/util';

function serializeId(record, relationship) {
  if (!record) {
    return null;
  }
  if (relationship.options.polymorphic) {
    return {
      id: record.get('id'),
      type: recordKey(record)
    };
  }
  else {
    return record.get('id');
  }
}

var Serializer = DS.JSONSerializer.extend({

  serializeHasMany: function(record, json, relationship) {
    if(relationship.options.serialize === false) {
      return;
    }
    var key = relationship.key;
    var rel = record.get(key);

    if(relationship.options.async && rel){
      rel = record._relationships[key].manyArray.toArray();
    }

    if (rel){
      json[key] = rel.map(function(record) {
        return serializeId(record, relationship);
      });
    }
  },

  serializeBelongsTo: function(record, json, relationship) {
    if(relationship.options.serialize === false) {
      return;
    }
    if (relationship.options && relationship.options.async){
      var key = relationship.key;
      var belongsTo = record._relationships[key].inverseRecord;
      json[key] = serializeId(belongsTo, relationship);
    } else {
      this._super(record, json, relationship);
    }
  }
});

export default Serializer;<|endoftext|>