20210116のHTMLに関する記事は13件です。

Luminousが上手く動かない件

ウェブサイトの復旧作業の中で、ギャラリーのページをカスタマイズする作業の中で、jQuery不要なLightboxスクリプトLuminousを知りました。

jQueryを使わないので、小規模のHTMLを手入力で作ったようなウェブサイトのギャラリーページのカスタマイズに最適だと思いました。

でも、下記のコードを設置しても、動かないです。

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/luminous-lightbox@2.3.2/dist/luminous-basic.min.css">
<script src="https://cdn.jsdelivr.net/npm/luminous-lightbox@2.3.2/dist/luminous.min.js"></script>
<script>
new LuminousGallery(document.querySelectorAll('.luminous'));
</script>

複数の画像に対応するため、このコードを使いました。

このコードは、こちらの記事で見つけました。
jQuery不要なLightbox代替スクリプトLuminousが本当に軽量

こちらの記事を読んで、原因が分かりました。
Luminousを適用したいaタグの直下に、このコードを設置する必要があります。
理由は、他のCSSの影響を受けないように、最後にLuminousのCSSを適用させるためです。

luminous がうまく動かない

設置例

<div>
 <ul>

        <li><a class="luminous" href="./img/1_big.jpg"><img src="./img/1.jpg" alt="image" /></a></li>
        <li><a class="luminous" href="./img/2_big.jpg"><img src="./img/2.jpg" alt="image" /></a></li>

    </ul>


    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/luminous-lightbox@2.3.2/dist/luminous-basic.min.css" />
    <script src="https://cdn.jsdelivr.net/npm/luminous-lightbox@2.3.2/dist/luminous.min.js"></script>
    <script>new LuminousGallery(document.querySelectorAll('.luminous'));</script>

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

はじめまして

自己紹介

初めまして、フミといいます。

私は専門学校に通う駆け出しコーダーなのですが、教材やprogateを勉強していて「あれ、実際web作ってみたら見れたものじゃなくね?」と痛感しました。

なので、良かったことであれ悪かったことであれここでアウトプットしようと決めた次第です。

アウトプットするもの

特に縛りもなく雑多に投稿するつもりですが、一応。

・模写コーディングしたもの(著作権による)
・コーディングした感想、反省
・よかったツール等

終わりに

人前に出すことによってリアクションが返ってきたり、日記のようにまた振り返りやすいと思ったりする。それは、自分のスキルの向上とモチベーションの維持につながると思うので頑張ります。

長くなりました。それでは、また。

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

PythonでWordPressに画像付き記事を投稿する

はじめに

WordPressでブログ記事を書く際に、Pythonで集計したグラフを入れてそのままPythonから画像付き記事を投稿出来ないか調べた備忘録です。

PythonからWordPressに投稿する方法

2種類方法があるらしいですが、ここでは Python-wordpress-xmlrpc を使用しました。

python-wordpress-xmlrpc

使用環境

$python -V
Python 3.8.3

インストール

python-wordpress-xmlrpcのインストールはpipでします。
私はAnacondaを使用しているので、本来はcondaでインストールしたいのですが見つかりませんでした。

pip install python-wordpress-xmlrpc

画像付き記事を投稿するサンプルコード

# import
import os
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods import media
from wordpress_xmlrpc.methods.posts import GetPosts, NewPost
from wordpress_xmlrpc.methods.users import GetUserInfo


def upload_image(in_image_file_name, out_image_file_name):
    if os.path.exists(in_image_file_name):
        with open(in_image_file_name, 'rb') as f:
            binary = f.read()

        data = {
            "name": out_image_file_name,
            "type": 'image/png',
            "overwrite": True,
            "bits": binary
        }

        media_id = wp.call(media.UploadFile(data))['id']
        print(in_image_file_name.split('/')
              [-1], 'Upload Success : id=%s' % media_id)
        return media_id
    else:
        print(in_image_file_name.split('/')[-1], 'NO IMAGE!!')


# Set URL, ID, Password
WORDPRESS_ID = "YourID"
WORDPRESS_PW = "YourPassword"
WORDPRESS_URL = "YourURL/xmlrpc.php"
wp = Client(WORDPRESS_URL, WORDPRESS_ID, WORDPRESS_PW)

# Picture file name & Upload
imgPath = "picture.png"
media_id = upload_image(imgPath, imgPath)

# Blog Title
title = "記事タイトル"

# Blog Content (html)
body = """

<p>本文本文本文本文本文本文本文本文本文本文本文本文本文本文</p>

<h2>見出し</h2>

<figure class="wp-block-image alignwide size-large">
<img src="YourURL/wp-content/uploads/year/month/%s" alt="" class="wp-image-%s"/>
</figure>

""" %(imgPath, media_id)

# publish or draft
status = "draft"

#Category keyword
cat1 = 'category1'
cat2 = 'category2'
cat3 = 'category3'

