JavaScript 日付に日にちを加算する

Javascriptはいい感じに空気を読んでくれるのですが、いざというときにどのクラスなのかわからなくなってしまうというのがもどかしいです。

今日は文字列として受け取った日付を加算したりする方法で手こずりました。

日にちを加算する

[javascript]

// データの最終日をDateオブジェクト化
// まずはdayという文字列の日付を作成
var day = ‘2013-11-29’;
// 文字列をDateオブジェクト化
var date = new Date(day);
// ここから10日追加する
var i = 10;
var dateObj = new Date(date + i * 86400000);

[/javascript]

日にちを2013/11/01という文字列として表現する。
(2013/11/1ではだめ。01にしたい。)

[javascript]

// さきほど作ったdateObjを使う。
var dateStr = String(dateObj.getYear()+1900) + "/" + ("0" + (dateObj.getMonth()+1)).slice(-2) + "/" + ("0" + dateObj.getDate()).slice(-2);

[/javascript]

JavaScriptはカジュアルだけど、その分厳密な操作が難しいっすね。

MySQL : ある日から一定日数以内のユニークな値の数の集計

たとえば、2013年11月28日から20日以内のユニークなユーザーIDがいくつあるのか、といったデータを取るときのSQL文。

access_logというテーブルの中に、
dateというカラムに日にちが入っていて、
user_idというカラムにユニークなユーザーIDが入っている。

[sql]
SELECT DATE_FORMAT(date, ‘%Y-%m-%d’)
AS date,COUNT(DISTINCT user_id)
AS count
FROM access_log
WHERE DATE_SUB(‘2013-11-28’, INTERVAL 20 DAY) < date
AND date < ‘2013-11-28’
GROUP BY DATE_FORMAT(date, ‘%Y%m%d’);
[/sql]

 

ここで、

[sql]
DATE_SUB(‘2013-11-28’, INTERVAL 20 DAY)
[/sql]

は、
2013年11月28日から20日分を引いたもの、という意味。

[sql]
WHERE DATE_SUB(‘2013-11-28’, INTERVAL 20 DAY) < date
[/sql]

とすることで、「’2013-11-28’から20日引いたもの(つまり2013-11-28)より日にちが大きい物」ということになる。

jQueryを使って、スクロールしてデータを読み込み、Tableに表示させる

画面の最下部までスクロールしたら、JSONデータを読み込んで表示させる。というのをjQueryを使って実現する方法。

サンプルページ

[html]
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>jQueryを使ってスクロールしてデータ読み込み</title>
</head>
<body>
<h1>名前と住所</h1>
<div style="padding:20px 20px 100px 20px">
<table class="table table-striped table-bordered" border="1">
<thead>
<tr>
<th>名前</th>
<th>住所</th>
<tr>
</thead>
<tbody>
<tr>
<td>佐藤</td>
<td>千葉県千葉市</td>
</tr>
<tr>
<td>山田</td>
<td>埼玉県さいたま市</td>
</tr>
<tr>
<td>田中</td>
<td>神奈川県横浜市</td>
</tr>
<!– ここに読み込まれたデータが追加される –>
</tbody>
</table>
</div>

<!– jQueryを読み込み –>
<script src="http://code.jquery.com/jquery.js"></script>
<script type="text/javascript">
<!–
// データを受け取ったかどうか制御する変数
var gotRequestSuccessfully = false;

// 最下部にスクロールした時に発生するイベント
$(window).bind("scroll", function() {
scrollHeight = $(document).height();
scrollPosition = $(window).height() + $(window).scrollTop();
if ( (scrollHeight – scrollPosition) / scrollHeight <= 0.01) {
//スクロールの位置が下部1%の範囲に来た場合
//console.log(‘最下部’);
if(gotRequestSuccessfully == false){
getData(); // データを取りに行く
}
} else {
//それ以外のスクロールの位置の場合
gotRequestSuccessfully = false;
}
});

//APIからJSONのデータをもらってくる関数
//ajaxだけど同期通信にする
//データはJSONで取得する。
function getData() {
$.ajax({
url: ‘http://www.hugkey.com/test/20131127/api/getDataAPI’, // ここにはJSON形式のデータを送ってくるAPIのURLを書く
type: "GET",
dataType: "JSON", // 形式はJSON
async: false, // 非同期にしない
success: function (data) {
gotRequestSuccessfully = true;
if(data.length != 0){    // データが存在するとき
//console.log(data);
for(var i = 0; i < data.length; i++){
var str = addToTable(data[i]);
$(‘tbody’).append(str);
}
}
}
});
}

