CodeIgniter는 널리 사용되는 경량 오프 소스 프레임워크로 PHP로 작성되었으며 MVC(Model-View-Controller) 아키텍처 패턴을 기반으로 한다. jQuery는 신속한 경량 오픈소스 Javascript 라이브러리로 HTML 페이지와 Ajax 상호 작용을 처리하는 과정을 단순하게 하기 위해 디자인되었다. 이 두 가지 도구를 함께 사용하면 유용한 웹 사이트와 애플리케이션을 신속하게 개발할 수 있는 강력한 기반을 구축할 수 있다.
이 기사에서는 이러한 두 시스템을 하나의 프레임워크에 통합하는 방법과 jQuery를 사용하여 기존 웹 애플리케이션의 UI를 개선하는 방법을 살펴본다. 독자가 CodeIgniter 버전 1.7.2 이상, MySQL 버전 4.1 이상을 설치했으며 이 두 가지 도구를 사용하는 데 익숙하다고 가정한다. 또한, jQuery 라이브러리 버전 1.4.2 이상이 필요하다. CodeIgniter를 처음 사용하거나 이와 관련된 내용을 신속하게 다시 살펴보고자 하는 경우에는 참고자료에 있는 링크를 통해 자세한 정보를 확인하도록 한다.
Web 2.0의 가장 중요한 특성 중 하나는 사용자 경험이 웹 사이트보다는 데스크탑 애플리케이션에 가깝다는 점이다. 특히, 웹 페이지와 상호 작용하기 위해 웹 서버와 "시각적인 통신"(예를 들면, 제출 단추를 클릭하고 웹 서버가 제출된 정보를 처리하기를 기다리면 전체 웹 페이지가 업데이트된 내용으로 새로 고쳐짐)을 할 필요가 없다. 그 대신 변경해야 하는 내용만 업데이트되고 나머지 페이지는 그대로 유지된다.
이러한 "제출 과정이 적은(submission-less)" 프로세스는 Ajax를 사용하여 처리하며 이렇게 함으로써 웹 페이지를 새로 고치지 않고도 웹 개발자는 웹 클라이언트(브라우저)와 웹 서버 간에 정보를 전송할 수 있게 된다. 더 좋은 점은 사용자가 직접 개입하지 않고도 이러한 정보 전달을 트리거할 수 있다는 점이다.
웹 페이지에서 Ajax를 사용하는 경우에는 웹 서버와 웹 페이지 간의 데이터 통신(송신 및 수신)이 비동기적으로 수행된다. 이러한 전송 데이터는 일반 텍스트이기 때문에 XML, HTML, JSON 또는 일반 텍스트와 같은 다양한 형식이 될 수 있다.
데이터는 실제로 XMLHttpRequest라고 하는 API 호출과 Javascript를 사용하여 전송되며 이 과정에서 jQuery가 중요해진다. jQuery 라이브러리에는 Ajax 사용과
관련된 매우 단순화된 프로세스가 있다.
그리고 이 라이브러리를 이용하면 Ajax를 더욱 쉽게 사용할 수 있을 뿐만 아니라 업데이트된 데이터를 표시하기도 훨씬 더 수월하다.
(Javascript를 사용하여 HTML DOM을 처리한 적이 있다면 이렇게 하는 것이 얼마나 수월한지 진정으로 알 수 있을 것이다.)
이 기사에서는 기존 웹 애플리케이션의 UI를 개선하는 과정을 통해 CodeIgniter와 jQuery를 함께 사용하는 것이 얼마나 단순하고 강력한지 살펴보기로 한다. 이 애플리케이션은 교사가 학급 활동과 이 활동에 참여하는 각 부모를 관리할 수 있게 설계되었다. 교사는 먼저 위원회에서 승인된 옵션 목록에서 학급 활동을 선택하여 각 활동에 맞는 날짜를 스케줄한다. 그러면 부모가 해당 사이트에 등록하여 자신의 아이의 연락처 정보를 입력한다. 부모는 학급 활동 목록을 보고 자신의 참여 레벨(소모품 구입, 준비 과정 참여, 조력, 활동 리더로 봉사)을 선택할 수 있다.
참고: 이 시스템은 어린이 스포츠 팀, YMCA 그룹 등에 쉽게 적용할 수 있다.
이 기사의 내용을 수행하기 위해 이 애플리케이션의 데이터베이스에 이벤트 100개, 부모 5명, 교사 1명을 로드하였다. 부모의 사용자 이름은 parent1, parent2, . . . parent5이다. 교사의 사용자 이름은 teacher이며 모든 암호는 ibm이다. 웹 애플리케이션과 데이터베이스를 다운로드하고 웹 서버에 설정하여 이 과정을 함께 수행하도록 하자. 이 애플리케이션을 수행하려면 CodeIgniter 프레임워크가 서버의 루트에 있어야 한다.
jQuery를 사용하려면 먼저 jQuery 라이브러리를 다운로드해야 한다. (관련 링크는 참고자료를 확인한다.) 릴리스된 각 버전에 해당하는 두 개의 파일이 제공된다. 하나는 압축이 해제된 파일이며 다른 하나는 "축소된" 파일(이 파일은 강력하게 압축된 버전이며 로드 속도가 빠르지만 원하더라도 추적할 수 없음)이다. 개발 과정에서는 압축 해제된 버전을 사용하고 프로덕션 상태에서는 축소된 버전을 사용하기를 권장한다.
다음은 jQuery 라이브러리 파일을 웹 서버의 루트에 있는 .assets/js 폴더에 저장한다. 그런 다음, 같은 폴더에 Listing 1에 표시된 것과 같이 새로운 파일 global.js를 작성한다. 이 폴더에 전체 애플리케이션의 Javascript 코드를 저장하게 된다.
Listing 1. jQuery를 사용하여 "Hello World" 표시하기
/* Global JavaScript File for working with jQuery library */
// execute when the HTML file's (document object model: DOM) has loaded
$(document).ready(function() {
alert ('Hello World');
});
|
이 기사에 있는 대부분의 애플리케이션에서는 jQuery 코드의 대부분이 $(document).ready() 함수 안에 존재한다.
이 함수는 HTML 파일의 DOM이 모두 로드된 직후에 자동으로 트리거된다.
애플리케이션이 이러한 두 가지 파일을 모두 로드하도록 Listing 2에서와 같이 ./system/application/views/template.php 파일을 편집한다.
Listing 2. jQuery와 글로벌 Javascript 파일 로드하기
<head> <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <link href="/assets/css/screen.css" rel="stylesheet" type="text/css" /> <!-- the following two lines load the jQuery library and JavaScript files --> <script src="/assets/js/jquery-1.4.2.js" type="text/javascript"></script> <script src="/assets/js/global.js" type="text/javascript"></script> <title><?php echo $title;?></title> </head> |
이제, 웹 사이트의 색인 페이지를 탐색한다. 웹 페이지가 로드되면 Javascript 경보를 통해 "Hello World"가 표시된다.
CodeIgniter 프레임워크에서 jQuery와 Ajax 사용하기
jQuery 라이브러리와 global.js 파일이 해당 위치에 저장되어 있으면 애플리케이션 인터페이스를 개선할 준비가 된 것이다. 아직 준비되지 않았으면 잠시 기다렸다가 부모와 교사로 로그인하여 시스템에서 활동이 어떻게 수행되는지 익숙해지도록 한다.
먼저 등록 페이지의 UI를 개선하도록 하자. 현재는 사용자 이름이 이미 사용되었는지 여부가 등록 페이지를 제출한 이후에 확인된다. 그러나 Ajax를 사용하면 페이지를 제출하지 않고도 서버측에서 유효성을 검증하여 그 결과를 리턴할 수 있다.
그렇게 하려면 username 필드의 onblur() 이벤트에 코드를 바인드해야 하며 이 이벤트는 사용자의 커서가 필드를 벗어날 때 트리거된다. Listing 3에는
업데이트된 global.js 파일이 표시되어 있다.
Listing 3. 사용자 이름이 이미 등록되었는지 확인하기
/* Global JavaScript File for working with jQuery library */
// execute when the HTML file's (document object model: DOM) has loaded
$(document).ready(function() {
/* USERNAME VALIDATION */
// use element id=username
// bind our function to the element's onblur event
$('#username').blur(function() {
// get the value from the username field
var username = $('#username').val();
// Ajax request sent to the CodeIgniter controller "ajax" method "username_taken"
// post the username field's value
$.post('/index.php/ajax/username_taken',
{ 'username':username },
// when the Web server responds to the request
function(result) {
// clear any message that may have already been written
$('#bad_username').replaceWith('');
// if the result is TRUE write a message to the page
if (result) {
$('#username').after('<div id="bad_username" style="color:red;">' +
'<p>(That Username is already taken. Please choose another.)</p></div>');
}
}
);
});
});
|
이 코드에서는 ID가 username인 DOM 요소를 사용하여 jQuery 오브젝트를 작성한다. 그런 다음, jQuery blur() 메소드를 호출하며 이 메소드는 username 필드의
onblur() 이벤트에 함수를 바인드한다. 이 함수는 Ajax를 사용하여 username 필드의 값을 CodeIgniter 제어기(ajax)와 메소드 username_taken에
전송한다. 그러면 기존의 오류 메시지는 모두 지워지며 Ajax 포스트 결과에 따라 오류 메시지가 표시되거나 그렇지 않게 된다.
다음은 ./system/application/controllers에서 ajax.php 파일을 작성한다. 이 파일은 jQuery Ajax .post() 메소드에서 참조한다. Listing 4에는 이 제어기의
소스 코드가 표시되어 있다.
(이 제어기의 이름을 ajax로 지정한 데는 특별한 이유가 없다. .post() 메소드에 있는 URL이 올바른 제어기를 참조하는 한, 이름은 어떻게 지정하든 관계가 없다.)
Listing 4. Ajax 요청을 처리하는 CodeIgniter 제어기
<?php
class Ajax extends Controller {
public function Ajax() {
parent::Controller();
}
public function username_taken()
{
$this->load->model('MUser', '', TRUE);
$username = trim($_POST['username']);
// if the username exists return a 1 indicating true
if ($this->MUser->username_exists($username)) {
echo '1';
}
}
}
/* End of file ajax.php */
/* Location: ./system/application/controllers/ajax.php */
|
username_taken() 메소드는 값을 리턴하지 않는다. 이 메소드는 오히려 응답을 반향하는데 이점이 중요하다고 할 수 있다. jQuery Ajax 요청은
웹 페이지에 데이터를 포스트하고 그 결과로 생성된 페이지 데이터를 사용하지 프로그램을 통해 메소드 자체에 접근하지는 않는다.
이제 첫 번째 Ajax 함수가 완료되었다. 등록 페이지를 탐색하고 이미 입력된 사용자 이름으로 등록하여 해당 오류 메시지를 확인한다.
흥미롭게도 jQuery 코드의 결과는 작성할 때 의도했던 것과는 다른 결과가 나온다.
Ajax 함수는 ID가 username인 필드에 바인드되어 Login 페이지에 username 필드를 삽입한다. Listing 5에는 jQuery 오브젝트를 수정하여
registration_form 양식 내에 있는 username 필드에만 바인드되도록 하는 방법이 표시되어 있다.
Listing 5. username 필드의 유효성 검증
/* USERNAME VALIDATION */
// use element id=username within the element id=registration_form
// bind our function to the element's onblur event
$('#registration_form').find('#username').blur(function() {
|
다음에는 Class Activity Listing 페이지의 UI를 개선한다. 특정 활동에 참여를 표시할 부모는 해당 단일 선택 단추를 클릭한 후, save 링크를 클릭하여 학급 활동 목록 페이지를 제출한다. UI를 개선하려면 save 링크를 클릭한 다음, 페이지를 제출해야 하는 과정을 제거해야 한다.
먼저 global.js 파일에 다음 코드를 추가한다. 프로세스를 보다 쉽게 설명하기 위해 코드를 Listing 6, Listing 7 및 Listing 8에 나누어 놓았다.
Listing 6. jQuery를 사용하여 관련된 요소 값 가져오기
/* AUTOSAVE PARTICIPATION */
// use input element name=participation_type_id and type=radio
// bind our function to the element's onclick event
$('input[name=participation_type_id]:radio').click(function() {
var participation_type_id = this.value;
// create global variables for use below
var class_activity_id, user_id;
// get the form's two hidden input elements
// each is a sibling of the parent of the clicked radio button
// store their values in the global variables
var hidden_elements = $(this).parent().siblings('input:hidden');
$(hidden_elements).map(function() {
if (this.name == 'class_activity_id') {
class_activity_id = this.value;
}
if (this.name == 'user_id') {
user_id = this.value;
}
});
|
함수는 이름인 participation_type_id인 모든 단일 선택 단추의 onclick() 이벤트에 바인드된다. 이 함수는 클릭한 단일 선택 단추의 값을
가져온다. 그런 다음, 일련의 체인 메소드를 사용하여 숨겨진 양식 요소를 리턴한다. map() 메소드는 자신의 함수를 통해 각 요소를 전달하고
class_activity_id와 user_id 값을 검색한다.
부모의 참여를 설정하는 데 필요한 값이 식별되면 코드에서 Listing 7에 표시된 바와 같이 Ajax 요청이 실행되어 이러한 정보가 저장된다. 이 요청에 대한 서버의 응답은 데이터를 반향하지 않으므로 jQuery 응답 함수는 빈 상태가 되며 실제로는 제거된다.
Listing 7. Ajax 요청을 CodeIgniter에 포스트하기
// Ajax request to CodeIgniter controller "ajax" method "update_user_participation"
// post the user_id, class_activity_id and participation_type_id fields' values
$.post('/index.php/ajax/update_user_participation',
{ 'user_id':user_id,
'class_activity_id':class_activity_id,
'participation_type_id':participation_type_id },
// when the Web server responds to the request
function(result) { }
);
|
마지막으로 jQuery next() 메소드를 사용하여 단일 선택 단추 옆에 있는 텍스트의 색상을 각 문자열을 대상으로 적절하게 변경한다.
이 코드는 Listing 8에 있다.
Listing 8. 동적으로 변경되는 단일 선택 단추 텍스트 색상
// set the text next to the clicked radio button to red
$(this).next().css("color", "red");
// set the text next to the remaining radio buttons to black
var other_r_buttons = $(this).siblings('input[name=participation_type_id]:radio');
$(other_r_buttons).map(function() {
$(this).next().css("color", "black");
});
});
|
이제까지 jQuery 코드를 작성했으므로 이제는 Listing 9에서와 같이 ajax 제어기의 update_user_participation() 메소드를 작성해야 한다.
Listing 9. CodeIgniter에서 사용자 참여 처리하기
public function update_user_participation()
{
$this->load->model('MActivity', '', TRUE);
$this->MActivity->set_user_participation($_POST);
}
|
이 메소드는 MActivity 모델에서 이미 확인한 set_user_participation() 메소드를 사용하며 이 메소드는 Ajax 요청을 통해 포스트된 변수를 취한다.
마지막으로 Listing 10에 표시된 바와 같이 ./system/application/controller/activity.php에 있는 save 링크를 주석 처리한다.
Listing 10. 불필요한 save 링크 제거하기
'<span style="style="white-space: nowrap;">'.
$participation_type_buttons.' '.
/* the save link is no longer needed
'<a href="" onclick="document.forms[\'form_'.$activity->id.'\'].submit();
return false;">save</a>'. */
'</span>'.
'</form>';
|
이제 부모의 참여를 변경할 수 있으며 페이지를 새로 고치지 않아도 변경된 내용이 자동으로 저장된다.
Ajax의 기능 중에서 가장 효과적이고 널리 사용되는 것은 자동 제안이나 자동 완료 기능이다. 교사로 로그인하여 Manage Class Activities를 클릭한다. 활동을
추가하려면 길게 표시되는 가능한 활동 목록을 사용자가 스크롤 다운해야 한다. UI를 개선하기 위해 Listing 11과 같이 autosuggest 함수에 바인드된 입력 필드를
./system/application/views/activity_master_listing.php 파일의 맨 위에 추가한다. 이렇게 하면 교사가 스케줄되지 않은 모든 활동을 이용하여 활동을 보다 쉽게 선택할 수 있게 된다.
Listing 11. 자동 제안 입력 필드 추가
<div id="select_anchor">
<a href="" onclick="$('#select_anchor').hide(100);
$('#select_activity').show(100);
return false;">
Select an unscheduled Activity to add >></a>
<br /><br />
</div>
<div id="select_activity" class="requested_activity" style="display:none;">
<table>
<caption> Select an unscheduled Activity</caption>
<tr class="odd_row_add">
<td>
Begin by typing a few letters of an activity name<br />
then select from the resulting list<br />
<br />
<input type="text" value="" id="class_activity"
onkeyup="autosuggest(this.value);" class="autosuggest_input" />
<div class="autosuggest" id="autosuggest_list"></div>
</td>
</tr>
</table>
</div>
|
Javascript onclick() 이벤트에 바운드된 메소드와 두 개의 jQuery 오브젝트를 주목하자. jQuery는 Javascript 라이브러리이며
$(document).ready() 함수 내에서 뿐만 아니라 애플리케이션 전체에서 Javascript와 원활하게 상호 작용할 수 있다는 점을 기억한다.
다음은 global.js 파일에 있는 $(document).ready() 함수 외부에서 다음과 같은 Javascript 함수를 구현한다. 이 함수는 class_activity 입력 필드의
onkeyup() 이벤트에 바인드된다. 소스 코드는 Listing 12에 표시되어 있다.
Listing 12. jQuery를 사용하여 자동 제안 구현하기
/* AUTOSUGGEST SEARCH */
// triggered by input field onkeyup
function autosuggest(str){
// if there's no text to search, hide the list div
if (str.length == 0) {
$('#autosuggest_list').fadeOut(500);
} else {
// first show the loading animation
$('#class_activity').addClass('loading');
// Ajax request to CodeIgniter controller "ajax" method "autosuggest"
// post the str parameter value
$.post('/index.php/ajax/autosuggest',
{ 'str':str },
function(result) {
// if there is a result, fill the list div, fade it in
// then remove the loading animation
if(result) {
$('#autosuggest_list').html(result);
$('#autosuggest_list').fadeIn(500);
$('#class_activity').removeClass('loading');
}
});
}
}
|
이 함수가 $(document).ready() 함수 내에 있지 않다고 해도 이 함수는 여전히 jQuery 오브젝트와 메소드를 사용한다. 이 함수의 jQuery .post() 메소드는
Ajax 제어기의 autosuggest() 메소드를 호출하여 정렬되지 않은 자동 제안 결과 목록을 반향한다.
Listing 13에는 이 코드가 표시되어 있다.
Listing 13. 자동 제안 결과의 검색 및 반향
public function autosuggest()
{
// escapes single and double quotes
$str = addslashes($_POST['str']);
$this->load->model('MActivity', '', TRUE);
$unscheduled_activities_qry = $this->MActivity->find_unscheduled_activities($str);
// echo a list where each li has a set_activity function bound to its onclick() event
echo '<ul>';
foreach ($unscheduled_activities_qry->result() as $activity) {
echo '<li onclick="set_activity(\''.addslashes($activity->name).'\'';
echo ', '.$activity->id.');">'.$activity->name.'</li>';
}
echo '</ul>';
}
|
다음은 데이터베이스에서 자동 제안 결과를 리턴하도록 find_unscheduled_activities() 메소드를 추가한다.
Listing 14에는 ./system/application/models/mactivity.php의 코드가 있다.
Listing 14. 데이터베이스에서 스케줄되지 않은 활동 쿼리하기
// Finds all unscheduled activities that match the passed string
function find_unscheduled_activities($str)
{
$this->db->select('id, name
FROM master_activity
WHERE name LIKE \''.$str.'%\'
AND id NOT IN
(SELECT master_activity_id FROM class_activity)
ORDER BY name', FALSE);
return $this->db->get();
}
|
또한, UI가 보다 명료하고 list 요소가 클릭 가능하도록 autosuggest <div>와 list에 스타일을 지정한다. ./assets/css/screen.css에 추가된 스타일은
Listing 15에 표시되어 있다.
Listing 15. 자동 제안 목록을 명료하고 클릭 가능하게 하기
/***************/
/* Autosuggest */
.autosuggest {
border:1px solid #000000;
display:none;
overflow:hidden;
padding:0px;
position:absolute;
width:200px;
z-index:1;
}
.autosuggest ul li {
background-color:#FFFFFF;
cursor:pointer;
display:block;
list-style:none;
padding:5px;
white-space:nowrap;
}
.autosuggest ul li:hover {
background-color:#316AC5;
color:#FFFFFF;
}
.loading{
background-image:url('../img/indicator.gif');
background-position:right;
background-repeat:no-repeat;
}
.autosuggest_input {
width:200px;
}
.table_header_add {
background-color:#FFCC66;
}
.odd_row_add {
background-color:#FFCC66;
}
|
이제 어느 정도 완성이 되었다. 필드에 문자를 입력하여 일련의 일치하는 활동을 검색할 수 있다. 이제 학급 활동을 선택하고 표시, 저장할 코드를 구현하도록 하자. 먼저, global.js 파일에 함수 두 개를 추가하여 활동 이름 필드를 설정하고 활동 정보가 있는 행을 표시한다. Listing 16에는 이러한 두 가지 기능을 하는 코드가 표시되어 있다.
Listing 16. 선택된 활동을 가져와서 표시하기
/* AUTOSUGGEST SET ACTIVITY */
// triggered by an onclick from any of the li's in the autosuggest list
// set the class_acitity field, wait and fade the autosuggest list
// then display the activity details
function set_activity(activity_name, master_activity_id) {
$('#class_activity').val(activity_name);
setTimeout("$('#autosuggest_list').fadeOut(500);", 250);
display_activity_details(master_activity_id);
}
/* AUTOSUGGEST DISPLAY ACTIVITY DETAILS */
// called by set_activity()
// get the HTML to display and display it
function display_activity_details(master_activity_id) {
// Ajax request to CodeIgniter controller "ajax" method "get_activity_html"
// post the master_class_activity parameter values
$.post('/index.php/ajax/get_activity_html',
{ 'master_activity_id':master_activity_id },
// when the Web server responds to the request
// replace the innerHTML of the select_activity element
function(result) {
$('#select_activity').html(result);
}
);
}
|
또한, 이 코드도 Ajax를 사용하여 선택된 활동을 표시하는 테이블 행을 가져온다. 해당 HTML은 Listing 17에 있는 코드에서 생성된다.
Listing 17. 활동을 표시하는 HTML 테이블 반향하기
public function get_activity_html()
{
$this->load->model('MActivity', '', TRUE);
$this->load->library('table');
$requested_activity_id = $_POST['master_activity_id'];
$requested_activity_qry =
$this->MActivity->get_requested_master_activity($requested_activity_id);
// code leveraged from /controllers/activity.php manage_class_listing() method
// generate HTML table from query results
$tmpl = array (
'table_open' => '<table>',
'heading_row_start' => '<tr class="table_header_add">',
'row_start' => '<tr class="odd_row_add">'
);
$this->table->set_template($tmpl);
$this->table->set_caption(' Add this Activity');
$this->table->set_empty(" ");
$this->table->set_heading('<span class="date_column">Date</span>',
'<span class="activity_name_column">Activity Name</span>',
'<span class="address_column">Address</span>',
'City', 'Details');
$table_row = array();
foreach ($requested_activity_qry->result() as $activity)
{
$m_id = $activity->master_activity_id;
$table_row = NULL;
$table_row[] = ''.
'<form action="" name="form_'.$m_id.'" method="post">'.
'<input type="hidden" name="master_activity_id" value="'.$m_id.'"/> '.
'<input type="text" name="activity_date" size="12" /> '.
'<input type="hidden" name="action" value="save" /> '.
'</form>'.
'<span class="help-text">format: MM-DD-YYYY</span><br/>'.
'<a href="" onclick="document.forms[\'form_'.$m_id.'\'].submit();'.
'return false;">save</a>';
$table_row[] = '<input type="text" value="'.$activity->name.
'" id="class_activity" onkeyup="autosuggest(this.value);"'.
'class="autosuggest_input" />'.
'<div class="autosuggest" id="autosuggest_list"></div>';
$table_row[] = htmlspecialchars($activity->address);
$table_row[] = htmlspecialchars($activity->city);
$table_row[] = htmlspecialchars($activity->details);
$this->table->add_row($table_row);
}
$requested_activities_table = $this->table->generate();
echo $requested_activities_table;
}
}
|
이 코드는 최종 테이블을 리턴하지 않고 반향하도록 약간 수정하여 활동 제어기에 활용되었다. 또한, Listing 18에 표시된 것과 같은 SQL 쿼리가 필요하며 이 쿼리 코드는 ./system/application/models/mactivity.php에 있다.
Listing 18. 요청된 마스터 활동 리턴하기
// Returns a single master activity record
public function get_requested_master_activity($id)
{
$this->db->select('id as master_activity_id, name, address, city, details');
$this->db->where('id', $id);
return $this->db->get('master_activity');
}
|
마지막으로 새 활동을 이미 추가할 수 있다고 하더라도 스케줄되지 않은 활동을 제거하고 활동 목록을 오름 차순으로 다시 정렬한다. MActivity 모델에서 업데이트된 SQL 코드는 Listing 19에 표시되어 있다.
Listing 19. 스케줄되지 않은 활동만 리턴하기
// Retrieve all master activity records
function list_class_activities($activity_id)
{
// get all records
if (!$activity_id) {
$this->db->select('ma.id as master_activity_id, ma.name,
ma.address, ma.city,
ma.details, ca.id as class_activity_id, ca.date
FROM master_activity ma
/*LEFT*/ JOIN class_activity ca ON ca.master_activity_id = ma.id
ORDER BY ca.date /*DESC*/, ma.name', FALSE);
return $this->db->get();
// get all records except the one being requested
} else {
$this->db->select('ma.id as master_activity_id, ma.name,
ma.address, ma.city,
ma.details, ca.id as class_activity_id, ca.date
FROM (SELECT * FROM master_activity
WHERE master_activity.id != '.$activity_id.') ma
/*LEFT*/ JOIN class_activity ca ON ca.master_activity_id = ma.id
ORDER BY ca.date /*DESC*/, ma.name', FALSE);
return $this->db->get();
}
}
|
UI에서 마지막으로 개선해야 할 사항은 시각적 캘린더를 사용하여 날짜를 입력하는 데 필요한 텍스트 입력 필드를 바꾸는 일이다. 이렇게 하려면 jQuery UI 날짜 선택기를 사용해야 하며 이 선택기는 널리 사용되는 jQuery UI 라이브러리 플러그인(jQuery 라이브러리의 오픈 소스 확장)이다. Listing 20와 같이 ./system/application/views/template.php 파일을 업데이트한다.
Listing 20. jQuery UI 날짜 선택기 삽입하기
<!-- including the jQuery UI Datepicker and styles -->
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"
type="text/javascript"></script>
<link href="/assets/css/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />
<style type="text/css">
/* jQuery UI sizing override */
.ui-widget {font-size:1em;}
</style>
|
<script> 태그에서는 다운로드된 jQuery 라이브러리를 사용하는 대신 jQuery UI와 같은 다양한 라이브러리를 위한 무료 저장소인 http://ajax.googleapis.com을
참조한다. CSS 파일과 이미지는 필수 스타일만 포함되도록 구성되었다(http://jqueryui.com/download). 마지막으로 jQuery UI 라이브러리는
본문 글꼴 크기가 62.5%라고 가정하여 빌드되므로 기본 글꼴 크기를 대체하여 글꼴 크기를 적절하게 조정한다.
날짜 선택기는 HTML 내에서 ID나 CSS 클래스에 바인드되어 작동한다. 활동 편집 기능을 처리하기 위해 ./system/application/controllers/activity.php 210 행에 있는
날짜 입력 필드에 date-picker 클래스를 지정한다. 이 코드는 Listing 21에 표시되어 있다.
Listing 21. 활동 편집용 date-picker 클래스 지정
// add the date-picker class to the date input field
'<input type="text" name="activity_date" size="12" value="'.
date('m/d/Y', strtotime($activity->date)).'" class="date-picker" /> '.
'<input type="hidden" name="action" value="update" /> '.
'</form>'.
'<span class="help-text">format: MM/DD/YYYY</span><br/>'.
|
활동 추가 기능을 처리하기 위해 Listing 22에 표시된 바와 같이 ./system/application/controllers/ajax.php 83 행에 있는 날짜 입력 필드에 동일한 클래스를 지정한다.
Listing 22. 활동 추가용 date-picker 클래스 지정
// add the date-picker class to the date input field
'<input type="text" name="activity_date" size="12" class="date-picker" /> '.
'<input type="hidden" name="action" value="save" /> '.
'</form>'.
'<span class="help-text">format: MM/DD/YYYY</span><br/>'.
|
마지막으로 학급 활동을 편집하거나 추가할 때 표시되도록 날짜 선택기를 바인드한다. global.js 파일에 있는 $(document).ready() 함수 안에 삽입할 코드는
Listing 23에 표시되어 있다.
Listing 23. 날짜 선택기를 클래스에 바인드하기
/* jQUERY UI CALENDAR PLUGIN */
// bind the Datepicker to the date-picker class
$(".date-picker").datepicker();
|
이제 학급 활동을 편집하도록 하자. 날짜 입력 필드에 커서를 놓으면 캘린더가 표시되며 이 캘린더를 통해 학급 활동 날짜를 선택할 수 있다. 그러나
활동을 추가하려고 하면 이 캘린더가 작동하지 않는다. 그 이유는 문서가 이미 로드된(Ajax의 사용으로) 이후에 활동을 추가하는 HTML이 작성되어
날짜 선택기가 날짜 입력 필드에 바인드되지 않았기 때문이다. 이러한 문제점을 수정하려면 Ajax 함수가 HTML을 작성한 후에 날짜 선택기를 날짜 입력 필드에
바인드해야 한다. global.js 파일에 있는 display_activity_details() 함수를 대상으로 이와 같이 변경한 내용이 Listing 24에 표시되어 있다.
Listing 24. 날짜 선택기를 날짜 추가 필드에 바인드하기
function(result) {
$('#select_activity').html(result);
// because the add datepicker is not loaded with the DOM
// manually add it after the date input field is written
$(".date-picker").datepicker();
}
|
이제는 날짜 선택기 캘린더를 사용하여 클래스 활동을 추가할 수 있다.
이제 작업이 모두 완료되었다. jQuery 오브젝트를 통해 DOM 처리를 결합하고 Ajax를 통해 원활하게 통신하여 이러한 애플리케이션의 UI를 대폭 개선하는 방법을 살펴보았다. 그리고 이러한 기능을 수행하는 코드는 대부분 매우 간단했다. 이제는 Ajax를 사용하여 학급 활동의 편집 과정이 인라인으로 처리되게 하거나 이 기사를 읽는 동안 경험했을 수 있는 기타 UI 개념을 구현함으로써 애플리케이션을 더욱 개선해야 하는 과제를 수행할 수 있다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| SQL file to create classroom database | classroom_database.zip | 15KB | HTTP |
| Full initial code base including CodeIgniter files | source_w_codeigniter.zip | 411KB | HTTP |
| The initial MVC files for this article | source_only.zip | 23KB | HTTP |
| The jQuery library v1.4.2 | jquery_library.zip | 45KB | HTTP |
| CSS files needed for jQuery UI Datepicker | jquery_datepicker.zip | 53KB | HTTP |
| Full final code base including CodeIgniter files | final_source_w_codeigniter.zip | 515KB | HTTP |
| The final MVC files from this article | final_source_only.zip | 124KB | HTTP |
교육
-
"Getting started with CodeIgniter"(developerWorks, 2008년 8월): CodeIgniter 프레임워크에 대한 우수한 소개 기사를 읽어보자.
-
"Developing dynamic Web sites with CodeIgniter"(developerWorks, 2010년 1월): CodeIgniter와 MVC 아키텍처를 보다 자세히 살펴보자.
-
CodeIgniter User Guide: CodeIgniter의 온라인 문서를 읽어보자.
-
developerWorks 웹 개발 영역: 웹 개발 영역에서는 Web 2.0 개발에 대한 도구와 정보를 볼 수 있다.
-
IBM 기술 이벤트 및 웹 캐스트: developerWorks의 기술 이벤트 및 웹 캐스트에 대한 최신 정보를 얻을 수 있다.
제품 및 기술 얻기
-
CodeIgniter: CodeIgniter 최신 버전을 다운로드할 수 있다.
-
MySQL: MySQL 최신 버전을 다운로드할 수 있다.
-
jQuery: jQuery 라이브러리 최신 버전을 다운로드하여 자세히 배워보자.
-
jQuery UI: jQuery UI 웹 사이트에서 추가 위젯을 다운로드하여 자세히 배워보자.
-
IBM 제품 평가판: 이러한 평가판을 다운로드하거나 DB2®, Lotus®, Rational®, Tivoli® 및
WebSphere®의 애플리케이션 개발 도구 및 미들웨어 제품을 사용해 볼 수 있다.
토론
-
developerWorks 블로그: 블로그를 읽어 보고 developerWorks community에 참여하자.

With 20 years of experience in the high-tech industry, Kevin Howard Goldberg is a technology executive, author, and consultant residing in Westlake Village, Calif. He currently serves as CTO at imagistic, an award-winning digital marketing and technology company, which he co-founded in 1997. An expert on Web development and technology, he serves on the Santa Monica College Computer Science Advisory Board and held senior positions at Film Roman, Lionsgate, and Philips Interactive Media. He is the author of XML: Visual QuickStart Guide (2nd Edition), (PeachPit Press, 2008). You can reach him at http://kehogo.com/contact.