20200120のHTMLに関する記事は10件です。

React hooksとclassコンポーネントにおけるsetStateの挙動の違いについて(動かせるコードあり)

概要

こちらは以下の記事に書いたhooksとclassコンポーネントにおけるsetStateの違いを別記事にしたものです.
https://qiita.com/yseki_/items/71511db1a60ab22ee663

忙しい人向けまとめ

hooksとクラス型コンポーネントのsetStateでは挙動が違う
hooksでは古いステートが引き継がれないため,更新の際は古いステートもセットする必要がある

それぞれのステート更新について

まずはhooksとclassのsetStateの違いを体験してみてください.
以下二つをhtmlファイルに貼り付け,お好きなブラウザで開いてみてください.
うまく動作しない場合,以下のリポジトリをcloneしてファイルをブラウザに貼り付けてください.
https://github.com/YutaSeki36/reactSetStateDiff

クラス型コンポーネント

classComponent.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ClassComponent</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div><script type="text/babel">
class ClassComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
a: 0,
b: 0
};

this.handleChangeA = this.handleChangeA.bind(this);
}

handleChangeA(a) {
this.setState({ a: this.state.a + a });
}

render() {
console.log(`a: ${this.state.a}, b: ${this.state.b}`);
return (
<div>
<p>a: {this.state.a}</p>
<p>b: {this.state.b}</p>
​
<button onClick={() => this.handleChangeA(1)}>a+1</button>
</div>
);
}
}

ReactDOM.render(<ClassComponent />, document.getElementById("root"));
</script>
</body>
</html>

関数型コンポーネント

FunctionComponent.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>FuntionComponent</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
</head>
<body>
<div id="root"></div><script type="text/babel">
const FuncComponent = props => {
const [state, setState] = React.useState({ a: 0, b: 0 });

const handleChangeA = a => {
setState({ a: state.a + a });
};

console.log(`a: ${state.a}, b: ${state.b}`);

return (
<div>
<p>a: {state.a}</p>
<p>b: {state.b}</p>
​
<button onClick={() => handleChangeA(1)}>a+1</button>
</div>
);
};

ReactDOM.render(<FuncComponent />, document.getElementById("root"));
</script>
</body>
</html>

検証

それぞれ見た目は以下のようになるかと思います.

スクリーンショット 2020-01-20 20.25.43.png

まずはクラス型コンポーネントの a+1 を押してみましょう.
スクリーンショット 2020-01-20 20.27.44.png

このように,無事更新ができました.

次は関数型コンポーネントで動作確認を行なってみましょう.

スクリーンショット 2020-01-20 20.29.37.png

このように,hooksでステートの更新を行うと,bがundefinedになってしまいました.

解決策

公式チュートリアルに,以下のような記述があります.

しかしクラスでの this.setState とは異なり、state 変数の更新は、マージではなく必ず古い値を置換します。

とありますので,hooksによるステート更新の際は古いステートもセットする必要があります.

先ほどの関数型コンポーネントファイルのステート更新mesoddo部分を以下のように書き換えます.

funcCom.html
const handleChangeA = a => {
 // スプレッド構文を用いて、古いステートも記述する
          setState({ ...state, a: state.a + a });
};

これで無事にステート更新を行うことができました.
スクリーンショット 2020-01-20 20.38.32.png

結び

あまりReactに慣れていない状態でhooksに手を出してしまい,初歩的なところで躓いてしまいました.
しっかりと公式ドキュメントにも書いている内容だったため,今後新たな技術を学ぶ際は公式ドキュメントに目を通そうと思いました.

(誤字脱字,間違った内容などあればコメントください🙇‍♂️)

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

初心者によるプログラミング学習ログ 215日目

100日チャレンジの215日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

215日目は

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

javascript デジタルなカウントダウンタイマー

デジタルチックな良い感じのタイマーを実装したので速攻で共有します。
成果物はこんな感じです。
スクリーンショット 2020-01-17 20.47.30.png
コードはこんな感じ。
なお、スタイリングには Bootstrap4&CSS を使用しています。
bootstrap4 download

index.html
 /* 画面の右下に配置 */
