20210226のHTMLに関する記事は6件です。

プルダウンの作り方

プルダウンの作り方

select要素とoption要素を使用します。

<select>
  <option>スポーツを選択してください</option>
  <option>野球</option>
  <option>サッカー</option>
 <option>バスケットボール</option>
 <option>バレーボール</option>
  <option>水泳</option>
 <option>柔道</option>
</select>

select要素は・・・セレクトボックス
option要素は・・・プルダウンの選択肢

これでプルダウンが簡単に作れます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者でもわかる】ラジオボタンの選択で項目を出し分ける方法

どうも7noteです。選択したラジオボタンによって内容を出し分ける方法について。

男性にだけ効きたい質問だったり、学生にだけに効きたい質問。
または特定の条件にそって要素を出し分け質問項目を変える方法について書きます。

今回サンプルで作ったのは普段検索エンジン何を使っているのかによって質問を出し分けるフォームです。
※実際に送信ボタンの実装はしていませんので、あくまで出し分け部分のソースのみに特化した記事です。

ソース

※jQueryを使用しています。jQueryってなんだ?という方はこちら

index.html
<p>質問:普段使う検索エンジンを教えてください。</p>
<div>
  <label><input type="radio" name="engine" value="google">Google</label><br>
  <label><input type="radio" name="engine" value="yahoo">Yahoo!</label><br>
</div>
<p class="google_only">
  Googleをお使いの方に質問です。<br>
  Googleの良さを教えてください。<br>
  <input type="textarea">
</p>
style.css
.google_only {
  display: none;
}
script.js
$(function(){
  /* nameがengineのラジオボタンが変更された場合の処理 */
  $( 'input[name="engine"]:radio' ).change( function() {

    /* nameがengineのラジオボタンで選択されている値を取得 */
    var selectdata = $("input[name='engine']:checked").val();

    /* その値が`google`だったら追加質問項目を表示。違えば非表示にする */
    if(selectdata == "google"){
      $(".google_only").show();
    } else {
      $(".google_only").hide();
    }
  });
});

結果

sample.gif

解説

基本的な動作の流れはソースのコメントに書いていますが、以下のような順番です。

・ラジオボタンが変更される
 ↓
・値を取得
 ↓
もし値がgoogleだったらgoogle_onlyのクラスがついた要素を表示
 ↓
違った場合、google_onlyのクラスがついた要素を非表示

出し分けだけであればそこまで複雑なことはせず、シンプルに考えれば簡単に作ることができます。

これに加えて、実際にgetやpost等でデータを渡すかどうかなどの話になってくると、見えていないtextareaの情報を送信させないようにするための制御なども必要になってくるので、少し難しくなるかもしれません。

まとめ

出し分けはjavascriptで簡単に実装することができました。cssだけで行なう方法もなくはないのですが、今回のようなケースであればjavascriptやjQueryを使って実装するのが手がるで簡単かなと思います。
もしかしたらもっと簡単にできる方法もあるかも。もし知っている方がいればぜひコメントで教えてください!

おそまつ!

~ Qiitaで毎日投稿中!! ~
【初心者向け】WEB制作のちょいテク詰め合わせ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[JavaScript][iframe]別のフレームの入力フォームにアクセスしたい。

iframeでフレームを分けているWebサイトのようなものを作っているのですが。
フレームをまたいだDOM操作が難しく感じたので、備忘録として残しておきます。

スクリーンショット 2021-02-26 134057.png

index.htmlで左のフレーム、右のフレームそれぞれファイルを呼び出し、フレーム化しています。
今回のイメージは左のフレームのテキストをクリックして、右のフレームのフォームに入力するイメージです。

left.htmlの<p>タグをクリックするとindex.jsのinputText()ファンクションが発火するという流れです。

別フレームの要素にアクセスするための構文

parent.フレーム名.document.要素名称.プロパティ

//↓今回の場合
parent.right_frame.document.getElementById('target');

のようになります。

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <iframe src="left.html" name="left_frame"></iframe>
    <iframe src="right.html" name="right_frame"></iframe>
</body>
</html>
left.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="index.js"></script>
</head>
<body>
    <p onclick="inputText()" id="text">この文章を右フレームのフォームへ</p>
</body>
</html>
right.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="index.js"></script>
</head>
<body>
    <p onclick="inputText()" id="text">この文章を右フレームのフォームへ</p>