// テーブルに追加するためのHTMLを返す
// 引数のdataはJSONで、{"name":"鈴木", "address":"東京都大田区"}という形式を想定
function addToTable(data){
var strTR = ‘<tr bgcolor="red">’;
var str = strTR
+ ‘<td>’ + data.name + ‘</div></td>’
+ ‘<td>’ + data.address + ‘</div></td>’
+ ‘</tr>’;
return str;
}

–>
</script>
</body>
</html>
[/html]

大きく分けると3パートにわかれます。

  1. スクロール位置をトリガーとして、APIからデータを取ってくる
  2. 取ってきたデータをHTMLに直す
  3. 直したデータを.append()を使ってTableの最後尾に追記する

サンプルページ

↑すごいダサいHTMLだけのページですが、一応ちゃんと動作しますので。

ワードプレスの管理画面にベーシック認証を設定する。

WordPressの管理画面のセキュリティ強化のため、Basic認証の設定を行いました。

管理画面に入る際に、まずベーシック認証を経てから、ログイン画面になるという、2段階認証。

ベーシック認証画面
ベーシック認証画面
ワードプレス ログイン画面
ワードプレス ログイン画面

意外と詰まったので備忘のためメモ。

.htaccessの設定

.htaccess

[html]
# ベーシック認証を導入
<Files wp-login.php>
AuthUserFile /home/users/2/lolipop.jp-XXXXXXXXXXXX/web/.htpasswd
AuthGroupFile /dev/null
AuthName "Secret Area"
AuthType Basic

require valid-user
</Files>

<Files ~ "^.(htpasswd|htaccess)$">
deny from all
</Files>
[/html]

AuthUserFileにはフルパスと、最後に.htpasswdを書きます。
ロリポップの管理画面の場合、フルパスは「アカウント情報」に記載されています。
スクリーンショット 2013-11-26 14.34.11

.htpasswdの設定

.htpasswd

[html]
hoge:XFdMGsslDgYmo

[/html]

↑最後に改行が必要です。

パスワード用のファイル(.htpasswd)も書きます。
パスワードは生のままではダメなので、こちらのページから作成します。

スクリーンショット 2013-11-26 14.42.13

出来上がった2つのファイルを、wp-login.phpと同じディレクトリに設置します。
以上でベーシック認証のログインが追加されました。

CodeigniterのForm Helperの使い方 (パスワードをPOST送信)

iOSと全く関係ない、コードイグナイターのフォームヘルパーの使い方。
controllerのコンストラクタに

[php]
$this->load->helper(‘form’);
[/php]

と書いておいて、viewなどに以下のように書くと

[html]
<!–?php form_open(‘hoge/fuga’); ?–>
<!–?php echo form_password(‘password’); ?–>
<!–?php echo form_submit(‘submit’, ‘送信’); ?–>

[/html]

HTMLではこうなる

[html]</pre>
<form accept-charset="utf-8" action="http://yourdomain.com/hoge/fuga/" method="post"><input type="password" name="password/send" value="" />
<input type="submit" name="submit" value="送信" /></form>
<pre>[/html]

フォームを作ってくれて便利。

受け取り側のコントローラーではこんなふうに書いて値を取る

[php]
$data[‘password’] = $this->input->post(‘password’);
[/php]

iOSアプリの状態を確認する。起動中なのかバックグラウンドなのか。

iOSアプリが起動しているのか、バックグラウンドなのかを見る方法。

UIApplicationStateというクラスを使います。

[objc]
// アプリケーションの状態を見る。
UIApplicationState applicationState = [[UIApplication sharedApplication] applicationState];
NSString *state = @"Unknown";
if (applicationState == UIApplicationStateActive) {
// アクティブなとき
state = @"Active";
}else if(applicationState == UIApplicationStateBackground){
// バックグラウンドのとき
state = @"Background";
}else if(applicationState == UIApplicationStateInactive){
// アクティブじゃないとき
state = @"Inactive";
}
NSLog(@"アプリケーションの状態 : %@", state);
[/objc]

iOS7ではバックグラウンドでできることの幅が広がったので、これで状態をいろいろ確認しながらテスト開発できます。

リモートリポジトリの置いてあるサーバ上にローカルリポジトリを設置して、作業ツリーをWebに公開する

git リモートリポジトリ ローカルリポジトリ

Gitを使ってみて、Gitのしくみがいまいちわからなくて混乱したので、今日わかったことを羅列します。

今日やりたかったことは、

  1. 自分のパソコンにあるプロジェクトをGitでバージョン管理したい。
  2. Webサーバとして使っているサーバにリポジトリ(リモートリポジトリ)を置きたい。
  3. リモートリポジトリからプルしたものをWebに公開したい。

この3つです。

まずよくわかっていなかったのが、「リモートリポジトリ」というものの存在です。
リモートリポジトリというのは「遠隔にあるリポジトリ」だと思っていて、ローカルリポジトリの一種だと思っていました。

