20190310のHTMLに関する記事は12件です。

セキュリティ対策のため、target="_blank"のa タグに "noopener noreferrer"のrel属性を自動で付与するjavascript文

image.png
(”寝る人”さんのブログより、とてもわかりやすい画像を引用させていただきました)

脆弱性

target="_blank"のaタグには脆弱性があります。

遷移先から遷移元のページを不正に操作したり、オブジェクトにアクセスしたりできてしまいます。
これによって、フッシング詐欺攻撃を行う余地を生んでしまいます。

サイトで rel="noopener" を使用して外部アンカーを開く(Google Developers)

監査が重要である理由
target="blank" を使用して任意のページから別のページにリンクしている場合、リンク元のページとリンク先のページは同じプロセスで動作します。 そのため、リンク先のページで負荷の高い JavaScript が実行されていると、リンク元のページのパフォーマンスが低下するおそれがあります。
また、target="
blank" にはセキュリティ上の脆弱性もあります。リンク先のページでは window.opener を使用して親ウィンドウのオブジェクトにアクセスしたり、window.opener.location = newURL によって親ページの URL を変更したりできます。

対策

対策としては、target="_blank"を指定しいるaタグのrel属性に"noopener noreferrer"オプションを付与すれば良いです。

まずnoopenerですが、このオプションを指定することで「別タブの遷移先から、window.openerを参照できなくなる(≒不正操作ができなくなる)」という効果があります。
そのため、基本的な対策は noopenerだけで問題ありません。

しかし、Edgeなどの一部のブラウザではnoopener自体がサポートされていないこともあります。
その場合の対策としてnoreffererを指定することで、同じような挙動を実現することが可能です。

noreffererを指定することで、「遷移先のリソースからリファラーを送らないようにブラウザに指示を出す」ことが可能です。
そのため、noopener noreferrerの両方をしていすることが望ましいわけです。

ちなみに、rel属性をはじめ各ブラウザのオプション対応については以下のWebサービスで確認をすることができます。

Can I use... Support tables for HTML5, CSS3, etc

背景

既存のWebページ内で、target="_blank"オプションを指定したaタグが複数存在していました。

Reactであれば、eslintで危険なtarget="_blank"オプションが弾かれたり、wordpressであれば自動で上記のrel属性が付与されるようになっているので、あまり気にすることはありません。

しかし、生のhtmlで記述されたLPでは上記のようにデフォルトでtarget="_blank"を警戒することはできません。
ひとつひとつのaタグにrel属性を付与したりチームの規約にするのも大変なので、javascriptで自動的に属性を付与してあげるのが一番良さそうです。

スクリプト文

// aタグの中身を分解
var aTags = [].slice.call(document.getElementsByTagName('a'));

// 未対応であるIEを除外するため、ブラウザの種別を洗う
var userAgent = window.navigator.userAgent.toLowerCase();
var isIE = (~userAgent.indexOf('msie') || ~userAgent.indexOf('trident'));

function addRels() {
  if (!isIE) { //IEは弾く
    aTags.forEach(function (el) {
      if (el.target === '_blank') {
        var rels = el.rel.split(' ');
        if (!~rels.indexOf('noopener')) {
          rels.push('noopener');
          el.setAttribute('rel', rels.join(' ').trim());
        }
        if (!~rels.indexOf('noreferrer')) {
          rels.push('noreferrer');
          el.setAttribute('rel', rels.join(' ').trim());
        }
      }
    });
  }
};
// 関数を実行
addRels();

少しだけ解説

!~rels.indexOf(文字列)では、いわゆる「ビット反転演算子」を利用しています。

indexOfは「文字列が見つかれば文字列が見つかった場所(0以上)」を、「文字列が見つからなければ-1」を返します。
この挙動を利用し、「-1をビット反転演算子にかけ、0を返す」→「if文で0が真と判定される」という文字列マッチングの仕組みを実現しています。

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

IME(全角)入力におけるjsイベント現状調査

この記事で対象としているブラウザはChrome(mac/win), Safari(mac), Firefox(mac/win), Edge(win) の最新バージョンで、以降これらをモダンブラウザと表記する。

tl;dr

  • Safariで全角入力におけるJSイベントの挙動がおかしかったため調査したところ、仕様(draft含む)上はInputEventだけで判定できそうで期待したが、現状の挙動はベンダー毎に異なった
    • 本命のinputEvent.isComposingはSafari/Edgeで対応してなかったりChrome/Firefoxでも挙動が違って使い辛い
    • inputEvent.inputTypeは使える場面がありそう
  • CompositionEventはモダンブラウザ全てに実装されており最も有用
    • inputイベントと組み合わせる場合はFirefoxのcompositionendイベントの発火順に注意
  • KeyboardEvent.isComposingはEdge以外のモダンブラウザで実装され、特にkeyupイベントでの値は各ブラウザで揃っていた

仕様

UI EventsのW3C Working Draft(8 November 2018)の入力とイベント発火の表が非常にわかりやすい

ただ標準仕様に対するベンダーの実装が必ずしも仕様に則しきれていないのは2019年も相変わらず。

