2013年2月3日日曜日

jQueryでAjax中にボタンを無効にする

TwitterBootstrap+jqueryでAjax後ボタンを押せなくするメモ
http://zenback.itmedia.co.jp/contents/logmemotips.com/archives/2938

上の肝心のソースが見えなくなっていたので書いてみました。
大事なところはjQuery.ajax()の前処理をするbeforeSendと後処理をするcompleteですね。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Hello</title>
<script type="text/javascript"
 src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
 $(function() {
  $("button").click(function() {
   $.ajax({
    beforeSend: function(){
     $("button").attr("disabled","true"); 
     $("div").text("Waiting...");
    },
    type:"GET",
    url:"hello",
    success: function(msg){
     $("div").text(msg);
    },
    complete: function(xhr,event){
     $("button").removeAttr("disabled");
    }
   });
  });
 });
</script>

</head>
<body>
 <button>Submit</button>
 <div></div>
</body>
</html>

URL短縮サービス作りました。

URL短縮サービスを作りました。

 furl.jp

もともとGAE、jQueryの勉強が目的でつくったので特に特徴はないですがシンプルでいいんじゃないかと思います。

実はRailsでも作ろうとしたことがあるのですがrubyに慣れていないのとRailsの複雑さに挫折した経緯があったので結局単純にServletで作りました。

今後直していきたい、解決したいところは以下です。
1)URL短縮処理中にボタンが押せるので 押せないように制御する。
2)URL短縮処理中なのかよく分からないので分かるようにする。
3)データアクセスにLow-Level APIを使って少しでも速くしてみる。

独自ドメインURLのリダイレクトにGoogle Appsを使っており無料版が1ヶ月しか使えないので続ける場合はお金が必要になるというところが一番の課題ですね。。

2013年1月30日水曜日

SNSやめよう

最近意味なくFacebook/Twitter(たまにmixi..)のTLを見ている気がしてきた。 気づいてみるとときどき役に立ちそうなものもあったがほとんどが意味のない投稿を見ていた。 特に携帯のアプリの場合は暇なときにいつでも見えてしまうので気づいたら見ているといったことも多い。  メッセージに対応したりとまったく見ないわけではないけど時間がもったいないのでSNSは一旦辞めようと思う。
その代わり時間があったら上記に書いた問題に対応できるようなSNSを作ってみたいなあ。。最近は一日一枚だけ写真が投稿できるMy365とかPathなどのクローズドなSNSができたりと もう少し有意義なやり取りができるものもあるらしいですね。

2013年1月27日日曜日

山括弧(</>)をviでエスケープ処理するように一括置換する。

なんだかんだで毎回調べているのでメモ。 置換後の文字列に&を入れると置換前の文字列が入るのでエスケープしないといけない。

:%s/</\&lt;/g
:%s/>/\&gt;/g

jQueryからServletを呼び出すHelloWorld

jQueryからServletを呼び出すサンプルを作りました。 あとで書くけど直接JavaScriptからServletを呼び出すより格段に簡単に書けることが分かるかと思います。 Servlet側はHello,World返すだけだけど一応載せておきます。
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Hello</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(function() {
 $("button").click(function() {
  $.get("/hello", function(data) {
   $("div").text(data);
  });
 });
});
</script>

</head>
<body>
 <button>Submit</button>
 <div></div>
</body>
</html>

Hello.java
package com.test;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class Hello extends HttpServlet {
 public void doGet(HttpServletRequest req, HttpServletResponse resp)
   throws IOException {
  resp.setContentType("text/plain");
  resp.getWriter().println("Hello, world");
 }
}
web.xml
<web-app version="2.5" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
  <servlet-name>Hello</servlet-name>
  <servlet-class>com.test.Hello</servlet-class>
 </servlet>
 <servlet-mapping>
  <servlet-name>Hello</servlet-name>
  <url-pattern>/hello</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
 </welcome-file-list>
</web-app>
jQueryを利用しないでJavaScriptのみで書こうとした場合、以下のようになります。 buttonタグのonclick属性とメソッド名を紐づけないといけない、XMLHttpRequestを理解して書かないといけない、IEの対応などブラウザごとの対応も必要になってくるなど大変ですね。
<html>
<head>

<title>Hello</title>
<script type="text/javascript">
function submit(){
 if(window.XMLHttpRequest){
  req = new XMLHttpRequest();
 }else if(window.ActiveXObject){
  req = new ActiveXObject("Microsoft.XMLHTTP");
 }else{
  return false;
 }
 req.onreadystatechange=callback;
 req.open("GET","/hello",true);
 req.send(null);
}
function callback(){
 if(req.readyState==4 && req.status==200){
  document.getElementById("result").innerHTML=req.responseText;
 }
}
</script>
</head>
<body>
 <button onclick="submit()">Submit</button>
 <div id="result">