#Tag keyword
tag1 = 'tag1'
tag2 = 'tag2'
tag3 = 'tag3'

slug = "slug"

# Post
post = WordPressPost()
post.title = title
post.content = body
post.post_status = status
post.terms_names = {
    "category": [cat1, cat2, cat3],
    "post_tag": [tag1, tag2, tag3],
}
post.slug = slug

# Set eye-catch image
post.thumbnail = media_id

# Post Time
post.date = datetime.datetime.now() - datetime.timedelta(hours=9)

wp.call(NewPost(post))

課題

画像リンクがもっといい書き方があるのではないかと思いますが、改良方法が見つかれば修正します。

効果

データをPythonで処理してグラフ作成し、そのままグラフ付き記事にしてWordPressに投稿と自動化できるためとても楽です。これから活用していきたいです。

参考サイト

色々な記事を参考にさせていただきました。ありがとうございます。

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

【初心者向け】heightに%が効かない時に確認するポイント

どうも7noteです。heightに%を使っても効かない理由

heightに%(相対値)を使用しても効かない原因、それは・・・

「基準となる要素の高さが絶対指定設定されていないから」

「%」は相対指定となります。そのため**基準となる高さがなければ指定しても効かないのです。

「height」に%を使う方法

index.html
<div class="oya">
   <p>高さに%を使うよ</p>
</div>
style.css
.oya {
  height: 100px;         /* 高さを指定 */
  border: solid 1px #000;/* 1pxの線を引く */
}

p {
  height: 50%;           /* 高さを指定 */
  background: #CCC;      /* 背景色を入れる */
}

sample.png

親要素のdivが100px。
それに対しての50%なので、50px分がp要素の高さになります。

基準になる高ささえあれば親要素に高さが指定されてなくてもよい

index.html
<ul>
  <li>
    あああああああああああああああああああああああああああああああああああああああああああああ
  </li>
  <li>
    あああああああああああああああああああああああああああああああああああああああああ
  </li>
  <li>
    <p>高さに%を使うよ</p>
  </li>
</ul>
style.css
ul {
  display: flex;         /* フレックス要素にする */
  border: solid 1px #000;/* 1pxの線を引く */
}

ul li {
  width: 200px;          /* 横幅を指定 */
}

p {
  height: 50%;           /* 高さを指定 */
  background: #CCC;      /*  */
}

sample2.png

この例だと、pタグの親には何も高さを指定するものがないですが、flexboxは横並びにしたものの高さを揃える特徴があるので、他の要素で高さを指定していなくても、heightに%を指定することができます。

100vhで画面高さいっぱいを指定できる

もし画面全面に出したい時などは100vhを使えば%を使わなくても可能です。

style.css
/* 画面いっぱいのサイズにする */
div {
  width: 100vw; /* ウィンドウ幅いっぱい */
  height: 100vh /* ウィンドウ高さいっぱい */
}

まとめ

widthと同じ要領でheightを指定しがちなのですが、実際には効かない場合があります。
「おや?効いてるかな?」と思ったら、背景色を一時的に入れる等でチェックすることをおすすめします!

おそまつ!

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

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

繰り返し利用可能なドロワーをJavaScriptで書く

See the Pen 繰り返し利用可能なドロワーをJavaScriptだけで書く by 熊瀬川直也 (@momonoki1990) on CodePen.

使い方

  • ドロワーの開閉ボタンに data-drawer-btn="true" data-drawer-target="{ドロワーのid}" をセットする
  • ドロワー本体に id class="drawer" data-drawer="true" をセットする。
  • ドロワーを閉じるボタンに class="drawer" data-drawer-close-btn="true" data-drawer-target="{ドロワーのid}" をセットする

ベタがき

drawer.html
<div id="main">
  <div class="my-drawer1">
    <button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer1">
      開閉ボタン1
    </button>
    <div class="drawer" id="drawer1" data-drawer="true">
      <div>
        <button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer1">x</button>
      </div>
      <div class="drawer-menu">
        <div class="drawer-title">
          ドロワー1です
        </div>
      </div>
    </div>
  </div>
  <div class="my-drawer2">
    <button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer2">
      開閉ボタン2
    </button>
    <div class="drawer" id="drawer2" data-drawer="true">
      <div>
        <button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer2">x</button>
      </div>
      <div class="drawer-menu">
        <div class="drawer-title">
          ドロワー2です
        </div>
      </div>
    </div>
  </div>
  <div class="my-drawer3">
    <button class="drawer-btn" data-drawer-btn="true" data-drawer-target="drawer3">
      開閉ボタン3
    </button>
    <div class="drawer" id="drawer3" data-drawer="true">
      <div>
        <button class="drawer-close-btn" data-drawer-close-btn="true" data-drawer-target="drawer3">x</button>
      </div>
      <div class="drawer-menu">
        <div class="drawer-title">
          ドロワー3です
        </div>
      </div>
    </div>
  </div>