しかしその理解はまちがいでした。
リモートリポジトリとは、みんながコミットする集積所みたいなものなのですね。

git リモートリポジトリ ローカルリポジトリ

リモートリポジトリとローカルリポジトリがこんがらがっていたので、サーバ上のどれをWebに公開すればいいのかと、ずーと悩んでいました。
リモートリポジトリの作業ツリーを公開するのではなくて、サーバマシン内にGit Cloneして、そこの作業ツリーをWebに公開すればよかったのですね。

実際のコードとしては、

まず、クローンを設置する場所(/var/www/test/)に移動して、

[bash]
$ cd /var/www/test/
[/bash]

リモートリポジトリ(/var/git_repos/TEST_WEB.git)からクローンを作成する

[bash]
$ git clone /var/git_repos/TEST_WEB.git
[/bash]

 
こちらのページが非常に参考になりました。
Git初心者に捧ぐ!Gitの「これなんで?」を解説します。

iPhoneアプリ申請で新規アプリ作成をするときにBunlde IDに新しく作成したApp IDが出てこない

Bundle ID not found

iTunes ConnectからのiPhoneアプリ申請で、新規アプリ作成をするときに新しく作成したApp IDが出てこない問題が発生しました。(2013年 11月13日)

Bundle ID not found

先月も同様の問題が発生していたようです。(2013年 10月28日)

https://devforums.apple.com/message/912211#912211

そして前日にも同様の内容でフォーラムに投稿されていました。

https://devforums.apple.com/message/917778#917778

申請が出せないのは困るので(納期的に)、contact usから「問題があって新規にアプリ申請できませんよ!」って送ったのですが、「スクリーンショットとか添付してまた返信してください(じゃないと対応しないよ)」というつれない返事。

それで困り果ててしまったのですが、翌日再度見てみると、なんと追加されていました。意味がわかりません。(前日のスクリーンショットを再確認したのですが、前日は間違いなく追加されていなかったので、見落としではありませんでした。)

つまり、一日置いたらBundle IDがアプリ新規申請ページのドロップダウンメニューに追加されていたのです。他には何もしていません。

というわけで、Bundle IDが出てこない時の解決法としては「1日寝かせてみる」でしょうか。それでダメだったらアップルにメールしましょう。
iTunes ConnectやiOS dev centerはここ数ヶ月ぐらいずっと挙動がおかしい気がします。
安定するように改善して欲しいところです。。。

iOS7 : Star Rating 星をタッチして5段階のレーティングができるUIView

star rating objective-c uiview

レーティング用のUI素材を作成しました。

star rating objective-c uiview

5つ並んだ星をタッチして、AppStoreのレビューのように0~5の値を入出力できるUI用のパーツです。わかりやすくするよう、星ひとつひとつの背景色に色をつけてあります。また、一番端の赤い領域に触れると、星を0として入力できます。

Githubにサンプルコード置きました。

こちらがUIViewのサブクラスStarRatingViewの本体。

StarRatingView.h

[objc]
#import <UIKit/UIKit.h>

@interface StarRatingView : UIView{
UIView * zeroView;
UIImageView * firstStarView;
UIImageView * secondStarView;
UIImageView * thirdStarView;
UIImageView * fourthStarView;
UIImageView * fifthStarView;
}

@property(nonatomic) int starValue;

@property(strong, nonatomic) UIImage * starImage;
@property(strong, nonatomic) UIImage * darkStarImage;

@end

[/objc]

StarRatingView.m

[objc]
#import "StarRatingView.h"

#define STAR_WIDTH(width) width / 5.5
#define FIRST_STAR_X(width) width / 11
#define SECOND_STAR_X(width) (3 * width) /11
#define THIRD_STAR_X(width) (5 * width) /11
#define FOURTH_STAR_X(width) (7 * width) /11
#define FIFTH_STAR_X(width) (9 * width) /11

@implementation StarRatingView

