@fugaco

ガントチャートで予定と実績バーを並べてみました

Workaround for addTaskLayer (Displaying Additional Elements in the Timeline Area)


使っているガントチャートのライブラリ dhtmlxGantt から新しいバージョンがリリースされ、丁度欲しかった「予定と実績」を両方描く機能が追加されました。が、なんとそれは有料版のみの実装でした。この人も待っていただろうに…。


というわけで、無料版の機能で同じような物を自作しました。なんだ、簡単にできるじゃないですか。

こちらが公式の実装サンプル。下は私の実装サンプルです。青いバーが予定(デフォルトで描かれるもの)、オレンジのバーが実際の進捗(自作するもの)ということにしました。

20140917_1.png


必要なコードは以下です。


1. タスクのデータに「実際の開始日」と「実際の終了日」の項目を自作します。

自作なので名前は何でもよいです。

var tasks = {
    "data":[
        {
            "id":1,
            "text":"タスクの名前",
            "start_date": new Date(ほにゃらら),     // 予定開始日
            "end_date": new Date(ほにゃらら),       // 予定終了日
            "actual_start": new Date(ほにゃらら),   // 実際の開始日
            "actual_end": new Date(ほにゃらら)      // 実際の終了日(なくても可)
        },
        ...
    ]
};



2. actual_startactual_end の日付を変換します。

公式の説明によると、start_dateend_date は自動で変換しているそうなので、それに倣います。タスクが読み込まれたとき(ガントチャート描画前)に実行されるイベントを追加します。そしてこのデータを後のイベントに引き渡したいので、actual 変数に入れておきます。

var actual = [];
gantt.attachEvent("onTaskLoading", function(task){
    actual.push({
        id: task.id,
        actual_start: gantt.date.parseDate(task.actual_start, "xml_date"),
        actual_end: gantt.date.parseDate(task.actual_end, "xml_date"),
    });
    return true;
});



3. 実際のバー(オレンジ色)を描画します。

ガントチャートが描画されたときに呼び出されるイベントを追加します。getTaskPosition 関数に「タスク情報(たぶん使っているのはタスクID)」「開始日」「終了日」を渡すと、描画するバーの position: absolute 位置(top、left)と大きさ(width、height)を返してくれるので、それを使ってdiv要素を作り、予定のバーと同じ要素(.gantt_bars_area)に突っ込みます。実際のバーにはclass名を「gantt_task_line_actual」とでも付けておきます。

gantt.attachEvent("onGanttRender", function(){
    if(actual.length === 0) return;
    var html = [];
    var task;
    var position;
    var div;
    for(var i in actual) {
        task = actual[i];
        if(task.actual_start) {
            if(!task.actual_end) task.actual_end = today;
            position = gantt.getTaskPosition(task, task.actual_start, task.actual_end);
            div = document.createElement('div');
            div.className = 'gantt_task_line_actual';
            div.style.width = position.width + 'px';
            div.style.top = position.top + 'px';
            div.style.left = position.left + 'px';
            html.push(div);
        }
    }
    $('.gantt_bars_area').append(html);
});


4. 予定のバーと実際のバーをスタイリングする

あとはCSSの調整です。2つのバーをデフォルトよりも細くして位置を合わせます。あと、リンクの矢印の位置を少し上に上げて、青いバーとつながるようにしました。他にも使っている機能によってはCSSの追加調整が必要かもしれません。

gantt.config.row_height = 27;   // 一行の高さ
gantt.config.task_height = 12;  // 予定のバーの高さ


.gantt_task_line {
    margin-top: -5px;
}
.gantt_task_line_actual {
    margin-top: 16px;
    height: 8px;
    opacity: 0.6;
    background: #ffd180;
    border-radius: 2px;
    border: 1px solid rgb(255,153,0);
    box-sizing: border-box;
    position: absolute;
}
.gantt_task_link{
    position: relative;
    top: -5px;
}