</div>

<style>
  .drawer {
    position: fixed;
    top: 0;
    right: 0;
    padding: 1rem;
    background-color: red;
    width: 300px;
    height: 100%;
    z-index: 100;
    transition: all 0.2s;
    transform: translate(340px);
  }

  .drawer-open {
    transform: translate(0px);
  }

  .drawer-close-btn {
    position: absolute;
    top: 0;
    left: 0;
  }

  .fade-layer {
    position: absolute;
    top: 0px;
    left: 0px;

    width: 100%;
    height: 100%;

    background-color: #000000;
    opacity: 0.5;
    z-index: 99;
  }

  .d-none {
    display: none;
  }
</style>

<script type="text/javascript">

  // フェードレイヤーを生成しておく
  window.addEventListener('DOMContentLoaded', () => {
    const main = document.getElementById('main');
    const fadeLayer = document.createElement('div');
    fadeLayer.setAttribute('id', 'fade-layer');
    fadeLayer.classList.add('fade-layer', 'd-none');
    main.prepend(fadeLayer);
  })



  // フェードレイヤーの表示・非表示切り替え
  toggleFadeLayer = () => {
    const fadeLayer = document.getElementById('fade-layer');
    fadeLayer.classList.toggle('d-none');
  }



  // ドロワーの表示・非表示切り替え
  const toggleDrawer = (event) => {
    const target = event.target;
    const drawerTarget = target.getAttribute('data-drawer-target');
    const drawer = document.getElementById(drawerTarget);
    drawer.classList.toggle('drawer-open');
  }



  // ドロワーの開閉ボタンにクリックイベントを仕込む
  const drawers = document.querySelectorAll('[data-drawer-btn="true"]');
  drawers.forEach((drawer) => {
    drawer.addEventListener("click", (event) => {
      toggleDrawer(event);
      toggleFadeLayer()
    })
  })



  // ドロワーを閉じるボタンにクリックイベントを仕込む
  const drawerCloseBtns = document.querySelectorAll('[data-drawer-close-btn="true"]');
  drawerCloseBtns.forEach(closeBtn => {
    closeBtn.addEventListener('click', (event) => {
      toggleDrawer(event);
      toggleFadeLayer();
    })
  })



  // フェードレイヤーにクリックイベントを仕込む
  // フェードレイヤーがクリックされたらドロワーを閉じて、フェードレイヤーを非表示にする
  window.addEventListener('DOMContentLoaded', () => {
    const fadeLayer = document.getElementById('fade-layer');
    fadeLayer.addEventListener('click', () => {
    const openingDrawer = document.getElementsByClassName('drawer-open')[0];
    openingDrawer.classList.remove('drawer-open');
    fadeLayer.classList.add('d-none');
    })
  })

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

コーディング規則

はじめに

高校生でシステム開発などをしています
現在英単語学習用のアプリを開発しているのですが、もし複数人で開発した時のためと、
後で自分が見たときにわかりやすいコードを書けるようにするため、自分用のコーディング規則を書いておこうと思います。
こうしろ!みたいに書いていたら自分に言っています、強制しているとかじゃないので気にしないでください。
僕は現在angularをメインで使っているので、一部angularでしか使わないような規則も出てきますが気にしないでください。
ts,jsについても本当は一括で書きたいのですが、セキュリティー上の問題から限定公開記事として非公開にさせていただきますorz
まあ、それほどのつよつよエンジニアではないので読みたいと思う方がいるのかというのは怪しいところではありますが、、、

肌間隔ですが、システム開発者の方はhtml,cssを軽視しがちな印象がるので、もしよろしければ参考にしてみて下さい。
またこうしたほうが良いという点がありましたらぜひお教えください。

基本

インデント

インデントは空白2つとする

<div>
  <ul>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

文字

全てのコードは小文字で記述する

<!doctype html>
<html lang="ja">
</html>

HTML

意味のあるHTMLを書く

理解している範囲いいのでで意味のあるコードを書く
(ラジオボタンの役割をdivにさせてjsでcssを付与してimgを表示,非表示してオンオフマークを表示なんてコードを書かないでね!
「な… 何を言っているのかわからねーと思うが、おれも、何をされたのかわからなかった…」(実話))

<section>
  <article>
    <img src="画像のURL" alt="画像の説明">
  </article>
<section>

実体参照

ほんとはUTF-8なら実体参照を使用する必要はないんだろうけど
なんとなく使ってると気分がいいので使います、このルールは無視してもい怒らないよ(未来の自分や英単語アプリのコードを触る人へ)

<p>&copy;xxxx nantoka.com</p>

閉じタグをちゃんと使う

br, hr, img, inputなどの空要素を除きちゃんと閉じタグをする
省略されると落ち着かない天下のgoogle様は省略する派らしいからもう喧嘩