<div class="" style="position:fixed;bottom:-30px;right: -100px;z-index:100;width: 17em">
        <main>
            <!-- 時計 -->
            <div class="clock text-center">
                <!-- 時間 -->
                <div class="numbers">
                    <p class="hours mb-0"></p>
                    <p class="placeholder mb-0">88</p>
                </div>

                <div class="colon">
                    <p class="mb-0">:</p>
                </div>

                <!-- 分 -->
                <div class="numbers">
                    <p class="minutes mb-0"></p>
                    <p class="placeholder mb-0">88</p>
                </div>

                <div class="colon">
                    <p class="mb-0">:</p>
                </div>

                <!-- 秒 -->
                <div class="numbers">
                    <p class="seconds mb-0"></p>
                    <p class="placeholder mb-0">88</p>
                </div>
            </div>
        <!-- タイマーを止めるボタン(機能は実装しません) -->
            <div class="text-center">
                <button type="button" class="btn btn-light font-weight-bold my-0 px-5" >タイマーを止める</button>
            </div>
        </main>
    </div>

お次にcss

style.css
* {
    margin: 0;
    padding: 0;
}
main {
    color: #ffffff;
    background-color: #000000;
    font-family: 'digital-7', sans-serif;
}
main {
    transform: translate(-50%,-50%);
    padding: 15px;
    border: solid 5px #ffffff;
}

div.days {
    margin: 0 auto;
    color: #131212;
}

div.days .day {
    display: inline-block;
}

div.days .day p {
    font-size: 12px;
    font-weight: bold;
    font-family: sans-serif;
    text-transform: uppercase;
}

div.clock div{
    display: inline-block;
    position: relative;
}

div.clock div p{
    font-size: 30px;
    position: relative;
    z-index: 100;
}

div.clock .placeholder {
    color: #131212;
    position: absolute;
    top: 0;
    z-index: 50;
}

.light-on {
    color: #ffffff;
}

からのjavascript

index.js
// 9:00:00 -> 09:00:00 って一桁の数値の場合に0を付与してあげる関数
function addZero (val){
    return (val <= 9) ? ("0" + val) : val;
}

const second = 1000,
      minute = second * 60,
      hour = minute * 60,
      day = hour * 24;

let countDown = new Date('Nov 10, 2020 00:00:00').getTime(),
    hoge = setInterval(function() {

      let now = new Date().getTime(),
          distance = countDown - now;

        document.getElementsByClassName('hours')[0].innerText = addZero(Math.floor((distance % (day)) / (hour))),
       document.getElementsByClassName('minutes')[0].innerText = addZero(Math.floor((distance % (hour)) / (minute))),
       document.getElementsByClassName('seconds')[0].innerText = addZero(Math.floor((distance % (minute)) / (second)));

      // 時間が0以下になった時の処理
      if (distance < 0) {
        clearInterval(hoge);
      }

    }, second)

デジタルチックなフォント表現をするために Digital 7フォントを使用しています。
Digital 7フォントから任意のファイルをダウンロードしてhtmlファイル内で読み込んであげてください。

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

【初心者】JavaScriptで「おみくじゲーム」を作ってみた

最近、JavaScriptを勉強しています。
練習として、簡単すぎる「おみくじゲーム」を作ってみました。
ちなみに、10分くらいで完成しました。笑

HTMLを記述する

index.html
<input type="button" value="今日のあなたの運勢は?" id="btn">
<p id="fortune"></p>

<script src="main.js"></script>

一番上にボタンを配置して、
その下に運勢を表示するための要素を記述しています。
JavaScriptを読み込むことも忘れずに。

JavaScriptを記述する

main.js
const btn = document.getElementById('btn');

btn.addEventListener('click', () => {
  const fortunes = ['大吉', '', '中吉', '小吉', '末吉', '', '大凶'];
  const randomNumber = Math.floor(Math.random() * fortunes.length);
  fortune.textContent = fortunes[randomNumber] + '';
});

クリックされるボタンを定数 btn に代入します。
idbtn の要素を getElementById で取ってきています。

そのボタンがクリックされたときのイベントを、その下に記述しています。
運勢のうちのいずれかを、運勢を表示する要素の文字列として格納しています。

7つの運勢を配列として、定数 fortunes に格納し、
いずれかを取ってくるようにしています。

運勢について