それではまた。

IE10/11からアクセスすると、Apache server 2.4.6 が応答しなくなる問題

私の環境は Windows Apache 2.4.9 ですが、IE11からアクセスするとなぜか動かなくなり、毎度再起動しなくてはいけないので困っていました。解決方法を見つけたので共有します。

Apache server 2.4.6 hangs after serving requests from Internet Explorer 10/11
http://stijndewitt.wordpress.com/2014/01/10/apache-hangs-ie11/

以下翻訳です。


-----

症状:
Windows で動かしている Apache 2.4 が、IE10/11でアクセスしたときに、応答しなくなる

再現方法:
私の時はこのように再現してました。IEからの最初のリクエストはうまく行きますが、それ以降の全てのブラウザからのリクエストに応答しなくなりました。IEを使いさえしなければこの問題は起こらないようですが、ひとたびIEを使うと、Apache を再起動するまで何も応答しなくなりました。これを修正したあと(方法は下にあります)他のテストをしようと修正を戻したら、とても不思議なのですが、同じ問題が再現しなくなりました…

再現環境:
これらについてはよく分かりませんが、この問題が起こった時に使用した設定を共有しようと思います。なにか知っている人がいれば教えてください。

Windows 7
Apache: 2.4.6
VMWare network drivers installed (see explanation for why this might be relevant)
PHP: php-5.5.5-Win32-VC11-x64
ブラウザ: Internet Explorer 11
その他: Twitter Bootstrap, MySQL

原因:
Windows NT 向けに最適化された Apache のマルチプロセッシングモジュール日本語訳)のせいで起こったように思います。この問題と修正方法について説明しているサイトをを下に載せたので参考にしてください。

修正方法:
この定義を Apache24/conf/httpd.conf に追加してください。ファイルの最後がいいと思います。

# Apparently this fixes an issue with Apache 2.4.6 on Windows hanging
# when serving requests from Internet Explorer 10/11.
# see http://stijndewitt.wordpress.com/2014/01/10/apache-hangs-ie11/
AcceptFilter http none
AcceptFilter https none


解説:
Apache のドキュメントによると、AcceptFilter はこう書かれています。
From the Apache docs about AcceptFilter:

This directive enables operating system specific optimizations for a listening socket by the Protocol type.

On Windows, none uses accept() rather than AcceptEx() and will not recycle sockets between connections. This is useful for network adapters with broken driver support, as well as some virtual network providers such as vpn drivers, or spam, virus or spyware filters.
参照:

-----


記事に書いてあるように、httpd.conf にコードを足して再起動したらなおりました。そしてそのコードを削除して再起動しても、同じ問題は起こらなくなりました。コメントまで読めばなぜだか理由を教えてくれている人もいるかもしれません。

InstallShieldでインストーラを作ったときのtips

先月 InstallShield 11 という有料ソフトを使って、とあるプロジェクトのインストーラを作りました。インストーラの開発は初めてでしたが、ヘルプドキュメントと、Google先生(英語)を頼りに完成させることができました。

Google先生(日本語)では解決方法が見つからないものが多かったので、誰かのためにここに少し書いておこうと思います。今回はとりあえず2つだけ。



複数のコンポーネントを別々のフォルダへインストールする方法

InstallShield にはあらかじめ、TARGETDIR というシステム変数が用意されています。この TARGETDIR にインストール先のパス(SdAskDestPath ダイアログなどでユーザーにインストール先を入力してもらう)を代入しておくと、コンポーネントが自動的に TARGETDIR にインストールされます。

ところが複数のコンポーネントを別々のフォルダにインストールしたい時は、TARGETDIR 変数1つでは足りません。無理やり PROGRAMFILES を使っている人もいるようですが、PROGRAMFILES はプログラムフォルダ(C:\Program Files)のパスなので、上書きするのはあまりよくありません。同じ問題にぶつかり、Microsoft のサイトで質問している人がいましたが、残念ながら解決していませんでした。

