<button type="button" id="myButton" data-loading-text="Loading..." class="btn btn-primary" autocomplete="off">
  Loading state
</button>

<script>
  $('#myButton').on('click', function () {
    var $btn = $(this).button('loading');
    // business logic...
    $btn.button('reset');
  })
</script>





참고 :
http://getbootstrap.com/javascript/#buttons






Lesson 1 / Iterations
- https://codility.com/demo/results/trainingBFYF8S-38C/


Lesson 2 / Arrays

1. CyclicRotation
- https://codility.com/demo/results/training94SFQB-X5K/

2. OddOccurrencesInArray
- https://codility.com/demo/results/training8547WH-RU7/




가이드에 따라 진행해보자


http://spring.io/guides/gs/rest-service/

==================================================





http://spring.io/guides/gs/sts/

Spring Tool Suite (STS) 이용하려면 위 페이지 스샷을 참고하고 마지막 프로젝트 템플릿 중 Consuming Rest 대신 Rest Service를 선택하면 된다.


선택하고 나면 두 개의 프로젝트가 생기게 되는데

gs-rest-service-initial 프로젝트는 초기화 된 상태의 프로젝트고 

gs-rest-service-complete 프로젝트는 가이드를 완료한 결과 상태의 프로젝트이다.



따라서 gs-rest-service-initial 에 아래 코드를 작성하면 된다.



출력 될 데이터 형태를 정의한 Greeting.java 클래스를 작성한다.

package hello;

public class Greeting {

    private final long id;
    private final String content;

    public Greeting(long id, String content) {
        this.id = id;
        this.content = content;
    }

    public long getId() {
        return id;
    }

    public String getContent() {
        return content;
    }
}


컨트롤러인 GreetingController도 작성 한다.

package hello;

import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/greeting")
    public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) {
        return new Greeting(counter.incrementAndGet(),
                            String.format(template, name));
    }
}


마지막으로 어플리케이션을 실행할 수 있도록 해주는 Application.java 를 작성한다.

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}


스프링을 사용해 봤다면 크게 새로운것은 없다.



필요한 항목은 모두 작성 되었고 실행은 STS 상에서 간단히 가능하다.

(프로젝트 우클릭 -> Run As -> Spring Boot App)



서버 구동 후 

http://localhost:8080/greeting?name=User 접속시


{"id":2,"content":"Hello, User!"}

형태로 출력된다면 정상적으로 완료 된 것이다.



완료 소스 :

https://github.com/hangaebal/stsREST




회사에서는 GitLab에 SourceTree 사용하느라 Github는 사용해본지 오래 되었다.

오랜만에 사용하는거니 가이드를 읽어보자.


https://guides.github.com/activities/hello-world/

=====================================================




Step 1. Create a Repository

(리파지토리 생성)

개발자가 아니어도 이해하기 좋게 리파지토리 개념 설명이 적혀있다.

리파지토리를 생성하려면

1. 우상단 + 누르고 'New repository' 클릭
2. 이름은 hello-world
3. 설명은 적당히
4. 'Initialize this repository with a README' 체크
(Repository 초기화 + README 파일 생성)
> 생성 버튼 클릭
new-repo-form





Step 2. Create a Branch

(브랜치 생성)

브랜치 관련한 설명이 이어진다. git 공통 내용이라 개발자라면 익숙하다.

브랜치를 생성하려면

1. 생성한 hello-world 프로젝트로 이동
2. [branch: master] 써있는 부분을 클릭한다.
3. 브랜치 이름은 readme-edits 라고 쓰고
4. [Create branch] 를 클릭하거나 엔터키를 누른다.
branch gif

이제 master 와 readme-edits 두 개의 브랜치가 있다.





Step 3. Make and commit changes

(커밋)

변경사항을 만들고 커밋하려면

1. 'README.md' 파일 클릭
2. 우상단 연필 아이콘 클릭
3. 에디터에 적당히 기입
4. 커밋 메시지에 변경 사항을 설명
5. [Commit changes] 버튼 클릭
commit