運勢の良さは、fortunes に記述してある順番の通りみたいです。
大吉の次が吉なのは知りませんでした。
僕はてっきり、小吉、吉、末吉の順番かと思ってました。(世界で一番どうでもいい余談)

addEventListener について

addEventListener(種類, 関数, false) という形で使います。
種類とは、イベントの種類のことで、clickload などがあります。
アロー関数の形であれば、先述したようにコードを書くことができます。

Math.random() について

Math.random() は、0以上1未満 の数を返します。
今回の場合、fortunes.length7 であるため、
Math.random() * fortunes.length は、0以上7未満 の数を返します。

Math.floor について

Math.random だと小数も返すことになるので、都合が悪いです。
できれば整数が返ってきてほしいところです。
そこで Math.floor を使うことで、小数点を切り捨ててくれます。

そのため、Math.floor(Math.random * fortunes.length)
0以上7未満の整数 すなわち 0から6のいずれかの整数 を返してくれます。

おわりに

すごく簡単に「おみくじゲーム」を作ることができました。
JavaScriptの一番最初の練習としては良かったです。
これはあまりにも簡単だったので、他にもミニゲームを作ってみたいと思います。

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

Web制作の初心者で知っていると便利な英単語一覧

Web制作初心者制作で知っていると便利な英単語一覧

クラスの名前付けをしているとここは何てクラス名を付ければいいんだろうとか、参考にしたいソースを見た時にこれ何て読むのだろうとか、書けるけど読み方がわからなくて同僚と話すときにタジタジになってしまうなどあると思います。
web制作初心者の方や英語なんて日本にいるんだから使わないわ!と思っていた人や、英語の勉強を避けてきた人などが参考になればいいなと思ってまとめてみました。
よく使うやつと誤字しやすいつを載せています。

クラス名一覧

wrapper (ラッパー)
・要素を内包する
 もっとわかりやすく言うとサラ○ラップのラップのように包み込むということ
・タイプミスしやすいので注意

wrap(ラッパー)
・wrapperをただ略しただけ

container(コンテナ)
・コンテナ
 スペル的に語尾を伸ばしたくなるけど伸ばさない方が伝わりやすい

content(コンテント)
・内容、中身
・コンテンツともいう人はいる

common(コモン)
・共通

product(プロダクト)
・製品、商品

concept(コンセプト)
・コンセプト
 conseptではないので注意

index(インデックス)
・索引

inquiry(インクアリー)
・問い合わせ
 クアリーって発音しながらquaryではなくquiryなので注意

access(アクセス)
・アクセス
 cとsが2つなので注意

privacy(プライバシー)
・プライバシー
 sではなくてcなので注意

input(インプット)
・入力

confirm(コンファーム)
・確認
ファームって発音しておきながらfarmではなくてfirmなので注意

finish(フィニッシュ)
・完了

section(セクション)
・部分

description(ディスクリプション)
・説明

summary(サマリー)
・概要

inner(インナー)
・内側

outer(アウター)
・外側

agree(アグリー)
・同意

address(アドレス)
・住所
 dとsが二つずつあるので注意

active(アクティブ)
・アクティブ、有効

disabled(ディセイブルド)
・無効

icon(アイコン)
・アイコン

breadcrumb(ブレッドクラム)
・パンクズリスト
 普段つかわない言葉なんで馴染みがないのでわかりにくいですね

navigation(ナビゲーション)
・ナビゲーション

nav(ナビゲーション)
・navigationを略しただけ

button(ボタン)
・ボタン
 botton やbottom のように間違えてしますことが多いので注意

bottom(ボトム)
・下部
 ちなみに上からtop(トップ)、middle(ミドル)、bottom(ボトム)となる




共に働くWebエンジニアを募集しています!

不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくはWantedlyからお問い合わせください。

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

Web制作初心者制作で知っていると便利な英単語一覧

Web制作初心者制作で知っていると便利な英単語一覧

クラスの名前付けをしているとここは何てクラス名を付ければいいんだろうとか、参考にしたいソースを見た時にこれ何て読むのだろうとか、書けるけど読み方がわからなくて同僚と話すときにタジタジになってしまうなどあると思います。
web制作初心者の方や英語なんて日本にいるんだから使わないわ!と思っていた人や、英語の勉強を避けてきた人などが参考になればいいなと思ってまとめてみました。
よく使うやつと誤字しやすいつを載せています。