</body>
</html>
test.js
function inputText() {
    var frame = parent.right_frame;
    var input_form = frame.document.getElementById('target');
    var element = document.getElementById('text').textContent;
    input_form.value = element;
}

基本的にはこれで大丈夫と思うのですが、Google ChromeではDOMExceptionという例外が発生する可能性もあります。
ぼくは発生してしまいました、、

クロスオリジンフレーム(?よくわからん)絡みのエラーなので、Eclipseなりでサーバー立ち上げて、試してみると無事に動きました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

匿名掲示板 6chan.jp を作成した話 - pull戦略について

オタクのための掲示板 6chan.jp を作成しました。その作成の経緯について書こうと思います。
http://6chan.jp

pull戦略

Joi Itoさんによると、Pullとは、情報や資材を備蓄するのではなく、必要に応じてネットワークから引っ張り出す方法です。
https://www.techrepublic.com/article/9-tools-to-navigate-an-uncertain-future-from-new-book-whiplash/

例えば、我々の掲示板 6chan.jp では phpBB というオープンソースのフォーラムをそのまま利用しています。これは、githubというネットワークから必要なソースコードをpullした状態と言えます。

同じように、マーケティング、マネタイズ、運用マニュアル作成なども、pullによって行うことができます。つまり、必要に応じてネットワークから必要なだけリソースを引っ張り出すのです。

マネジメントの面では、支出を削減し、柔軟性を高めることができます。

例えば、Safecastは、Kickstarterでの資金提供、寄付者の強力なネットワーク、市民科学者の協力によって生まれたオープンな環境データプラットフォームであり、福島の住民が放射線がどのように拡散しているかを知る上で重要な公共プロジェクトで、プル戦略によって成功しています。

プル戦略は、コミュニケーション、プロトタイピング、資金調達、学習などの新しい方法がもたらしたイノベーションのコスト削減を利用しています。

pull戦略で気を付けたい点

pull戦略は万能ではありません。気を付けたい点がいくつかあります。

修正可能性

pullによって行われた物事を、管理者がいつでも修正でき、しかもその修正を理解している必要があります。

管理可能性

ウェブサイトは、長期的に管理する必要があるため、管理者を設置する必要があります。しかし、プルによって管理を担うことができないため、プルによって行われた機能追加・修正を含めて、管理マニュアルの作成自体をプルする必要があります。

セキュリティ

ウェブサイトに対する機能追加・修正を行うために管理パスワードを教える必要があるのであれば、セキュリティの心配が出てきます。少なくとも、担当者に実際に会い、日本にいることを確認したほうが安全です。

多重請負の防止

プルした人材が別の業者へ委託する可能性があります。これにより、コスト増えてしまいがちです。プルした相手がプロであることを確認するために、ちょっとした尋問をする必要があります。例えば、当該のソースコードの管理に必要な知識についていくつか質問しておくとよいと思います。

コンタクトの維持

プルによって機能追加・修正された事柄について質問できるように、相手とのコンタクトを維持できているのがベターです。その相手が信頼するに値する人物なら、何度でもプルすることを検討することができます。

6chan.jpの具体的な管理方法

phpBBを使っているので、基本的にはextディレクトリにエクステンションを追加する形で機能追加をします。デザインはstyleディレクトリにテーマを設置します。

いくつかの継続的管理が要求されます。

  • 通報の監視
  • スパムの監視
  • トラフィックの監視
  • 書き込みの監視

利用者が少ないうちは監視作業は楽ですが、スケールするためにはマネタイズをし、運用要員を雇う必要があります。

マネタイズの具体的な方法については現時点では未定です。利用者が実際に増えてきた段階で考えます。

6chan.jpとは

最後に、6chan.jp を宣伝させていただきます。

6chan.jp はオタク向けの匿名掲示板です。4chanが発端となっています。

5ch (旧2ch) の「いやな雰囲気」「サイコパスやトロールがいる」ということをできるだけ避けるために、知的でオタクな議論をするよう推奨しております。

我々は、匿名性を「サイレントマジョリティーからクリエイティビティを引き起こす切符」だと考えております。

  • いいねやフォロワーの数で他者と競う必要がない。
  • プライバシーが守られる。
  • 自分のアイデンティティを傷つけることがない。

利用者が増えるほど楽しくなるので、どんどんトピックと返信を書き込んでください!

http://6chan.jp

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WEBページ上で、テーブルを列ごとにソートできるようにする

