JavaScript 簡易データベースもどきに(?)検索機能を付加してみた

<!DOCTYPE html>
<title>?</title>
<meta charset="utf-8">
<style>
li label { color: green; font-weight: bold; padding-right: 1ex;}
</style>

<body>
<div>
<label>KeyWord:</label>
<input type="search" autofocus>
<em>space で区切ることも可能</em>
<ul id="list"></ul>
</div>
<script>

{
  //_____________________________________________________

  /*
    関数を遅らせて実行する
    let func = new DelayWork ((s)=>{alert(s)}, 1000);
    func.start ('Start!!'); //実行
    func.stop (); //中止
  */

  class DelayWork {
    constructor (callBackFunc, wait = 500) {
      this.callBackFunc = callBackFunc; // func.bind (this)
      this.wait = wait;
      this.timerID = null;
    }

    start (...arg) {
      if (! this.timerID) {
        let cbfunc = () => {
          this.timerID = null;
          this.callBackFunc (...arg);
        };
        this.timerID = setTimeout (cbfunc, this.wait);
       }
      return this;
    }


    stop () {
      if (this.timerID)
        clearTimeout (this.timerID);
      this.timerID = null;
      return this;
    }
  }

  //_____________________________________________________


  class DelayHandler {

    constructor (handler, wait = 300) {
      let cbFunc;
      switch (Object.prototype.toString.call (handler)) {
      case '[object Object]' :
        if ('handleEvent' in handler)
          if ('function' === typeof handler.handleEvent)
            cbFunc = handler.handleEvent.bind (handler);
        break;

      case '[object Function]' :
        cbFunc = handler; break;

      default:
        throw new Error ('Not handleEvent'); break;
      }

      this.handler = new DelayWork (cbFunc, this.wait);
      this.wait = wait;
    }


    handleEvent (event) {
      this.handler.stop ().start (event);
    }
  }

  //_____________________________________________________


  //記事
  const
    Article_DEF_OPTION = { };


  class Article {
    constructor (title = '', key = title, text = '', date = new Date, option = { }) {
      if (1 > title.length)
        arguments.length;

      this.title  = title;
      this.text   = text;
      this.key    = key;
      this.date   = date;
      this.option = Object.assign ({ }, Article_DEF_OPTION, option);
    }
  }

  //_____________________________________________________


  const
    Book_DEF_OPTION = { };


  //記事を本にまとめる。keyをもとに検索機能がある
  class Book {

    constructor (book = [ ], option = { }) {
      this.book = book;
      this.option = Object.assign ({ }, Book_DEF_OPTION, option);
    }


    append (...args) {
      this.book.push (new Article (...args));
      return this;
    }


    load (ary) {
      ary.forEach (args => this.append (...args));
      return this;
    }

  }

  //_____________________________________________________


  //Book に検索機能を追加する
  const
    ExBook_DEF_OPTION = { },
    
    REG_NORMALIZATION = /[-\/\\^$*+?.()|\[\]{}]/g, //正規化
    REG_SPLITER = /\s+/g,//空白で区切る
    REG_TRIM = /(^\s+|\s+$|\s+(?=\s))/g,//前後の空白と中間の2文字以上の空白にマッチ

    REG_KEY = (str) => {//検索文字から正規表現を作る //x(?=y0)(?=y1)(?=yn)...
      let [a, ...bc] = str.replace(REG_NORMALIZATION, '\\$&').split (REG_SPLITER);
      return new RegExp (a + bc.map (s => `(?=.*${s})`).join (''), 'i'); 
    };



  class ExBook extends Book {

    constructor (book = [ ], display, option = { }) {
      super (book, Object.assign ({ }, ExBook_DEF_OPTION, option));
      this.display = display;
      this.found   = [ ]; //検索対象
      this.key     = '';
    }


    find (arg = '') {
      let 
        key = arg.replace (REG_TRIM, ''),
        len = key.length;

      if (len) {
        let cnt = this.key.length;

        if (! cnt || len < cnt)
          this.found = this.book.slice ();//検索対象を初期化 copy

        if (key !== this.key) {
          let reg = REG_KEY (key);
          this.found = this.found.filter (rec => reg.test (rec.key));
          this.key = key;
          this.display.write (this.found.slice());
        }
      }
      else {
        this.display.cls ();
        this.key = '';
      }

     return this;
    }

    
    handleEvent (event) {
      this.find (event.target.value);
    }

  }
//_____________________________________________________
  
  const
    Display_DEF_OPTION = {
      disp_row : 1, //一回の処理で表示する行
      disp_wait : 30, //次の表示処理までの時間
      disp_max : 30 //最大の表示する行
    },

    createElement = function (n) { return this.createElement (n) },

    createRow = (function (doc) {
      let [li, label, span] = ['li', 'label', 'span'].map (createElement, doc)
      li.appendChild (label);
      li.appendChild (span);

      return function (title, text) {
        label.textContent = title;
        span.textContent = text;
        return li.cloneNode (true);
      };
    })(document);
  


  class Display {

    constructor (target, option = { }) {
      option = Object.assign ({ }, Display_DEF_OPTION, option)
      this.target = target;
      this.option = option;
      this.loop = new DelayWork (this.outByBit.bind (this), option.disp_wait);
    }


    write (rows = [ ]) {
      this.cls ();
      this.outByBit (rows.splice (0, this.option.disp_max));
      return this;
    }


    outByBit (rows) {
      let
        fgm  = this.target.ownerDocument.createDocumentFragment (),
        part = rows.splice (0, this.option.disp_row);
        
      this.target.appendChild (part.reduce ((a,b)=>{
        a.appendChild (createRow (b.title + ":", b.text));
        return a;
      }, fgm));

      if (rows.length)
        this.loop.start (rows);

      return this;
    }


    cls () {
      this.loop.stop ();
      for (let p = this.target, e; e = p.firstChild; )
        e.remove ();
      return this;
    }

  }

  //_____________________________________________________

  this.Article = Article;
  this.Book = ExBook;
  this.Display = Display;
  this.DelayHandler = DelayHandler;
}