インストール先を複数指定するには、TARGETDIR ではない変数を作り、それをコンポーネントの「インストール先」に指定すればよいです。


20140908_1.png


この例では TARGETDIR_PHP という変数を作りました。この変数にパスを保存するには、次のようにします。

ComponentSetTarget( MEDIA, "<TARGETDIR_PHP>", szDirPHP );


szDirPHP には、SdAskDestPath ダイアログでユーザーに入力してもらったパスを入れておきます。このままインストールを続行すると、TARGETDIR_PHP に保存したパスに、このコンポーネントがインストールされます。この値はレジストリに保存されているので、アンインストール時にも使えます。

TARGETDIR_PHP に入っている値を取得したいときは、次のようにします。

TextSub.Value( "TARGETDIR_PHP" )


直接 TARGETDIR や TARGETDIR_PHP を参照しても、正しい値は取れません。



アンインストール時に、ファイルなどを消されないようにする方法

InstallShield では、インストール時に作成したフォルダやファイルが全部記録され、アンインストール時に自動的に削除されるようになっています。ところが、インストール時に作成したファイルが、新規作成ではなく上書き作成だった場合でも、アンインストール時に消えてしまうので困ることがあります。

例えば、PostgreSQL をコマンドラインから実行する場合に使う %APPDATA%\postgresql\pgpass.conf(パスワードを保存しておく隠しファイル)ですが、インストール時にこのファイルを作成すると、すでに同名ファイルが存在していた場合でも、アンインストール時に削除されてしまいます。

これを回避するには、別名でファイルを作成してからファイル名を変更する、という方法があります。pgpass.conf.dummy という名前でファイルを作成した後に、pgpass.conf というファイル名に変更(RenameFile)するのです。そうすると、アンインストール時には pgpass.conf.dummy というファイル名をアンインストールするようになるので、pgpass.conf は残ったままになります。

Windows の環境変数の場合も同様です。例えばPHPをインストールした場合では、PHPフォルダへのパスを通すため、Path変数に「C:\php;」を追記しますよね。このときPath変数を上書き登録していると、アンインストール時にPath変数自体が削除されてしまいます。そうすると C:\Windows\System32 などへのパスモ全て無くなってしまうので、とても困ったことになります。環境変数には名前変更用の関数が無いので、この場合はアンインストール後にPath変数を登録しなおす必要があります。OnMaintUIBefore(アンインストール処理前に実行される処理)とOnMaintUIAfter(アンインストール処理後に実行される処理)に、以下のような処理を追加します。

#define REGISTRY_PATH_KEY    "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
#define REGISTRY_PATH_NAME    "Path"
#define REGISTRY_PATH_TYPE    REGDB_STRING_EXPAND

(OnMaintUIBefore内)
    RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
    szKey = REGISTRY_PATH_KEY;
    nvType = REGISTRY_PATH_TYPE;
    szName = REGISTRY_PATH_NAME;
    szEnvPath = "";

    // 環境変数取得
    nResult = RegDBGetKeyValueEx (szKey, szName, nvType, szEnvPath, nvSize);
    put_env_path(szEnvPath);

(OnMaintUIAfter内)
    RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
    szKey = REGISTRY_PATH_KEY;
    nvType = REGISTRY_PATH_TYPE;
    szName = REGISTRY_PATH_NAME;
    szEnvPath = get_env_path();

    // 環境変数登録
    nResult = RegDBSetKeyValueEx(szKey, szName, nvType, szEnvPath, -1);
    if(nResult < 0) then
        MessageBox("環境変数「PATH」の設定に失敗しました。手動で以下のように変更してください。\n" +
                    szEnvPath, WARNING);
    else
        // レジストリをすべてのアプリケーションにフラッシュ。
        szEnv = "環境";  
        pEnv = &szEnv;
        SendMessage (HWND_BROADCAST, 0x001A, 0, pEnv );
    endif;


