プログラムな日常>ウェブプログラム作品集>
スクロールバー2023年版
(scrollbars v.2023 in javascript)
sc1
realbase mechanicalbase feedback
 
inversed direction

スクロールバー(javascript)の新版であり、2022年版 から変わったのは以下の諸点です。

  1. プログラム上で、スクロールバーのオブジェクトと、これの元になる画面上の実体を、名前として区別しなくなり、 2022年版 の中で、関数とイベントを並べた表で述べた 「getbody:実体(div)を返す」という機能が不要に。

  2. スクロールバーを作るときの new の宣言がなくなった。

  3. スクロールバーは div を材料に作る場合のみとし、div を「保証人」として(その一部に)作る機能は廃止した。

  4. いわゆる small-change のボタンを押し続けると、連続動作するように。

  5. いわゆる small-change のボタンの矢印のデザインを変えた。

機能を再定義すると、次の通り。

scroll の関数:
関数文例
scroll : div のスクロール化 html 等で既に定義された領域(div など)を利用してスクロールバーにする。例えば、
  scroll(scr1, false);
ここで、scr1 は id だが、文字列のままでも良く、
  scroll("scr1", false);
各引数は、1:利用される領域、2:逆方向指定(右から、下から) 2 の false は省略可
getbase : 値を得るvar b=scr1.getbase();
setbase : 値を設定scr1.setbase(b);
setwhole : 全体を設定scr1.setwhole(wh); // === whole は base の最大値と view との和 !!!
setview : 視野を設定scr1.setview(v);
setwholeandview : 全体と視野を設定scr1.setwholeandview(wh, v);
setlargechange : 大きな変化量を設定scr1.setlargechange(L);
setinverse : 右や下からなら true 設定scr1.setinverse(false);
setx : 位置(x)設定scr1.setx(20)
sety : 位置(y)設定scr1.sety(150)
setxy : 位置(x, y)設定scr1.setxy(x, y)
setw : 幅設定scr1.setw(200)
seth : 高さ設定scr1.seth(25)
setwh : 幅と高さ設定scr1.setwh(w, h)

イベントは次の通り。

scroll のイベント:

イベント伝達の原因文例
basechangedmechanicalマウス操作(スクロールとクリック)のみscr1.addEventListner('basechangedmechanical', ()=>{ ... });
basechangedanywayマウス操作(スクロールとクリック)および set** 関数 (setbase, setwhole, setview, setwholeandview)scr1.addEventListner('basechangedanyway', ()=>{ ... });
basechangedbycodeset** 関数 (setbase, setwhole, setview, setwholeandview)のみscr1.addEventListner('basechangedbycode', ()=>{ ... });

ボタンやスクロールバーは、javascript のオブジェクトの機能によっています。

javascript で、オブジェクトは、関数を new して残すことでできる(下の方でご説明します)と共に、document.getElementById('...') などで得た実体はやはりオブジェクトであり、 イベントを設定できるのは後者のオブジェクトに限られますが、ここに変数や関数を後付けできることもわかったことから、今回の書き換えをしました。

スクロールバー自体のソースコードは次の通り。

scroll.js:


また、これを活用しているスクリプトは次の通り。

003.js:


【javascript におけるオブジェクトの特徴】

今回気が付いた蘊蓄を少し述べたいと思います。

次のプログラムをご覧下さい。

// ############################################################# 
function box() {
    this.v=0; 
    this.addone=function() { this.v++; } 
    return 10; // === neglected if 'new' is used on calling !!! 
} // =========================================================== 
function for_premium(abox) {
    abox.w=100; 
    abox.addtwo=function() { abox.v += 2; } 
} // =========================================================== 
var aaa=new box(), bbb=new box(), ccc=box(); // ccc == 10 
var aaa0=aaa.v, bbb0=bbb.v; // 0 0 
aaa.addone();  bbb.addone(); 
var aaa1=aaa.v, bbb1=bbb.v; // 1 1  
for_premium(aaa); 
var aaaw=aaa.w; // 100  
aaa.addtwo(); 
var aaa2=aaa.v // 3 
// === for_premium() is not called for bbb !!! 
var bbbw=bbb.w; // === undefined 
bbb.addtwo(); // === Error: not a function !!! 
// ############################################################# 
上のプログラムでは、最初に関数を2つ定義しています。

次に box を実際に呼び出していますが、その方法は2通りです。 1つは new して変数(aaa と bbb)に代入するやり方です。これによって関数の実体は持続するので、java や C# の コンストラクタと同じと言えます。new を用いない呼び出しもしています(ccc に代入)が、こちらは、関数の帰り値が戻されます。 new する場合は return の値が仮にあっても無視されることになります。

さて、aaa と名付けられた box は変数 v と関数 addone() とを既に有していますが、 これを引数としてもう一つの関数 for_premium を呼び出すことで、新たな変数 w と関数 addtwo とを追加することができます。

この流れをオブジェクト指向言語と比較すると、クラスの内容を継承して派生クラスを作っていたのと同じことができていると言えます。
オブジェクト指向言語では新たな派生クラスの名前を少なくとも用意しなければいけなかったし、 既に作られたオブジェクトをそのままに派生、拡張することがそもそも困難だったことに比べれば、 必要が生じ次第の拡張が易々とできていることに気づきます。