【AngularJS】コントローラーの変更がビューに反映されない時は$scope.apply();

jQueryのイベントを使ってモデルの値を変更した場合など、ビューに変更が伝わらない場合がある。

具体的には以下のような場合

HTML

<div id="images">
    <div ng-repeat="picture in pictures">
      <div class="img">
        <a target="_blank" href="">
          <img src="{{picture.img_url}}">
        </a>
      </div>
    </div>
</div>
.controller('PictureDetailController', function($scope, $http) {
  $(function() {
      //★初回クリック(jQueryのイベントを使用)
      $('#images').one('click', function() {
          $scope.pictures.push(picture);
      });
  });
}

このような場合は、手動でモデルの変更をビューへ伝える必要がある。 この時に使うのがapply()だ。上記の例を、applyを使ってモデルの変更をビューに伝えるよう修正する。

.controller('PictureDetailController', function($scope, $http) {
  $(function() {
      //初回クリック(jQueryのイベントを使用)
      $('#images').one('click', function() {
          $scope.pictures.push(picture);
          $scope.apply(); ★モデルの変更をビューに伝える
      });
  });
}

これで、ビューにモデルの変更が通知されて、DOMが変化している。

Javascriptを使って5分でできるタブ切り替え

タイトルの通り、手軽にタブ切り替えを実装します。 JavascriptCSSを利用します。

まずはHTML

<!-- トグルボタン -->
<div id="tab">
  <div>
    <input type="radio" class="selected" checked>
    <div>Tab A</div>
  </div>
  <div>
    <input type="radio">
    <div>Tab B</div>
  </div>
</div>

<div class="content_wrap">
コンテンツ1
</div>
<div class="cotent_wrap nodis">
コンテンツ2
</div>

次にJavaScript

$(function() {
    $("#tab input").click(function() {
        var num = $("#tab input").index(this);
        $(".content_wrap").addClass('nodisp');
        $(".content_wrap").eq(num).removeClass('nodisp');
        $("#tab input").removeClass('selected');
        $(this).addClass('selected')
    });
});

ラジオボタンが押されると、nodispクラスが切り替わります。

最後にCSS

.selected {
  background: yellow;
}

.nodisp {
  display: none;
}

.selectedでは、選択されているタブの背景色をyellowに指定しています。 .nodispを非選択状態のcontent_wrapperに付加しています。

Sublime TextでCSSのリアルタイムプレビュー

Sublimeではリアルタイムプレビューがないものだと思い込んで諦めていたところ、ふと見つけたので使ってみたら便利さに衝撃を受けたのでメモ。 ざっくりと使い方をまとめておきます。

導入方法

  1. Sublime Textにプラグイン「LiveStyle」をインストール
  2. Chrome拡張機能Emmet LiveStyle拡張」を追加
  3. リアルタイムプレビューしたいページで、Emmet LiveStyleを有効にして、CSSを編集※

chromeのDeveloper Toolsを編集すると、Sublimeで開いているCSSに適用されるし、Sublimeで開いているCSSファイルを編集すると、ブラウザで開いているページがリアルタイムで変更される。

詳しい使い方は以下

livestyle.io

EmmetLiveStyleでSublimeText3でリアルタイムプレビューが出来て超便利! | Taka's Life

タブパネルでGoogle Mapを表示させる

タブパネルでGoogle Mapを表示させる際、最初に表示されるページにGoogle Mapを設置していれば問題ないが、最初に表示されないタブ内に設置していた場合、initialize処理が別途必要になるので、メモ。

例に2枚タブ構成のスクリプトを示す。

      <div id="tabs" class="tabs">
        <nav>
          <ul>
            <li><a href="#section-1"><i class="fa fa-list-ul">タブ1</i></a></li>
            <li><a href="#section-2" ><i class="fa fa-map-marker">タブ2</i></a></li>
          </ul>
        </nav>
        <div class="content">
          <!-- Time Line view -->
          <section id="section-1">
            <div class="mediabox">
              <h3>最初に表示されるタブ</h3>
            </div>
          </section>

          <section id="section-2">
            <div class="mediabox">
              <h3>Google Mapエリア</h3>
              <div id="map_canvas" style="width:500px; height:300px"</div>
            </div>
          </section>

        </div><!-- /content -->

いつもどおりのGoogle Mapのinitialize処理は以下。

    <script>
      //initialize google map
      function initialize() {
        var latlng = new google.maps.LatLng(35.539001,134.228468);
        var opts = {
          zoom: 13,
          center: latlng,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map(document.getElementById("map_canvas"), opts);
      }
      google.maps.event.addDomListener(window, "load", initialize);
    </script>

今回は、タブ2にGoogle Mapが埋め込まれ、初回ページロード時にinitializeが走らない。 そこで、以下のようにして、初回タブ2クリック時にのみinitializeが実行されるようにスクリプトを追加。

      $(function(){
        $("#map-tab").one(
          'click',
          function(){
            initialize();
          }
        );
      });

これで、初回表示画面以外のタブにGoogle Mapを設置した場合でも、地図が表示されるようになる。

ruby on railsでwheneverでrakeタスクを実行させようとすると”/bin/bash: bundle: コマンドが見つかりません”

railsのタスクスケジューリングgem「whenever」でrakeタスクを登録してログを見てみると、以下のようなエラーが出た。

/bin/bash: bundle: コマンドが見つかりません

どうやら、パスをschedule.rbに登録しておく必要がある。

以下の記述をconfig/schedule.rbの上の方に追加

env :PATH, ENV['PATH']

これでシステムのPATHをそのまま使える

参考までに、scheduler.rbを載せときます。

set :output, "/home/hoge/application/log/whenever.log"
set :environment, :development

env :PATH, ENV['PATH']

every '0,15,30,45 * * * *' do
  rake 'twitter:tweet'
end

ちなみに、wheneverのインストールはここを参考

Wheneverは導入が超簡単なcrontab管理ライブラリGemです![Rails4.2 x Ruby2.3] - 酒と泪とRubyとRailsと

【mecab】hatenaキーワードとwikipediaのタイトルからオリジナルの辞書を作る

mecabデフォルトの辞書では以下のようにちょっと専門用語などが入ってくると解析が不十分

$ mecab
クラウド
クラ    名詞,固有名詞,一般,*,*,*,クラ,クラ,クラ
ウド    名詞,一般,*,*,*,*,ウド,ウド,ウド
EOS

hatenaキーワードやwikiからもっと多くの単語を取り込むことで精度を上げる

wikipediaの辞書をダウンロード

$ curl -L http://dumps.wikimedia.org/jawiki/latest/jawiki-latest-all-titles-in-ns0.gz | gunzip > jawiki-latest-all-titles-in-ns0

はてなキーワードのリスト取得

$ curl -L http://d.hatena.ne.jp/images/keyword/keywordlist_furigana.csv | nkf -w  > keywordlist_furigana.csv

辞書用のCSVにフォーマットを変更するスクリプトを作成

$ vi store_wikipedia_and_hatena_to_csv.rb

require 'csv'

original_data = {
  wikipedia: 'jawiki-latest-all-titles-in-ns0',
  hatena: 'keywordlist_furigana.csv'
}

CSV.open("custom.csv", 'w') do |csv|
  original_data.each do |type, filename|
    next unless File.file? filename
    open(filename).each do |title|
      title.strip!

      next if title =~ %r(^[+-.$()?*/&%!"'_,]+)
      next if title =~ /^[-.0-9]+$/
      next if title =~ /曖昧さ回避/
      next if title =~ /_\(/
      next if title =~ /^PJ:/
      next if title =~ /の登場人物/
      next if title =~ /一覧/

      title_length = title.length

      if title_length > 3
        score = [-36000.0, -400 * (title_length ** 1.5)].max.to_i
        csv << [title, nil, nil, score, '名詞', '一般', '*', '*', '*', '*', title, '*', '*', type]
      end
    end
  end
end

さっきダウンロードしてきたファイルをCSVに出力。

$ ruby store_wikipedia_and_hatena_to_csv.rb

実行するとcustom.csvが作成される

ユーザー辞書を作成する

custom.csvを元に mecab-dict-index コマンドでユーザー辞書 custom.dic を作ります。

$ /usr/lib/mecab/mecab-dict-index -d /usr/lib/mecab/dic/ipadic -u custom.dic -f utf-8 -t utf-8 custom.csv
reading custom.csv ... 1720131
emitting double-array: 100% |###########################################|

done!

これでユーザー辞書は完成

作成した辞書を使ってみる

$ mecab -u custom.dic
クラウド
クラウド        名詞,一般,*,*,*,*,クラウド,*,*,wikipedia
EOS

今度はクラウドが名詞として認識された!

システムとして作成した辞書を使うなら/etc/mecabrcのuserdicに指定しておくこと