クラス名一覧

wrapper (ラッパー)
・要素を内包する
 もっとわかりやすく言うとサラ○ラップのラップのように包み込むということ
・タイプミスしやすいので注意

wrap(ラッパー)
・wrapperをただ略しただけ

container(コンテナ)
・コンテナ
 スペル的に語尾を伸ばしたくなるけど伸ばさない方が伝わりやすい

content(コンテント)
・内容、中身
・コンテンツともいう人はいる

common(コモン)
・共通

product(プロダクト)
・製品、商品

concept(コンセプト)
・コンセプト
 conseptではないので注意

index(インデックス)
・索引

inquiry(インクアリー)
・問い合わせ
 クアリーって発音しながらquaryではなくquiryなので注意

access(アクセス)
・アクセス
 cとsが2つなので注意

privacy(プライバシー)
・プライバシー
 sではなくてcなので注意

input(インプット)
・入力

confirm(コンファーム)
・確認
ファームって発音しておきながらfarmではなくてfirmなので注意

finish(フィニッシュ)
・完了

section(セクション)
・部分

description(ディスクリプション)
・説明

summary(サマリー)
・概要

inner(インナー)
・内側

outer(アウター)
・外側

agree(アグリー)
・同意

address(アドレス)
・住所
 dとsが二つずつあるので注意

active(アクティブ)
・アクティブ、有効

disabled(ディセイブルド)
・無効

icon(アイコン)
・アイコン

breadcrumb(ブレッドクラム)
・パンクズリスト
 普段つかわない言葉なんで馴染みがないのでわかりにくいですね

navigation(ナビゲーション)
・ナビゲーション

nav(ナビゲーション)
・navigationを略しただけ

button(ボタン)
・ボタン
 botton やbottom のように間違えてしますことが多いので注意

bottom(ボトム)
・下部
 ちなみに上からtop(トップ)、middle(ミドル)、bottom(ボトム)となる

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

Googleの検索結果に意図したファビコンが表示されない

背景

GoogleのPC検索結果にファビコンが表示されるようになった。
が、指定のファビコン画像ではなく、タッチアイコンに指定している別の画像が表示されてしまっていた。

現状

問題のサイトではアイコン類を以下のように指定。

<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png">

タブやお気に入りのファビコンは favicon.ico が表示されているのだが、
検索結果は touch-icon.png が表示されてしまっている。

検索結果でも favicon.ico を表示したい。

Googleのガイドライン

Googleのガイドラインは以下のページに記載されている。

疑いポイント1:アイコンのサイズ

ガイドライン では以下のように指定されている。

ファビコンのサイズが 48 ピクセルの倍数になっていること(例: 48 x 48 ピクセル、96 x 96 ピクセル、144 x 144 ピクセルなど)。SVG ファイルの場合は、サイズに関して特別な指定はありません。有効なファビコン形式は、すべてサポートされています。Google では画像サイズを 16 x 16 ピクセルに変換するため、その解像度で適切に表示されるか、あらかじめご確認ください。16 × 16 ピクセルのファビコンは指定しないでください

対して、問題のサイトのアイコンのサイズは 64 x 64
サイズ違反が原因?

疑いポイント2:アイコン系の記載順

ガイドライン では以下のように指定されている。

ホームページのヘッダーに次の構文の タグを追加します。

rel
 次のいずれかを指定できます。
 ・"shortcut icon"
 ・"icon"
 ・"apple-touch-icon"
 ・"apple-touch-icon-precomposed"

対して、問題のサイトではアイコン系の設定を以下のように2つ記載している。

<link rel="shortcut icon" href="/favicon.ico">
<link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png">

記載順から apple-touch-icon がファビコンとして認識されている?

結論

「疑いポイント:2」のアイコンの記載順が原因っぽかった。
以下のように記載順を修正することで、Googleの検索結果に favicon.ico が表示されるようになった。
※ただし、反映まで2日ほどかかった。

<link rel="apple-touch-icon" sizes="192x192" href="/touch-icon.png">
<link rel="shortcut icon" href="/favicon.ico">