readme-edits 브랜치에 변경사항이 생겨서 master 브랜치와 차이가 생겼다.





Step 4. Open a Pull Request


풀 리퀘스트를 오픈하면, 너의 수정사항을 제안하고, 누군가가 그걸 검토하고 그들의 브랜치에 머지하도록 요청하게 된다.
풀 리퀘스트는 추가사항 녹색, 제거사항 빨간색 으로 각 브랜치의 차이를 보여준다.

본인 소유의 리파지토리에도 풀 리퀘스트를 오픈할 수 있다. 큰 프로젝트에서 작업하기 전 GitHub 흐름을 익히는데 좋은 방법이다.


1. Pull Request 탭을 클릭하고 [New pull request] 버튼을 클릭
pr-tab

2. 베이스와 비교대상을 선택
branch

3. 비교 페이지에서 차이점을 볼 수 있다.
diff

4. 전송하려면 [Create Pull Request] 버튼을 클릭
create-pull

5. 풀 리퀘스트의 제목과 설명을 작성
pr-form

6. Create pull request 클릭




Step 5. Merge your Pull Request

(풀 리퀘스트 머지)

1. [Merge pull request] 버튼 클릭
2. [Confirm merge]을 클릭하면 머지가 완료된다.
3. [Delete branch] 버튼을 클릭하면 readme-edits 브랜치가 제거된다.
merge
delete




Hello World 완료!

- jsp test char exception

- javax.servlet.jsp.el.ELException: An exception occurred trying to convert String "x" to type "java.lang.Long"





<c:when test="${value eq 'x'}">


JSP에서 위와 같은 단순한 비교문을 사용했는데, 아래와 같은 예외가 발생헀다



javax.servlet.jsp.el.ELException: An exception occurred trying to convert String "x" to type "java.lang.Long"



찾아보니 Expression Language Specification 2.2에 char를 Long으로 비교한다고 명시 되어있다.

(1.8.1 단락 / 13 페이지)


=================================================

1.8.1 A {<,>,<=,>=,lt,gt,le,ge} B

■ If A==B, if operator is <=, le, >=, or ge return true.
■ If A is null or B is null, return false
■ If A or B is BigDecimal, coerce both A and B to BigDecimal and use the return
value of A.compareTo(B).
■ If A or B is Float or Double coerce both A and B to Double apply operator
■ If A or B is BigInteger, coerce both A and B to BigInteger and use the return
value of A.compareTo(B).
Chapter 1 Language Syntax and Semantics 13
■ If A or B is Byte, Short, Character, Integer, or Long coerce both A and B to
Long and apply operator
■ If A or B is String coerce both A and B to String, compare lexically
■ If A is Comparable, then:
■ If A.compareTo(B) throws exception, error.
■ Otherwise use result of A.compareTo(B)
■ If B is Comparable, then:
■ If B.compareTo(A) throws exception, error.
■ Otherwise use result of B.compareTo(A)
■ Otherwise, error
=================================================




해결 방법은 아래와 같이 .charAt(0) 부분을 추가해주면 된다


<c:when test="${value eq 'x'.charAt(0)}">







참고 :
http://download.oracle.com/otn-pub/jcp/expression_language-2.2-mrel-eval-oth-JSpec/expression_language-2_2-mrel-spec.pdf

http://www.coderanch.com/t/569524/JSP/java/Issues-Character-comparison-JSTL



Excel Data read




라이브러리 설치

0. pip가 설치되어있지 않다면 먼저 설치

$ sudo easy_install pip


1. pip를 이용해서 openpyxl 라이브러리 설치

$ sudo pip install openpyxl




2. 기본 활용

>>> from openpyxl import load_workbook
>>> wb = load_workbook(filename = 'empty_book.xlsx')
>>> sheet_ranges = wb['range names']
>>> print(sheet_ranges['D18'].value)
3











로컬에서 MultiPartForm 전송시 유용한 class


import itertools
import mimetools
import mimetypes
from cStringIO import StringIO
import urllib
import urllib2