//_____________________________________________________

const
  //[タイトル...   | 検索キー] テキスト(次のタイトル区切りの"["の直前までが対象となる
  notes = `
    [ Array.prototype.push | array push ]  配列の最後に要素を追加する
    [ Array.prototype.pop | array pop ]  配列の最後から要素を削除し、その要素を返す
    [Array.prototype.map | array map] 配列から生成した配列を返す
    [ array.prototype.slice | array slice ] 配列から指定した要素を削除する
  `;


let reg, ary, words = [ ];
{
  let text = '(.+?)';
  let spc = '\\s*';
  let text2 = '([\\s\\S]+?)';
  
  let title = '\\['+ spc + text + '(?:' + spc + '\\|' + spc + text + ')?'+ spc + '\\]';
  let note = spc + text2 + '(?=\\s*\\[|\\s*$)';

  reg = new RegExp (title + note , 'gi');
}


while (ary = reg.exec (notes)) {
  let [, ...arg] = ary;
  console.log(arg);
  words.push (new Article (...arg));
}

let dic = new Book (words, new Display (document.getElementById ('list')));

document.querySelector ('input[type="search"]')
  .addEventListener ('input', new DelayHandler (dic), false);

</script>

Javascript イベントを遅らせて発火させる

Javascript イベントを遅らせて発火させる

  class DelayWork {
    constructor (callBackFunc, wait = 500) {
      this.callBackFunc = callBackFunc; // func.bind (this)
      this.wait = wait;
      this.timerID = null;
    }

    start (...arg) {
      if (! this.timerID) {
        let cbfunc = () => {
          this.timerID = null;
          this.callBackFunc (...arg);
         };
        this.timerID = setTimeout (cbfunc, this.wait);
       }
      return this;
    }


    stop () {
      if (this.timerID)
        clearTimeout (this.timerID);
      this.timerID = null;
      return this;
    }
  }

  //_____________________________________________________


  class DelayHandler {

    constructor (handler, wait = 300) {
      let cbFunc;
      switch (Object.prototype.toString.call (handler)) {
      case '[object Object]' :
        if ('handleEvent' in handler)
          if ('function' === typeof handler.handleEvent)
            cbFunc = handler.handleEvent.bind (handler);
        break;

      case '[object Function]' :
        cbFunc = handler; break;

      default:
        throw new Error ('Not handleEvent'); break;
      }

      this.handler = new DelayWork (cbFunc, this.wait);
      this.wait = wait;
    }


    handleEvent (event) {
      this.handler.stop ().start (event);
    }
  }