はじめに

image.png

WEBページを作る際、こういったテーブルを表示したいという時があるかと思います。
この時、テーブルのタイトル行をクリックしたら、その列に従って中身がソートされればいいのになと思うことがあるかと思います。
「名前」を一回クリックしたとき
 
「名前」をもう一回クリック

「おいしさ」を一回クリック

こういう動きを実装するにあたって、テーブルの中身が別ファイルから取ってくるもの(今回はWEBAPIでGETしてきたJSONデータ)だった場合に、簡単に実装出来てかつ思う通りに動くものがなかなか見つからなかったため、ここで紹介させていただきます。
sortable.jsです。

環境

OS:Windows10
sortable.js:Version 1.5.7

実装

sortable.jsの使い方を簡単に説明します。

JavaScript側

上記URLからsortable.jsをダウンロードし、sortable.jsとして保存します。
今回は、「js」フォルダを作成して、その中に置きました。


URL先が見れなかったときのためのコピペ
/*
Table sorting script  by Joost de Valk, check it out at http://www.joostdevalk.nl/code/sortable-table/.
Based on a script from http://www.kryogenix.org/code/browser/sorttable/.
Distributed under the MIT license: http://www.kryogenix.org/code/browser/licence.html .

Copyright (c) 1997-2007 Stuart Langridge, Joost de Valk.

Version 1.5.7

2007/9/26 japanese ver by KazumaNishihata
http://blog.webcreativepark.net/2007/09/26-024416.html
*/

/* You can change these values */
var image_path = "./";
var image_up = "arrow-up.gif";
var image_down = "arrow-down.gif";
var image_none = "arrow-none.gif";
var europeandate = true;
var alternate_row_colors = true;

/* Don't change anything below this unless you know what you're doing */
addEvent(window, "load", sortables_init);

var SORT_COLUMN_INDEX;
var thead = false;

function sortables_init() {
    // Find all tables with class sortable and make them sortable
    if (!document.getElementsByTagName) return;
    tbls = document.getElementsByTagName("table");
    for (ti=0;ti<tbls.length;ti++) {
        thisTbl = tbls[ti];
        if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
            ts_makeSortable(thisTbl);
        }
    }
}

function ts_makeSortable(t) {
    if (t.rows && t.rows.length > 0) {
        if (t.tHead && t.tHead.rows.length > 0) {
            var firstRow = t.tHead.rows[t.tHead.rows.length-1];
            thead = true;
        } else {
            var firstRow = t.rows[0];
        }
    }
    if (!firstRow) return;

    // We have a first row: assume it's the header, and make its contents clickable links
    for (var i=0;i<firstRow.cells.length;i++) {
        var cell = firstRow.cells[i];
        var txt = ts_getInnerText(cell);
        if (cell.className != "unsortable" && cell.className.indexOf("unsortable") == -1) {
            cell.innerHTML = '<a href="#" class="sortheader" onclick="ts_resortTable(this, '+i+');return false;">'+txt+'<span class="sortarrow">&nbsp;&nbsp;<img src="'+ image_path + image_none + '" alt="&darr;"/></span></a>';
        }
    }
    if (alternate_row_colors) {
        alternate(t);
    }
}

function ts_getInnerText(el) {
    if (typeof el == "string") return el;
    if (typeof el == "undefined") { return el };
    if (el.innerText) return el.innerText;  //Not needed but it is faster
    var str = "";

    var cs = el.childNodes;
    var l = cs.length;
    for (var i = 0; i < l; i++) {
        switch (cs[i].nodeType) {
            case 1: //ELEMENT_NODE
                str += ts_getInnerText(cs[i]);
                break;
            case 3: //TEXT_NODE
                str += cs[i].nodeValue;
                break;
        }
    }
    return str;
}

