ドラッグ&ドロッブの失敗コード

時計ツールで一番苦労したのは、ドラッグ&ドロップのコードでした。 当初のコードは詰めが甘く、画像アップロードのために画像パレットに画像をドロップすると、時計がドロップした位置に移動するという、笑ってしまいそうなバグがありました。

 

 

ドラック&ドロップのコードは、移動開始と移動終了でしっかり完結したコードでなくてはならない様です。 終了コードを厳密にしていなかったので、他のドロップイベントを、時計のイベントと判断して移動が生じたのです。

 

この問題は既に改善済みですが、ドラック&ドロップのコードについては、まだまだ慣れが足りないと感じています。

 

 

 

プレビュー画面に時計が表示されてしまう問題 

これは、他の方に指摘してもらうまで見落としていた問題です。 編集画面で設定した位置に、プレビュー画面上に時計が表示されると、かなり多くの場合に「不適当な場所」に表示される事になります。 更新バージョンは、これを改善しました。

 

◎「別ウインドウ」の「プレビュー」は、以下の「exclude」指定で抑止しました。

 

// @exclude      https://blog.ameba.jp/ucs/entry/srventryouterpreview.do

 

◎「同じウインドウ」の「プレビュー」では、以下の抑止コードを追加しました。

 

let view_button=document.querySelector('.js-tab-header[data-tab="preview"]');
let write_button=document.querySelector('.js-tab-header[data-tab="edit"]');

if(view_button){
    view_button.addEventListener('mouseup', function(){
        setTimeout(()=>{
            let pheader_tab=document.querySelectorAll('.p-header__tab__item');
            if(pheader_tab[1].classList.contains('is-selected')){
                let d_watch=document.querySelector('#d_watch');
                d_watch.style.display='none'; }
        }, 400); }); }

if(write_button){
    write_button.addEventListener('mouseup', function(){
        setTimeout(()=>{
            let pheader_tab=document.querySelectorAll('.p-header__tab__item');
            if(pheader_tab[0].classList.contains('is-selected')){
                let d_watch=document.querySelector('#d_watch');
                d_watch.style.display='block'; }
        }, 400); }); }

 

「プレビュー」ボタンと「ブログを書く」ボタンで、クリックして 0.4sec後にボタン選択が切替わった事を確認して、時計の「表示 / 非表示」を切換えています。 選択の確認なしでも動作しますが、動作を確実にしたコードです。

 

 

 

編集画面のカラーパレットに表示される問題  〔追記〕2020.12.10

「カラーパレット」のダイアログは「iframe」で構成されていて、その内部には別のHTMLが構成されて、そこにも時計が表示されてしまう事に気付きました。 時計の配置は Cookieに登録された指定に従うので、「iframe」内に割込む場合に気付きますが、外になり判らない場合もあります。

 

下図は「カラーパレット」に割込んで表示された例です。

 

 

「編集画面」で使われる他の「iframe」要素にも、時計が表示される可能性があるので、これを抑止する「@noframes」を指定しました。

 

このページのコードは全て修正して「ver. 0.7」に改めました。

 

 

 

HOME画面上へのドラッグを抑止していた問題  〔追記〕2020.12.12.

ブラウザのデフォルト機能によって、ページ表示領域に「別ページのリンク」をドロップすると、リンク先にページが遷移します。 これは便利で、私はデスクトップにページリンクを置いて、それをブラウザ上にドロップする操作を頻繁に使います。

(再編集画面では編集内容を失う場合があり、Firefox等では注意が要りますが)

 

アメブロの「HOME」画面は、記述入力内容は無いので、このリンクドロップ→移動の操作は気軽に出来ます。 しかし、「Time On My Side」の時計のドラッグ関連コードが、この機能を抑止するコードを含んでいました。 リンクへの遷移が出来なくなったので気付いていましたが、この問題を修正しました。

 

「Time On My Side D」では、150行目の以下の太字コードを削除しました。

 