サイズについては、64 x 64 のままで表示されるようになったので、
ガイドラインに沿っていなくてもよしなにやってくれるようです。

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

[自動更新が止まらない]RailsでJavascriptファイル(html機能)を用いて自動更新機能実装をした時に、ブラウザ上の繰り返し表示が止まらないエラーの解決例

1.エラーの様子と間違っていたファイル

まず筆者が起こしたエラーは下のものです

<エラーの様子(gifなので動かない場合は画像をクリックしてご確認ください)>
qiita4.gif

言葉で表現すると、仕様としてはsendボタンを押したら、1回だけ「家に帰ってお母さんに報告だ!」が出て(ブラウザ上の)更新が止まる予定でした。(裏では1秒に1度更新する設定にはしていますが、見た目に反映させない仕様を目指していました。)

しかしご覧の通り表面上ループを抜けられずコメントがずっと繰り返されてしまいます。
(これでは永遠にお母さんに報告し続けることとなってしまいます。)

困ったなと思いながら、この表記をするファイルにlinkを組んである「qiitaに聞いた」をクリックするとコメントは1度のみ投稿されたこととなっています(データベースへの取得は一回だけと設定ができている状態でした。)

<間違いがあったファイル(下記は間違っている状態です)>

app/assets/javascripts/message.js
$(function(){ 
  function buildHTML(message){
   if ( message.image ) {
     var html =
      `<div class="chat-main__message-list" data-message-id=${message.id}>
         <div class="chat-main__message-list__name">
            ${message.user_name}        
            <div class="chat-main__message-list__name__date">
              ${message.created_at}
            </div>
         </div>
         <div class="chat-main__message-list__comment">
           <p class="chat-main__message-list__comment__content">
             ${message.content}
           </p>
         </div>
         <img src=${message.image} >
       </div>`
     return html;
   } else {
     var html =
     `<div class="chat-main__message-list" data-message-id=${message.id}>
        <div class="chat-main__message-list__name">
            ${message.user_name}        
            <div class="chat-main__message-list__name__date">
              ${message.created_at}
            </div>
        </div>
        <div class="chat-main__message-list__comment">
          <p class="chat-main__message-list__comment__content">
            ${message.content}
          </p>
        </div>
       </div>`
     return html;
   };
 }

 $('#new_message').on('submit', function(e){
  e.preventDefault();
  var formData = new FormData(this);
  var url = $(this).attr('action')
  $.ajax({
    url: url,
    type: "POST",
    data: formData,
    dataType: 'json',
    processData: false,
    contentType: false
  })
  })
  var reloadMessages = function() {
  //カスタムデータ属性を利用し、ブラウザに表示されている最新メッセージのidを取得
  last_message_id = $('.message:last').data("message-id");
  $.ajax({
    //ルーティングで設定した通りのURLを指定
    url: "api/messages",
    //ルーティングで設定した通りhttpメソッドをgetに指定
    type: 'get',
    dataType: 'json',
    //dataオプションでリクエストに値を含める
    data: {id: last_message_id}
    })
    .done(function(messages) {
      if (messages.length !== 0) {
        //追加するHTMLの入れ物を作る
        var insertHTML = '';
        //配列messagesの中身一つ一つを取り出し、HTMLに変換したものを入れ物に足し合わせる
        $.each(messages, function(i, message) {
          insertHTML += buildHTML(message)
        });
        //メッセージが入ったHTMLに、入れ物ごと追加
        $('.messages').append(insertHTML);
        $('.messages').animate({ scrollTop: $('.messages')[0].scrollHeight});
        $("#new_message")[0].reset();
        // $('form')[0].reset();
        $('.chat-main__message-form__new_message__send__btn').attr('disabled', false);
      }
    })
    .fail(function() {
      console.log('error');
    });
  };
  // });
  if (document.location.href.match(/\/groups\/\d+\/messages/)) {
    setInterval(reloadMessages, 7000);
  }
});

app/views/messages/_message.html.haml
.message{data: {message: {id: message.id}}}

.chat-main__message-list
  .chat-main__message-list__name
    =message.user.name
    .chat-main__message-list__name__date
      =message.created_at.strftime("%y年%m月%d日%H時%M分")
  .chat-main__message-list__comment
    - if message.content.present?
      %p.chat-main__message-list__comment__content
        = message.content
        = image_tag message.image.url, class: 'chat-main__message-list__comment__content__image' if message.image.present?