function ts_resortTable(lnk, clid) {
    var span;
    for (var ci=0;ci<lnk.childNodes.length;ci++) {
        if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
    }
    var spantext = ts_getInnerText(span);
    var td = lnk.parentNode;
    var column = clid || td.cellIndex;
    var t = getParent(td,'TABLE');
    // Work out a type for the column
    if (t.rows.length <= 1) return;
    var itm = "";
    var i = 0;
    while (itm == "" && i < t.tBodies[0].rows.length) {
        var itm = ts_getInnerText(t.tBodies[0].rows[i].cells[column]);
        itm = trim(itm);
        if (t.tBodies[0].rows[i].cells[column].tagName == "TH" || t.tBodies[0].rows[i].className == "unsortable" || t.tBodies[0].rows[i].className.indexOf("unsortable") != -1 || itm.length == 0) {
            itm = "";
        }
        i++;
    }
    if (itm == "") return; 
    sortfn = ts_sort_caseinsensitive;
    if (itm.match(/^\d\d[\/\.-][a-zA-z][a-zA-Z][a-zA-Z][\/\.-]\d\d\d\d$/)) sortfn = ts_sort_date;
    if (itm.match(/^\d\d[\/\.-]\d\d[\/\.-]\d\d\d{2}?$/)) sortfn = ts_sort_date;
    if (itm.match(/^-?\\?(\d+[,\.]?)+(\u5186)?%?$/)) sortfn = ts_sort_numeric;
    SORT_COLUMN_INDEX = column;
    var firstRow = new Array();
    var newRows = new Array();
    for (k=0;k<t.tBodies.length;k++) {
        for (i=0;i<t.tBodies[k].rows[0].length;i++) { 
            firstRow[i] = t.tBodies[k].rows[0][i]; 
        }
    }
    for (k=0;k<t.tBodies.length;k++) {
        if (!thead) {
            // Skip the first row
            for (j=1;j<t.tBodies[k].rows.length;j++) { 
                newRows[j-1] = t.tBodies[k].rows[j];
            }
        } else {
            // Do NOT skip the first row
            for (j=0;j<t.tBodies[k].rows.length;j++) { 
                newRows[j] = t.tBodies[k].rows[j];
            }
        }
    }
    newRows.sort(sortfn);
    if (span.getAttribute("sortdir") == 'down') {
            ARROW = '&nbsp;&nbsp;<img src="'+ image_path + image_down + '" alt="&darr;"/>';
            newRows.reverse();
            span.setAttribute('sortdir','up');
    } else {
            ARROW = '&nbsp;&nbsp;<img src="'+ image_path + image_up + '" alt="&uarr;"/>';
            span.setAttribute('sortdir','down');
    } 
    // We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
    // don't do sortbottom rows
    for (i=0; i<newRows.length; i++) { 
        if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) {
            t.tBodies[0].appendChild(newRows[i]);
        }
    }
    // do sortbottom rows only
    for (i=0; i<newRows.length; i++) {
        if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) 
            t.tBodies[0].appendChild(newRows[i]);
    }
    // Delete any other arrows there may be showing
    var allspans = document.getElementsByTagName("span");
    for (var ci=0;ci<allspans.length;ci++) {
        if (allspans[ci].className == 'sortarrow') {
            if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
                allspans[ci].innerHTML = '&nbsp;&nbsp;<img src="'+ image_path + image_none + '" alt="&darr;"/>';
            }
        }
    }       
    span.innerHTML = ARROW;
    alternate(t);
}

function getParent(el, pTagName) {
    if (el == null) {
        return null;
    } else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) {
        return el;
    } else {
        return getParent(el.parentNode, pTagName);
    }
}

function sort_date(date) {  
    // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
    dt = "00000000";
    if (date.length == 11) {
        mtstr = date.substr(3,3);
        mtstr = mtstr.toLowerCase();
        switch(mtstr) {
            case "jan": var mt = "01"; break;
            case "feb": var mt = "02"; break;
            case "mar": var mt = "03"; break;
            case "apr": var mt = "04"; break;
            case "may": var mt = "05"; break;
            case "jun": var mt = "06"; break;
            case "jul": var mt = "07"; break;
            case "aug": var mt = "08"; break;
            case "sep": var mt = "09"; break;
            case "oct": var mt = "10"; break;
            case "nov": var mt = "11"; break;
            case "dec": var mt = "12"; break;
            // default: var mt = "00";
        }
        dt = date.substr(7,4)+mt+date.substr(0,2);
        return dt;
    } else if (date.length == 10) {
        if (europeandate == false) {
            dt = date.substr(6,4)+date.substr(0,2)+date.substr(3,2);
            return dt;
        } else {
            dt = date.substr(6,4)+date.substr(3,2)+date.substr(0,2);
            return dt;
        }
    } else if (date.length == 8) {
        yr = date.substr(6,2);
        if (parseInt(yr) < 50) { 
            yr = '20'+yr; 
        } else { 
            yr = '19'+yr; 
        }
        if (europeandate == true) {
            dt = yr+date.substr(3,2)+date.substr(0,2);
            return dt;
        } else {
            dt = yr+date.substr(0,2)+date.substr(3,2);
            return dt;
        }
    }
    return dt;
}