(put_env_path と get_env_path は自作のプロパティ関数です。)

インストーラの作成って結構おもしろいですね。
それではまた~。

JavaScriptや画像を使わずにカラムの高さを揃える方法(IE8~)

どうもー。明日は社内イベントでみなとみらいのナイトクルーズに乗ってきます。社員の家族も呼ぶので、楽しみです。

さてさて、Webサイトで横にカラムを並べるデザインってよくありますよね。JavaScriptや画像(data uriも)は一切使わずに間に線を引いたり背景色をつけるサンプルを紹介します。この記事の最後のサンプルは、退職した社員からこのサイトを教えてもらいました。


HTML例

<div class="wrap">
<div class="left">
左のカラム
</div>
<div class="center">
   中央のカラム(3カラムのときのみ)
</div>
<div class="right">
    右のカラム
</div>
</div>


■線を描くだけ


線を描くだけなら簡単です。


サンプル1

カラムの線を重ねる方法です。
左のカラムには右に線を引き、右のカラムには左に線を引き、marginでずらして重ねます。そうすると、長い方の線が下まで伸びるので、同じ色の線にしておけば、間に一本線が引かれたように見えます。

20140807_1.png


.wrap{
background: #eee;
overflow: hidden;
}
.wrap>div{
width: 50%;
float: left;

/* padding込みで幅指定できるようにする */
padding: 10px;
box-sizing: border-box;

/* 線の幅の分左にずらす */
margin-left: -1px;
/* 右のカラムには左に線を引く */
border-left: 1px solid #00f;
}
.wrap>div:first-child{
/* 左のカラムには右に線を引く */
border-left: 0;
border-right: 1px solid #f00;
}


メリット
  • 簡単
デメリット
  • 3カラム以上では使えない

サンプル2

カラムの線を描くためだけの別要素を用意する方法です。
別要素とはいっても、HTMLに余計な要素を追加したくないので、疑似要素(:before)を使います。カラムを囲っているラップ要素に position:relative をつけると、ラップ要素の高さに合う線が描けます。カラムに float がかかっているので、ラップ要素には overflow: hidden も必要です。

20140807_3.png


.wrap{
background: #eee;
overflow: hidden;

/* 線の高さを100%で描くため */
position: relative;
}
.wrap>div{
width: 33.3%;
float: left;

/* padding込みで幅指定できるようにする */
padding: 10px;
box-sizing: border-box;
}
.wrap>div:before{
content: '';
display: block;

/* 線の高さを100%で描く */
height: 100%;
border-left: 1px solid #f00;
position: absolute;
top: 0;
/* 一番左のカラムの線を隠す(paddingも考慮) */
margin-left: -11px;
}



■背景も塗る


サンプル3(失敗)

カラムのラップ要素に背景グラデーション(background-image)でストライプ模様を描く方法です。
IE8のfilterでは、途中で色を変えることができなかったので失敗です。ていうか激重たい filter を使ってまでやりたくないです。

20140807_2.png