document.addEventListener("drop", function(event){
    event.preventDefault();
    toMove(event); }, false); // ドロップ時に位置を取得して配置修正

 

以下の「ver. 0.7」のコードは、全て修正済です。

 

 

 

「Time On My Side」の扱い方 

時計はドラッグ&ドロップで配置場所を任意に変更できます。 また、表示サイズ変更が可能です。 アナログ時計「Time On My Side A」は時計自体の左クリック、デジタル時計「Time On My Side D」は時計上のアイコン「⏰」の左クリックで、サイズが変ります。

 

 

 

「Time On My Side」ver. 0.7 の利用するには

以下の掲載コードは、修正したアナログ時計とデジタル時計の更新コードです。

このツールは、Chrome・Edge / Firefox の「Tampermonkey」上で動作するユーザースクリプトツールです。

 

「Tampermonkey」の「新規スクリプト」編集画面で、初期テンプレートを完全に空白にした上で、下記のコードをペーストして「保存」する事で、このツールを動作させる事ができます。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

 

〔 Time On My Side A 〕ver. 0.7 アナログ時計版

 

// ==UserScript==
// @name         Time On My Side A
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  HOME画面にアナログ時刻表示
// @author       Ameba Blog User
// @match        https://www.ameba.jp/home
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @exclude      https://blog.ameba.jp/ucs/entry/srventrylist.do*
// @exclude      https://blog.ameba.jp/ucs/entry/srventryinsertend.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryupdateend.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryinsertdraft.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryupdatedraft.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryouterpreview.do
// @noframes
// @grant        none
// ==/UserScript==


main();