function ts_sort_date(a,b) {
    dt1 = sort_date(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
    dt2 = sort_date(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));

    if (dt1==dt2) {
        return 0;
    }
    if (dt1<dt2) { 
        return -1;
    }
    return 1;
}
function ts_sort_numeric(a,b) {
    var aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    aa = clean_num(aa);
    var bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    bb = clean_num(bb);
    return compare_numeric(aa,bb);
}
function compare_numeric(a,b) {
    var a = parseFloat(a);
    a = (isNaN(a) ? 0 : a);
    var b = parseFloat(b);
    b = (isNaN(b) ? 0 : b);
    return a - b;
}
function ts_sort_caseinsensitive(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
    if (aa==bb) {
        return 0;
    }
    if (aa<bb) {
        return -1;
    }
    return 1;
}
function ts_sort_default(a,b) {
    aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
    bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
    if (aa==bb) {
        return 0;
    }
    if (aa<bb) {
        return -1;
    }
    return 1;
}
function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+,   NS6 and Mozilla
// By Scott Andrew
{
    if (elm.addEventListener){
        elm.addEventListener(evType, fn, useCapture);
        return true;
    } else if (elm.attachEvent){
        var r = elm.attachEvent("on"+evType, fn);
        return r;
    } else {
        alert("Handler could not be removed");
    }
}
function clean_num(str) {
    str = str.replace(new RegExp(/[^-?0-9.]/g),"");
    return str;
}
function trim(s) {
    return s.replace(/^\s+|\s+$/g, "");
}
function alternate(table) {
    // Take object table and get all it's tbodies.
    var tableBodies = table.getElementsByTagName("tbody");
    // Loop through these tbodies
    for (var i = 0; i < tableBodies.length; i++) {
        // Take the tbody, and get all it's rows
        var tableRows = tableBodies[i].getElementsByTagName("tr");
        // Loop through these rows
        // Start at 1 because we want to leave the heading row untouched
        for (var j = 0; j < tableRows.length; j++) {
            // Check if j is even, and apply classes for both possible results
            if ( (j % 2) == 0  ) {
                if ( !(tableRows[j].className.indexOf('odd') == -1) ) {
                    tableRows[j].className = tableRows[j].className.replace('odd', 'even');
                } else {
                    if ( tableRows[j].className.indexOf('even') == -1 ) {
                        tableRows[j].className += " even";
                    }
                }
            } else {
                if ( !(tableRows[j].className.indexOf('even') == -1) ) {
                    tableRows[j].className = tableRows[j].className.replace('even', 'odd');
                } else {
                    if ( tableRows[j].className.indexOf('odd') == -1 ) {
                        tableRows[j].className += " odd";
                    }
                }
            } 
        }
    }
}


また、URL先(と上のコピペ)の実装では▲マークの表現にgif画像を使っているのですが、個人的に画像を用意するのが面倒だったため、image_up系はこのような文字列に変更しました。
cell.innerHTMLに代入するHTML文の中の、<span>タグ内の<img>内をそのままimage_noneに書き換える形です。
他の箇所もそれぞれ書き換えました。

var image_up = '&nbsp;&nbsp;▲▽';
var image_down = '&nbsp;&nbsp;△▼';
var image_none = '&nbsp;&nbsp;▲▼';

HTML側

ここでは普通にheadタグ内でsortable.jsを設定し、bodyタグ内でテーブルを作成します。
ソートができるようにするには<table>のclassにsortableを追加するだけです。
ここで、「購入」ボタンはソートできてもしょうがないので、ソート無しの設定にします。classにunsortableを追加することで、この列ではソートしないように設定することができます。

<head>
    <!-- 色々省略 -->
    <script src="./js/sortable.js" type="text/javascript"></script>
</head>
...
<body>
<div style="height:250pt; width:100%; overflow-y:scroll; margin-top: 10px;">
    <table id="eattable" border="solid gray 1px" class="sortable">
        <thead>
            <tr>
                <th class="th_1">名前</th>
                <th class="th_2">分類</th>
                <th class="th_3">収穫日時</th>
                <th class="th_4">おいしさ</th>
                <th class="th_5 unsortable">購入</th>
            </tr>
        </thead>
        <tbody id="eattablebody"></tbody>
        <!-- テーブルの中身はJSONデータから取得して別で設定 -->
    </table>