<ul>
  <li>嘘ですgoogle様</li>
  <li>いつも楽しくangularを使わせていただいています</li>
  <li>感謝</li>
<ul>

属性

属性はこの順番で書いてます
ちなみに可読性を上げるための改行は全然ありだと思います

<ng-content
  class
  src
  alt
  type
  name
  id
  for
  value
  placeholder
  data-label
  href
  routerLink
  *ngFor
  *ngIf
  [(ngModel)]
>
</ng-content>

css

命名規則

BEMっぽいものを使っています
これマネするくらいだったらBEMで記述したほうがいいと思います

命名は死ぬほど長くなっても気にしない
outer > wrapper > container > inner > content の順に入れ子にしていく「outer > wrapper」は画面外から
ul > li みたいなときは 〇〇_list > 〇〇_list_item みたいに書く

複数の単語を入れたいときはcamelCase記法を使うex) .lastName

よく使う機能は
u-〇〇

よく使うパーツは
m-〇〇
と書く
(↓こっちの話↓)
そのなかでも特に複数ページで使うものはstyles.scssに書く(こっちの話)
一番最初の要素にはコンポーネント名を使い、それ以降はそれを省略したものを先頭につける

login.component.html
<div class="login">
  <div class="lg_container">
    <div class="lg_container_inner">
      <button class="lg_container_inner_btn m-btn"></button>
    </div>
  </div>
</div>

cssの順番

こんな感じの順番で書いてます
上下左右は上から順に時計回りに指定などなど
まあ常識的にかんがえて決めてくれ

.test {
  // 位置系
  position:;
  display:;
  flex-delection:;
 justify-content:;
 align-items:;
  text-align:;
  width:;
  height:;
  margin:;
  padding:;

  // 色とか大きさとか
  font:;
 font-size:;
 font-weight:;
 font-family:;
  font-color:;
  background:;
  border:;
 border-radius:;
  outline:;
  line-height:;
  text-decoration:;

  // その他
  transform:;
  overflow:;
  cursor:;
  content:;
}

その他

全称セレクタはテンプレートを使う
!importantは極力使わない同じクラスを重ねて優先順位を上げる

終わり

こんかいはこのくらいで
これから定期的に追加するかもしれないししないかもしれないです
tsについてもなんとなくの物も書きたかったのですが、どうしてもハッシュ化についてとか書く必要があり、
公開するべきではないので書けません

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

ほぼ自分用コーディング規則

はじめに

高校生でシステム開発などをしています
現在英単語学習用のアプリを開発しているのですが、もし複数人で開発した時のためと、
後で自分が見たときにわかりやすいコードを書けるようにするため、自分用のコーディング規則を書いておこうと思います。
こうしろ!みたいに書いていたら自分に言っています、強制しているとかじゃないので気にしないでください。
僕は現在angularをメインで使っているので、一部angularでしか使わないような規則も出てきますが気にしないでください。
ts,jsについても本当は一括で書きたいのですが、セキュリティー上の問題から限定公開記事として非公開にさせていただきますorz
まあ、それほどのつよつよエンジニアではないので読みたいと思う方がいるのかというのは怪しいところではありますが、、、

肌間隔ですが、システム開発者の方はhtml,cssを軽視しがちな印象がるので、もしよろしければ参考にしてみて下さい。
またこうしたほうが良いという点がありましたらぜひお教えください。

基本

インデント

インデントは空白2つとする

<div>
  <ul>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

文字

全てのコードは小文字で記述する

<!doctype html>
<html lang="ja">
</html>

HTML

意味のあるHTMLを書く

理解している範囲いいのでで意味のあるコードを書く
(ラジオボタンの役割をdivにさせてjsでcssを付与してimgを表示,非表示してオンオフマークを表示なんてコードを書かないでね!
「な… 何を言っているのかわからねーと思うが、おれも、何をされたのかわからなかった…」(実話))

<section>
  <article>
    <img src="画像のURL" alt="画像の説明">
  </article>
<section>

実体参照

ほんとはUTF-8なら実体参照を使用する必要はないんだろうけど
なんとなく使ってると気分がいいので使います、このルールは無視してもい怒らないよ(未来の自分や英単語アプリのコードを触る人へ)

<p>&copy;xxxx nantoka.com</p>

閉じタグをちゃんと使う

br, hr, img, inputなどの空要素を除きちゃんと閉じタグをする
省略されると落ち着かない天下のgoogle様は省略する派らしいからもう喧嘩

<ul>
  <li>嘘ですgoogle様</li>
  <li>いつも楽しくangularを使わせていただいています</li>
  <li>感謝</li>
<ul>

属性

属性はこの順番で書いてます
ちなみに可読性を上げるための改行は全然ありだと思います

<ng-content
  class
  src
  alt
  type
  name
  id
  for
  value
  placeholder
  data-label
  href
  routerLink
  *ngFor
  *ngIf
  [(ngModel)]