//_____________________________________________________

function handler (event) {
  ;
}

document.querySelector ('input[type="search"]')
  .addEventListener ('input', new DelayHandler (handler), false);

時間間隔をちょっと考えて

時間間隔をちょっと考えて

class DateInterval {
  constructor (begin, end) {
    this.begin = begin;
    this.end   = end;
  }
  
  isInRange (date = new Date) {
    let b = +this.begin, e = +this.end, d = +date;
    return b <= d ? d <= e: false;
  }
  
  copy () {
    return new DateInterval (new Date (this.begin), new Date (this.end));
  }
  
  static range (...arg) {
    let [s, m, h, d] = [...arg.reverse (), 0, 0, 0, 0];
    if (31 < d) throw new Error;
    return new Date (Date.UTC (1970, 0, d + 1, h, m, s, (s % 1 * 1000)));
  }
  
  static split (dateInterval, date) {
    let rst = [ ], max = +dateInterval.end, step = +date;
    for (let i = new Date (dateInterval.begin); i < max; i.setTime (+i +step))
      rst.push (new Date (i));
    return rst;
  }
  
  static create (a, b) {
    return new DateInterval (new Date (...a), new Date (...b));
  }
}

let a = DateInterval.range (1,0,0);
let b = DateInterval.create ([1,0,1], [1,0,2]);

console.log (DateInterval.split (b, a));

まだ移譲が不足なのだろうか?

まだ移譲が不足なのだろうか?

<!DOCTYPE html>
<title>?</title>
<meta charset="utf-8">
<style>
label { color: green; margin: 1ex 1ex 1ex; font-weight: bold;}
</style>

<body>
<div>
  <label>KeyWord:</label>
  <input type="search" id="keyword" autofocus>
  <em>space で区切ることも可能</em>
  <ul id="list"></ul>
</div>
<script>