</div>
</body>

また、このままだとリストを更新した際に、ソート状態は解除されるのに「▲▽」「△▼」の表示が残ってしまいます。
なのでリスト更新処理を書いた後は以下のようにしてテーブル名内の▲マークを元の状態に戻すと良いかと思います。

var allspans = document.getElementsByTagName("span");
for (var ci=0;ci<allspans.length;ci++) {
    if (allspans[ci].className == 'sortarrow') {
        allspans[ci].innerHTML = '&nbsp;&nbsp;▲▼';
    }
}

CSS

ここは人それぞれの好みがあるかと思うため読み飛ばしOKです。
個人的にテーブル名にリンクの下線が引いてあるのはあまり見ないのでリンク線は無し、▲マークが黒だと列名の邪魔なので色を灰色にしました。

a.sortheader{
    text-decoration: none;
    color: black;
}

.sortarrow{
    color: gray;
}

注意点

テーブル内の列名(文字列)に対してリンク(<a>タグ)が設定されているため、テーブル名の文字列部分をクリックしないとソートできないようになっています。
なので、上の画像のように
「名前 ▲▼      」
のような不格好な状態になっている列名の右半分の白い部分をクリックしてもソートされないため、場合によっては文句を言われるかもしれません。

最後に

URL先を見ると、固定行を用意する、行ごとに色を変える、という実装も可能なようです。
今回実現したい内容には不要だったので試しませんでしたが、どちらもソート可能設定と同じく簡単な設定で実現可能なようなので、大変ありがたいです。
あと「名前 ▲▼    」みたいなのじゃなくて「名前    ▲▼」みたいにしたかったんですけども、「::after」とかを使うと3パターンの切り替えが大変そうだったので日和りました。

固定行と色

・行ごとに色を変える
 奇数行のclassに「odd」、偶数行のclassに「even」が追加されるため、CSSで指定すればOKです。
 (上に貼った画像の表はElements見てもなぜかodd, even等の設定が無かった…やはりファイル取得してくるパターンだとダメなのか)
・固定行を作る
 固定にしたい行(tr)のclassに「sortbottom」を追加すればOKです。
 ただし、「bottom」とついているだけあって最下行に固定されることに注意してください。

参考リンク

https://blog.webcreativepark.net/2007/09/26-024416.html (日本語対応版)
https://blog.webcreativepark.net/2007/09/24-172811.html (↑の元の紹介記事)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails 6】favicon の設定以降、他のアプリでも同じfaviconが表示される不具合を解消

概要

favicon を設定したものの、他のアプリのfaviconまで同じシンボル画像になっていました。

他のアプリにはfavicon を設定していないのにも関わらず、同じfaviconが設定されていることの疑問を解消しましたので、その共有です。

image.png

結論

他のアプリのfaviconも、設定することで解決する。

image.png

同じfaviconが表示されることの仮説

※調べても情報がなかったので仮説となっています。ご参考までに。

情報が保存されるcookieが原因かと仮説を立てております。

一度アプリで設定したfaviconの情報がcookie上で保存されて、他アプリを立ち上げた際にも、その保存データが残っている。デフォルトでfaviconを設定していない場合に限り、そのデータが適用され、他アプリでも同じfaviconが表示されることになるのだと考えています。

なので、他アプリ内で新しくfaviconを設定することで、固有のfaviconを設定できるのだと思います。

補足

faviconとは

favorite iconの略で、サイトにアクセスした際のブラウザのタブやブックマークに表示されるなど、サイトのシンボルとして重要な役割を果たします。

主にブラウザのタブや履歴、お気に入りに表示されるアイコンや、スマホでサイトをホーム画面に置いたときの表示アイコンなどのことを指します。

cookieとは

cookie(クッキー)とは、自身が見ているWebサイトから自身のスマホやPCの中に保存される情報のこと

faviconを設定されるまでの手順

①app/assets/imagesに画像をセットする。
(画像で言うと一番したのものになります。)

image.png

②app/views/layouts/application.html.erbに以下のコードを設置する。
拡張子は記述しません。ファイル名のみで問題ありません。

app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>

# ~省略~

<%= favicon_link_tag('homekatajiten') %>

# ~省略~

</head>

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む