>
</ng-content>

css

命名規則

BEMっぽいものを使っています
これマネするくらいだったらBEMで記述したほうがいいと思います

命名は死ぬほど長くなっても気にしない
outer > wrapper > container > inner > content の順に入れ子にしていく「outer > wrapper」は画面外から
ul > li みたいなときは 〇〇_list > 〇〇_list_item みたいに書く

複数の単語を入れたいときはcamelCase記法を使うex) .lastName

よく使う機能は
u-〇〇

よく使うパーツは
m-〇〇
と書く
(↓こっちの話↓)
そのなかでも特に複数ページで使うものはstyles.scssに書く(こっちの話)
一番最初の要素にはコンポーネント名を使い、それ以降はそれを省略したものを先頭につける

login.component.html
<div class="login">
  <div class="lg_container">
    <div class="lg_container_inner">
      <button class="lg_container_inner_btn m-btn"></button>
    </div>
  </div>
</div>

cssの順番

こんな感じの順番で書いてます
上下左右は上から順に時計回りに指定などなど
まあ常識的にかんがえて決めてくれ

.test {
  // 位置系
  position:;
  display:;
  flex-delection:;
 justify-content:;
 align-items:;
  text-align:;
  width:;
  height:;
  margin:;
  padding:;

  // 色とか大きさとか
  font:;
 font-size:;
 font-weight:;
 font-family:;
  font-color:;
  background:;
  border:;
 border-radius:;
  outline:;
  line-height:;
  text-decoration:;

  // その他
  transform:;
  overflow:;
  cursor:;
  content:;
}

その他

全称セレクタはテンプレートを使う
!importantは極力使わない同じクラスを重ねて優先順位を上げる

終わり

こんかいはこのくらいで
これから定期的に追加するかもしれないししないかもしれないです
tsについてもなんとなくの物も書きたかったのですが、どうしてもハッシュ化についてとか書く必要があり、
公開するべきではないので書けません

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

ドラッグ&ドロップされた画像や音声ファイルをインラインimgやaudioタグに変換するツールをつくってみた

HTMLに画像を埋め込みたい場合に、下記のように、URLではなく直接データをBase64エンコードして埋め込むことができます。
<img src="data:image/png;base64,iVBORw0KGgoAAAAN...">

今回は、このタグを簡単に作成できるツールを作ってみました。

インラインimgタグ生成ツール

MIME type image/pngimage/jpeg 1 だけ受け付けるようにしてます。あと、とりあえず1MB以下の制限をつけてます。
【追記】音声ファイル(audio/wavとmp3ファイル(audio/mpeg)のみ)も対応してみました。

See the Pen ImageAndAudioFileBase64Encoder(Under Construction) by kob58im (@kob58im) on CodePen.

参考サイト

参考サイト(画像関連)

参考サイト(Audio関連)


  1. 一度描画してから再エンコーディングする処理となっているので、画質が劣化する可能性があります。音声ファイルの処理のほうを真似れば改善できそうですが、今のところ対応予定はありません。(単純に面倒くさい・・・) 

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

ドラッグ&ドロップされた画像をインラインimgタグに変換するツールをつくってみた

HTMLに画像を埋め込みたい場合に、下記のように、URLではなく直接データをBase64エンコードして埋め込むことができます。
<img src="data:image/png;base64,iVBORw0KGgoAAAAN...">

今回は、このタグを簡単に作成できるツールを作ってみました。

インラインimgタグ生成ツール

MIME type image/pngimage/jpeg だけ受け付けるようにしてます。あと、とりあえず1MB以下の制限をつけてます。

See the Pen ImageFileToBase64(Under Construction) by kob58im (@kob58im) on CodePen.

参考サイト

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

node.jsのモジュールをHTMLで読み込む

背景

HTMLファイルから3rd Partyのnode.jsのモジュールを利用しようとして、「require is not defined」というエラーにぶち当たった。

そこで、node.jsのモジュールをライブラリとしてHTMLに読み込む方法があるかを調べてみたところ、browserifyというものがあるのを知ったので、試してみた。

ちなみに、HTML用のjsファイルが用意されているモジュールもあるっぽいので、その場合は、それをそのまま読み込めばよいと思う。

「require is not defined」エラーについて

例えば、下記のようなhtmlとjsファイルを作ったとき。

test.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Test</title>
  </head>

  <body>
    <p>Test</p>
    <div>
      <textarea id="token" rows="8" cols="120">{hoge: 'hogehoge'}</textarea>
      <textarea id="signed" rows="12" cols="120"></textarea>
    </div>
    <button id="sign">Sign</button>
  </body>

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

</html>
test.js
// 注意:このコードは動作しません。

var jwt = require('jsonwebtoken');    

document.getElementById("sign").onclick = () => {
  const jwt = document.getElementById("token").value;
  const signedJwt = sign(jwt);
  document.getElementById("signed").innerText = signedJwt;
};