– (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code

// 初期値
self.starValue = 0;

// タッチができるようにする
self.userInteractionEnabled = YES;

// 星用のimageViewを作成
zeroView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];
firstStarView = [[UIImageView alloc] initWithFrame:CGRectMake(FIRST_STAR_X(self.frame.size.width), 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];
secondStarView = [[UIImageView alloc] initWithFrame:CGRectMake(SECOND_STAR_X(self.frame.size.width), 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];
thirdStarView = [[UIImageView alloc] initWithFrame:CGRectMake(THIRD_STAR_X(self.frame.size.width), 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];
fourthStarView = [[UIImageView alloc] initWithFrame:CGRectMake(FOURTH_STAR_X(self.frame.size.width), 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];
fifthStarView = [[UIImageView alloc] initWithFrame:CGRectMake(FIFTH_STAR_X(self.frame.size.width), 0, STAR_WIDTH(self.frame.size.width), self.frame.size.height)];

// 星を作成
self.starImage = [UIImage imageNamed:@"star.png"];
self.darkStarImage = [UIImage imageNamed:@"star_black_a50.png"];

// 画像を指定
firstStarView.image = self.darkStarImage;
secondStarView.image = self.darkStarImage;
thirdStarView.image = self.darkStarImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;

// viewに追加
[self addSubview:zeroView];
[self addSubview:firstStarView];
[self addSubview:secondStarView];
[self addSubview:thirdStarView];
[self addSubview:fourthStarView];
[self addSubview:fifthStarView];

// 背景色を変更
zeroView.backgroundColor = [UIColor redColor];
firstStarView.backgroundColor = [UIColor orangeColor];
secondStarView.backgroundColor = [UIColor yellowColor];
thirdStarView.backgroundColor = [UIColor greenColor];
fourthStarView.backgroundColor = [UIColor blueColor];
fifthStarView.backgroundColor = [UIColor purpleColor];
self.backgroundColor = [UIColor grayColor];

}
return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
– (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

// タッチ開始
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//NSLog(@"Began x:%f y:%f", location.x, location.y);
int starInt = [self calculateTouchLocation:location.x];
NSLog(@"Begin starInt : %d", starInt);
[self showStar:starInt];
self.starValue = starInt;
}

// タッチ移動
– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//NSLog(@"Moved x:%f y:%f", location.x, location.y);
int starInt = [self calculateTouchLocation:location.x];
//NSLog(@"Moved starInt : %d", starInt);
[self showStar:starInt];
self.starValue = starInt;
}

// タッチ終了
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
//NSLog(@"Ended x:%f y:%f", location.x, location.y);
int starInt = [self calculateTouchLocation:location.x];
NSLog(@"Ended starInt : %d", starInt);
[self showStar:starInt];
self.starValue = starInt;
}

// 座標を0~5の数値に変換
-(int)calculateTouchLocation:(double)locationX
{
int starInt = 0;
if (locationX < FIRST_STAR_X(self.frame.size.width)) {
starInt = 0;
}else if (locationX >= FIRST_STAR_X(self.frame.size.width) && locationX < SECOND_STAR_X(self.frame.size.width)){
starInt = 1;
}else if (locationX >= SECOND_STAR_X(self.frame.size.width) && locationX < THIRD_STAR_X(self.frame.size.width)){
starInt = 2;
}else if (locationX >= THIRD_STAR_X(self.frame.size.width) && locationX < FOURTH_STAR_X(self.frame.size.width)){
starInt = 3;
}else if (locationX >= FOURTH_STAR_X(self.frame.size.width) && locationX < FIFTH_STAR_X(self.frame.size.width)){
starInt = 4;
}else if (locationX >= FIFTH_STAR_X(self.frame.size.width)){
starInt = 5;
}else{
starInt = 0;
}
return starInt;
}

-(void)showStar:(int)value{
switch (value) {
case 0:
firstStarView.image = self.darkStarImage;
secondStarView.image = self.darkStarImage;
thirdStarView.image = self.darkStarImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;
break;

case 1:
firstStarView.image = self.starImage;
secondStarView.image = self.darkStarImage;
thirdStarView.image = self.darkStarImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;
break;

case 2:
firstStarView.image = self.starImage;
secondStarView.image = self.starImage;
thirdStarView.image = self.darkStarImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;
break;

case 3:
firstStarView.image = self.starImage;
secondStarView.image = self.starImage;
thirdStarView.image = self.starImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;
break;

case 4:
firstStarView.image = self.starImage;
secondStarView.image = self.starImage;
thirdStarView.image = self.starImage;
fourthStarView.image = self.starImage;
fifthStarView.image = self.darkStarImage;
break;

case 5:
firstStarView.image = self.starImage;
secondStarView.image = self.starImage;
thirdStarView.image = self.starImage;
fourthStarView.image = self.starImage;
fifthStarView.image = self.starImage;
break;

default:
firstStarView.image = self.darkStarImage;
secondStarView.image = self.darkStarImage;
thirdStarView.image = self.darkStarImage;
fourthStarView.image = self.darkStarImage;
fifthStarView.image = self.darkStarImage;
break;
}
}

@end

[/objc]

設置方法

実装するときはStarRatingViewオブジェクトをaddSubViewすれば設置できます。
viewControllerなどにこんなかんじで設置します。

[objc]
StarRatingView *starRatingView = [[StarRatingView alloc] initWithFrame:CGRectMake(10, 100, 275, 50)];
[self.view addSubview:self.starRatingView];
[/objc]

値を出し入れするときは、「starRatingView.starValue」からアクセスします。

Githubにサンプルコード置きました。

 

iOS7 StarRating