</div>
</body>
</html>

2013年1月4日金曜日

JavaScriptでJavaのString#hashCode()を実装する。

普段Javaを利用している人がJavaScriptを利用するとJavaだとすぐにできるのにといったことがよくある。(逆もあるかもしれないが。) そのなかでJavaのString#hashCode()に相当するものがないので作りました。
String.prototype.hashCode = function(){
 var hash = 0;
 for(var i=0 ; i < this.length; i++){     
  hash = hash * 31 + this.charCodeAt(i);
  hash = hash | 0; //符号付き32bit整数にする。
 }
 return hash; 
}
こんな感じでかくとJavaScriptのString型でhashCodeメソッドを使えるように拡張できるようです。 使い方は以下。
"abc".hashCode()
ちなみにJavaのString#hashCode()は以下です。
public int hashCode()
{
  int hashCode = 0;
  int limit = count + offset;
  for (int i = offset; i < limit; i++)
    hashCode = hashCode * 31 + value[i];
  return hashCode;
}
JavaScriptではint型に強制的に変換する場合、ビット演算を行う必要があるらしいのでそれを利用した。ただ後でみて分かりづらいのであまりよくないノウハウではある気がする。

2012年12月28日金曜日

GAE/JのスタートガイドをJPA対応する。

GAE/JのスタートガイドをみたところJDOベースになっていたためJPAに対応してみた。

EMF.java
package guestbook;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EMF {
 
 private static final EntityManagerFactory emfInstance =
   Persistence.createEntityManagerFactory("transactions-optional");
 
 private EMF(){}
 
 public static EntityManagerFactory get(){
  return emfInstance;
 }

}
Greeting.java
package guestbook;

import java.util.Date;

import javax.jdo.annotations.Persistent;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;

@Entity
public class Greeting {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Key key;
 
 private User author;
 
 private String content;
 
 private Date date;
 
    public Greeting(User author, String content, Date date) {
        this.author = author;
        this.content = content;
        this.date = date;
    }

    public Key getKey() {
        return key;
    }

    public User getAuthor() {
        return author;
    }

    public String getContent() {
        return content;
    }

    public Date getDate() {
        return date;
    }

    public void setAuthor(User author) {
        this.author = author;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public void setDate(Date date) {
        this.date = date;
    } 
 
}

SignServlet.java
package guestbook;

import java.io.IOException;
import java.util.Date;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;

public class SignServlet extends HttpServlet{

 private static final Logger log = Logger.getLogger(SignServlet.class.getName());
 
 public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException{
  UserService userService = UserServiceFactory.getUserService();
  User user = userService.getCurrentUser();
  String content = req.getParameter("content");
  Date date = new Date();
  Greeting greeting = new Greeting(user,content,date);
  EntityManager em = EMF.get().createEntityManager();
  try{
   em.persist(greeting);
  }finally{
   em.close();
  }
  resp.sendRedirect("/test.jsp");
 }
 
}
test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="javax.persistence.EntityManager" %> 
<%@ page import="com.google.appengine.api.users.User" %>
<%@ page import="com.google.appengine.api.users.UserService" %>
<%@ page import="com.google.appengine.api.users.UserServiceFactory" %>
<%@ page import="guestbook.Greeting" %>
<%@ page import="guestbook.EMF" %>

<html>
  <body>
   <head>
    <link type="text/css" rel="stylesheet" href="/stylesheet/main.css" />
   </head>
<%
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();
    if (user != null) {
%>
<p>Hello, <%= user.getNickname() %>! (You can
<a href="<%= userService.createLogoutURL(request.getRequestURI()) %>">sign out</a>.)</p>
<%
    } else {
%>
<p>Hello!!
<a href="<%= userService.createLoginURL(request.getRequestURI()) %>">Sign in</a>
to include your name with greetings you post.</p>
<%
    }
%>
<%
 EntityManager em = EMF.get().createEntityManager();
 String query = "select i from Greeting i";
 List<Greeting> greetings = (List<Greeting>)em.createQuery(query).getResultList();
 if(greetings.isEmpty()){
%>
<p>The guestbook has no messages.</p>
<%
 }else{
  
  for(Greeting g: greetings){
   if(g.getAuthor() == null){  
%>
<p>An anonymous person wrote:</p>
<%
   } else {
%>
<p><b><%= g.getAuthor().getNickname() %></b> wrote:</p>
<%
   }
%>
<blockquote><%= g.getContent() %></blockquote>
<%
  }
 }
 em.close();
%>
  <form action="/sign" method="post">
    <div><textarea name="content" rows="3" cols="60"></textarea></div>
    <div><input type="submit" value="Post Greeting" /></div>
  </form>
  </body>
</html>