function sign(payload) {
  return jwt.sign(payload, 'secret');
}

ブラウザで開くと、見た目はこんな感じ。

image.png

「Sign」ボタンを押すと、上のテキストエリアにあるJSON形式のテキストに署名をして、下のテキストエリアに表示しようとしたコード。

実際には、このコードは動かなくて、以下のようなエラーになる。

image.png

まぁ、当たり前なのかもしれないけど、ただのhtmlなので、require('jsonwebtoken')はエラーになる。

ちなみに、jsonwebtokenはJWTとかに署名できるライブラリで、nodejsであれば「npm install jsonwebtoken」とかでインストール後、上記のような呼び出しで利用できるようになる。

browserifyの利用

ということで、これを動くようにするために、browserifyを使って頑張ってみる。

browserifyは、node.jsのコードをブラウザで動作するようにしてくれるらしい。

最終的にはhtmlとjsだけで動くようにする予定だが、とりあえず、開発にはnode.jsの環境が必要なので環境を作る。

> mkdir browserify
> cd browserify
> yarn init

適当に作ったnode環境のプロジェクト直下に、さきほどのtest.htmlとtest.jsを置く。

続いて、jsonwebtokenをインストール。

> yarn add jsonwebtoken

もちろん、これだけでは状況は変わらない。

ということで、browserifyをインストール。

> yarn global add browserify

browserifyを使って実行してみる。

> browserify test.js -o test2.js

生成された「test2.js」は下記のような感じ。

test2.js
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;...

... (約3万行)

document.getElementById("sign").onclick = () => {
  const jwt = document.getElementById("token").innerText;
  const signedJwt = sign(jwt);
  document.getElementById("signed").innerText = signedJwt;
};

function sign(payload) {
  return jwt.sign(payload, 'secret');
}
},{"jsonwebtoken":208}]},{},[232]);

3万行ぐらいのファイルが生成された。

依存のファイルがすべて一つにまとめられた模様。

test.htmlを以下のように編集して、動作確認。

test.html
<!DOCTYPE html>
<html>
  ...

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

</html>

再度、test.htmlをブラウザで開いてみる。

image.png

「Sign」ボタンを押すと、署名されたっぽい文字列が表示された。

とりあえず、それっぽいものが表示されたけど、何か変な気もする。

このままだと、デバッグしようにも、test.jsを書き換えるたびに、browserifyでファイル生成が必要となる。

やはり「jsonwebtoken」部分だけをライブラリとしてhtmlに読み込んで、test.jsから利用するようにしたい。

node.jsのモジュールをライブラリとしてHTMLで読み込む

ということで、「jsonwebtoken」をライブラリとしてHTMLで読み込める形に出来ないか試してみた。

色々試行錯誤してみたところ、下記のようなjsファイル(jsonwebtoken-wrapper.js)を用意し、browserifyをかけることで、それっぽく動作した。

jsonwebtoken-wrapper.js
(function (factory) {
  typeof define === 'function' && define.amd ? define(factory) :
  factory();
}((function () { 'use strict';

  // 以降に、元のライブラリのI/Fをそのままそのまま呼び出すだけのfuntionを追加

  var jwt = require('jsonwebtoken');

  function sign(payload, secretOrPrivateKey, options, callback) {
    return jwt.sign(payload, secretOrPrivateKey, options, callback);
  }

 function verify(jwtString, secretOrPublicKey, options, callback) {
    return jwt.verify(jwtString, secretOrPublicKey, options, callback);
  }

  function decode(jjwt, options) {
    return jwt.decode(jwt, options);
  }

  // 以降で外から呼び出せるように定義する。
  if (window) {
    if (typeof window.define == "function" && window.define.amd) {
      window.define("jwt_sign", function() {
        return sign;
      });
      window.define("jwt_verify", function() {
        return verify;
      });
      window.define("jwt_decode", function() {
        return decode;
      });
    } else {
      window.jwt_sign = sign;
      window.jwt_verify = verify;
      window.jwt_decode = decode;
    }
  }

})));

browserifyを使って、htmlから読み込み可能にしておく。

> browserify jsonwebtoken-wrapper.js -o jsonwebtoken.js

jsonwebtoken.jsというファイルが生成される。

test.htmlは、下記のように修正。

test.html
<!DOCTYPE html>
<html>
  ...
 <body>
    <script src="./jsonwebtoken.js"></script>
    ... 
  </body>

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

</html>

ライブラリとして、生成したファイルを読み込むようにした。

また、さきほど、test2.jsに変更した部分をtest.jsに戻しておく。

test.jsは以下のように書き換え。

test.js
// var jwt = require('jsonwebtoken'); この行を削除

...

function sign(payload) {
  return jwt_sign(payload, 'secret'); // jwt.sign(..)をjwt_sign(..)に変更
}

ブラウザにtest.htmlを表示して確認。

