Orpheus作曲ページ拡張機能

和声選択をより簡単にするブックマークレットを作りました。2020.05.14

OrpheusEnhancer_20200514T0700

↑のリンクをブックマークしてください(右クリックしてブックマーク追加かドラッグ&ドロップで)。
そして作曲ページを開いているときに、追加したブックマークをクリックしてください。
使用は自己責任で。動かなかったらごめんなさい

作成者について

作成の動機

予定

コード(unminified)

悪意あるコードがないか確認しましょう。Orpheus外にアクセスするコードが一切ないことはすぐわかると思います。(むしろヘボと罵られる可能性の方が高い)

内容を展開
javascript:void(
(()=>{

var oe = {
  params: {},
  palette: {},
};

oe.getDoc = function(){
  var iframe = document.querySelector('iframe');
  this.win = (iframe? iframe.contentWindow: window);
  this.doc = this.win.document;
};

oe.prepareCSS = function(){
  var style = this.doc.createElement('style');
  style.textContent = `
    body {
      position: relative;
    }
    .label {
      cursor: pointer;
    }
    .palette {
      width: 200px;
      position: absolute;
      top: 0;
      right: 0;
      background: #eef;
      height: 500px;
      border: 1px solid #666;
      border-radius: 1rem;
    }
    .palette select {
      height: 300px;
      width: 200px;
    }
    .palette input,
    .palette audio {
      width: 200px;
      box-sizing: border-box;
    }
  `;
  this.doc.body.appendChild(style);
};

oe.createPalette = function(){
  var palette = this.doc.createElement('div');
  palette.classList.add('palette');
  
  var p = this.doc.createElement('p');
  var textbox = this.doc.createElement('input');
  textbox.type = 'text';
  textbox.placeholder = '検索';
  textbox.classList.add('search');
  p.appendChild(textbox);
  palette.appendChild(p);

  var section = this.doc.createElement('p');
  section.textContent = '--';
  palette.insertBefore(section, palette.firstChild);
  
  var audio = this.doc.createElement('audio');
  audio.controls = true;
  audio.preload = 'none';
  palette.appendChild(audio);
  
  this.palette.elem = palette;
  this.palette.section = section;
  this.palette.textbox = textbox;
  this.palette.audio = audio;

  textbox.addEventListener('input', this.palette.textbox_handler.bind(this), false);
};

oe.palette.textbox_handler = function(e){
  var query = e.target.value.toLowerCase();
  for(const op of Array.from(this.palette.select.options)){
    op.style.display = (op.textContent.toLowerCase().indexOf(query) !== -1? "": "none");
  }
};

oe.replaceHarmony = function(){
  for(var harmony of Array.from(this.doc.querySelectorAll('select[name$=":harmony"]'))){
    var input = this.doc.createElement('input');
    input.type = 'hidden';
    input.name = harmony.name;
    input.value = harmony.value;
    
    var label = this.doc.createElement('span');
    label.classList.add('label');
    label.textContent = harmony.selectedOptions[0].textContent;
    label.dataset.name = harmony.name;
    label.addEventListener('click', this.palette.label_handler.bind(this), false);
    
    this.params[harmony.name] = {
      input: input,
      label: label,
    };
    
    harmony.removeAttribute('name');
    harmony.parentNode.insertBefore(label, harmony);
    harmony.parentNode.replaceChild(input, harmony);
    
    if(this.palette.select === undefined){
      var select = harmony;
      select.size = '20';
      this.palette.elem.insertBefore(select, this.palette.audio);
      this.doc.body.appendChild(this.palette.elem);
      
      select.addEventListener('change', this.palette.select_handler.bind(this), false);
      
      this.palette.select = select;
    }
  }
};

oe.palette.label_handler = function(e){
  this.palette.select.value = this.params[e.target.dataset.name].input.value;
  this.palette.section.textContent = this.params[e.target.dataset.name].input.name;
  
  var top = e.target.parentNode.getBoundingClientRect().top;
  this.palette.elem.style.top = (top+this.win.pageYOffset)+'px'; 
};

oe.palette.select_handler = function(e){
  var name = this.palette.section.textContent;
  var filename = e.target.value.split('/').pop().split('.')[0];
  this.palette.audio.src = `/samples/harmony/${filename}.mp3`;
  
  if(name === "--") return;
  this.params[name].input.value = e.target.value;
  this.params[name].label.textContent = e.target.selectedOptions[0].textContent;
};

oe.run = function(){
  this.getDoc();
  
  if(this.win.oe) return;

  this.prepareCSS();
  this.createPalette();
  this.replaceHarmony();
  
  this.win.oe = this;
};

oe.run();

})()
);

Orpheus関連へ戻る