function main(){
    let wa_size=0;
    let x_p=0;
    let y_p=0;

    let wa_cookie_pos=get_cookie('time_a_pos');
    if(wa_cookie_pos!=0 && wa_cookie_pos.split(':')[0]){
        x_p=wa_cookie_pos.split(':')[0]; }
    if(wa_cookie_pos!=0 && wa_cookie_pos.split(':')[1]){
        y_p=wa_cookie_pos.split(':')[1]; }
    if(x_p!=0 && y_p!=0){ // Cookieの更新
        document.cookie='time_a_pos='+x_p+':'+y_p+'; Max-Age=2592000'; }

    let wa_cookie_siz=get_cookie('time_a_siz');
    if(wa_cookie_siz){ // Cookieの更新
        wa_size=wa_cookie_siz;
        document.cookie='time_a_siz='+wa_size+'; Max-Age=2592000'; }



    let wa_inner=
        '<span class="a_watch_hour"></span>'+ // 時計
        '<span class="a_watch_min"></span>'+ // 分針
        '<span class="a_watch_sec"></span>'+ // 秒針
        '<span class="a_watch_12">●</span>'+ // 時計文字
        '<span class="a_watch_3">●</span>'+ // 時計文字
        '<span class="a_watch_6">●</span>'+ // 時計文字
        '<span class="a_watch_9">●</span>'; // 時計文字

    wa_inner +=
        '<style>'+
        '#a_watch { position: fixed; width: 80px; height: 80px; z-index: 10; '+
        'background: #fff; border: 1px solid #f80; border-radius: 50%; '+
        'transition-duration: 0.02s; transform-origin: center center; } '+
        '.a_watch_hour { position: absolute; top: calc(50% - 24px); left: calc(50% - 2px); '+
        'width: 4px; height: 24px; border-radius: 4px; '+
        'background: #2196f3; transform-origin: bottom; } '+
        '.a_watch_min { position: absolute; top: calc(50% - 30px); left: calc(50% - 1px); '+
        'width: 2px; height: 30px; '+
        'background: #2196f3; transform-origin: bottom; } '+
        '.a_watch_sec { position: absolute; top: calc(50% - 36px); left: calc(50% - .5px); '+
        'width: 1px; height: 36px; '+
        'background: #ff0000; transform-origin: bottom; } '+
        '.a_watch_12, .a_watch_3, .a_watch_6, .a_watch_9 { '+
        'position: absolute; color: #f80; font: normal 10px meiryo; } '+
        '.a_watch_12 { top: -2px; left: calc(50%); transform: translateX(-50%); } '+
        '.a_watch_3 { top: 50%; right: 0; transform: translateY(-50%); } '+
        '.a_watch_6 { bottom: -2px; left: calc(50%); transform: translateX(-50%); } '+
        '.a_watch_9 { top: 50%; left: 0; transform: translateY(-50%); } '+
        '</style>';

    let base=document.querySelector('body');

    let watch=document.createElement('div');
    watch.setAttribute('id', 'a_watch');
    watch.style.top=y_p+'px';
    watch.style.left='calc(50% - '+x_p+'px)';
    watch.setAttribute('draggable', 'true');
    trans_size(watch, wa_size);
    watch.innerHTML=wa_inner;
    if(!base.querySelector('#a_watch')){
        base.appendChild(watch); }


    let time_a=setInterval(disp_a_watch, 1000);

    function disp_a_watch(){
        let now=new Date();
        get_a(now);

        function get_a(time){
            let Hour=time.getHours();
            let Min=time.getMinutes();
            let Sec=time.getSeconds();

            let deg_Hour=Hour*(360/12) + Min*(360/12/60);
            let deg_Min=Min*(360/60);
            let deg_Sec=Sec*(360/60);

            document.querySelector(".a_watch_hour").style.transform=
                `rotate(${deg_Hour}deg)`;
            document.querySelector(".a_watch_min").style.transform=
                `rotate(${deg_Min}deg)`;
            document.querySelector(".a_watch_sec").style.transform=
                `rotate(${deg_Sec}deg)`; }}



    let a_watch=document.querySelector('#a_watch');
    a_watch.onclick=function(event){
        event.stopImmediatePropagation();
        drage=0;
        if(wa_size==0){
            wa_size=1; }
        else if(wa_size==1){
            wa_size=2; }
        else if(wa_size==2){
            wa_size=3; }
        else if(wa_size==3){
            wa_size=0; }
        trans_size(a_watch, wa_size);
        document.cookie='time_a_siz='+wa_size+'; Max-Age=2592000'; }

    function trans_size(elem, n){
        if(n==0){
            elem.style.transform='scale(1)'; }
        else if(n==1){
            elem.style.transform='scale(0.9)'; }
        else if(n==2){
            elem.style.transform='scale(0.8)'; }
        else if(n==3){
            elem.style.transform='scale(0.6)'; }}



    let view_button=document.querySelector('.js-tab-header[data-tab="preview"]');
    let write_button=document.querySelector('.js-tab-header[data-tab="edit"]');

    if(view_button){
        view_button.addEventListener('mouseup', function(){
            setTimeout(()=>{
                let pheader_tab=document.querySelectorAll('.p-header__tab__item');
                if(pheader_tab[1].classList.contains('is-selected')){
                    let a_watch=document.querySelector('#a_watch');
                    a_watch.style.display='none'; }
            }, 400); }); }

    if(write_button){
        write_button.addEventListener('mouseup', function(){
            setTimeout(()=>{
                let pheader_tab=document.querySelectorAll('.p-header__tab__item');
                if(pheader_tab[0].classList.contains('is-selected')){
                    let a_watch=document.querySelector('#a_watch');
                    a_watch.style.display='block'; }
            }, 400); }); }



    let drage=0; // ドラッグ処理中の管理
    let shiftX; // ホールド箇所による位置ズレ補正
    let shiftY; // ホールド箇所による位置ズレ補正

    let html_area=document.querySelector('html');
    html_area.ondragover=function(){ return false; } // HOMEでドラッグ可能にする

    a_watch.onmousedown=function(event){
        drage=1;
        shiftX=event.clientX-a_watch.getBoundingClientRect().left;
        shiftY=event.clientY-a_watch.getBoundingClientRect().top; }

    a_watch.onmouseup=function(event){
        drage=0; }

    document.addEventListener('drop', function(event){
        toMove(event); }, false); // ドロップ時に位置を取得して配置修正

    function toMove(event){
        if(drage==1){
            drage=0;
            let x=event.clientX-shiftX;
            let y=event.clientY-shiftY;
            a_watch.style.top=y+'px';
            a_watch.style.left='calc(50% - '+(document.body.offsetWidth/2-x)+'px)';
            document.cookie=
                'time_a_pos='+(document.body.offsetWidth/2-x)+':'+y+'; Max-Age=2592000'; }}


    function get_cookie(name){
        let cookie_req=document.cookie.split('; ').find(row=>row.startsWith(name));
        if(cookie_req){
            if(cookie_req.split('=')[1]==null){
                return 0; }
            else{
                return cookie_req.split('=')[1]; }}
        if(!cookie_req){
            return 0; }}

} // main()


 