class MultiPartForm(object):
    """Accumulate the data to be used when posting a form."""

    def __init__(self):
        self.form_fields = []
        self.files = []
        self.boundary = mimetools.choose_boundary()
        return
    
    def get_content_type(self):
        return 'multipart/form-data; boundary=%s' % self.boundary

    def add_field(self, name, value):
        """Add a simple field to the form data."""
        self.form_fields.append((name, value))
        return

    def add_file(self, fieldname, filename, fileHandle, mimetype=None):
        """Add a file to be uploaded."""
        body = fileHandle.read()
        if mimetype is None:
            mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
        self.files.append((fieldname, filename, mimetype, body))
        return
    
    def __str__(self):
        """Return a string representing the form data, including attached files."""
        # Build a list of lists, each containing "lines" of the
        # request.  Each part is separated by a boundary string.
        # Once the list is built, return a string where each
        # line is separated by '\r\n'.  
        parts = []
        part_boundary = '--' + self.boundary
        
        # Add the form fields
        parts.extend(
            [ part_boundary,
              'Content-Disposition: form-data; name="%s"' % name,
              '',
              value,
            ]
            for name, value in self.form_fields
            )
        
        # Add the files to upload
        parts.extend(
            [ part_boundary,
              'Content-Disposition: file; name="%s"; filename="%s"' % \
                 (field_name, filename),
              'Content-Type: %s' % content_type,
              '',
              body,
            ]
            for field_name, filename, content_type, body in self.files
            )
        
        # Flatten the list and add closing boundary marker,
        # then return CR+LF separated data
        flattened = list(itertools.chain(*parts))
        flattened.append('--' + self.boundary + '--')
        flattened.append('')
        return '\r\n'.join(flattened)

if __name__ == '__main__':
    # Create the form with simple fields
    form = MultiPartForm()
    form.add_field('firstname', 'Doug')
    form.add_field('lastname', 'Hellmann')
    
    # Add a fake file
    form.add_file('biography', 'bio.txt', 
                  fileHandle=StringIO('Python developer and blogger.'))

    # Build the request
    request = urllib2.Request('http://localhost:8080/')
    request.add_header('User-agent', 'PyMOTW (http://www.doughellmann.com/PyMOTW/)')
    body = str(form)
    request.add_header('Content-type', form.get_content_type())
    request.add_header('Content-length', len(body))
    request.add_data(body)

    print
    print 'OUTGOING DATA:'
    print request.get_data()

    print
    print 'SERVER RESPONSE:'
    print urllib2.urlopen(request).read()


참고:
https://pymotw.com/2/urllib2/


UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)



문서 상단에 아래와 같이 선언시 해결 가능


import sys
reload(sys)
sys.setdefaultencoding('utf-8')




사용하면 위험하다는 의견과 괜찮다는 의견이 분분하긴 한데 테스트 결과 문제는 없었다.



참고 :
http://stackoverflow.com/questions/3828723/why-should-we-not-use-sys-setdefaultencodingutf-8-in-a-py-script

SyntaxError: Non-ASCII character ......  but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details



최상단에 해당 문서의 인코딩을 선언하면 된다.
# -*- coding: utf-8 -*-



 // 최대 바이트 제한
function fnMaxByte(e, max) {
    var $target = $(e.target);  
    var byteCount = getByteLength($target.val());  
    if (byteCount > max) {
        var rtnStr = $target.val();      
        var rtnByte = getByteLength(rtnStr);
        var leng = rtnStr.length;
        while (rtnByte > max) {
            rtnStr = rtnStr.substr(0, leng--);
            rtnByte = getByteLength(rtnStr);
        }
        $target.val(rtnStr);
    } else {
        $($target.closest('div.row')).find('.limitTextNum span').text(byteCount);    }
}


// 바이트 카운트
function getByteLength(s,b,i,c){
    for(b=i=0;c=s.charCodeAt(i++);b+=c>>11?3:c>>7?2:1);
    return b;
}





http://hangaebal.blogspot.kr/2015/09/javascript-string-byte-length.html

+ Recent posts