image.png

とりあえず正しく動作している模様。

ちなみに、「test.html」、「test.js」、「jsonwebtoken.js」の3つだけを適当なフォルダにおいて実行しても、同じように動作した(nodeから切り離された環境でも動作した)。

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

ProgateでHTML,CSSを学んでみた(3日目)

概要

Web開発に興味が出てきたのでとりあえず一通り必要そうなものを触ってみることにしました。
ただ触るだけだと忘れてしまいそうなのでメモとして学んだことを書いてみます。
ここにあるコードはほぼ全てProgateで出てきたものです。

<head>要素の中身

<head>要素はには以下の要素が含まれる。

  1. 文字コードの指定
  2. ページのタイトルの設定(ブラウザのタブに表示される)
  3. CSSの読み込み

書き方は以下。
link rel="stylesheet"でCSSを読み込むよ!と宣言

<head>
<meta charset="utf-8">
<title>Progate</title>
<link rel="stylesheet" href="stylesheet.css">
</head>

Webページのレイアウト

<div>でbody要素の中にレイアウトを構成する。
divはdivisionの略で要素をグループ化するために使用される。
これを使って、ヘッダー、メイン、フッターの要素を作る。

<div class="header">
</div>
<div class="main">
</div>
<div class="fotter">
</div>

ヘッダーの作り方

ヘッダーの中にロゴとリストを作ってみる。

  <div class="header-logo">
    LOGO
  </div>
  <div class="header-list">
      <ul>
          <li>fuga</li>
          <li>moge</li>
  </div>

リストに黒点をつけない方法

CSSに以下のように書くと黒点がつかない

hoge.css
    li{
      list-style: none;
    }

要素を横並びにする

要素を横並びにするにはfloat:leftをCSSで指定する。
floatの種類は3種類あり、left、right、noneである。
以下のURLにfloatで引っかかりそうな罠が乗っていた。
floatした要素の下に別の要素を配置したいときはclear:leftが必要みたい。
https://udemy.benesse.co.jp/design/web-design/css-float.html

hoge.css
    .header-logo {
        float: left;
        font-size: 36px;
     }

余白を入れる

余白を入れるにはCSSでpaddingを追加する。
paddingは上下左右に入れることができ、以下のように書く。

hoge.css
    .hoge{
        padding-top:20px;
        padding-right:10px;
        padding-bottom:30px;
        padding-left:5px;
    }

以下のように書くと左から、上右下左(上から時計回り)の順に余白のサイズを指定することができる。

hoge.css
    .hoge{
        padding:20px 10px 30px 5px;
    }

また、以下のように書くと、上下に20px、左右に10pxを指定することができる。

hoge.css
    .hoge{
        padding:20px 10px;
    }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】クリックしたときにポップアップを表示する

イメージ図

ポップアップ.png

HTML

<button id="click-btn">クリック!</button>
<div id="popup-wrapper">
  <div id="popup-inside">
    <div id="close">x</div>
      <div id="message">
      <h2>あの人気のマンガが...</h2>
      <p>今なら80%オフ!</p>
      <a href="#">ゲットする</a>
    </div>
  </div>
</div>

CSS

#click-btn {
  display: block;
  margin: 20px auto;
  background-color: purple;
  color: white;
  border: 0;
  padding: 6px 10px;
}

#popup-wrapper {
  background-color: rgba(0, 0, 0, .5);
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: none;
}

#popup-inside {
  text-align: center;
  width: 100%;
  max-width: 300px;
  background: white;
  margin: 10% auto;
  padding: 20px;
  position: relative;
}

#message a {
  background: purple;
  color: white;
  text-decoration: none;
  padding: 6px 10px;
}

#close {
  position: absolute;
  top: 0;
  right: 5px;
  cursor: pointer;
}

JavaScript

const clickBtn = document.getElementById('click-btn');
const popupWrapper = document.getElementById('popup-wrapper');
const close = document.getElementById('close');

// ボタンをクリックしたときにポップアップを表示させる
clickBtn.addEventListener('click', () => {
  popupWrapper.style.display = "block";
});