{
  class DelayWork {
    constructor (callBackFunc, wait = 1000) {
      this.callBackFunc = callBackFunc; // func.bind (this)
      this.wait         = wait;
      this.timerID      = null;
    }
    

    start (...arg) {
      if (! this.timerID) {
        let cbfunc = () => {
          this.timerID = null;
          this.callBackFunc (...arg);
        };
        this.timerID = setTimeout (cbfunc, this.wait);
      }
      return this;
    }
    
    
    stop () {
      if (this.timerID)
        clearTimeout (this.timerID);
      this.timerID = null;
      return this;
    }
  }
  


  //記事
  const Article_DEF_OPTION = { };
  
  class Article {
    constructor (title = '', text = '', date = new Date, keyword = title, option = { }) {
      if (1 > title.length)
        arguments.length;

      this.title  = title;
      this.text   = text;
      this.key    = keyword;
      this.date   = date;
      this.option = Object.assign ({ }, Article_DEF_OPTION, option);
    }
  }

  //_____________________________________________________

  const
    Book_DEF_OPTION = { },
    Book_REG_NORMALIZATION = /[-\/\\^$*+?.()|\[\]{}]/g,
    book_REG_SPLITER = /\s+/g,
    
    Book_createRegkey = (str) => {
      let [a, ...bc] = str.replace(Book_REG_NORMALIZATION, '\\$&').split (book_REG_SPLITER);
      return new RegExp (a + bc.map (s => `(?=.*${s})`), 'i'); //x(?=y0)(?=y1)(?=yn)...
    };


  //記事を本にまとめる。keyをもとに検索機能がある
  class Book {
    constructor (book = [ ], option = { }) {
      this.book    = book;
      this.option  = Object.assign ({ }, Book_DEF_OPTION, option);
      this.current = [ ]; //検索された記事
      this.key     = '';  //検索ワードの記憶
    }


    append (...args) {
      this.book.push (new Article (...args));
      return this;
    }
    

    load (ary) {
      ary.forEach (args => this.append (...args));
      return this;
    }
    
    
    search (key = '') {
      key = key.trim ();
      let len = key.length;

      if (len) {
        if (0 === this.key.length || len < this.key.length)
          this.current = this.book.slice ();
        
        if (key !== this.key) {
          let reg = Book_createRegkey (key);
          this.current = this.current.filter (rec => reg.test (rec.key));
          this.key = key;
        }
      }
      else {
        this.current = [ ];
        this.key = '';
      }

      return this;
    }

  }

  //_____________________________________________________
  

  //Book に表示機能を追加する
  const
    ExBook_DEF_OPTION = {
     disp_row  : 3, //一回の処理で表示する行
     disp_wait : 300, //次の表示処理までの時間
     disp_max  : 30 //最大の表示する行
    };


  class  ExBook extends Book {

    constructor (book = [ ], output, option = { }) {
      option = Object.assign ({ }, ExBook_DEF_OPTION, option);
      super (book, option);
      this.output = output;
      this.loop   = new DelayWork (this.outByBit.bind (this), option.disp_wait);
    }
    

    display (rows = this.current.slice ()) {
      this.cls ();
      this.outByBit (rows.splice (0, this.option.disp_max));
      return this;
    }

    
    cls () {
      this.loop.stop ();
      this.output.cls ();
      return this;
    }
    
    
    outByBit (rows = [ ]) {
      this.output.out (rows.splice (0, this.option.disp_row));
      if (rows.length)
        this.loop.start (rows);
      return this;
    }
    
  }

  //_____________________________________________________


  //Book に入力機能を追加する
  const
    Ex2Book_DEF_OPTION = {
      inkey_wait: 1000
    }


  class Ex2Book extends ExBook {

    constructor (book, input, output, option = { }) {
      option = Object.assign ({ }, Ex2Book_DEF_OPTION, option);
      super (book, output, option);
      this.input   = input;
      this.routine = new DelayWork (this.find.bind (this), option.inkey_wait);
      
      input.addEventListener ('input', this, false);
    }
    

    find (key = '') {
      key = key.trim ();

      if (key !== this.key)
        this.search (key).display ();

      return this;
    }
    

    handleEvent (event) {
      this.routine.stop ().start (event.target.value);
      return this;
    }

  }

  //_____________________________________________________

  class ListViewer {
    
    constructor (target) {
      this.target = target;
    }
    
    
    cls () {
      for (let p = this.target, e; e = p.firstChild; e.remove ());
      return this;
    }
    
    
    out (rows = [ ]) {
      let
        doc = this.target.ownerDocument,
        li    = doc.createElement ('li'),
        label = doc.createElement ('label'),
        span  = doc.createElement ('span'),
        fgm   = doc.createDocumentFragment ();
      
      li.appendChild (label);
      li.appendChild (span);
      
      this.target.appendChild (rows.reduce ((a, {title, text}) => {
        label.textContent = title;
        span.textContent  = text;
        fgm.appendChild (li.cloneNode (true));
        return a;
      }, fgm));
      
      return this;
    }
  }
  //_____________________________________________________

 
  this.Book       = Ex2Book;
  this.ListViewer = ListViewer;

}

//_____________________________________________________

const
  article = [
    { key: 'array map',    title: 'Array.map',    text: '配列から新たに作成した配列を返す'},
    { key: 'array filter', title: 'Array.filter', text: '配列から条件を満たす配列を返す'},
    { key: 'array some',   title: 'Array.some',   text: '配列から条件を一つでも満たすと true を返す'},
    { key: 'array reduce', title: 'Array.reduce', text: '配列評価しながら配列を返す'}
  ],
  DIC2 = `
    Array.prototype.push       配列の末尾に要素を追加する  array push
    Array.prototype.pop        配列の末尾の要素を削除する  array pop       
    Array.prototype.shift      配列の先頭の要素を削除する  array shift     
    Array.prototype.unshift    配列の先頭に要素を追加する  array unshift 
    Array.prototype.indexOf    要素のインデックスを取得する  array indexOf 
    Array.prototype.splice     インデックス位置を指定して要素を削除する  array splice  
    Array.prototype.slice      配列のコピー  array slice   
  `;