2.エラー元発見までの過程

解決までの道のりから記載した方がおそらく類似のエラーでも発見がしやすくなり皆さんのエラーへのお力になれると思うので過程から書かせていただきます。お急ぎの方は3.原因と解決方法をご覧ください。(エラーの元がわかれば原因と解決がやりやすくなると考え先に記載しています。原因究明だけ読まれると筆者のエラーと全く同じの場合しか解決できなく、せっかく時間をかけて調べられた内容で応用を効かせること(他のエラーの対処に役立たせること)ができず勿体無いと思っています。ですので、ぜひこの章もご覧ください)

<エラー元発見への過程>
①エラーの挙動から見てフロントに関する記述(HTMLのコード)がおかしいんだろうな

②フロント(HTMLのコード)ならGoogleChromeの検証機能だ!ということで下の画像のように検証を開いてみました

スクリーンショット 2020-01-20 7.49.37.png

③繰り返し表示されてるコメントの"data-message-id=44"はclass名が"chat-main__message-list"で、正しく表記されている上のコメントの"data-message-id=42"や"data-message-id=43"のクラス名は"massage"になってる!と気づきます

④③のタイミングで正しく表記された部分とエラーの部分の差異がエラーの元となっていると予想し、自動更新(JavaScriptファイル)のchat-main__message-listの部分がおかしいんだなと気づくことができ探しに行けたという流れでした

このように、挙動を見ながら正しい部分と間違った部分を比べて差異を見つけることがエラー発見の基本となり、これ以外のエラーでも役立つ作業なのです。

3.原因と解決方法

<原因>
まず結論から言いますとこのように繰り返されてしまった原因は、id振り分け機能の不全でした。

詳しく説明しますと、当初の予定ではまずapp/controllers/api/messages_controller(更新機能を取り付けるためのコントローラ)の部分で「idが以前のものより大きいものを全て受け取る」ようにする。
次に更新(api)でidを得た後、大元の"app/controllers/messages_controller"で現在振り分け済みのidと更新(api)で得たidを同期する。
すると、apiで入れ込もうとするidが振り分け済みのidとイコールの関係になるので一回しか表示されないとなるはずでした
ところが、"app/controllers/api/messages_controller"で手に入れてくるidのクラス名が間違っているので"app/controllers/messages_controller"で同期できずに繰り返し表示されるという始末でした。(じゃあなんでlinkボタンで更新すると直るのかと言われると想像の話となってしまうのですが、検証のid振り分けの挙動から推測するに、railsのgemのどれかで、他からのアクセス時に描画に関するidとclass名が大元のコントローラと一致しないものを大元に合わせた修正を行ってくれるものがあるんじゃないかと思っています。浅学で申し訳ない。)

<解決方法>
親クラスが合っていればidで整合を取れるので、
①JavaScriptファイル(app/asset/javascripts/massage.js)のHTML記載の親クラスのみmessageに変える