InputEvent

  • 仕様上はinputTypeisComposingプロパティでIME入力状態を判別可能
    • ただしisComposingはSafari未実装
    • そしてChrome/Firefoxで挙動が異なる(下記参照)
  • inputTypeのENUM値はInput Events Level 2の仕様(draft)を参考
  • dataプロパティでマルチバイト判定する手もあるが、現状Safari/Chromeのみ

モダンブラウザのinputType/isComposing/data

  • 入力に対するinputType(string)/isComposing(boolean)/data(string)の値を記載
    • -はundefined
  • Edge(win)はどちらのプロパティもないため省略
入力 Chrome Firefox Safari
1(全角、未確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/true/- 'insertCompositionText'/-/'1'
Enter(上記確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/false/-1 'deleteCompositionText'/-/null
'insertFromComposition'/-/'1'
2(半角) 'insertText'/false/'2' 'insertText'/false/- 'insertText'/-/'2'
  • 全角入力がinputType: 'insertCompositionText'で半角入力がinputType: 'insertText'であることは共通
  • Enter押下での確定には一貫性がない
    • compositionendイベント発火前にinputイベントが発火した場合にisComposing: true。つまりChromeとFirefoxとでcompositionendの発火タイミングが異なる(後述)
    • safariはinputイベント発火数が他のブラウザより多い
  • マウスで確定させた場合は、Chrome/Safariでは確定時にinputイベントは発火しない一方、FirefoxではEnterと同じ値で発火した

CompositionEvent

IMEによるテキスト編集監視に用いるイベント。半角入力時は当然発火しない。

KeyboardEvent

キーボード操作、keydown/keyupイベントで監視

  • if (KeyboardEvent.keyCode === 229)でIME入力を判定しているスクリプトを見かけるがKeyboardEvent.keyCodeはDeprecated
  • Enter押下を検知して力技で......
    • IME確定以外でのEnter押下を区別できるのか疑問
    • ライブ変換とか確定に必要なEnter回数はIMEの設定によって異なる気がする
    • マウスからの確定は当然検知できない
    • とはいえIEサポートしたいならこれしかない?
  • KeyboardEvent.isComposingの実装はEdge以外は済んでいる
    • このbool値の仕様はinputEvent.isComposing同様、compositionstartとcompositionendの間がtrueでそれ以外はfalse
    • しかしSafariだけ下表の通り異なる
    • だがkeyupは揃っており、判定には有益
    • KeyboardEventの発火順は各ブラウザともW3Cの仕様に即している

入力に対するイベント発火の流れ

  • 値はEvent.type
  • 太字はisComposingがtrue
  • Edgeでのマウスクリック確定の方法がわからず未調査
入力 Chrome Firefox Safari Edge
1(全角、未確定) keydown keydown keydown keydown
compositionstart compositionstart compositionstart compositionstart
compositionupdate compositionupdate compositionupdate compositionupdate
input input input keyup
keyup keyup keyup input
Enter押下で確定 keydown keydown keydown compositionend
compositionupdate compositionend input
input input input
compositionend keyup compositionend
keyup keyup
マウスクリックで確定 compositionend compositionend compositionend ?
input1 ?

その他の手段

changeイベント

  • 入力確定後のEnter押下やfocusが外れた時に発火
  • 入力時にリアルタイムに処理したい場合には使えない

Appendix

調査スクリプト

  • 単純に各イベントリスナーにconsole.logを入れるだけだとダメ
    • ロギング順と発火順が同じとは限らない
  • 各種Eventオブジェクトのtimestampを見てsortして表示
check_inputEvent.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
<body>
<input id="x"/>
<button id="y">out</button>
<script>
var stores = [];
var store = ({timeStamp, type, isComposing, inputType, data, key}) => {
  stores.push({timeStamp, type, isComposing, inputType, data, key});
};
var x = document.getElementById('x');
var y = document.getElementById('y');
x.addEventListener('input', store);
x.addEventListener('keyup', store);
x.addEventListener('keydown', store);
x.addEventListener('compositionstart', store);
x.addEventListener('compositionupdate', store);
x.addEventListener('compositionend', store);
y.addEventListener('click', (e) => {
  console.table(stores.sort((a, b) => a.timeStamp > b.timeStamp));
});
</script>

調査背景

  • 入力値に対してフォーマットした値を再代入するJSを書いた
    • 例えば、郵便番号入力欄で、全角半角問わずリアルタイムに3桁目と4桁目の間にハイフンを補ってあげる処理
  • Safariのみ全角入力時に重複入力される現象が起きた
    • 下記は全角1234と入力した場合の挙動

safari_bug.gif

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
<body>
<input id="x"/>
<script>
var formatFn = (v) => v.replace(/^([^-]{3})([^-]{1,})/, '$1-$2');
var inputElement = document.getElementById('x');
inputElement.addEventListener('input', (e) => {
  e.target.value = formatFn(e.target.value);
});
</script>

全角入力は確定までフォーマットしない、という方針なら、例えばinputイベント部分を下記のようにすればモダンブラウザ対応可能

let isComposing = false;
inputElement.addEventListener('compositionstart', (e) => {
  isComposing = true;
});
inputElement.addEventListener('input', (e) => {
  if (!isComposing) {
    e.target.value = formatFn(e.target.value);
  }
});
inputElement.addEventListener('compositionend', (e) => {
  e.target.value = formatFn(e.target.value);
  isComposing = false;
});

またはinputTypeをみる(Edgeでは常にundefinedだが重複入力問題はSafariのみ)

inputElement.addEventListener('input', (e) => {
  if (e.inputType !== 'insertCompositionText') {
    e.target.value = formatFn(e.target.value);
  }
});

イベントリスナーの確認

何故Safariだけ上記バグがあるのか、Safari(を含むモダンブラウザ)のコンソールではgetEventListeners(node)というAPIが使えるので調べて見たが、特に異常はなかった。

safari_api.png

またmonitorEvents(document)2で発火イベントを全体的に監視してみた。SafariではtextInputイベントが全角確定時の一度だけ発火し、Chromeではinputイベントが全角入力の度に発火していた。
(念の為inputElement.removeEventListener('textInput', listener);してみたが効果なし)

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

IME(全角)入力におけるjsイベント現状調査

ブラウザの対象はChrome(mac/win), Safari(mac), Firefox(mac/win), Edge(win) の最新バージョンのみ

tl;dr

  • 全角入力におけるJSイベントについて調査し、仕様(draft含む)上はInputEventだけで判定できそうで期待したが、現状の挙動はベンダー毎に異なった
    • 本命のinputEvent.isComposingはSafari/Edgeで対応してなかったりChrome/Firefoxで挙動が違って使い辛い
    • inputEvent.inputTypeは使える場面がありそう
  • 現状はCompositionEventの方が安定しているが、やはりブラウザによって挙動は異なった

仕様

UI EventsのW3C Working Draft(8 November 2018)の入力とイベント発火の表が非常にわかりやすい

ただ標準仕様に対するベンダーの実装が必ずしも仕様に則しきれていないのは2019年も相変わらず。

InputEvent

  • 仕様上はinputTypeisComposingプロパティでIME入力状態を判別可能
    • ただしisComposingはSafari未実装
    • そしてChrome/Firefoxで挙動が異なる(下記参照)
  • inputTypeのENUM値はInput Events Level 2の仕様(draft)を参考
  • dataプロパティでマルチバイト判定する手もあるが、現状Safari/Chromeのみ

モダンブラウザのinputType/isComposing/data

  • 入力に対するinputType(string)/isComposing(boolean)/data(string)の値を記載
    • -はundefined
  • Edge(win)はどちらのプロパティもないため省略
入力 Chrome Firefox Safari
1(全角、未確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/true/- 'insertCompositionText'/-/'1'
Enter(上記確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/false/- 'deleteCompositionText'/-/null
'insertFromComposition'/-/'1'
2(半角) 'insertText'/false/'2' 'insertText'/false/- 'insertText'/-/'2'
  • 全角入力がinputType: 'insertCompositionText'で半角入力がinputType: 'insertText'であることは共通
  • Enter押下での確定には一貫性がない
    • compositionendイベント発火前にinputイベントが発火した場合にisComposing: true。つまりChromeとFirefoxとでcompositionendの発火タイミングが異なる(後述)
    • safariはinputイベント発火数が他のブラウザより多い
  • マウスで確定させた場合は、Chrome/Safariでは確定時にinputイベントは発火しない一方、FirefoxではEnterと同じ値で発火した(後述)
入力 Chrome Firefox Safari
1(全角、未確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/true/- 'insertCompositionText'/-/'1'
Enter(上記確定) 'insertCompositionText'/true/'1' 'insertCompositionText'/false/- 'deleteCompositionText'/-/null
'insertFromComposition'/-/'1'
check_inputEvent.html
<html>
<head>
  <meta charset="utf-8">
<body>
<input id="x"></input>
<script>
document.getElementById('x').addEventListener('input', console.log);
</script>

CompositionEvent

IMEによるテキスト編集監視に用いるイベント

入力に対する発火イベントの種別を記載

入力 Chrome Firefox Safari Edge
1(全角、未確定) compositionstart compositionstart compositionstart
compositionupdate compositionupdate compositionupdate
input input input
Enter押下で確定 compositionupdate compositionend input
input input input
compositionend compositionend
マウスクリックで確定 compositionend compositionend compositionend
input
2(半角) input input input

その他の手段

changeイベント

  • 入力確定後のEnter押下やfocusが外れた時に発火
  • 入力時にリアルタイムに処理したい場合には使えない

KeyboardEvent

keydown/keyupイベントで頑張る

  • if (KeyboardEvent.keyCode === 229)でIME入力を判定しているスクリプトを見かけるがKeyboardEvent.keyCodeはDeprecatedなので注意
  • KeyboardEvent.isComposingがIME確定状態判定に使えそうだが、現状こちらも未対応ブラウザが多く決定力に欠ける
  • Enter押下を検知して力技で......
    • IME確定以外でのEnter押下を区別できるのか疑問
    • ライブ変換とか確定に必要なEnter数はIMEの設定で異なるけど大丈夫?
    • マウスからの確定は?
  • とはいえIEサポートしたいならこれしかない?

調査の背景

  • 入力値に対してフォーマットした値を再代入する下記のようなJSを書いた
    • 例えば郵便番号入力欄で、リアルタイムで3桁目と4桁目の間にハイフンを補うなど
  • Safariのみ全角入力時に重複入力された
before.js
inputElement.addEventListener('input', (e) => {
  e.target.value = formatFn(e.target.value);
});

例えば今回の調査結果を加味すると下記のように書ける(ベストプラクティスかは自信ないが......)

after.js
inputElement.addEventListener('input', (e) => {
  if (e.inputType !== 'insertCompositionText') {
    e.target.value = formatFn(e.target.value);
  }
});
inputElement.addEventListener('compositionend', (e) => {
  e.target.value = formatFn(e.target.value);
});
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング初心者がUdemyを使って勉強してみた。(前編)

・初学者がUdemyで2日間フロントを勉強してみた(前編)

まず自己紹介

  • 6ヶ月前にプロゲートをやってみるも2日も続かず挫折
  • 某プログラミングスクールに1ヶ月通う事にするも、通学がきつく挫折×2
  • 人口知能に興味を持ち、自分も人工知能のWebサービスを作りたい!と奮起してドットインストールのプレミアム会員になるも1週間で挫折、、×3

.しかしまたあることがきっかけでまたプログラミングに挑戦。。。

プログラミングに何度も打ち拉がれた筆者がなぜまたプログラミングに挑戦したか。

  1. 気づいたら最新の言語や、テクノロジーについて調べていたから。
  2. 正社員になってみたが向いていない為、転職する、or フリーランスとして稼ぐ為。
  3. まなブログさんのブログに影響された。
  4. やっぱエンジニアかっこいいって思った。

そんな理由で再びチャレンジ!!だが、、、

フリーランスとして稼げるようになるには大体200時間くらい必要らしい、スクールに通うお金もない、、、

Web記事を漁っているとUdemyというサービスがあるということを発見。『んーYouTubeの広告で出てくる、pythonエンジニアが長々と話しているあれか、、』と思ったが、まあとりあえず調べてみるか、とサービスを見てみると、、、 

『なんやこれ、、めっちゃ面白いやん、、某pythonエンジニアのSさんの動画めちゃ面白いやん!』ということで、再びプログラミングに挑戦。

pythonいいけど、やっぱり稼げるようになるにはやっぱフロントからという記事を見つけたのでとりあえずUdemyのフロント(HTML、CSS、Javascript,jQuery,ruby)の動画を購入。

学習内容

・とりあえず200時間の学習を最短でクリアできるための学習計画

  • 毎日通算4.4時間フロントエンドについて学習する
  • HTML、CSS、Javascript、jQueryに絞って学習
  • 毎日Qitaに記事をあげる

とりあえず土日で学習してみた結果、感想。

・1日目マックで通算6時間13分学習。(HTML基礎)
・2日目ココスの朝食バイキングでバカ食いしながら5時間24分学習。(HTML応用)

あれ?意外と楽しくないか?なんか前より楽しく、学習できている、、果たしてこれが気のせいなのか、、

次回へ続く。

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

無料でiOSでシンプルなWebアプリを作ってアイコンをホーム画面に設置する方法

はじめに

iOSでシンプルなWebアプリを作って、アイコンをホーム画面に設置する方法です。HTMLとCSS、JavaScriptを使用してアプリを作ることができます。簡単なツールなどであればこれで十分です。

ちなみに、Swiftを使ってアプリ開発をする場合でも、実機テストは無料ですることができます(ただし有効期限は1週間で、1週間ごとに延長が必要)。
誰でも無料でiPhoneの実機を使ってiOSアプリ開発する方法 - Qiita などを参照。

テンプレート

data:text/html;charset=utf-8,
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link rel="apple-touch-icon" href="アイコンのURL">
<title>アプリのタイトル</title>
<style>*{-webkit-tap-highlight-color: rgba(0, 0, 0, 0); -webkit-touch-callout: none; -webkit-user-select: none;}</style>

-webkit-tap-highlight-color: rgba(0, 0, 0, 0); : リンクタップ時のグレーの影をOFF
-webkit-touch-callout: none; : 長押しでのメニュー呼び出しの無効化
-webkit-user-select: none; : テキスト選択の無効化

ステータスバーの色

<meta name="apple-mobile-web-app-status-bar-style" content="default">

<meta name="apple-mobile-web-app-status-bar-style" content="black">

透明

<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

追加する方法

  1. この作成した長いテキストをSafariで開く(Macの場合はHandoffでコピーするのが便利)
  2. Safariの画面下の共有ボタンから、ホーム画面に追加 を選ぶ

注意点

デスクトップ版ChromeやFirefoxで動作確認する場合は、すべての #%23に置換してください。でないと正常に表示されません。
参考:https://qiita.com/shge/items/325b3c4fc95b9190c9cd

参考文献

ウェブページをできる限りネイティブアプリっぽく魅せるテクニックまとめ 〜アップルにリジェクトされつづけるなら、ウェブアプリとストアをつくって自前で配信してしまおうという企み〜 - KAYAC engineers' blog
https://techblog.kayac.com/2016/12/12/090000

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

【GAS】Font Awesome でくるくる回るローディングアイコンを実装する

目的

何らかの処理を行っている間だけローディングアイコンを出したい。

外部ライブラリを使ってもできるのですが、デザインがいまいちしっくり来なかったので、FontAwesomeのローディングアイコンをつかって実装しました。

Fontawesomeとは

ウェブサイトでよく使いそうなアイコンを無料で提供してくれるサービスです。(有料プランもありますが今回は無料プランのアイコンを使います)

https://fontawesome.com

動作

名称未設定.mov.gif

ボタンを押したら何らかの処理が走って、処理が終了するまでローディングアイコンがくるくる回ります。

ソース

HTML
 <!-- ボタン -->
 <button>ここを押すと何らかの処理が始まる</button>

 <!-- ローディングアイコン -->
  <div class="loading">
    <i class="fas fa-spinner fa-5x fa-spin"></i>
  </div>

css
.loading {
  display: none; /* 通常時は非表示 */
  z-index: 1;
  position: fixed;
  top: 50%;
  left: 50%;
  color: gray;
}
javascript
  $('button').on('click', function(){
    // ローディングアイコンを表示
    $('.loading').css('display', 'block');

    // doSomethingでなにか処理を実行し、処理が終わったらダイアログを出す
    google.script.run
    .withSuccessHandler(function(){
      $('.loading').css('display', 'none');
      alert('成功しました');
    })
    .doSomething();
  });
GoogleAppsScript
  function doSomething(){
    // なにかする
    return true;
  }

解説

まずHTML側でローディングアイコンを用意しておきます。
classにfa-spinを指定することでアイコンがくるくる回ります。

 <!-- ローディングアイコン -->
  <div class="loading">
    <i class="fas fa-spinner fa-5x fa-spin"></i>
  </div>

しかし、用意したアイコンはCSSからdisplay:none;で非表示にしておき、ボタンが押されたタイミングでdisplay:block;にし、画面上に表示させます。

ローディングアイコンを表示させたら、その後行いたい処理をdoSomething()で実行、終わったらアイコンをdisplay:none;で消して、ダイアログを表示します。

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

CSSで吹き出しを作成する方法

HTMLとCSSで簡単な吹き出しを作成する方法をメモ書き程度に残しておきます。
もともと、Wordpressでやっているブログのちょっとしたデザイン変更で書いたけれど、何となくいらなくなった。
デモは以下のような感じ。

【デモデザイン】 CSSで作る吹き出しデザイン

Create_a_new_fiddle_-_JSFiddle.png

html

<p>
  <span class="check-point-ballon">
    Point
  </span>
  吹き出しを作成したよ
</p>

css

.check-point-ballon {
  background-color: #415cf5;
  padding: 9px;
  color: white;
  border-radius: 9px;
  text-align: center;
  position: relative;
  margin-right: 10px;
}

.check-point-ballon::before {
    content: '';
    position: absolute;
    right: -22px;
    border-style: solid;
    border-width: 13px;
    border-color: transparent transparent transparent #415cf5;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

data:text/htmlから始まるデータスキームが動作しないときの対処法

以前までメモ帳などの簡単なWebアプリを data:text/html から始まるデータURIスキームを使用して作れたのですが、それが Chrome 72 から動作しなくなっています。

原因

Treat '#' as ending data URI body content (removed)
https://www.chromestatus.com/feature/5656049583390720

URL内での # は本来は指定したIDを持つ要素へ飛ぶようにするものです。例えば index.html#foo というURLであれば、foo をIDに持つ要素にジャンプします。しかし、Chromeではそれをデータスキーム内では無視していました。
そのおかげでデータスキームを使用したWebアプリが作れていたのですが、それらがアップデートにより動作しなくなってしまいました。

これは、データスキームの # 以降が無視されることによって発生します。
例えば data:text/html,<html><style>body{color:#ddd}</style><p>test を開くと、color:#ddd に含まれる # 以降が無視されて、test という文字列が描画されません。

Firefox は以前から # 以降を無視するようになっていましたが、Safari(2019/3/10現在)は # 以降もそのまま描画します。

対処法

URL内に含まれるすべての # をエスケープして %23 とすればOKです。
お使いのテキストエディタや テキスト操作ツール などを使って一括置換するだけです。

参考文献

データスキームメモ帳の注意
Treat '#' as ending data URI body content - Chrome Platform Status

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

data:text/htmlから始まるデータスキームが動作しないときの対処法 (原因は#)

以前までメモ帳などの簡単なWebアプリを data:text/html から始まるデータURIスキームを使用して作れたのですが、それが Chrome 72 から動作しなくなっています。

原因

Treat '#' as ending data URI body content (removed)
https://www.chromestatus.com/feature/5656049583390720

URL内での # は本来は指定したIDを持つ要素へ飛ぶようにするものです。例えば index.html#foo というURLであれば、foo をIDに持つ要素にジャンプします。しかし、Chromeではそれをデータスキーム内では無視していました。
そのおかげでデータスキームを使用したWebアプリが作れていたのですが、それらがアップデートにより動作しなくなってしまいました。

これは、データスキームの # 以降が無視されることによって発生します。
例えば data:text/html,<html><style>body{color:#ddd}</style><p>test を開くと、color:#ddd に含まれる # 以降が無視されて、test という文字列が描画されません。

Firefox は以前から # 以降を無視するようになっていましたが、Safari(2019/3/10現在)は # 以降もそのまま描画します。

対処法

URL内に含まれるすべての # をエスケープして %23 とすればOKです。
お使いのテキストエディタや テキスト操作ツール などを使って一括置換するだけです。

参考文献

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

個人または家族で使える自宅用のWebポータルシステム「MyHome Portal」

PHPで作成した個人または家族で使える自宅用のWebポータルシステム「MyHome Portal」をオープンソース/フリーソフトとして公開しています。
2008年から2016年にかけて、こつこつとバージョンアップを繰り返して作成したものです。
中級プログラマの作品ですので、ソースコードはあまりきれいとは言えません。バージョンアップを繰り返したことでコードがきたなくなってしまっている部分もあります。モジュールの構造を複雑にしすぎたかもしれません。
2016/08/02以降、バージョンアップしていません。Webサービスを利用している機能など一部は、Webサービスの停止等の理由により動作しなくなっています。

公開ページ

https://ok2nd.github.io/myportal/

ブログ

最近、更新はほとんどありません。
中級プログラマの自宅でPHP ブログ

コンセプト

  • 自宅でポータルとして使えるシステム。(家庭内グループウェア)
  • データはインターネット上ではなく、ローカルPCまたはローカルサーバに保管。
  • 初級、中級プログラマにも理解可能なシステム。
  • PHP、SQL、JavaScript、HTML、CSSの知識だけで理解可能なシステム。
  • PHPの良さを生かしたHTMLインラインコーディング。(なるべくprint文を使わない。)
  • ブラックボックスの少ないシステム。
  • オブジェクト指向型プログラミングを使わない。手続き型(関数型)プログラミングを採用。
  • MVCを使わない。
  • フレームワークに頼らないシステム。
  • テキストエディタ以外の開発ツールを必要としない。

対象者

  • 自分または家族専用のWebポータルサイトが作りたい。
  • Webポータルサイトをインターネット上ではなく、ローカルPCまたは自宅サーバーで立ち上げたい。
  • 日常的に良く使う機能が、個々のアプリケーションを起動せずに、ブラウザの中で出来たらうれしい。
  • スケジュールその他自分の個人情報をインターネット上に置きたくない。
  • パスワードなどのID情報をインターネット上に置きたくない。
  • Webプログラム開発初心者。
  • プログラミングを仕事でなく、趣味でやりたい。
    • オブジェクト指向が苦手。
    • MVCは面倒。
    • システム全体を把握したい。(ブラックボックスは少ない方が良い。)
    • フレームワークを使いたくない。(PHP、SQL、JavaScriptだけで開発したい。)

機能一覧

  • ホームページインデックス(ブックマーク)&検索
    • ブログパーツ貼り付け
  • 付箋
  • カレンダー(スケジューラ)
    • 天気出現率表示
  • 旅行記
  • ToDo
  • 掲示板
  • RSSリーダー
  • メモ
  • フォトアルバム
    • スライドショー
    • 動画サムネイル
    • FLV,MP4,WMV,MPG,MOV,M2TS(AVCHD)動画再生
  • 学習
  • 住所録
    • PDF葉書宛名書き
  • メール(一括受信)
  • SVGお絵かき
  • ペン画
  • チャット(Chat)
  • ID・パスワード管理
  • GPSログ(GPX)ビューワ
  • 預貯金管理
  • 縦計だけの表計算
  • HTML URL抽出&ファイルダウンロード
  • テキスト縦書き表示
  • Excel to グラフ
  • ソースコード表示&編集+ファイルマネージャー
  • MySQL管理ツール
  • ファイル暗号化/復号化
  • タイマーアラート

特徴・補足

  • 自宅で個人や家族で使えるシステムを目指して作りました。家庭内LANでの利用を想定しています。
  • 少人数の会社のイントラでの利用も可能かもしれません。 セキュリティは万全ではないので、スケジュール共有など機能を限定して利用願います。
  • ユーザー登録など、インターネット上での利用を想定した機能も付けています。ただし、セキュリティ等保障はできませんので、インターネット上での実利用は、自己責任にてお願いいたします。あくまで、LAN内またはPC単体での利用を想定しています。
  • 簡単なユーザー管理機能もあります。
  • 認証機能もあります。
  • ユーザー単位で他のユーザーに対して参照・書込の権限設定ができます。
  • レコード単位での非公開の設定もできます。
  • ただし、システム管理者はデータベースを直接見ることで全ての情報を参照ができてしまいますので、悪用しないように。
  • ID管理では、二重の認証が必要なしくみにしています。
  • ID管理では、パスワードを独自の方式で暗号化しています。ID情報は、2つのテーブルに分割して保存します。 暗号化のキーと2つのテーブルを別々にバックアップすれば、ID情報の復元はしづらい(?)と思います。
  • 簡単なログ機能も付けています。
  • 簡単なシステム管理者機能も付けています。
  • コンテンツを追加しやすい構造にしています。
  • ページ分割有りの一覧形式のページを簡単に作れる共有ライブラリを用意しています。一覧形式での編集もできます。 /myhome/common_/include-common-mp-list.php 各コンテンツのlist.php、category.phpを参考にしてください。
  • 一覧形式の表示部分のみを、独自のphpソースに置き換えられます。($mp_list_arg['template_view'])

開発環境

  • (Ver.3.27以降)XAMPP 1.7.1 (Windows)

    • Apache 2.2.11
    • MySQL 5.1.33 (Community Server)
    • PHP 5.2.9 + PEA
  • (Ver.3.26以前)XAMPP 1.6.6a (Windows)

    • Apache 2.2.8
    • MySQL 5.0.51a
    • PHP 5.2.5
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【マテリアルデザイン】Materializeを使ってみよう。

マテリアルデザイン with Materialize

Webページのデザインをどうするか。

案の1つとして、マテリアルデザインがあります。

マテリアルデザインを簡単に作れるCSS Frameworkは色々ありますが、その中でも有名なMaterializeというものを使ってみます。

MaterializeはCSSとJavaScriptを組み合わせて使いますので、どちらも読み込んでください。

Materialize ←公式サイトはこちらになります。

CDN形式でも使えますし、ダウンロードしても使えます。
ちょっと試しに使ってみるときにCDNって便利ですよね。

この記事ではお試しレベルで使う方法を書いていってみます。

  • ナビゲーション
  • カラー
  • ボタン
  • グリッドレイアウト
  • カード

ナビゲーション

シンプルナビゲーション

sample.html
  <nav>
    <div class="nav-wrapper">
      <ul>
        <li><a href="#">サンプルナビ</a></li>
        <li><a href="#">左メニュー1</a></li>
        <li><a href="#">左メニュー2</a></li>
        <li><a href="#">左メニュー3</a></li>
      </ul>
        <ul class="right">
          <li><a href="#">HTML5</a></li>
          <li><a href="#">CSS</a></li>
          <li><a href="#">JavaScript</a></li>
      </ul>
    </div>
  </nav>

Nav1.png

➡ 解説

ご覧のとおりで、nav-wrapperというクラスで囲ってやると、その部分が横ナビになります。
rightで囲った部分は、右寄せになります。これだけで結構おしゃれなナビっぽくなりますね。

ドロップダウン入りナビゲーション

sample.html
  <nav>
    <div class="nav-wrapper">
      <ul>
        <li><a href="#">サンプル</a></li>
        <li><a href="#" class="dropdown-trigger" data-target="submenu1">ドロップダウン</a></li>
        <li><a href="#">メニュー2</a></li>
        <li><a href="#">メニュー3</a></li>
      </ul>
      <ul class="right">
        <li><a href="#">HTML5</a></li>
        <li><a href="#">CSS</a></li>
        <li><a href="#">JavaScript</a></li>
      </ul>
      <ul id="submenu1" class="dropdown-content">
        <li><a href="#">サブメニュー1</a></li>
        <li><a href="#">サブメニュー2</a></li>
        <li class="divider" tabindex="-1"></li>
        <li><a href="#">サブメニュー3</a></li>
      </ul>
    </div>
  </nav>
sample.js
$(document).ready(function(){
  $('.dropdown-trigger').dropdown({
      coverTrigger:false
    }
  );
})

nav-dropdown.png

➡ 解説

ここから少し気を付けるところが出てきます。
JavaScriptを使ってやらないといけなくなるのでご注意を。
Materializeでは、各種アクションを加えたい場所に対して、明示的にJavaScriptで設定してあげる必要があります。
今回の例であれば、まずhtmlファイルの中で、Dropdownアクションを加えたい場所に対して、.dropdown-triggerというCSSクラスを設定しています。
そして、.dropwon-triggerクラスに対して、JavaScriptでドロップダウン効果を持たせる設定をしています。
.dropdown()という関数によって、ドロップダウン効果を持たせられるのですが、このとき様々なオプションが設定できます。
今回はcoverTrigger:falseというオプションを設定しており、これによってトリガーボタンよりも下にドロップダウンメニューが出る、となっております。
coverTrigger:trueにすると、トリガーボタンに覆いかぶさるようにドロップダウンメニューがでます。
この方式はひとつのページ内でオプションが異なるドロップダウンボタンを複数配置したい場合でも、設定がしやすくてよいですね。

ちなみにですが、私はjQuery使ってますけど依存はしていないので、別にjQuery使わなくてもよいです。

追記予定

  • グリッド
  • フォーム関連
  • モーダル
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Wordpressに、jQueryプログラムを反映させたい

やりたいこと

wordpressにチェックリスト(html,css,javascrpitで作成したもの)を反映したい。

以下のようなプログラムを作成しました。だだしデザインは未完成です

プログラム機能
  ・6個のチェックボックスがあります。[図1]
  ・ それぞれのチェックボックスに、チェックするかしないか自分で、入れます。
  ・チェックが終わったら、送信ボタンを押します。

 送信のした後、
 チェックしたチェックボックスが3個以上だと赤信号
 1、2個だと黄色信号[図2]
 0個だと 青信号

[図1]
スクリーンショット 2019-02-12 21.02.27.png

[図2]
スクリーンショット 2019-02-12 21.04.41.png

プログラムのコード内容(ローカル環境で動くプログラム)

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Input to page</title>

    <link rel="stylesheet" href="style.css">

    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>

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

  </head>
 <body>
<div>
    <h1>健康診断</h1>
    <ul>
    <li>aの問い<input type="checkbox" id="check1"></li>
    <li>bの問い<input type="checkbox" id="check2"></li>
    <li>cの問い<input type="checkbox" id="check3"></li>
    <li>dの問い<input type="checkbox" id="check4"></li>
    <li>eの問い<input type="checkbox" id="check5"></li>
    <li>fの問い<input type="checkbox" id="check6"></li>
    <input type="button" id="Button" value="送信">
    <br>
    </ul>

  <p><div id="output"><div></p>
</div>    
 </body>
</html>

style.css
ul, ol {
  background: #fffcf4;
  border-radius :8px;/*角の丸み*/
  box-shadow :0px 0px 5px silver;/*5px=影の広がり具合*/
  padding: 0.5em 0.5em 0.5em 2em;
}
ul li, ol li {
  line-height: 1.0;
  padding: 0.5em 0;
}

h1 {
  background: #b0dcfa; /*背景色*/
  padding: 0.5em;/*文字周りの余白*/
  color: white;/*文字を白に*/
  border-radius: 0.5em;/*角の丸み*/
}

main.js
$(function() {
  $("#Button").click(function() {

    var count = 0;

    if ($("#check1").prop("checked")) {
      count += 1;
    }
    if ($("#check2").prop("checked")) {
      count += 1;
    }
    if ($("#check3").prop("checked")) {
      count += 1;
    }
    if ($("#check4").prop("checked")) {
      count += 1;
    }
    if ($("#check5").prop("checked")) {
      count += 1;
    }
    if ($("#check6").prop("checked")) {
      count += 1;
    }

    if (count >= 4) {

      $("#output").text("赤信号");

    }
    else if (count >= 1) {
      $("#output").text("黄色信号");
    }
    else {
      $("#output").text("青信号");
    }


  });

});

wordpressにjqueryのプログラムに反映させたい。(調査編)

 調べた結果、2つのやり方で反映させることが可能だと知った

   ・直接コードを打つ

   ・プラグインで設定する
    ->結果プラグインを入れなくても

まず直接コードを打ち込むことにした。

->結果動かない
理由は、jqueryコードだから。

javascrpitだと直接いけます。

下のURLは、wordpressにjavascrpitコードを反映させる記事です。

https://routecompass.net/post-838/#JavaScript

なんとかなりそう

やり方発見

jqueryを反映させる記事を見つけました

http://primarytext.jp/blog/1298

要約すると以下通りです。

WordPressでjQueryを使いたいのに動かない時は、「jQuery(function($){ });」で前後を囲んでカプセル化してやれば簡単です。
これで囲むと、その中では「$」が使えますので、サンプルコードもそのままコピーすれば動きます。カプセル化した中には普通のjQueryの書き方でOKです。特に修正は必要ありません。

実際のコード

qiita.rb
<meta http-equiv="content-type" charset="utf-8">

<div>
    <h1>健康診断</h1>
    <ul style="background:#fffcf4;">
    <li>aの問い<input type="checkbox" id="check1"></li>
    <li>bの問い<input type="checkbox" id="check2"></li>
    <li>cの問い<input type="checkbox" id="check3"></li>
    <li>dの問い<input type="checkbox" id="check4"></li>
    <li>eの問い<input type="checkbox" id="check5"></li>
    <li>fの問い<input type="checkbox" id="check6"></li>

    <br>
    </ul>
    <input type="button" id="Button" value="送信">

  <p><div id="output"><div></p>
</div>
<div>

<script type="text/javascript">
jQuery(function($){
  $("#Button").click(function() {
    var count = 0;
    if ($("#check1").prop("checked")) {
      count += 1;
    }
    if ($("#check2").prop("checked")) {
      count += 1;
    }
    if ($("#check3").prop("checked")) {
      count += 1;
    }
    if ($("#check4").prop("checked")) {
      count += 1;
    }
    if ($("#check5").prop("checked")) {
      count += 1;
    }
    if ($("#check6").prop("checked")) {
      count += 1;
    }
    if (count >= 4) {
      $("#output").html("<b>赤信号です。</b> 至急体重減らす");
      $("div b").append(document.createTextNode("!!!"))
            .css("color", "red");
    }
    else if (count >= 1) {
      $("#output").html("<b>黄色信号です。</b> 体重減らす");
      $("div b").append(document.createTextNode("!!!"))
            .css("color", "yellow");
    }
    else {
      $("#output").html("<b>青信号です。</b> 体重維持");
      $("div b").append(document.createTextNode("!!!"))
            .css("color", "blue");
    }
  });
});
</script>



参考文献

https://routecompass.net/post-838/

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