function add_comma($str) {
if (preg_match('/"/', $str)) {
$str = preg_replace('/"/', '""', $str);
}
if (preg_match('/[,"]/', $str)) {
$str = '"' . $str . '"';
}
return $str;
}
開発メモ,主に補足by子連れ親父プログラマー
2010-07-26
phpでカンマ区切りのcsvを出力する
ラベル:
php
とりあえず、データの中に改行は含まれない、という前提にしてしまえば比較的楽なのではないかと。
いうことで、暫定版ですが。。
2010-06-25
smartyの{section}関数に渡す配列は0から順番になってないと表示されない
smartyの{section}関数に渡す配列は0から順番になってないと表示されない
今見た感じバージョンはSmarty 2.6.18だけど。
以下のような{section}を使ったループ表示で、
{section name=key loop=$message}
{$message[key]|escape}<br />
{/section}
php側を、
$message = array('123','456','abc');
$o_smarty -> assign("message", $message);
とすると、ちゃんと表示されるが、
$message[3] = '123';
$message[7] = '456';
$message[] = 'abc';
$o_smarty -> assign("emes", $emes);
とすると、何も表示されない。
悩まず、{foreach}に変更すべし。
2010-05-06
jQueryで作るタブのメニュー画面がリンクから飛んできた時も選択した状態にしたい
ラベル:
jQuery
今開発してるシステムでちょっとおもしろそうな題材があったので紹介しておきます。
ソース全部載せると分かりづらいので一部だけで概念的に説明しますが、これはまあ、普通にレフトメニューがあって、そしてメインの部分にはタブでメニューを選択できるようなレイアウトの画面だと思って下さい。
レフトメニューはこんな感じ
<a href="#menu2"> のタブには選択した状態のクラス(selected)をあてたい、しかもレフトメニューからのクリックでも同じ動きができて、レフトメニューはサイト内の他のページにもそのまま(同じまま)設置されるので、他のページから、
<a href="sample.html#menu2"> というリンクで飛んできた時にも menu2 の内容を表示したい、ということなんですね。
んで、最初に送られてきたソースがこんな感じでした。
2行目でタブのクリックを取得して、クリックされたタブについてあれこれ処理しています。
3行目は全てのタブから selected クラスの除去。
4行目は選択されたタブに selected クラスを付加。
5行目は各メニューの内容を一旦全部隠して。
6行目でクリックされたタブの href 属性と同じ id のメニューの内容を表示。
このままでは確かにレフトメニューからクリックされた時も、このページに他のページからリンクで飛んできた時も動きません。
ということで、どうやって、<a href="sample.html#menu2"> の#以下の部分を取得するか、なんですが、とりあえず
あと、jQueryの .attr() の場合は単に、
今回の場合基本的に #menu2 という文字列がキーになっていて、あとはタブ部分のオブジェクトをなにがしか操作すればよさそうなので、メインの部分はこんな感じで。
7行目は、タブをクリックしたか、あるいはレフトメニューをクリックしたか、で動かして、クリックしたリンクの .attr("hash") を渡す処理にしています。
ということで、function tabchange はこんな感じで。
一応完成っす。
ソース全部載せると分かりづらいので一部だけで概念的に説明しますが、これはまあ、普通にレフトメニューがあって、そしてメインの部分にはタブでメニューを選択できるようなレイアウトの画面だと思って下さい。
レフトメニューはこんな感じ
<div class="left">
<p>メニュー</p>
<ul>
<li><a href="sample.html#menu1">menu1</a></li>
<li><a href="sample.html#menu2">menu2</a></li>
<li><a href="sample.html#menu3">menu3</a></li>
<li><a href="sample.html#menu4">menu4</a></li>
<li><a href="sample.html#menu5">menu5</a></li>
</ul>
</div>
メイン部分のタブはこんな感じ
<div class="menu-tab">
<ul>
<li><a href="#menu1" class="selected">menu1</a></li>
<li><a href="#menu2">menu2</a></li>
<li><a href="#menu3">menu3</a></li>
<li><a href="#menu4">menu4</a></li>
<li><a href="#menu5">menu5</a></li>
</ul>
</div>
そして、このメイン部分のタブ表示の下に、以下のような、各タブをクリックした時に表示すべき内容を menu1 から menu5 まで全部並べておきます。
<div class="menu">
<div id="menu1" class="list">
menu1の内容
</div>
<div id="menu2" class="list">
menu2の内容
</div>
<div id="menu3" class="list">
menu3の内容
</div>
<div id="menu4" class="list">
menu4の内容
</div>
<div id="menu5" class="list">
menu5の内容
</div>
</div>
これを jQuery を使って、menu2 のタブをクリックした時は <div id="menu2"> の内容だけを表示させ、かつ、<a href="#menu2"> のタブには選択した状態のクラス(selected)をあてたい、しかもレフトメニューからのクリックでも同じ動きができて、レフトメニューはサイト内の他のページにもそのまま(同じまま)設置されるので、他のページから、
<a href="sample.html#menu2"> というリンクで飛んできた時にも menu2 の内容を表示したい、ということなんですね。
んで、最初に送られてきたソースがこんな感じでした。
$("div.list:not("+$(".menu-tab li a.selected").attr("href")+")").hide();
$(".menu-tab li a").click(function(){
$(".menu-tab li a").removeClass("selected");
$(this).addClass("selected");
$("div.list").hide();
$($(this).attr("href")).show();
return false;
});
1行目で、クラスが selected になっている(=つまり選択状態)のタブの href 属性を取得して(この場合は #menu1 )、それ以外の $("div.list")、すなわち各メニューの内容を隠しています。2行目でタブのクリックを取得して、クリックされたタブについてあれこれ処理しています。
3行目は全てのタブから selected クラスの除去。
4行目は選択されたタブに selected クラスを付加。
5行目は各メニューの内容を一旦全部隠して。
6行目でクリックされたタブの href 属性と同じ id のメニューの内容を表示。
このままでは確かにレフトメニューからクリックされた時も、このページに他のページからリンクで飛んできた時も動きません。
ということで、どうやって、<a href="sample.html#menu2"> の#以下の部分を取得するか、なんですが、とりあえず
location.hashで取得できる、ということです。
あと、jQueryの .attr() の場合は単に、
.attr("hash")
でいけると。今回の場合基本的に #menu2 という文字列がキーになっていて、あとはタブ部分のオブジェクトをなにがしか操作すればよさそうなので、メインの部分はこんな感じで。
$(function(){
var selected_tab = location.hash;
var link_tab = $(".menu-tab li a");
tabchange(selected_tab, link_tab);
$(".menu-tab li a, .left li a").click(function(){
tabchange($(this).attr("hash"), link_tab);
});
});
tabchange という function を別途用意することにして、それに #menu2 という文字列と、タブ部分のオブジェクトを渡してなんとかすることにします。7行目は、タブをクリックしたか、あるいはレフトメニューをクリックしたか、で動かして、クリックしたリンクの .attr("hash") を渡す処理にしています。
ということで、function tabchange はこんな感じで。
function tabchange(selected_tab, link_tab){
link_tab.removeClass("selected");
link_tab.each(function(n){
if ($(this).attr("hash") == selected_tab){$(this).addClass("selected");}
});
$(selected_tab).siblings().hide();
$(selected_tab).show();
}
each とか、siblings とか使っちゃってますが、やってる内容は元々のやつと同じです。一応完成っす。
2010-04-17
DISTINCT と ORDER BY を一緒に使う時の、PostgresとMySQLの違い
今やってるやつで、出てきた現象なのでちょっとメモ。
例えば items というようなテーブルがあって、id と name がある。
紐づけ用のテーブルは items_categories というようなもので、こんな感じになっている。
そのカテゴリー1の中での並ぶ順番が orders ということで設定されている。
アイテム2が順番は1、アイテム1が2番と。
で、こいつをまず順番関係なしに、join してみると
Postgresでも
例えば items というようなテーブルがあって、id と name がある。
id | name ----+-------- 1 | test 2 | sampleで、この items には複数のカテゴリーとサブカテゴリーが紐づけられている。
紐づけ用のテーブルは items_categories というようなもので、こんな感じになっている。
item_id | category_id | sub_category_id | orders
---------+-------------+-----------------+--------
1 | 1 | 1 | 2
1 | 1 | 2 | 2
2 | 1 | 2 | 1
アイテム1はサブカテゴリー1と2に、アイテム2はサブカテゴリー2に紐付いていて、どちらもカテゴリーは1だが、そのカテゴリー1の中での並ぶ順番が orders ということで設定されている。
アイテム2が順番は1、アイテム1が2番と。
で、こいつをまず順番関係なしに、join してみると
SELECT ic.item_id, i.name FROM items_categories ic INNER JOIN items i ON ic.item_id=i.id WHERE ic.category_id=1こうなる。
item_id | name
---------+--------
1 | test
1 | test
2 | sample
orders 順にしたいので、
SELECT ic.item_id, i.name FROM items_categories ic INNER JOIN items i ON ic.item_id=i.id WHERE ic.category_id=1 ORDER BY ic.ordersとすると、
item_id | name
---------+--------
2 | sample
1 | test
1 | test
これは動く。item_id が重複してるので、distinct を使うと、
SELECT DISTINCT ic.item_id, i.name FROM items_categories ic INNER JOIN items i ON ic.item_id=i.id WHERE ic.category_id=1 ORDER BY ic.ordersPostgresの場合、エラーになる。
ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select listMySQLの場合、
item_id | name
---------+--------
2 | sample
1 | test
出る。Postgresでも
SELECT DISTINCT ic.item_id, i.name, ic.orders FROM items_categories ic INNER JOIN items i ON ic.item_id=i.id WHERE ic.category_id=1 ORDER BY ic.ordersとすればちゃんと出る。
item_id | name | orders
---------+--------+--------
2 | sample | 1
1 | test | 2
そりゃ、おかしいのはMySQLでしょう。この場合。
2010-04-13
デザイナーが作った.htmlファイルを一括して.tplファイルにする
find ./ -name '*.html' | while read line; do mv $line `echo $line | sed -e 's,\.html$,.tpl,'` doneいや、理解はできてない。。
2010-04-03
jQueryのWYSIWYGエディターでkeyupとかkeypressのイベントを取り出す
ラベル:
jQuery
今週ずーっとやってた不毛なjQueryアプリですが、一番はまってたWYSIWYGエディター部分についてまとめておきます。
WYSIWYGエディターというと世間ではFCKeditorが有名ですが、まあ、あれはちょっと重いんじゃない?
ってことで、jQueryのプラグインで探す訳ですが、どーもね、これっていうのがない訳で。
最初に使ってみたのがこれ
LIGHTWEIGHT RICH TEXT EDITOR (RTE / WYSIWYG) PLUGIN FOR JQUERY
使い方はこんな感じ
firebugで見てるとキーを入力する度に
次がこれ
JHTMLAREA - WYSIWYG HTML EDITOR FOR JQUERY
使い方はこんな感じ
ドキュメントがあまり詳しくなくていまいちですかねー。
Microsoft Public License というあまり聞いたことのない?ライセンスです。
最後にこれ
HTMLBOX
使い方はこんな感じ
UndoRedoManager plugin とか。
おもしろそうなんだけど、さっぱりわからんのだー。
ま。最後のが一番よさそうですけどね。
で、今回の課題はこのエディターで文字を入力してる最中にそのイベントを取りたいってことなんだけども、
そもそもこういうエディターというのはフォームの textarea に設定するけれども、textarea そのものは非表示にして、その近くに iframe をつっこんで
でhtmlを表示させて機能しているようで、DOMがどうなってるんだかさっぱり分からない。
どういうからくりになってるんだか・・・。
で、結論から言うと、
編集中の文字とかを取り出すには
試しに文字を入力する度にその中の文字数を表示するというのをやってみると、
WYSIWYGエディターというと世間ではFCKeditorが有名ですが、まあ、あれはちょっと重いんじゃない?
ってことで、jQueryのプラグインで探す訳ですが、どーもね、これっていうのがない訳で。
最初に使ってみたのがこれ
LIGHTWEIGHT RICH TEXT EDITOR (RTE / WYSIWYG) PLUGIN FOR JQUERY
使い方はこんな感じ
<textarea name="info1" cols="100" rows="10" class="rte1"></textarea>
<script type="text/javascript">
$(document).ready(function() {
$('.rte1').rte({
css: ['default.css'],
controls_rte: rte_toolbar,
controls_html: html_toolbar
});
});
</script>
jquery.rte.tb.js にツールバーの設定がまとめられてるのでそれを編集する。firebugで見てるとキーを入力する度に
!keyup イベントでは charCode プロパティの値には意味がないため使用すべきではありません。の警告が出るのがいまいちです。
次がこれ
JHTMLAREA - WYSIWYG HTML EDITOR FOR JQUERY
使い方はこんな感じ
<script type="text/javascript">
$(function() {
$("#info").htmlarea({
toolbar: [
["bold", "italic", "underline", "|", "forecolor"],
["p", "h1", "h2", "h3", "h4", "h5", "h6"],
["link", "unlink", "|", "image"],
[{
css: "custom_disk_button",
text: "Save",
action: function(btn) {
alert('SAVE!\n\n' + this.toHtmlString());
}
}]
],
loaded: function() {
//
}
});
});
</script>
<textarea id="info" cols="50" rows="15"></textarea>
loaded とかでエディターが起動した後になにか処理を入れられる。ドキュメントがあまり詳しくなくていまいちですかねー。
Microsoft Public License というあまり聞いたことのない?ライセンスです。
最後にこれ
HTMLBOX
使い方はこんな感じ
<textarea id='hb'></textarea>
<script language="Javascript" type="text/javascript">
var hb = $("#hb").htmlbox({
buttons:[
["separator_dots","bold","italic","underline"]
],
icons:"default",
skin:"green"
});
</script>
一応PDFのドキュメントがあるんですが、どうも説明が足りなくて使い方が分からない。UndoRedoManager plugin とか。
おもしろそうなんだけど、さっぱりわからんのだー。
ま。最後のが一番よさそうですけどね。
で、今回の課題はこのエディターで文字を入力してる最中にそのイベントを取りたいってことなんだけども、
そもそもこういうエディターというのはフォームの textarea に設定するけれども、textarea そのものは非表示にして、その近くに iframe をつっこんで
<div> <iframe style="height: 305px; width: 415px;"> <html> <head> </head> <body> </body> </html> </iframe> </div>みたいにして。
でhtmlを表示させて機能しているようで、DOMがどうなってるんだかさっぱり分からない。
どういうからくりになってるんだか・・・。
で、結論から言うと、
編集中の文字とかを取り出すには
$('iframe').contents().find('body').html()
keyupのイベントを取り出すには、
$('iframe').contents().keyup(function(){
// なにか処理
}
でいけます。試しに文字を入力する度にその中の文字数を表示するというのをやってみると、
<script language="Javascript" src="jquery-1.3.2.min.js" type="text/javascript"></script>
<script language="Javascript" src="htmlbox.min.js" type="text/javascript"></script>
<script language="Javascript" src="formState.js" type="text/javascript"></script>
<textarea id='hb'></textarea>
<script language="Javascript" type="text/javascript">
var hb = $("#hb").htmlbox({
buttons:[
["separator_dots","bold","italic","underline"]
],
icons:"default",
skin:"green"
});
$(function() {
$('iframe').contents().keyup(function(){
$('#count').val($('iframe').contents().find('body').text().length);
});
});
</script>
<input type="text" id="count" />
こんな感じになります。
2010-03-21
[見積システム:01]サイトマップ
最初にサイトマップくらい作っておこうってことで、作った。
かなりメニューが多くなってしまったが・・・。
見積もり編集のパターン選択のあたりのインターフェースをどうするか、まだ考えていないのでそこはちょっとまた後で直すことにして、とりあえず、おおまかにはこんな感じで行こう。
かなりメニューが多くなってしまったが・・・。
見積もり編集のパターン選択のあたりのインターフェースをどうするか、まだ考えていないのでそこはちょっとまた後で直すことにして、とりあえず、おおまかにはこんな感じで行こう。
2010-03-20
gitを使ってデザイナーとの並行作業でテンプレートを修正する
テンプレートで修正が入った場合について、
例えば自分が作った index.tpl がこんなようなソースだったとする。
例えば、以下のようにエラーメッセージの表示を追加した。
divにclass指定が追加になってる。
問題なのは、デザイナーの修正が、以下のようなものだった場合、
以下のように順番を決めて編集保存して、
例えば自分が作った index.tpl がこんなようなソースだったとする。
<div> <h1>Colored Pencils</h1> </div>まずはコミットする。
$ git add index.tpl $ git commit -m 'first commit'ここで一旦リリースするが、その時にブランチを作っておく
$ git branch design_fixその後なにか修正する。
例えば、以下のようにエラーメッセージの表示を追加した。
<div>
<h1>Colored Pencils</h1>
{$message|escape}
</div>
それをコミットする
$ git commit -a -m 'add message'それを知らないデザイナーからファイルが届いた。
divにclass指定が追加になってる。
<div class="main"> <h1>Colored Pencils</h1> </div>作っておいたデザイナー用のブランチに移動して、
$ git checkout design_fixこの状態で、デザイナーが作った index.tpl をコピーしてからコミットする。
$ git commit -a -m 'design chenged'再びマスターに戻り、マージする
$ git checkout master $ git merge design_fix以下のようにマージされた。
<div class="main">
<h1>Colored Pencils</h1>
{$message|escape}
</div>
ここでまたすかさず次のブランチを作っておくといいかもしれない。問題なのは、デザイナーの修正が、以下のようなものだった場合、
<div> <h1>Colored Pencils</h1> <h2>12 colors</h2> </div>マージでエラーになる。
Auto-merging index.tpl CONFLICT (content): Merge conflict in index.tpl Automatic merge failed; fix conflicts and then commit the result.そのindex.tplを見るとこんなんなってる。
<div>
<h1>Colored Pencils</h1>
<<<<<<< HEAD:index.tpl
{$message|escape}
=======
<h2>12 colors</h2>
>>>>>>> design_fix:index.tpl
</div>
message の行と h2 の行とどっちが上でどっちが下か分からないってことだろう。以下のように順番を決めて編集保存して、
<div>
<h1>Colored Pencils</h1>
<h2>12 colors</h2>
{$message|escape}
</div>
コミットする。
$ git commit -a -m 'design fix'無事マージされた
--- a/index.tpl
+++ b/index.tpl
@@@ -1,5 -1,5 +1,6 @@@
<div>
<h1>Colored Pencils</h1>
+ <h2>12 colors</h2>
+{$message|escape}
</div>
2010-03-18
MacPortsでOSXにphp5.3を入れる
OSXに、php5.3を入れようということで、
PHPのバージョン5.3.2になっている。
が、phpが動いていない。 そこで、以下を実行。
以下を追加。
なったがな、しかし。だな。
port installedで見たところ、apache2とかはもうインストール済みになってるみたいだったので、もう一回以下のコマンドでphpのインストールに挑戦。
sudo port -d install php5 +apache2 +macox +mysql5 +pear +postgres +sockets +sqlite最後に出た以下のメッセージを完全に見逃す
To customize php, copy /opt/local/etc/php5/php.ini-development (if this is a development server) or /opt/local/etc/php5/php.ini-production (if this is a production server) to /opt/local/etc/php5/php.ini and then make changes. If this is your first install, you need to activate PHP in your web server. To enable PHP in Apache, run cd /opt/local/apache2/modules /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.soこうして入れたシステム一式は、OSXの
/opt/localの下に入るようです。
PHPのバージョン5.3.2になっている。
$ php -v PHP 5.3.2 (cli) (built: Mar 18 2010 03:49:53) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologiespearも入っている。
$ pear -V PEAR Version: 1.9.0 PHP Version: 5.3.2 Zend Engine Version: 2.3.0でアパッチを起動したいということで、
sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plistとりあえずこうするだけでapache動いた。
が、phpが動いていない。 そこで、以下を実行。
sudo cp php.ini-development php.ini sudo /opt/local/apache2/bin/apxs -a -e -n "php5" libphp5.soアパッチのhttpd.confに
以下を追加。
Include conf/extra/mod_php.conf以下を付け足し。
で、DirectoryIndex index.html index.php
sudo /opt/local/apache2/bin/apachectl restartしたら、phpもオッケーに。
なったがな、しかし。だな。
登録:
投稿 (Atom)
このブログを検索
人気の投稿
Powered by Blogger.