let 
  inp = document.querySelector ('#keyword'),
  out = new ListViewer (document.querySelector ('#list')),
  dic = new Book (article, inp, out);

dic.load (
  DIC2
  .trim ()
  .split (/\r|\n|\r|\n/)
  .map (s =>
    s.trim().split (/\t|\s{2,}/g)
     .map (s => s.trim ())
  )
);


</script>

teratail に登録する

それにしても色々な質問があるものだ。

すべてには答えきれないね。

そこでふと考えた。

解説などしないで、男ならコードだけで勝負しようと思った。

解説などいっさしない!

それに無視することも私の自由だ。

これからは、そうしよう。

 

タグ別ランキング1位の人の喰い入り様は、尋常ではない。

 

--

人様の書いたコードは、容易く理解できるものではない。

理解しようともせず、丸投げしてきた。

これも無視しよう。

 

 

使われた言葉に数値をつけてみる

https://oshiete.goo.ne.jp/qa/10921080.html

使われた言葉に点数を加算していくのだが、最大値を超えないようにするには?
そんで、考えた。
あっ!光の速度はこえられない!
相対論的な速度の加算方式を利用しよっと。

<!DOCTYPE html>
<meta charset="UTF-8">
<html lang="ja">
<title>?</title>
<style>

</style>

<body>
<h1>Test</h1>
<input type="search" value="リンゴ" onblur="dic(this.value)"><br>
<textarea cols="80" rows="10"></textarea>

<body>

<script>

class R {
  constructor (key, level) {
    this.key = [ ].concat (key);
    this.level = level;
  }
  
  add (key, level) {
    this.key.push (key);
    let
      l0 = this.level,
      l1 = level;
    this.level = (l0 + l1) / (1 + l0 * l1);
    return this;
  }
  
  sort () {
    this.key.sort ((a, b) => HASH[a].level < HASH[b].level);
  }
}


let words = [
   ['苺', '赤い', 'おいしい', 'すっぱい'],
   ['リンゴ', '青森', '赤い', 'おいしい', 'すっぱい', 'シャイニーアップルジュース']
];

let HASH = { };

for (let ws of words) {
  let key = ws.shift ();
  let gain = 1 / ws.length;
  let c = 1;

  HASH[key] = new R (ws, c);
  
  for (let w of ws) {
    c *= gain;
    if (w in HASH) {
      HASH[w].add (key, c);
    }
    else {
      HASH[w] = new R (key, c);
    }
  }
}


function dic (key) {
  let mess = '知らない';
  if (key in HASH) {
    let obj = HASH[key];
    obj.sort ();
    mess = obj.key.map (s => s + '(' +HASH[s].level+ ')').join ('\n');
  }
  document.querySelector ('textarea').value = mess;
}
</script>

ANYCUBIC i3 Mega 3Dプリンタを使いこなす

まともに記事を書き上げたことがないが、ちょいちょい写真もアップしながら書こうと思う

2018年、4台のマシンを購入する

トラブルの解決法をまとめておく

ネジは必ず締めましする

4台購入したが、どれもどこかしら緩んでいた。なので手当たり次第ネジを締める。

長く使用できるように改造する

スッテッピングモーターが5個使用されている。モータはトルクもあるし発熱もする。
なのでヒートシンクを全てに取り付ける

https://www.amazon.co.jp/gp/product/B07HFQWZM8/ref=oh_aui_search_detailpage?ie=UTF8&th=1

裏面を外し、内部にある下部のモーターにもヒートシンクを貼る(3ヶ使用)

ヘッドを支えるフレームの中に隠れているモーターが2個、それぞれにヒートシンクを貼る


ヒートベットが暖まりやすいように、その裏に断熱材を貼る

https://www.amazon.co.jp/gp/product/B0793NVCL4/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1
`

印刷中にフィラメントを溶かすヘッドの温度が安定しない

温度センサーを固定するネジが緩んでいる

温度センサーのヘッド側の出張った配線が断熱してしまう
これは交換しかない