〔追記〕2021.01.26

アナログ時計のコードの間違いで、プレビュー時の非表示化が出来ていませんでした。 上記は修正済です。

 

〔 Time On My Side D 〕ver. 0.7 デジタル時計版

 

// ==UserScript==
// @name         Time On My Side D
// @namespace    http://tampermonkey.net/
// @version      0.7
// @description  HOME画面に時刻表示
// @author       Ameba Blog User
// @match        https://www.ameba.jp/home
// @match        https://blog.ameba.jp/ucs/entry/srventry*
// @exclude      https://blog.ameba.jp/ucs/entry/srventrylist.do*
// @exclude      https://blog.ameba.jp/ucs/entry/srventryinsertend.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryupdateend.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryinsertdraft.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryupdatedraft.do
// @exclude      https://blog.ameba.jp/ucs/entry/srventryouterpreview.do
// @noframes
// @grant        none
// ==/UserScript==


main();

function main(){
    let w_size=0;
    let x_p=0;
    let y_p=0;

    let w_cookie_pos=get_cookie('time_d_pos');
    if(w_cookie_pos!=0 && w_cookie_pos.split(':')[0]){
        x_p=w_cookie_pos.split(':')[0]; }
    if(w_cookie_pos!=0 && w_cookie_pos.split(':')[1]){
        y_p=w_cookie_pos.split(':')[1]; }
    if(x_p!=0 && y_p!=0){ // Cookieの更新
        document.cookie='time_d_pos='+x_p+':'+y_p+'; Max-Age=2592000'; }

    let w_cookie_siz=get_cookie('time_d_siz');
    if(w_cookie_siz){ // Cookieの更新
        w_size=w_cookie_siz;
        document.cookie='time_d_siz='+w_size+'; Max-Age=2592000'; }



    let wd_inner=
        '<span id="w_icon">⏰ </span>'+
        '<span id="time_disp"></span>'+
        '<style>'+
        '#d_watch { position: fixed; z-index: 10; '+
        'font: bold 16px Meiryo; color: #0292a5; background: #fff; '+
        'height: 27px; padding: 1px 0 0 6px; box-sizing: border-box; '+
        'border: 1px solid #ccc; border-radius: 3px; width: 240px; } '+
        '#w_icon { vertical-align: 1px; }';

    let base=document.querySelector('body');
    let watch=document.createElement('div');
    watch.setAttribute('id', 'd_watch');
    watch.style.top=y_p+'px';
    watch.style.left='calc(50% - '+x_p+'px)';
    watch.setAttribute('draggable', 'true');
    watch.innerHTML=wd_inner;
    if(!base.querySelector('#d_watch')){
        base.appendChild(watch); }

    let time_d=setInterval(disp_watch, 1000);

    function disp_watch(){
        let d_watch=document.querySelector('#d_watch');
        let time_disp=document.querySelector('#time_disp');
        let now=new Date();
        get_d(now);

        function get_d(time){
            let Year=time.getFullYear();
            let Month=getdouble(time.getMonth()+1);
            let Date=getdouble(time.getDate());
            let Hour=getdouble(time.getHours());
            let Min=getdouble(time.getMinutes());
            let Sec =getdouble(time.getSeconds());

            function getdouble(number){
                return ("0" + number).slice(-2); }

            if(w_size==0){
                d_watch.style.width='240px';
                time_disp.innerHTML=
                    Year+"."+Month+"."+Date+" "+Hour+":"+Min+":"+Sec; }
            else if(w_size==1){
                d_watch.style.width='190px';
                time_disp.innerHTML=
                    Month+"."+Date+" "+Hour+":"+Min+":"+Sec; }
            else if(w_size==2){
                d_watch.style.width='122px';
                time_disp.innerHTML=
                    Hour+":"+Min+":"+Sec; }}}



    let w_icon=document.querySelector('#w_icon');
    w_icon.onclick=function(event){
        event.stopImmediatePropagation();
        drage=0;
        if(w_size==0){
            w_size=1; }
        else if(w_size==1){
            w_size=2; }
        else if(w_size==2){
            w_size=0; }
        document.cookie='time_d_siz='+w_size+'; Max-Age=2592000'; }



    let view_button=document.querySelector('.js-tab-header[data-tab="preview"]');
    let write_button=document.querySelector('.js-tab-header[data-tab="edit"]');

    if(view_button){
        view_button.addEventListener('mouseup', function(){
            setTimeout(()=>{
                let pheader_tab=document.querySelectorAll('.p-header__tab__item');
                if(pheader_tab[1].classList.contains('is-selected')){
                    let d_watch=document.querySelector('#d_watch');
                    d_watch.style.display='none'; }
            }, 400); }); }

    if(write_button){
        write_button.addEventListener('mouseup', function(){
            setTimeout(()=>{
                let pheader_tab=document.querySelectorAll('.p-header__tab__item');
                if(pheader_tab[0].classList.contains('is-selected')){
                    let d_watch=document.querySelector('#d_watch');
                    d_watch.style.display='block'; }
            }, 400); }); }



    let d_watch=document.querySelector('#d_watch');
    let drage=0; // ドラッグ処理中の管理
    let shiftX; // ホールド箇所による位置ズレ補正
    let shiftY; // ホールド箇所による位置ズレ補正


    d_watch.onmousedown=function(event){
        drage=1;
        shiftX=event.clientX-d_watch.getBoundingClientRect().left;
        shiftY=event.clientY-d_watch.getBoundingClientRect().top; }

    d_watch.onmouseup=function(event){
        drage=0; }

    let body_area=document.querySelector('body');
    body_area.ondragover=function(){ return false; } // HOMEでドラッグ可能にする

    document.addEventListener("drop", function(event){
        toMove(event); }, false); // ドロップ時に位置を取得して配置修正

    function toMove(event){
        if(drage==1){
            drage=0;
            let x=event.clientX-shiftX;
            let y=event.clientY-shiftY;
            d_watch.style.top=y+"px";
            d_watch.style.left='calc(50% - '+(document.body.offsetWidth/2-x)+'px)';
            document.cookie=
                'time_d_pos='+(document.body.offsetWidth/2-x)+':'+y+'; Max-Age=2592000'; }}


    function get_cookie(name){
        let cookie_req=document.cookie.split('; ').find(row=>row.startsWith(name));
        if(cookie_req){
            if(cookie_req.split('=')[1]==null){
                return 0; }
            else{
                return cookie_req.split('=')[1]; }}
        if(!cookie_req){
            return 0; }}

} // main()

 

〔追記〕2020.12.03

デジタル時計の枠線色を「#ccc」の淡い指定に変更しました。 上記コード48行で以下の太字部分を書換えると枠線色を好みに変更できます。

 

'border: 1px solid #ccc; border-radius: 3px; width: 240px; } '+

 

 

 

「Time On My Side A/D」最新版について 

旧いバージョンの JavaScriptツールは、アメーバのページ構成の変更で動作しない場合があり、導入する場合は最新バージョンをお勧めします。

 

●「Time On My Side A/D」の最新バージョンへのリンクは、以下のページのリンクリストから探せます。