.wrap{
background: #eee;
overflow: hidden;
/* IE8-9 */
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#f0b7a1', endColorstr='#bf6e4e', GradientType=0)";
/* IE10 Consumer Preview */
background-image: -ms-linear-gradient(left, #FFCCDD 0%, #FFCCDD 50%, #CCDDFF 50%, #CCDDFF 100%);
/* Mozilla Firefox */
background-image: -moz-linear-gradient(left, #FFCCDD 0%, #FFCCDD 50%, #CCDDFF 50%, #CCDDFF 100%);
/* Opera */
background-image: -o-linear-gradient(left, #FFCCDD 0%, #FFCCDD 50%, #CCDDFF 50%, #CCDDFF 100%);
/* Webkit (Safari/Chrome 10) */
background-image: -webkit-gradient(linear, left top, right top, color-stop(0, #FFCCDD), color-stop(0.5, #FFCCDD), color-stop(0.5, #CCDDFF), color-stop(50%, #CCDDFF));
/* Webkit (Chrome 11+) */
background-image: -webkit-linear-gradient(left, #FFCCDD 0%, #FFCCDD 50%, #CCDDFF 50%, #CCDDFF 100%);
/* W3C Markup, IE10 Release Preview */
background-image: linear-gradient(to right, #FFCCDD 0%, #FFCCDD 50%, #CCDDFF 50%, #CCDDFF 100%);

}
.wrap>div{
width: 50%;
float: left;

/* padding込みで幅指定できるようにする */
padding: 10px;
box-sizing: border-box;
}



メリット
  • あんまりない
デメリット
  • 古いIEで使えない
  • 処理負荷が高い
  • ブラウザごとに書き方が違って面倒

サンプル4

背景色を塗るためだけの別要素を用意する方法です。
別要素とはいっても、HTMLに余計な要素を追加したくないので、疑似要素(:before)を使います。サンプル2と考え方は同じですね。ただ、疑似要素の横位置を指定するために、全カラムの left を指定しないといけません。ま、JavaScriptや画像を使わないという制限があるので、そのくらいは仕方ないと妥協しましょう。

20140807_4.png


.wrap{
overflow: hidden;
position: relative;
}
.wrap>div{
width: 33.3%;
float: left;

/* padding込みで幅指定できるようにする */
padding: 10px;
box-sizing: border-box;
}
.wrap>div:before{
width: 33.3%;
content: '';
position: absolute;
top: 0;
bottom: 0;
z-index: -1;
}
.wrap>.left:before{
left: 0;
background: #fcd;
}
.wrap>.center:before{
left: 33.3%;
background: #cdf;
}
.wrap>.right:before{
left: 66.6%;
background: #ff9;
}


メリット
  • 他に方法がない…?
デメリット
  • 全カラムの位置指定が面倒くさい
  • 背景色のz-indexがマイナスになるので、他要素との関係によっては調整が必要



それではまた~。

検索した英単語を保存するChrome拡張を作りました

どうも。暑いですね。復職して気がついたらもう半年以上…子供も1歳7ヶ月になっていました。

ちょっと前のことですが、うちの会社の内定者向けサイトの自己紹介で、「趣味:水泳、編み物、アプリ開発」と書きました。以前は他にもいろいろな趣味があったんですが、子どもがいてもできる趣味って言うと限られてきますよね。アプリ開発は週末家にいるときだけ子どもの昼寝中にやっています。毎週できるわけでもなく、できても1~2時間がいいとこなので、亀の歩みです。

で、ちょっと作ってみたいブラウザの拡張機能があったので、その前に練習がてら軽めのアプリを作りました。Google Chromeの拡張機能です。自分用なので、Chromeだけ。

promo_s.png


アルクやその他のオンライン辞書サイトで単語を検索すると、勝手にブックマークしていくものです。

20140725_1.png

私は英単語の検索をすることが多いのですが、検索履歴がほしいとずっと思っていました。だって調べてもすぐ忘れてしまうんですもん。他にも使っている辞書サイトはあるんですが、動作確認をする時間が足りなかったのでとりあえずこれだけです。最初は全部OFFになってるので欲しいものだけONにしてください。
自分用に3時間くらいで作ったので適当なところがありますが、Chromeの拡張機能はすごく作りやすいということが分かりました。別にいらないのにポップアップも作っちゃいました。笑

20140725_2.png

Windows上でフォルダを作って、指定のファイルを作って、それをブラウザで読み込むだけで開発ができます。特別なソフトは何もいりません。そしてウェブストアにアップロードして最初の1回だけ約5ドル払えばいくつでもアプリを公開できます。何かアイディアがある人は作ってみるといいと思います。


Chrome公式サイト
Getting Started: Building a Chrome Extension
https://developer.chrome.com/extensions/getstarted

1/37  | 次のページ »