// ポップアップの外側又は「x」のマークをクリックしたときポップアップを閉じる
popupWrapper.addEventListener('click', e => {
  if (e.target.id === popupWrapper.id || e.target.id === close.id) {
    popupWrapper.style.display = 'none';
  }
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel】投稿機能をていねいに。

投稿機能を実装

投稿機能のビュー、コントローラー、モデルの実装をしたので自分用にメモ。
作っているアプリ:日本酒のレビュー投稿アプリを作成中

以下3つのファイルを編集しました。
①review.blade.php(ビュー)
②ReviewsController.php(コントローラー)
③Review.php(モデル)

フォーム自体はこちら↓。

image.png
※画像投稿、保存に関しては後日機能を追加する予定なので今回は省きます。

まず最初に!

・HTMLタグのnamevalueはサーバーサイド側で処理を行う上で重要!これがあればOKと言っても過言ではないくらい大事。
→私はinput要素にvalueをつけず、
nameがテーブルのカラムと一致しない値のため修正しました。
カラム;image、html:review_image

ビューの編集

<div class="md-form">
        <label class="wf-mplus1p">日本酒名</label>
        <input type="text" name="title" class="form-control" required value="{{ old('title') }}">
    </div>

    <div class="nihonshu-image pl-5">
        <label class="nihonshu-image  wf-mplus1p">画像</label>
        <input type="file" name="image" accept="image/jpeg, image/png"  class="mx-auto pt-3">
    </div>


    <div class="taste-ev ">
        <label class="taste-evl pl-5 wf-mplus1p">味の濃さ</label>
        <div class="ratebutton text-center">
            <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="taste_intensity" value="1">
                <label for="1">1</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="taste_intensity" value="2">
                <label for="2">2</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="taste_intensity" value="3" checked>
                <label for="3">3</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="taste_intensity" value="4">
                <label for="4">4</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="taste_intensity" value="5">
                <label for="5">5</label>
            </div>
        </div>
    </div>


    <div class="scent-evl">
        <label class="taste-evl pl-5 wf-mplus1p">香りの強さ</label>
        <div class="ratebutton text-center">
                <div class="md-radio md-radio-inline d-inline">
                <input  type="radio" name="scent_strength" value="1" checked>
                <label for="1">1</label>
                </div>
                <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="scent_strength" value="2" checked>
                <label for="2">2</label>
                </div>
                <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="scent_strength" value="3" checked>
                <label for="3">3</label>
                </div>
                <div class="md-radio md-radio-inline d-inline">
                <input type="radio" name="scent_strength" value="4">
                <label for="4">4</label>
                </div>
                <div class="md-radio md-radio-inline d-inline">
                <input  type="radio" name="scent_strength" value="5">
                <label for="5">5</label>
                </div>
        </div>
    </div>


    <div class="comp-evl">
        <label class="taste-evl pl-5 wf-mplus1p">総合評価</label>
        <div class="ratebutton text-center">
            <div class="md-radio md-radio-inline d-inline">
            <input  type="radio" name="evaluation" value="1">
            <label for="1">1</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
            <input type="radio" name="evaluation" value="2">
            <label for="2">2</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
            <input  type="radio" name="evaluation" value="3" checked>
            <label for="3">3</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
            <input type="radio" name="evaluation" value="4">
            <label for="4">4</label>
            </div>
            <div class="md-radio md-radio-inline d-inline">
            <input  type="radio" name="evaluation" value="5">
            <label for="5">5</label>
            </div>
    </div>
    </div>

    <div class="form-group">
        <label></label>
        <textarea name="content" required class="form-control wf-mplus1p" rows="4" placeholder="メモ">{{ old('body') }}</textarea>
    </div>


コントローラー編集

?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Review;

class ReviewsController extends Controller
{

    public function index()
    {
        return view('top.index');
    }


    public function create(Request $request)
    {
        $inputs = $request->all();

        // $inputsが空じゃなかったら実行
        if ( !empty($inputs) ) {
            // ログイン中のユーザーIDを取得
            $current_user_id = Auth::user()->id;

            $value = [
                'user_id'         => $current_user_id,
                'title'           => (string) $inputs['title'] ?? '',
                'content'         => (string) $inputs['content'] ?? '',
                'taste_intensity' => (int) $inputs['taste_intensity'],
                'scent_strength'  => (int) $inputs['scent_strength'],
                'evaluation'      => (int) $inputs['evaluation'],
                'image'           => (string) $inputs['image'],
            ];
            Review::create($value);
        }
        return view('top.index');
    }
}


ポイント

・createメソッドの作成
$request->allで全てを取得
!empty$inputsが空ではない場合に実行するよ、という関数。
 逆はempty
$current_user_idでログインユーザーidを取得
$valueでレコードのカラム型に応じた連装配列を作る
・Reviewモデルに渡す
・投稿し終わったらtop.indexを表示
★ (int)によって型チェックを行う
★ ?? ''を設定してもし絵文字などint型以外の入力があった場合は空白にする

モデル編集

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Carbon\Carbon;

class Review extends Model
{
    protected $table = "reviews";

    // ★idカラムの更新・挿入はさせない
    protected $guarded = ['id'];

    // ★自動でupdated_atとcreated_atをレコード挿入時に入れてくれる
    public $timestamps = true;


    /* ----- リレーション ----- */
    public function user(): BelongsTo
    {     
        return $this->belongsTo('App\User');
    }
}

 ポイント

★ idカラムの更新や挿入ができないようにする
★ 自動でupdated_id,created_atをレコード挿入時に入れる

無事DBにも保存できました〜〜!

スクリーンショット 2021-01-16 0.42.05.png

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