app/assets/javascripts/message.js
$(function(){ 
  function buildHTML(message){
   if ( message.image ) {
     var html =
      `<div class="message" data-message-id=${message.id}>  #クラス名を変えました
         <div class="chat-main__message-list__name">
            ${message.user_name}        
            <div class="chat-main__message-list__name__date">
              ${message.created_at}
            </div>
         </div>
         <div class="chat-main__message-list__comment">
           <p class="chat-main__message-list__comment__content">
             ${message.content}
           </p>
         </div>
         <img src=${message.image} >
       </div>`
     return html;
   } else {
     var html =
     `<div class="message" data-message-id=${message.id}>    #クラス名を変えました
        <div class="chat-main__message-list__name">
            ${message.user_name}        
            <div class="chat-main__message-list__name__date">
              ${message.created_at}
            </div>
        </div>
        <div class="chat-main__message-list__comment">
          <p class="chat-main__message-list__comment__content">
            ${message.content}
          </p>
        </div>
       </div>`
     return html;
   };
 }
#以下は同じです

②app/views/messages/_massages.html.haml(大元のコントローラと繋がっているview)で.messageを1番目の親とするネスト形態とする

app/views/messages/_message.html.haml
.message{data: {message: {id: message.id}}}
#以下のインデントを全て一つ下げました
  .chat-main__message-list
    .chat-main__message-list__name
      =message.user.name
      .chat-main__message-list__name__date
        =message.created_at.strftime("%y年%m月%d日%H時%M分")
    .chat-main__message-list__comment
      - if message.content.present?
        %p.chat-main__message-list__comment__content
          = message.content
          = image_tag message.image.url, class: 'chat-main__message- 
  list__comment__content__image' if message.image.present?

この①と②でこのバグは解消されます

<解決した画面(gifなので動かない場合は画像をクリックしてご確認ください)>
qiita3.gif

ご参考になればと思います。

4.参考(gif作成に参考にさせてもらった記事のリンク、関連ファイルの内容の提示)

参考までに、gif作成の参考サイトへのリンクと、修正はしなかったけど、ここまでに名前がでてきたファイルを下に貼付しておきます

<gif作成の参考にさせてもらった記事へのリンク>

https://qiita.com/syamaoka/items/4d4054cd75df00460925#ffmpeg%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

<api用コントローラ>

app/controllers/api/messages_controller.rb
class Api::MessagesController < ApplicationController
  def index
    # ルーティングでの設定によりparamsの中にgroup_idというキーでグループのidが入るので、これを元にDBからグループを取得する
    group = Group.find(params[:group_id])
    # ajaxで送られてくる最後のメッセージのid番号を変数に代入
    last_message_id = params[:id].to_i
    # 取得したグループでのメッセージ達から、idがlast_message_idよりも新しい(大きい)メッセージ達のみを取得
    @messages = group.messages.includes(:user).where("id > #{last_message_id}")


  end
end

<大元のコントローラ>

app/controllers/messages_controller.rb
class MessagesController < ApplicationController
  before_action :set_group

  def index
    @message = Message.new
    @messages = @group.messages.includes(:user)
  end

  def create
    @message = @group.messages.new(message_params)
    if @message.save
      respond_to do |format|
        format.json
      end
    else
      @messages = @group.messages.includes(:user)
      flash.now[:alert] = 'メッセージを入力してください。'
      render :index
    end
  end

  private

  def message_params
    params.require(:message).permit(:content, :image).merge(user_id: current_user.id)
  end

  def set_group
    @group = Group.find(params[:group_id])
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

社内の月朝ゆるもく会で作ったバーチカルメニュー

毎週月曜朝、7:00~8:30くらいでゆるっともくもく会をやり始めました。
頑張って早起きして、アウトプット出していきたい。。。

成果物

See the Pen circle by UMA (@umaniel) on CodePen.

その昔、横方向の開きメニューを作ったことがあったので、縦方向でも作ってみようと思い、やってみました。

やってること

特に難しいことはしておらず、classの付け替えでheightが変わるだけです。

[class*="home--"].active {
  height: 100%;
}
[class*="home--"].disactive {
  height: 0%;
}

純javascriptはclassの付け替えが面倒。。。

const home = document.querySelectorAll("div[class*='home--']");

const active = _self => {
  const selfClass = _self.className.replace(/^(home--(top|bottom|center)).*/, "$1");
  for (i = 0; i < home.length; i++) {
    home[i].className = home[i].className.replace(/^(home--(top|bottom|center)).*/, "$1");
    home[i].className += selfClass == home[i].className ? " active" : " disactive";
  }
};

const disactive = () => {
  for (i = 0; i < home.length; i++) {
    home[i].className = home[i].className.replace(/^(home--(top|bottom|center)).*/, "$1");
  }
};
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

前澤さんの当選発表サイトを考察

前澤さんのお年玉当選発表サイトでわかること

表ではただ単に丁寧語だが、あえて見えないところでは相手を立てて自分をへりくだり謙譲語を使っている。
こういう隠れたところまでこだわるところが好きである。

スクリーンショット 2020-01-20 2.21.39.png

 <!-- お待たせ致しました by 前澤友作 -->
 <div class="text-center pt-1 mb-0">
  <br>
  <img src="./image/yusakumaezawa_01.png" class="rounded" alt="お待たせ致しました by 前澤友作" width="315px">
 </div>
 <!-- お待たせ致しました by 前澤友作 -->
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む