[jsp] include

프로그래밍/Web 2011. 5. 25. 13:06 Posted by galad
http://www.aboutjsp.com/lec/include.jsp

<jsp:include page="aaa.jsp" flush="true" />
=> JSP Action 구문의 include 는 include되는 파일과 include 시키는 파일를 각각 컴파일 한후 두 파일의 실행 결과를 한곳에 합쳐서 출력. 완전히 "별도로" 동작

<%@include file="bbb.jsp" %>
=>
include 지시어 와 Action 구문과의 가장 큰 차이점은 include 지시어는 컴파일 되기전에 파일이 내용이 합쳐진다는 것입니다.  자신의 문서내에 포함하여 하나의 파일로 인식

[jQuery] form validation

프로그래밍/Web 2011. 3. 2. 15:24 Posted by galad
http://bassistance.de/jquery-plugins/jquery-plugin-validation/

간단하게 쓰기. class만 맞춰주면 OK.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>이미지 추가 생성 화면</title>

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/cms/make_new_image.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/cms/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/cms/jquery/jquery.validate.js"></script>

<script type="text/javascript">
$(document).ready(function(){
    $("#mainForm").validate();
});
</script>
</head>
<body>
<form action="" id="mainForm">
컨텐트 종류 <s:select name="contentType" list="contentTypeList" listValue="label" listKey="key"></s:select>
<br>
원본 메타 필드명 <s:textfield name="srcMeta" cssClass="required"></s:textfield>
<br>
대상 메타 필드명 <s:textfield name="destMeta" cssClass="required"></s:textfield>
<br>
리사이즈 크기 : 가로 <s:textfield name="width" cssClass="required number"></s:textfield> 세로 <s:textfield name="height" cssClass="required number"></s:textfield>
<br>
<s:submit></s:submit>
</form>
</body>
</html>


경고문구 css 설정하기
label.error {
    /* remove the next line when you have trouble in IE6 with labels in list */
    color: red;
    font-style: italic
}

그밖의 여러가지 사용법 - 나만의 유효성검사룰 설정하기, ajax 등은 예제 참고.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="org.apache.commons.lang.StringUtils"%>
<%@ page import="com.omp.commons.utils.SessionUtil" %>
<%@ page import="com.omp.bp.cms.member.MemberConstants"%>
<%@ page import="com.omp.bp.cms.member.model.LoginUserInfo" %>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>이미지 추가 생성 화면</title>

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/cms/make_new_image.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/cms/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/cms/jquery/jquery.validate.js"></script>

<script type="text/javascript">
var m_browser;
var m_version;

function detectBrowser() {
    if($.browser.msie) {
        m_browser = "msie";
    }
    else if($.browser.safari) {
        m_browser = "safari";
    }
    else if($.browser.opera) {
        m_browser = "opera";
    }
    else if($.browser.mozilla) {
        m_browser = "mozilla";
    }

    m_version = $.browser.version;
    //alert(m_browser + " " + m_version);
}

$(document).ready(function(){
    detectBrowser(); // browser/version check

    // 폼 유효성 검사
    $("#mainForm").validate({
        submitHandler: function(form) {
            // do other stuff for a valid form
            disableSubmit();
            form.submit();
        }
    });

    /*$("#submitBtn").click(function(){ // 유효성 검사 통과했을 때만 실행하도록 수정
        disableSubmit();
    });*/

    parentResize(); // admin poc 화면 크기 조절용
});

function disableSubmit() {
    $("#submitBtn").hide();
    $("#submitLbl").show();
}

function parentResize() {
<%
    LoginUserInfo loginInfo = (LoginUserInfo)SessionUtil.getMemberSession(request);
    boolean isAdmin = StringUtils.equalsIgnoreCase(loginInfo.getMemberType(), MemberConstants.MEMBER_TYPE_ADMIN);
%>
    //운영자면 adminpoc의 프레임 크기 조절용 스크립트를 실행
    var isAdmin = <%=isAdmin%>;
    if(isAdmin) {
        rsize();
    }
}

function rsize() {
    var iframe = document.getElementById( 'inneriframe' );
    var height = Math.max( 200, document.body.scrollHeight + 500 );
    iframe.src = '<%=loginInfo.getAdminpocResizeUrl()%>?height='+height;
}
</script>
</head>
<body>
<form action="${pageContext.request.contextPath}/common/makeNewImage.omp" id="mainForm" method="post">
컨텐트 종류 <s:select name="contentType" list="contentTypeList" listValue="label" listKey="key"></s:select>
<br>
원본 메타 필드명 <s:textfield name="srcMeta" cssClass="required"></s:textfield>
<br>
대상 메타 필드명 <s:textfield name="destMeta" cssClass="required"></s:textfield>
<br>
리사이즈 크기 : 가로 <s:textfield name="width" cssClass="required number"></s:textfield> 세로 <s:textfield name="height" cssClass="required number"></s:textfield>
<br>
<s:submit id="submitBtn" value="이미지 생성 시작"></s:submit><label id="submitLbl" style="display: none;">이미지 생성 처리중...</label>
</form>
</body>
</html>



'프로그래밍 > Web' 카테고리의 다른 글

[jsp] include  (0) 2011.05.25
[jsp/servlet] jsp 와 servlet 의 차이  (0) 2010.10.29
[펌] jQuery Fundamentals  (1) 2010.10.07
[html] 웹페이지에서 마우스 툴팁(Tooltip; 말풍선) 태그(Tag)  (0) 2010.05.31
[script] 정규식  (0) 2010.05.20
http://nicho.tistory.com/131
http://www.terms.co.kr/servlet.htm

서블릿은 멀티쓰레딩에 의해 사용자 요구를 처리하고 가공해서 이에 대한 결과를 내보내게 된다. CGI가 클라이언트 프로세스로 처리하는데 반해 서블릿은 클라이언트를 쓰레드로 처리한다. 그래서 많은 클라이언트의 요구를 효과적으로 처리할 수 있다. 서블릿 객체는 쓰레드가 여러 개 돌아가면서 처리하기 때문에 서블릿 메소드들은 반드시 멀티쓰레드에 대한 고려를 해야한다.

 JSP와 서블릿은 자바 기반으로 만들어진 웹 프로그래밍 언어이다. 서블릿이 자바 코드에 의존적이라면 JSP는 덜 의존적이라 프로그래밍하기가 더 쉽고 편하다. JSP와 서블릿은 같은 처리 구조를 가진다. 엄밀히 말하면, JSP는 페이지 요청이 있을 시에는 최초에 한 번 자바 코드로 변환된 후 서블릿 클래스로 컴파일된다. 결론적으로 JSP는 실행시 서블릿으로 변환된다. 단 한번만 서블릿으로 변경되며 코드를 수정하기 전까지 재 변환 작업이 일어나지 않기 때문에 수행 속도는 JSP나 서블릿간에 별차이가 없다.
 
 서블릿과 JSP는 상호 연계되어 JSP에서 정적인 부분을 담당하고, 서블릿은 보다 동적인 처리를 위한 부분으로 사용되어 보다 효율적인 웹사이트를 구성할수 있다. JSP는 주로 사용자용 뷰(view)의 구현에 사용되고 서블릿은 사용자의 뷰와 프로그램 로저 사이를 제어해주는 역활을 주로 사용한다.

서블릿은 서버에서 실행되는 작은 프로그램이다. 이 용어는 웹 페이지와 함께 별도의 파일로 보내지는 작은 프로그램인 자바 애플릿의 맥락에서 만들어진 신조어이다. 자바 애플릿들은 사용자를 위해 간단한 계산업무를 수행하거나 사용자의 반응에 기반하여 이미지를 위치시키는 등과 같은 서비스를 위해 대개 클라이언트에서 실행되도록 만들어진다.

그러나, 사용자의 입력에 따라 데이터베이스와 연계되는 프로그램들은 서버에서 실행될 필요가 있다. 보통, 이러한 것들은 CGI를 이용하여 구현된다. 그러나, 서버에서 실행되는 자바 가상머신을 이용하면, 그러한 프로그램들을 자바 언어로 구현할 수 있다. 서버에 있는 자바 서블릿의 장점은 CGI 응용프로그램보다 더 빠르게 실행될 수 있다는 것이다. 서블릿은 각 사용자의 요청마다 별도의 프로세스가 생기는 대신, 단 하나의 데몬 프로세스 내에서 스레드로 호출되는데, 이는 각 요구에 따른 시스템 오버헤드가 적다는 것을 의미한다.


결국,
jsp 나 servlet 이나 결론적으로는 같음.
단, jsp는 서버에서 서블릿으로 변환되어 - 처음 한번만 - 실행됨
jsp 가 view단을 처리하기에 편리함. 서블릿의 경우엔 모두 프로그램적으로 처리해야함(out.println("<html>"); 이런 식으로)

MVC는 각각의 효율성을 봐서 V를 jsp, C를 서블릿에 맡긴 것.

다 배웠던 건데 왜 싹 다 까먹었나 ㅡ.ㅡ;;

'프로그래밍 > Web' 카테고리의 다른 글

[jsp] include  (0) 2011.05.25
[jQuery] form validation  (0) 2011.03.02
[펌] jQuery Fundamentals  (1) 2010.10.07
[html] 웹페이지에서 마우스 툴팁(Tooltip; 말풍선) 태그(Tag)  (0) 2010.05.31
[script] 정규식  (0) 2010.05.20

[펌] jQuery Fundamentals

프로그래밍/Web 2010. 10. 7. 10:46 Posted by galad
http://jqfundamentals.com/book/book.html

아래의 내용은 위의 링크의 내용을 그대로 복사한 것입니다.
단지 보존의 목적으로만 사용함을 밝힙니다.

With contributions by James Padolsey, Paul Irish, and others. See the GitHub repository for a complete history of contributions.

Licensed by Rebecca Murphey under the Creative Commons Attribution-Share Alike 3.0 United States license. You are free to copy, distribute, transmit, and remix this work, provided you attribute the work to Rebecca Murphey as the original author and reference the GitHub repository for the work. If you alter, transform, or build upon this work, you may distribute the resulting work only under the same, similar or a compatible license. Any of the above conditions can be waived if you get permission from the copyright holder. For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to the license.


Table of Contents

1. Welcome
Getting the Code
Software
Adding JavaScript to Your Page
JavaScript Debugging
Exercises
Conventions used in this book
Reference Material
I. JavaScript 101
2. JavaScript Basics
Overview
Syntax Basics
Operators
Basic Operators
Operations on Numbers & Strings
Logical Operators
Comparison Operators
Conditional Code
Truthy and Falsy Things
Conditional Variable Assignment with The Ternary Operator
Switch Statements
Loops
The for loop
The while loop
The do-while loop
Breaking and continuing
Reserved Words
Arrays
Objects
Functions
Using Functions
Self-Executing Anonymous Functions
Functions as Arguments
Testing Type
Scope
Closures
II. jQuery: Basic Concepts
3. jQuery Basics
$(document).ready()
Selecting Elements
Does My Selection Contain Any Elements?
Saving Selections
Refining & Filtering Selections
Selecting Form Elements
Working with Selections
Chaining
Getters & Setters
CSS, Styling, & Dimensions
Using CSS Classes for Styling
Dimensions
Attributes
Traversing
Manipulating Elements
Getting and Setting Information about Elements
Moving, Copying, and Removing Elements
Creating New Elements
Manipulating Attributes
Exercises
Selecting
Traversing
Manipulating
4. jQuery Core
$ vs $()
Utility Methods
Checking types
Data Methods
Feature & Browser Detection
Avoiding Conflicts with Other Libraries
5. Events
Overview
Connecting Events to Elements
Connecting Events to Run Only Once
Disconnecting Events
Namespacing Events
Inside the Event Handling Function
Triggering Event Handlers
Increasing Performance with Event Delegation
Unbinding Delegated Events
Event Helpers
$.fn.hover
$.fn.toggle
Exercises
Create an Input Hint
Add Tabbed Navigation
6. Effects
Overview
Built-in Effects
Changing the Duration of Built-in Effects
Doing Something when an Effect is Done
Custom Effects with $.fn.animate
Easing
Managing Effects
Exercises
Reveal Hidden Text
Create Dropdown Menus
Create a Slideshow
7. Ajax
Overview
Key Concepts
GET vs. Post
Data Types
A is for Asynchronous
Same-Origin Policy and JSONP
Ajax and Firebug
jQuery's Ajax-Related Methods
$.ajax
Convenience Methods
$.fn.load
Ajax and Forms
Working with JSONP
Ajax Events
Exercises
Load External Content
Load Content Using JSON
8. Plugins
What exactly is a plugin?
How to create a basic plugin
Finding & Evaluating Plugins
Writing Plugins
Writing Stateful Plugins with the jQuery UI Widget Factory
Adding Methods to a Widget
Working with Widget Options
Adding Callbacks
Cleaning Up
Conclusion
Exercises
Make a Table Sortable
Write a Table-Striping Plugin
III. Advanced Topics
This Section is a Work in Progress
9. Performance Best Practices
Cache length during loops
Append new content outside of a loop
Keep things DRY
Beware anonymous functions
Optimize Selectors
ID-Based Selectors
Specificity
Avoid the Universal Selector
Use Event Delegation
Detach Elements to Work With Them
Use Stylesheets for Changing CSS on Many Elements
Use $.data Instead of $.fn.data
Don't Act on Absent Elements
Variable Definition
Conditionals
Don't Treat jQuery as a Black Box
10. Code Organization
Overview
Key Concepts
Encapsulation
The Object Literal
The Module Pattern
Managing Dependencies
Getting RequireJS
Using RequireJS with jQuery
Creating Reusable Modules with RequireJS
Optimizing Your Code: The RequireJS Build Tool
Exercises
Create a Portlet Module
11. Custom Events
Introducing Custom Events
A Sample Application

List of Examples

1.1. An example of inline Javascript
1.2. An example of including external JavaScript
1.3. Example of an example
2.1. A simple variable declaration
2.2. Whitespace has no meaning outside of quotation marks
2.3. Parentheses indicate precedence
2.4. Tabs enhance readability, but have no special meaning
2.5. Concatenation
2.6. Multiplication and division
2.7. Incrementing and decrementing
2.8. Addition vs. concatenation
2.9. Forcing a string to act as a number
2.10. Forcing a string to act as a number (using the unary-plus operator)
2.11. Logical AND and OR operators
2.12. Comparison operators
2.13. Flow control
2.14. Values that evaluate to true
2.15. Values that evaluate to false
2.16. The ternary operator
2.17. A switch statement
2.18. Loops
2.19. A typical for loop
2.20. A typical while loop
2.21. A while loop with a combined conditional and incrementer
2.22. A do-while loop
2.23. Stopping a loop
2.24. Skipping to the next iteration of a loop
2.25. A simple array
2.26. Accessing array items by index
2.27. Testing the size of an array
2.28. Changing the value of an array item
2.29. Adding elements to an array
2.30. Working with arrays
2.31. Creating an "object literal"
2.32. Function Declaration
2.33. Named Function Expression
2.34. A simple function
2.35. A function that returns a value
2.36. A function that returns another function
2.37. A self-executing anonymous function
2.38. Passing an anonymous function as an argument
2.39. Passing a named function as an argument
2.40. Testing the type of various variables
2.41. Functions have access to variables defined in the same scope
2.42. Code outside the scope in which a variable was defined does not have access to the variable
2.43. Variables with the same name can exist in different scopes with different values
2.44. Functions can "see" changes in variable values after the function is defined
2.45. Scope insanity
2.46. How to lock in the value of i?
2.47. Locking in the value of i with a closure
3.1. A $(document).ready() block
3.2. Shorthand for $(document).ready()
3.3. Passing a named function instead of an anonymous function
3.4. Selecting elements by ID
3.5. Selecting elements by class name
3.6. Selecting elements by attribute
3.7. Selecting elements by compound CSS selector
3.8. Pseudo-selectors
3.9. Testing whether a selection contains elements
3.10. Storing selections in a variable
3.11. Refining selections
3.12. Using form-related pseduo-selectors
3.13. Chaining
3.14. Formatting chained code
3.15. Restoring your original selection using $.fn.end
3.16. The $.fn.html method used as a setter
3.17. The html method used as a getter
3.18. Getting CSS properties
3.19. Setting CSS properties
3.20. Working with classes
3.21. Basic dimensions methods
3.22. Setting attributes
3.23. Getting attributes
3.24. Moving around the DOM using traversal methods
3.25. Iterating over a selection
3.26. Changing the HTML of an element
3.27. Moving elements using different approaches
3.28. Making a copy of an element
3.29. Creating new elements
3.30. Creating a new element with an attribute object
3.31. Getting a new element on to the page
3.32. Creating and adding an element to the page at the same time
3.33. Manipulating a single attribute
3.34. Manipulating multiple attributes
3.35. Using a function to determine an attribute's new value
4.1. Checking the type of an arbitrary value
4.2. Storing and retrieving data related to an element
4.3. Storing a relationship between elements using $.fn.data
4.4. Putting jQuery into no-conflict mode
4.5. Using the $ inside a self-executing anonymous function
5.1. Event binding using a convenience method
5.2. Event biding using the $.fn.bind method
5.3. Event binding using the $.fn.bind method with data
5.4. Switching handlers using the $.fn.one method
5.5. Unbinding all click handlers on a selection
5.6. Unbinding a particular click handler
5.7. Namespacing events
5.8. Preventing a link from being followed
5.9. Triggering an event handler the right way
5.10. Event delegation using $.fn.delegate
5.11. Event delegation using $.fn.live
5.12. Unbinding delegated events
5.13. The hover helper function
5.14. The toggle helper function
6.1. A basic use of a built-in effect
6.2. Setting the duration of an effect
6.3. Augmenting jQuery.fx.speeds with custom speed definitions
6.4. Running code when an animation is complete
6.5. Run a callback even if there were no elements to animate
6.6. Custom effects with $.fn.animate
6.7. Per-property easing
7.1. Using the core $.ajax method
7.2. Using jQuery's Ajax convenience methods
7.3. Using $.fn.load to populate an element
7.4. Using $.fn.load to populate an element based on a selector
7.5. Turning form data into a query string
7.6. Creating an array of objects containing form data
7.7. Using YQL and JSONP
7.8. Setting up a loading indicator using Ajax Events
8.1. Creating a plugin to add and remove a class on hover
8.2. The Mike Alsup jQuery Plugin Development Pattern
8.3. A simple, stateful plugin using the jQuery UI widget factory
8.4. Passing options to a widget
8.5. Setting default options for a widget
8.6. Creating widget methods
8.7. Calling methods on a plugin instance
8.8. Responding when an option is set
8.9. Providing callbacks for user extension
8.10. Binding to widget events
8.11. Adding a destroy method to a widget
10.1. An object literal
10.2. Using an object literal for a jQuery feature
10.3. The module pattern
10.4. Using the module pattern for a jQuery feature
10.5. Using RequireJS: A simple example
10.6. A simple JavaScript file with dependencies
10.7. Defining a RequireJS module that has no dependencies
10.8. Defining a RequireJS module with dependencies
10.9. Defining a RequireJS module that returns a function
10.10. A RequireJS build configuration file

jQuery is fast becoming a must-have skill for front-end developers. The purpose of this book is to provide an overview of the jQuery JavaScript library; when you're done with the book, you should be able to complete basic tasks using jQuery, and have a solid basis from which to continue your learning. This book was designed as material to be used in a classroom setting, but you may find it useful for individual study.

This is a hands-on class. We will spend a bit of time covering a concept, and then you’ll have the chance to work on an exercise related to the concept. Some of the exercises may seem trivial; others may be downright daunting. In either case, there is no grade; the goal is simply to get you comfortable working your way through problems you’ll commonly be called upon to solve using jQuery. Example solutions to all of the exercises are included in the sample code.

The code we’ll be using in this book is hosted in a repository on Github. You can download a .zip or .tar file of the code, then uncompress it to use it on your server. If you’re git-inclined, you’re welcome to clone or fork the repository.

Logical operators allow you to evaluate a series of operands using AND and OR operations.


Though it may not be clear from the example, the || operator returns the value of the first truthy operand, or, in cases where neither operand is truthy, it'll return the last of both operands. The &&operator returns the value of the first false operand, or the value of the last operand if both operands are truthy.

Be sure to consult the section called “Truthy and Falsy Things” for more details on which values evaluate to true and which evaluate to false.

Note

You'll sometimes see developers use these logical operators for flow control instead of using if statements. For example:

// do something with foo if foo is truthy
foo && doSomething(foo);

// set bar to baz if baz is truthy;
// otherwise, set it to the return
// value of createBar()
var bar = baz || createBar();

This style is quite elegant and pleasantly terse; that said, it can be really hard to read, especially for beginners. I bring it up here so you'll recognize it in code you read, but I don't recommend using it until you're extremely comfortable with what it means and how you can expect it to behave.

Sometimes you only want to run a block of code under certain conditions. Flow control — via if andelse blocks — lets you run code only under certain conditions.


Note

While curly braces aren't strictly required around single-line if statements, using them consistently, even when they aren't strictly required, makes for vastly more readable code.

Be mindful not to define functions with the same name multiple times within separate if/elseblocks, as doing so may not have the expected result.

Loops let you run a block of code a certain number of times.


Note that in 
Example 2.18, “Loops” even though we use the keyword var before the variable namei, this does not "scope" the variable i to the loop block. We'll discuss scope in depth later in this chapter.

Functions contain blocks of code that need to be executed repeatedly. Functions can take zero or more arguments, and can optionally return a value.

Functions can be created in a variety of ways:



I prefer the named function expression method of setting a function's name, for some rather in-depth and technical reasons. You are likely to see both methods used in others' JavaScript code.

"Scope" refers to the variables that are available to a piece of code at a given time. A lack of understanding of scope can lead to frustrating debugging experiences.

When a variable is declared inside of a function using the var keyword, it is only available to code inside of that function -- code outside of that function cannot access the variable. On the other hand, functions defined inside that function will have access to to the declared variable.

Furthermore, variables that are declared inside a function without the var keyword are not local to the function -- JavaScript will traverse the scope chain all the way up to the window scope to find where the variable was previously defined. If the variable wasn't previously defined, it will be defined in the global scope, which can have extremely unexpected consequences;






The most basic concept of jQuery is to “select some elements and do something with them.” jQuery supports most CSS3 selectors, as well as some non-standard selectors. For a complete selector reference, visit http://api.jquery.com/category/selectors/.

Following are a few examples of common selection techniques.






Note

When you use the :visible and :hidden pseudo-selectors, jQuery tests the actual visibility of the element, not its CSS visibility or display — that is, it looks to see if the element's physical height and width on the page are both greater than zero. However, this test doesn't work with <tr> elements; in this case, jQuery does check the CSS display property, and considers an element hidden if its display property is set to none. Elements that have not been added to the DOM will always be considered hidden, even if the CSS that would affect them would render them visible. (See the Manipulation section later in this chapter to learn how to create and add elements to the DOM.)

For reference, here is the code jQuery uses to determine whether an element is visible or hidden, with comments added for clarity:

jQuery.expr.filters.hidden = function( elem ) {
    var width = elem.offsetWidth, height = elem.offsetHeight,
        skip = elem.nodeName.toLowerCase() === "tr";

    // does the element have 0 height, 0 width, 
    // and it's not a <tr>?
    return width === 0 && height === 0 && !skip ?

        // then it must be hidden
        true :

        // but if it has width and height 
        // and it's not a <tr>
        width > 0 && height > 0 && !skip ?

            // then it must be visible
            false :

            // if we get here, the element has width
            // and height, but it's also a <tr>,
            // so check its display property to
            // decide whether it's hidden
            jQuery.curCSS(elem, "display") === "none";
};

jQuery.expr.filters.visible = function( elem ) {
    return !jQuery.expr.filters.hidden( elem );
};

Every time you make a selection, a lot of code runs, and jQuery doesn't do caching of selections for you. If you've made a selection that you might need to make again, you should save the selection in a variable rather than making the selection repeatedly.


Note

In Example 3.10, “Storing selections in a variable”, the variable name begins with a dollar sign. Unlike in other languages, there's nothing special about the dollar sign in JavaScript -- it's just another character. We use it here to indicate that the variable contains a jQuery object. This practice -- a sort of Hungarian notation -- is merely convention, and is not mandatory.

Once you've stored your selection, you can call jQuery methods on the variable you stored it in just like you would have called them on the original selection.

Note

A selection only fetches the elements that are on the page when you make the selection. If you add elements to the page later, you'll have to repeat the selection or otherwise add them to the selection stored in the variable. Stored selections don't magically update when the DOM changes.

Once you have a selection, you can call methods on the selection. Methods generally come in two different flavors: getters and setters. Getters return a property of the first selected element; setters set a property on all selected elements.

jQuery includes a handy way to get and set CSS properties of elements.

Note

CSS properties that normally include a hyphen need to be camel cased in JavaScript. For example, the CSS property font-size is expressed asfontSize in JavaScript.



Note the style of the argument we use on the second line -- it is an object that contains multiple properties. This is a common way to pass multiple arguments to a function, and many jQuery setter methods accept objects to set mulitple values at once.

Once you've made a selection, the fun begins. You can change, move, remove, and clone elements. You can also create new elements via a simple syntax.

For complete documentation of jQuery manipulation methods, visithttp://api.jquery.com/category/manipulation/.

There are any number of ways you can change an existing element. Among the most common tasks you'll perform is changing the inner HTML or attribute of an element. jQuery offers simple, cross-browser methods for these sorts of manipulations. You can also get information about elements using many of the same methods in their getter incarnations. We'll see examples of these throughout this section, but specifically, here are a few methods you can use to get and set information about elements.

Note

Changing things about elements is trivial, but remember that the change will affect all elements in the selection, so if you just want to change one element, be sure to specify that in your selection before calling a setter method.

Note

When methods act as getters, they generally only work on the first element in the selection, and they do not return a jQuery object, so you can't chain additional methods to them. One notable exception is $.fn.text; as mentioned below, it gets the text for all elements in the selection.

$.fn.html

Get or set the html contents.

$.fn.text

Get or set the text contents; HTML will be stripped.

$.fn.attr

Get or set the value of the provided attribute.

$.fn.width

Get or set the width in pixels of the first element in the selection as an integer.

$.fn.height

Get or set the height in pixels of the first element in the selection as an integer.

$.fn.position

Get an object with position information for the first element in the selection, relative to its first positioned ancestor. This is a getter only.

$.fn.val

Get or set the value of form elements.


There are a variety of ways to move elements around the DOM; generally, there are two approaches:

  • Place the selected element(s) relative to another element

  • Place an element relative to the selected element(s)

For example, jQuery provides $.fn.insertAfter and $.fn.after. The $.fn.insertAftermethod places the selected element(s) after the element that you provide as an argument; the$.fn.after method places the element provided as an argument after the selected element. Several other methods follow this pattern: $.fn.insertBefore and $.fn.before;$.fn.appendTo and $.fn.append; and $.fn.prependTo and $.fn.prepend.

The method that makes the most sense for you will depend on what elements you already have selected, and whether you will need to store a reference to the elements you're adding to the page. If you need to store a reference, you will always want to take the first approach -- placing the selected elements relative to another element -- as it returns the element(s) you're placing. In this case,$.fn.insertAfter, $.fn.insertBefore, $.fn.appendTo, and $.fn.prependTo will be your tools of choice.


jQuery offers a trivial and elegant way to create new elements using the same $() method you use to make selections.



Note that in the attributes object we included as the second argument, the property name class is quoted, while the property names text and href are not. Property names generally do not need to be quoted unless they are reserved words (as class is in this case).

When you create a new element, it is not immediately added to the page. There are several ways to add an element to the page once it's been created.


Strictly speaking, you don't have to store the created element in a variable -- you could just call the method to add the element to the page directly after the $(). However, most of the time you will want a reference to the element you added, so you don't need to select it later.

You can even create an element as you're adding it to the page, but note that in this case you don't get a reference to the newly created element.


Note

The syntax for adding new elements to the page is so easy, it's tempting to forget that there's a huge performance cost for adding to the DOM repeatedly. If you are adding many elements to the same container, you'll want to concatenate all the html into a single string, and then append that string to the container instead of appending the elements one at a time. You can use an array to gather all the pieces together, then join them into a single string for appending.

var myItems = [], $myList = $('#myList');

for (var i=0; i<100; i++) {
    myItems.push('<li>item ' + i + '</li>');
}

$myList.append(myItems.join(''));

jQuery offers several utility methods in the $ namespace. These methods are helpful for accomplishing routine programming tasks. Below are examples of a few of the utility methods; for a complete reference on jQuery utility methods, visit http://api.jquery.com/category/utilities/.

$.trim

Removes leading and trailing whitespace.

$.trim('    lots of extra whitespace    ');
// returns 'lots of extra whitespace'
$.each

Iterates over arrays and objects.

$.each([ 'foo', 'bar', 'baz' ], function(idx, val) {
    console.log('element ' + idx + 'is ' + val);
});

$.each({ foo : 'bar', baz : 'bim' }, function(k, v) {
    console.log(k + ' : ' + v);
});

Note

There is also a method $.fn.each, which is used for iterating over a selection of elements.

$.inArray

Returns a value's index in an array, or -1 if the value is not in the array.

var myArray = [ 1, 2, 3, 5 ];

if ($.inArray(4, myArray) !== -1) {
    console.log('found it!');
}
$.extend

Changes the properties of the first object using the properties of subsequent objects.

var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };

var newObject = $.extend(firstObject, secondObject);
console.log(firstObject.foo); // 'baz'
console.log(newObject.foo);   // 'baz'

If you don't want to change any of the objects you pass to $.extend, pass an empty object as the first argument.

var firstObject = { foo : 'bar', a : 'b' };
var secondObject = { foo : 'baz' };

var newObject = $.extend({}, firstObject, secondObject);
console.log(firstObject.foo); // 'bar'
console.log(newObject.foo);   // 'baz'
$.proxy

Returns a function that will always run in the provided scope — that is, sets the meaning of thisinside the passed function to the second argument.

var myFunction = function() { console.log(this); };
var myObject = { foo : 'bar' };

myFunction(); // logs window object

var myProxyFunction = $.proxy(myFunction, myObject);
myProxyFunction(); // logs myObject object

If you have an object with methods, you can pass the object and the name of a method to return a function that will always run in the scope of the object.

var myObject = {
    myFn : function() {
        console.log(this);
    }
};

$('#foo').click(myObject.myFn); // logs DOM element #foo
$('#foo').click($.proxy(myObject, 'myFn')); // logs myObject

As your work with jQuery progresses, you'll find that there's often data about an element that you want to store with the element. In plain JavaScript, you might do this by adding a property to the DOM element, but you'd have to deal with memory leaks in some browsers. jQuery offers a straightforward way to store data related to an element, and it manages the memory issues for you.


You can store any kind of data on an element, and it's hard to overstate the importance of this when you get into complex application development. For the purposes of this class, we'll mostly use$.fn.data to store references to other elements.

For example, we may want to establish a relationship between a list item and a div that's inside of it. We could establish this relationship every single time we interact with the list item, but a better solution would be to establish the relationship once, and then store a pointer to the div on the list item using $.fn.data:


In addition to passing $.fn.data a single key-value pair to store data, you can also pass an object containing one or more pairs.

Although jQuery eliminates most JavaScript browser quirks, there are still occasions when your code needs to know about the browser environment.

jQuery offers the $.support object, as well as the deprecated $.browser object, for this purpose. For complete documentation on these objects, visit http://api.jquery.com/jQuery.support/ andhttp://api.jquery.com/jQuery.browser/.

The $.support object is dedicated to determining what features a browser supports; it is recommended as a more “future-proof” method of customizing your JavaScript for different browser environments.

The $.browser object was deprecated in favor of the $.support object, but it will not be removed from jQuery anytime soon. It provides direct detection of the browser brand and version.

jQuery offers convenience methods for most common events, and these are the methods you will see used most often. These methods -- including $.fn.click, $.fn.focus, $.fn.blur,$.fn.change, etc. -- are shorthand for jQuery's $.fn.bind method. The bind method is useful for binding the same hadler function to multiple events, and is also used when you want to provide data to the event hander, or when you are working with custom events.




You'll frequently use jQuery to add new elements to the page, and when you do, you may need to bind events to those new elements -- events you already bound to similar elements that were on the page originally. Instead of repeating your event binding every time you add elements to the page, you can use event delegation. With event delegation, you bind your event to a container element, and then when the event occurs, you look to see which contained element it occurred on. If this sounds complicated, luckily jQuery makes it easy with its $.fn.live and $.fn.delegate methods.

While most people discover event delegation while dealing with elements added to the page later, it has some performance benefits even if you never add more elements to the page. The time required to bind event handlers to hundreds of individual elements is non-trivial; if you have a large set of elements, you should consider delegating related events to a container element.

Note

The $.fn.live method was introduced in jQuery 1.3, and at that time only certain event types were supported. As of jQuery 1.4.2, the $.fn.delegatemethod is available, and is the preferred method.



Frequently used effects are built into jQuery as methods:

$.fn.show

Show the selected element.

$.fn.hide

Hide the selected elements.

$.fn.fadeIn

Animate the opacity of the selected elements to 100%.

$.fn.fadeOut

Animate the opacity of the selected elements to 0%.

$.fn.slideDown

Display the selected elements with a vertical sliding motion.

$.fn.slideUp

Hide the selected elements with a vertical sliding motion.

$.fn.slideToggle

Show or hide the selected elements with a vertical sliding motion, depending on whether the elements are currently visible.


Proper use of Ajax-related jQuery methods requires understanding some key concepts first.

jQuery generally requires some instruction as to the type of data you expect to get back from an Ajax request; in some cases the data type is specified by the method name, and in other cases it is provided as part of a configuration object. There are several options:

text

For transporting simple strings

html

For transporting blocks of HTML to be placed on the page

script

For adding a new script to the page

json

For transporting JSON-formatted data, which can include strings, arrays, and objects

Note

As of jQuery 1.4, if the JSON data sent by your server isn't properly formatted, the request may fail silently. See http://json.org for details on properly formatting JSON, but as a general rule, use built-in language methods for generating JSON on the server to avoid syntax issues.

jsonp

For transporting JSON data from another domain

xml

For transporting data in a custom XML schema

I am a strong proponent of using the JSON format in most cases, as it provides the most flexibility. It is especially useful for sending both HTML and data at the same time.

While jQuery does offer many Ajax-related convenience methods, the core $.ajax method is at the heart of all of them, and understanding it is imperative. We'll review it first, and then touch briefly on the convenience methods.

I generally use the $.ajax method and do not use convenience methods. As you'll see, it offers features that the convenience methods do not, and its syntax is more easily understandable, in my opinion.

jQuery’s core $.ajax method is a powerful and straightforward way of creating Ajax requests. It takes a configuration object that contains all the instructions jQuery requires to complete the request. The $.ajax method is particularly valuable because it offers the ability to specify both success and failure callbacks. Also, its ability to take a configuration object that can be defined separately makes it easier to write reusable code. For complete documentation of the configuration options, visit http://api.jquery.com/jQuery.ajax/.


Note

A note about the dataType setting: if the server sends back data that is in a different format than you specify, your code may fail, and the reason will not always be clear, because the HTTP response code will not show an error. When working with Ajax requests, make sure your server is sending back the data type you're asking for, and verify that the Content-type header is accurate for the data type. For example, for JSON data, the Content-type header should beapplication/json.

There are many, many options for the $.ajax method, which is part of its power. For a complete list of options, visit http://api.jquery.com/jQuery.ajax/; here are several that you will use frequently:

async

Set to false if the request should be sent synchronously. Defaults to true. Note that if you set this option to false, your request will block execution of other code until the response is received.

cache

Whether to use a cached response if available. Defaults to true for all dataTypes except "script" and "jsonp". When set to false, the URL will simply have a cachebusting parameter appended to it.

complete

A callback function to run when the request is complete, regardless of success or failure. The function receives the raw request object and the text status of the request.

context

The scope in which the callback function(s) should run (i.e. what this will mean inside the callback function(s)). By default, this inside the callback function(s) refers to the object originally passed to $.ajax.

data

The data to be sent to the server. This can either be an object or a query string, such asfoo=bar&baz=bim.

dataType

The type of data you expect back from the server. By default, jQuery will look at the MIME type of the response if no dataType is specified.

error

A callback function to run if the request results in an error. The function receives the raw request object and the text status of the request.

jsonp

The callback name to send in a query string when making a JSONP request. Defaults to "callback".

success

A callback function to run if the request succeeds. The function receives the response data (converted to a JavaScript object if the dataType was JSON), as well as the text status of the request and the raw request object.

timeout

The time in milliseconds to wait before considering the request a failure.

traditional

Set to true to use the param serialization style in use prior to jQuery 1.4. For details, seehttp://api.jquery.com/jQuery.param/.

type

The type of the request, "POST" or "GET". Defaults to "GET". Other request types, such as "PUT" and "DELETE" can be used, but they may not be supported by all browsers.

url

The URL for the request.

The url option is the only required property of the $.ajax configuration object; all other properties are optional.

If you don't need the extensive configurability of $.ajax, and you don't care about handling errors, the Ajax convenience functions provided by jQuery can be useful, terse ways to accomplish Ajax requests. These methods are just "wrappers" around the core $.ajax method, and simply pre-set some of the options on the $.ajax method.

The convenience methods provided by jQuery are:

$.get

Perform a GET request to the provided URL.

$.post

Perform a POST request to the provided URL.

$.getScript

Add a script to the page.

$.getJSON

Perform a GET request, and expect JSON to be returned.

In each case, the methods take the following arguments, in order:

url

The URL for the request. Required.

data

The data to be sent to the server. Optional. This can either be an object or a query string, such asfoo=bar&baz=bim.

Note

This option is not valid for $.getScript.

success callback

A callback function to run if the request succeeds. Optional. The function receives the response data (converted to a JavaScript object if the data type was JSON), as well as the text status of the request and the raw request object.

data type

The type of data you expect back from the server. Optional.

Note

This option is only applicable for methods that don't already specify the data type in their name.


jQuery’s ajax capabilities can be especially useful when dealing with forms. The jQuery Form Pluginis a well-tested tool for adding Ajax capabilities to forms, and you should generally use it for handling forms with Ajax rather than trying to roll your own solution for anything remotely complex. That said, there are a two jQuery methods you should know that relate to form processing in jQuery:$.fn.serialize and $.fn.serializeArray.



The notation for creating a typical plugin is as follows:

(function($){
    $.fn.myNewPlugin = function() {
        return this.each(function(){
            // do something
        });
    };
}(jQuery));

Don't let that confuse you though. The point of a jQuery plugin is to extend jQuery's prototype object, and that's what's happening on this line:

$.fn.myNewPlugin = function() { //...

We wrap this assignment in an immediately-invoked function:

(function($){
    //...
}(jQuery));

This has the effect of creating a "private" scope that allows us to extend jQuery using the dollar symbol without having to risk the possibility that the dollar has been over-written by another library.

So our actual plugin, thus far, is this:

$.fn.myNewPlugin = function() {
    return this.each(function(){
        // do something
    });
};

The this keyword within the new plugin refers to the jQuery object on which the plugin is being called.

var somejQueryObject = $('#something');

$.fn.myNewPlugin = function() {
    alert(this === somejQueryObject);
};

somejQueryObject.myNewPlugin(); // alerts 'true'

Your typical jQuery object will contain references to any number of DOM elements, and that's why jQuery objects are often referred to as collections.

So, to do something with a collection we need to loop through it, which is most easily achieved using jQuery's each() method:

$.fn.myNewPlugin = function() {
    return this.each(function(){
    
    });
};

jQuery's each() method, like most other jQuery methods, returns a jQuery object, thus enabling what we've all come to know and love as 'chaining' ($(...).css().attr()...). We wouldn't want to break this convention so we return the this object. Within this loop you can do whatever you want with each element. Here's an example of a small plugin using some of the techniques we've discussed:

(function($){
    $.fn.showLinkLocation = function() {
        return this.filter('a').each(function(){
            $(this).append(
                ' (' + $(this).attr('href') + ')'
            );
        });
    };
}(jQuery));
    
// Usage example:
$('a').showLinkLocation();

This handy plugin goes through all anchors in the collection and appends the href attribute in brackets.

<!-- Before plugin is called: -->
<a href="page.html">Foo</a>
    
<!-- After plugin is called: -->
<a href="page.html">Foo (page.html)</a>

Our plugin can be optimised though:

(function($){
    $.fn.showLinkLocation = function() {
        return this.filter('a').append(function(){
              return ' (' + this.href + ')';
        });
    };
}(jQuery));

We're using the append method's capability to accept a callback, and the return value of that callback will determine what is appended to each element in the collection. Notice also that we're not using the attr method to retrieve the href attribute, because the native DOM API gives us easy access with the aptly named href property.

Here's another example of a plugin. This one doesn't require us to loop through every elememt with the each() method. Instead, we're simply going to delegate to other jQuery methods directly:

(function($){
    $.fn.fadeInAndAddClass = function(duration, className) {
        return this.fadeIn(duration, function(){
            $(this).addClass(className);
        });
    };
}(jQuery));
    
// Usage example:
$('a').fadeInAndAddClass(400, 'finishedFading');

Sometimes you want to make a piece of functionality available throughout your code; for example, perhaps you want a single method you can call on a jQuery selection that performs a series of operations on the selection. In this case, you may want to write a plugin.

Most plugins are simply methods created in the $.fn namespace. jQuery guarantees that a method called on a jQuery object will be able to access that jQuery object as this inside the method. In return, your plugin needs to guarantee that it returns the same object it received, unless explicitly documented otherwise.

Here is an example of a simple plugin:


For more on plugin development, read Mike Alsup's essential post, A Plugin Development Pattern. In it, he creates a plugin called $.fn.hilight, which provides support for the metadata plugin if it's present, and provides a centralized method for setting global and instance options for the plugin.


While most existing jQuery plugins are stateless — that is, we call them on an element and that is the extent of our interaction with the plugin — there’s a large set of functionality that doesn’t fit into the basic plugin pattern.

In order to fill this gap, jQuery UI has implemented a more advanced plugin system. The new system manages state, allows multiple functions to be exposed via a single plugin, and provides various extension points. This system is called the widget factory and is exposed asjQuery.widget as part of jQuery UI 1.8; however, it can be used independently of jQuery UI.

To demonstrate the capabilities of the widget factory, we'll build a simple progress bar plugin.

To start, we’ll create a progress bar that just lets us set the progress once. As we can see below, this is done by calling jQuery.widget with two parameters: the name of the plugin to create and an object literal containing functions to support our plugin. When our plugin gets called, it will create a new plugin instance and all functions will be executed within the context of that instance. This is different from a standard jQuery plugin in two important ways. First, the context is an object, not a DOM element. Second, the context is always a single object, never a collection.


The name of the plugin must contain a namespace; in this case we’ve used the nmk namespace. There is a limitation that namespaces be exactly one level deep — that is, we can't use a namespace like nmk.foo. We can also see that the widget factory has provided two properties for us.this.element is a jQuery object containing exactly one element. If our plugin is called on a jQuery object containing multiple elements, a separate plugin instance will be created for each element, and each instance will have its own this.element. The second property, this.options, is a hash containing key/value pairs for all of our plugin’s options. These options can be passed to our plugin as shown here.

Note

In our example we use the nmk namespace. The ui namespace is reserved for official jQuery UI plugins. When building your own plugins, you should create your own namespace. This makes it clear where the plugin came from and whether it is part of a larger collection.


When we call jQuery.widget it extends jQuery by adding a method to jQuery.fn (the same way we'd create a standard plugin). The name of the function it adds is based on the name you pass to jQuery.widget, without the namespace; in our case it will createjQuery.fn.progressbar. The options passed to our plugin get set in this.options inside of our plugin instance. As shown below, we can specify default values for any of our options. When designing your API, you should figure out the most common use case for your plugin so that you can set appropriate default values and make all options truly optional.


Now that we can initialize our progress bar, we’ll add the ability to perform actions by calling methods on our plugin instance. To define a plugin method, we just include the function in the object literal that we pass to jQuery.widget. We can also define “private” methods by prepending an underscore to the function name.


To call a method on a plugin instance, you pass the name of the method to the jQuery plugin. If you are calling a method that accepts parameters, you simply pass those parameters after the method name.


Note

Executing methods by passing the method name to the same jQuery function that was used to initialize the plugin may seem odd. This is done to prevent pollution of the jQuery namespace while maintaining the ability to chain method calls.

One of the easiest ways to make your plugin extensible is to add callbacks so users can react when the state of your plugin changes. We can see below how to add a callback to our progress bar to signify when the progress has reached 100%. The _trigger method takes three parameters: the name of the callback, a native event object that initiated the callback, and a hash of data relevant to the event. The callback name is the only required parameter, but the others can be very useful for users who want to implement custom functionality on top of your plugin. For example, if we were building a draggable plugin, we could pass the native mousemove event when triggering a drag callback; this would allow users to react to the drag based on the x/y coordinates provided by the event object.


Callback functions are essentially just additional options, so you can get and set them just like any other option. Whenever a callback is executed, a corresponding event is triggered as well. The event type is determined by concatenating the plugin name and the callback name. The callback and event both receive the same two parameters: an event object and a hash of data relevant to the event, as we’ll see below.

If your plugin has functionality that you want to allow the user to prevent, the best way to support this is by creating cancelable callbacks. Users can cancel a callback, or its associated event, the same way they cancel any native event: by calling event.preventDefault() or using return false. If the user cancels the callback, the _trigger method will return false so you can implement the appropriate functionality within your plugin.


Please visit http://github.com/rmurphey/jqfundamentals to contribute!

This chapter covers a number of jQuery and JavaScript best practices, in no particular order. Many of the best practices in this chapter are based on the jQuery Anti-Patterns for Performancepresentation by Paul Irish.

Selector optimization is less important than it used to be, as more browser implementdocument.querySelectorAll() and the burden of selection shifts from jQuery to the browser. However, there are still some tips to keep in midn.

When you move beyond adding simple enhancements to your website with jQuery and start developing full-blown client-side applications, you need to consider how to organize your code. In this chapter, we'll take a look at various code organization patterns you can use in your jQuery application and explore the RequireJS dependency management and build system.

The first step to code organization is separating pieces of your application into distinct pieces; sometimes, even just this effort is sufficient to lend

An object literal is perhaps the simplest way to encapsulate related code. It doesn't offer any privacy for properties or methods, but it's useful for eliminating anonymous functions from your code, centralizing configuration options, and easing the path to reuse and refactoring.


The object literal above is simply an object assigned to a variable. The object has one property and several methods. All of the properties and methods are public, so any part of your application can see the properties and call methods on the object. While there is an init method, there's nothing requiring that it be called before the object is functional.

How would we apply this pattern to jQuery code? Let's say that we had this code written in the traditional jQuery style:

// clicking on a list item loads some content
// using the list item's ID and hides content
// in sibling list items
$(document).ready(function() {
  $('#myFeature li')
    .append('<div/>')
    .click(function() {
      var $this = $(this);
      var $div = $this.find('div');
      $div.load('foo.php?item=' +
        $this.attr('id'), 
        function() {
          $div.show();
          $this.siblings()
            .find('div').hide();
        }
      );
    });
});

If this were the extent of our application, leaving it as-is would be fine. On the other hand, if this was a piece of a larger application, we'd do well to keep this functionality separate from unrelated functionality. We might also want to move the URL out of the code and into a configuration area. Finally, we might want to break up the chain to make it easier to modify pieces of the functionality later.


The first thing you'll notice is that this approach is obviously far longer than the original — again, if this were the extent of our application, using an object literal would likely be overkill. Assuming it's not the extent of our application, though, we've gained several things:

  • We've broken our feature up into tiny methods. In the future, if we want to change how content is shown, it's clear where to change it. In the original code, this step is much harder to locate.

  • We've eliminated the use of anonymous functions.

  • We've moved configuration options out of the body of the code and put them in a central location.

  • We've eliminated the constraints of the chain, making the code easier to refactor, remix, and rearrange.

For non-trivial features, object literals are a clear improvement over a long stretch of code stuffed in a $(document).ready() block, as they get us thinking about the pieces of our functionality. However, they aren't a whole lot more advanced than simply having a bunch of function declarations inside of that $(document).ready() block.

The module pattern overcomes some of the limitations of the object literal, offering privacy for variables and functions while exposing a public API if desired.


In the example above, we self-execute an anonymous function that returns an object. Inside of the function, we define some variables. Because the variables are defined inside of the function, we don't have access to them outside of the function unless we put them in the return object. This means that no code outside of the function has access to the privateThing variable or to thechangePrivateThing function. However, sayPrivateThing does have access toprivateThing and changePrivateThing, because both were defined in the same scope assayPrivateThing.

This pattern is powerful because, as you can gather from the variable names, it can give you private variables and functions while exposing a limited API consisting of the returned object's properties and methods.

Below is a revised version of the previous example, showing how we could create the same feature using the module pattern while only exposing one public method of the module,showItemByIndex().


When a project reaches a certain size, managing the script modules for a project starts to get tricky. You need to be sure to sequence the scripts in the right order, and you need to start seriously thinking about combining scripts together into a bundle for deployment, so that only one or a very small number of requests are made to load the scripts. You may also want to load code on the fly, after page load.

RequireJS, a dependency management tool by James Burke, can help you manage the script modules, load them in the right order, and make it easy to combine the scripts later via the RequireJS optimization tool without needing to change your markup. It also gives you an easy way to load scripts after the page has loaded, allowing you to spread out the download size over time.

RequireJS has a module system that lets you define well-scoped modules, but you do not have to follow that system to get the benefits of dependency management and build-time optimizations. Over time, if you start to create more modular code that needs to be reused in a few places, the module format for RequireJS makes it easy to write encapsulated code that can be loaded on the fly. It can grow with you, particularly if you want to incorporate internationalization (i18n) string bundles, to localize your project for different languages, or load some HTML strings and make sure those strings are available before executing code, or even use JSONP services as dependencies.

The easiest way to use RequireJS with jQuery is to download a build of jQuery that has RequireJS built in. This build excludes portions of RequireJS that duplicate jQuery functionality. You may also find it useful to download a sample jQuery project that uses RequireJS.

Using RequireJS in your page is simple: just include the jQuery that has RequireJS built in, then require your application files. The following example assumes that the jQuery build, and your other scripts, are all in a scripts/ directory.


The call to require(["app"]) tells RequireJS to load the scripts/app.js file. RequireJS will load any dependency that is passed to require() without a .js extension from the same directory as require-jquery.js, though this can be configured to behave differently. If you feel more comfortable specifying the whole path, you can also do the following:

<script>require(["scripts/app.js"]);</script>

What is in app.js? Another call to require.js to load all the scripts you need and any init work you want to do for the page. This example app.js script loads two plugins, jquery.alpha.jsand jquery.beta.js (not the names of real plugins, just an example). The plugins should be in the same directory as require-jquery.js:


RequireJS makes it easy to define reusable modules via require.def(). A RequireJS module can have dependencies that can be used to define a module, and a RequireJS module can return a value — an object, a function, whatever — that can then be consumed by yet other modules.

If your module does not have any dependencies, then just specify the name of the module as the first argument to require.def(). The second argument is just an object literal that defines the module's properties. For example:

Example 10.7. Defining a RequireJS module that has no dependencies

require.def("my/simpleshirt",
    {
        color: "black",
        size: "unisize"
    }
);

This example would be stored in a my/simpleshirt.js file.

If your module has dependencies, you can specify the dependencies as the second argument torequire.def() (as an array) and then pass a function as the third argument. The function will be called to define the module once all dependencies have loaded. The function receives the values returned by the dependencies as its arguments (in the same order they were required in the array), and the function should return an object that defines the module.


In this example, a my/shirt module is created. It depends on my/cart and my/inventory. On disk, the files are structured like this:

my/cart.js
my/inventory.js
my/shirt.js

The function that defines my/shirt is not called until the my/cart and my/inventorymodules have been loaded, and the function receives the modules as the cart and inventoryarguments. The order of the function arguments must match the order in which the dependencies were required in the dependencies array. The object returned by the function call defines the my/shirt module. Be defining modules in this way, my/shirt does not exist as a global object. Modules that define globals are explicitly discouraged, so multiple versions of a module can exist in a page at a time.

Modules do not have to return objects; any valid return value from a function is allowed.


Only one module should be required per JavaScript file.


Once you incorporate RequireJS for dependency management, your page is set up to be optimized very easily. Download the RequireJS source and place it anywhere you like, preferrably somewhere outside your web development area. For the purposes of this example, the RequireJS source is placed as a sibling to the webapp directory, which contains the HTML page and the scripts directory with all the scripts. Complete directory structure:

requirejs/ (used for the build tools)
webapp/app.html
webapp/scripts/app.js
webapp/scripts/require-jquery.js
webapp/scripts/jquery.alpha.js
webapp/scripts/jquery.beta.js

Then, in the scripts directory that has require-jquery.js and app.js, create a file called app.build.js with the following contents:


To use the build tool, you need Java 6 installed. Closure Compiler is used for the JavaScript minification step (if optimize: "none" is commented out), and it requires Java 6.

To start the build, go to the webapp/scripts directory, execute the following command:

# non-windows systems
../../requirejs/build/build.sh app.build.js

# windows systems
..\..\requirejs\build\build.bat app.build.js

Now, in the webapp-build directory, app.js will have the app.js contents, jquery.alpha.jsand jquery.beta.js inlined. If you then load the app.html file in the webapp-builddirectory, you should not see any network requests for jquery.alpha.js andjquery.beta.js.

We’re all familiar with the basic events — click, mouseover, focus, blur, submit, etc. — that we can latch on to as a user interacts with the browser. Custom events open up a whole new world of event-driven programming. In this chapter, we’ll use jQuery’s custom events system to make a simple Twitter search application.

It can be difficult at first to understand why you'd want to use custom events, when the built-in events seem to suit your needs just fine. It turns out that custom events offer a whole new way of thinking about event-driven JavaScript. Instead of focusing on the element that triggers an action, custom events put the spotlight on the element being acted upon. This brings a bevy of benefits, including:

  • Behaviors of the target element can easily be triggered by different elements using the same code.

  • Behaviors can be triggered across multiple, similar, target elements at once.

  • Behaviors are more clearly associated with the target element in code, making code easier to read and maintain.

Why should you care? An example is probably the best way to explain. Suppose you have a lightbulb in a room in a house. The lightbulb is currently turned on, and it’s controlled by two three-way switches and a clapper:

<div class="room" id="kitchen">
    <div class="lightbulb on"></div>
    <div class="switch"></div>
    <div class="switch"></div>
    <div class="clapper"></div>
</div>

Triggering the clapper or either of the switches will change the state of the lightbulb. The switches and the clapper don’t care what state the lightbulb is in; they just want to change the state.

Without custom events, you might write some code like this:

$('.switch, .clapper').click(function() {
    var $light = $(this).parent().find('.lightbulb');
    if ($light.hasClass('on')) {
        $light.removeClass('on').addClass('off');
    } else {
        $light.removeClass('off').addClass('on');
    }
});

With custom events, your code might look more like this:

$('.lightbulb').bind('changeState', function(e) {
    var $light = $(this);
    if ($light.hasClass('on')) {
        $light.removeClass('on').addClass('off');
    } else {
        $light.removeClass('off').addClass('on');
    }
});

$('.switch, .clapper').click(function() { 
    $(this).parent().find('.lightbulb').trigger('changeState');
});

This last bit of code is not that exciting, but something important has happened: we’ve moved the behavior of the lightbulb to the lightbulb, and away from the switches and the clapper.

Let’s make our example a little more interesting. We’ll add another room to our house, along with a master switch, as shown here:

<div class="room" id="kitchen">
    <div class="lightbulb on"></div>
    <div class="switch"></div>
    <div class="switch"></div>
    <div class="clapper"></div>
</div>
<div class="room" id="bedroom">
    <div class="lightbulb on"></div>
    <div class="switch"></div>
    <div class="switch"></div>
    <div class="clapper"></div>
</div>
<div id="master_switch"></div>

If there are any lights on in the house, we want the master switch to turn all the lights off; otherwise, we want it to turn all lights on. To accomplish this, we’ll add two more custom events to the lightbulbs: turnOn and turnOff. We’ll make use of them in the changeState custom event, and use some logic to decide which one the master switch should trigger:

$('.lightbulb')
    .bind('changeState', function(e) {
        var $light = $(this);
        if ($light.hasClass('on')) {
            $light.trigger('turnOff');
        } else {
            $light.trigger('turnOn');
        }
    })
    .bind('turnOn', function(e) {
        $(this).removeClass('off').addClass('on');
    })
    .bind('turnOff', function(e) {
        $(this).removeClass('off').addClass('on');
    });
 
$('.switch, .clapper').click(function() { 
    $(this).parent().find('.lightbulb').trigger('changeState');
});
 
$('#master_switch').click(function() {
    if ($('.lightbulb.on').length) {
        $('.lightbulb').trigger('turnOff');
    } else {
        $('.lightbulb').trigger('turnOn');
    }
});

Note how the behavior of the master switch is attached to the master switch; the behavior of a lightbulb belongs to the lightbulbs.

Note

If you’re accustomed to object-oriented programming, you may find it useful to think of custom events as methods of objects. Loosely speaking, the object to which the method belongs is created via the jQuery selector. Binding the changeState custom event to all $(‘.light’) elements is akin to having a class called Light with a method of changeState, and then instantiating newLight objects for each element with a classname of light.

To demonstrate the power of custom events, we’re going to create a simple tool for searching Twitter. The tool will offer several ways for a user to add search terms to the display: by entering a search term in a text box, by entering multiple search terms in the URL, and by querying Twitter for trending terms.

The results for each term will be shown in a results container; these containers will be able to be expanded, collapsed, refreshed, and removed, either individually or all at once.

When we’re done, it will look like this:


We’ll start with some basic HTML:

<h1>Twitter Search</h1>
<input type="button" id="get_trends" 
    value="Load Trending Terms" />
 
<form>
    <input type="text" class="input_text" 
        id="search_term" />
    <input type="submit" class="input_submit" 
        value="Add Search Term" />
</form>
 
<div id="twitter">
    <div class="template results">
        <h2>Search Results for 
        <span class="search_term"></span></h2>
    </div>
</div>

This gives us a container (#twitter) for our widget, a template for our results containers (hidden via CSS), and a simple form where users can input a search term. (For the sake of simplicity, we’re going to assume that our application is JavaScript-only and that our users will always have CSS.)

There are two types of objects we’ll want to act on: the results containers, and the Twitter container.

The results containers are the heart of the application. We’ll create a plugin that will prepare each results container once it’s added to the Twitter container. Among other things, it will bind the custom events for each container and add the action buttons at the top right of each container. Each results container will have the following custom events:

refresh

Mark the container as being in the “refreshing” state, and fire the request to fetch the data for the search term.

populate

Receive the returned JSON data and use it to populate the container.

remove

Remove the container from the page after the user verifies the request to do so. Verification can be bypassed by passing true as the second argument to the event handler. The remove event also removes the term associated with the results container from the global object containing the search terms.

collapse

Add a class of collapsed to the container, which will hide the results via CSS. It will also turn the container’s “Collapse” button into an “Expand” button.

expand

Remove the collapsed class from the container. It will also turn the container’s “Expand” button into a “Collapse” button.

The plugin is also responsible for adding the action buttons to the container. It binds a click event to each action’s list item, and uses the list item’s class to determine which custom event will be triggered on the corresponding results container.

$.fn.twitterResult = function(settings) {
    return $(this).each(function() {
        var $results = $(this),
            $actions = $.fn.twitterResult.actions = 
                $.fn.twitterResult.actions || 
                $.fn.twitterResult.createActions(),
            $a = $actions.clone().prependTo($results),
            term = settings.term;

        $results.find('span.search_term').text(term);

        $.each(
            ['refresh', 'populate', 'remove', 'collapse', 'expand'], 
            function(i, ev) { 
                $results.bind(
                    ev, 
                    { term : term },
                    $.fn.twitterResult.events[ev]
                ); 
            }
        );

        // use the class of each action to figure out 
        // which event it will trigger on the results panel
        $a.find('li').click(function() {
            // pass the li that was clicked to the function
            // so it can be manipulated if needed
            $results.trigger($(this).attr('class'), [ $(this) ]);
        });
    });
};

$.fn.twitterResult.createActions = function() {
    return $('<ul class="actions" />').append(
        '<li class="refresh">Refresh</li>' +
        '<li class="remove">Remove</li>' +
        '<li class="collapse">Collapse</li>'
    );
};

$.fn.twitterResult.events = {
    refresh : function(e) {
           // indicate that the results are refreshing
        var $this = $(this).addClass('refreshing');

        $this.find('p.tweet').remove();
        $results.append('<p class="loading">Loading ...</p>');

        // get the twitter data using jsonp
        $.getJSON(
            'http://search.twitter.com/search.json?q=' +                     
                escape(e.data.term) + '&rpp=5&callback=?', 
            function(json) { 
                $this.trigger('populate', [ json ]); 
            }
        );
    },

    populate : function(e, json) {
        var results = json.results;
        var $this = $(this);

        $this.find('p.loading').remove();

        $.each(results, function(i,result) {
            var tweet = '<p class="tweet">' + 
                '<a href="http://twitter.com/' + 
                result.from_user + 
                '">' +
                result.from_user + 
                '</a>: ' +
                result.text + 
                ' <span class="date">' + 
                result.created_at + 
                '</span>' +
            '</p>';
            $this.append(tweet);
        });

        // indicate that the results 
        // are done refreshing
        $this.removeClass('refreshing');
    },

    remove : function(e, force) {
        if (
            !force &&     
            !confirm('Remove panel for term ' + e.data.term + '?')
        ) {
            return;
        }
        $(this).remove();

        // indicate that we no longer 
        // have a panel for the term
        search_terms[e.data.term] = 0;
    },

    collapse : function(e) {
        $(this).find('li.collapse').removeClass('collapse')
            .addClass('expand').text('Expand');

        $(this).addClass('collapsed');
    },

    expand : function(e) {
        $(this).find('li.expand').removeClass('expand')
            .addClass('collapse').text('Collapse');

        $(this).removeClass('collapsed');
    }
};

The Twitter container itself will have just two custom events:

getResults

Receives a search term and checks to determine whether there’s already a results container for the term; if not, adds a results container using the results template, set up the results container using the $.fn.twitterResult plugin discussed above, and then triggers the refresh event on the results container in order to actually load the results. Finally, it will store the search term so the application knows not to re-fetch the term.

getTrends

Queries Twitter for the top 10 trending terms, then iterates over them and triggers thegetResults event for each of them, thereby adding a results container for each term.

Here's how the Twitter container bindings look:

$('#twitter')
    .bind('getResults', function(e, term) {
        // make sure we don't have a box for this term already
        if (!search_terms[term]) { 
            var $this = $(this);
            var $template = $this.find('div.template');

            // make a copy of the template div
            // and insert it as the first results box
            $results = $template.clone().
                removeClass('template').
                insertBefore($this.find('div:first')).
                twitterResult({
                    'term' : term
                });

            // load the content using the "refresh" 
            // custom event that we bound to the results container
            $results.trigger('refresh');
            search_terms[term] = 1;
        }
    })
    .bind('getTrends', function(e) {
        var $this = $(this);
        $.getJSON('http://search.twitter.com/trends.json?callback=?', function(json) {
                var trends = json.trends; 
                $.each(trends, function(i, trend) {
                    $this.trigger('getResults', [ trend.name ]);
                });
            });
    });

So far, we’ve written a lot of code that does approximately nothing, but that’s OK. By specifying all the behaviors that we want our core objects to have, we’ve created a solid framework for rapidly building out the interface.

Let’s start by hooking up our text input and the “Load Trending Terms” button. For the text input, we’ll capture the term that was entered in the input and pass it as we trigger the Twitter container’sgetResults event. Clicking the “Load Trending Terms” will trigger the Twitter container’sgetTrends event:

$('form').submit(function(e) {
    e.preventDefault();
    var term = $('#search_term').val();
    $('#twitter').trigger('getResults', [ term ]);
});

$('#get_trends').click(function() {
    $('#twitter').trigger('getTrends'); 
});

By adding a few buttons with the appropriate IDs, we can make it possible to remove, collapse, expand, and refresh all results containers at once, as shown below. For the remove button, note how we’re passing a value of true to the event handler as its second argument, telling the event handler that we don’t want to verify the removal of individual containers.

$.each(['refresh', 'expand', 'collapse'], function(i, ev) {
    $('#' + ev).click(function(e) { $('#twitter div.results').trigger(ev); });
});

$('#remove').click(function(e) {
    if (confirm('Remove all results?')) {
        $('#twitter div.results').trigger('remove', [ true ]);
    }
});


http://mwultong.blogspot.com/2006/05/html-tooltip-tag.html

HTML에서는 title 속성으로 말풍선을 만듭니다.

[script] 정규식

프로그래밍/Web 2010. 5. 20. 16:48 Posted by galad
http://kio.zc.bz/Lecture/regexp.html#chap03


1. 정규식이란?

String의 검색,치환,추출을 위한 패턴.
언어별 사용법은 대동소이함.
패턴예>전화번호 형식, 이메일 형식 등.
2. 정규식 만들기

Javascript
var regexp = /pattern/[flags] ;
var test = regexp.test(to be checked)
var regexp = new RegExp("pattern"[, "flags"]);
var test = regexp.test(to be checked)
flags for javascript
g : global match, 일반적으로 패턴이 1번만 발견되면 찾기를 종료하지만, g flag가 있으면, 문자열 내에서 모든 패턴을 찾는다.
i : ignore case, 대소문자를 고려하지 않고 체크한다.[a-z]와 [A-Z]는 같은 표현이 된다.
m : match over multiple lines, 여러 줄에 걸쳐 체크를 한다.
Java
java.util.regex package
Pattern p = Pattern.compile("pattern");
Matcher m = p.matcher("string to be checked");
boolean b = m.matches();
boolean b = Pattern.matches("pattern", "string to be checked");
3. 정규식 표현법

*ⓥ는 valid, ⓘ는 invalid
*두꺼운 글씨체는 매칭되는 부분.
*예제는 javascript 기준이며, 언어에 따라 다소 차이가 발생할 수 있다.
문자    용도    예제
\   
특수문자를 의미
특수문자의 사용을 제외(특수문자 앞에서)
b는 b라는 글자를 의미 하지만 \b는 단어 경계를 의미
*은 0번이상 반복이라는 의미이지만, \*는 *이라는 글자를 의미.
^    문자열의 시작. []안에서는 not의 의미
* ^A는 "A로 시작"이라기 보다는 "시작 직후에 A가 나온다"는 의미로 해석하는 것이 좋다. 즉, 시작과 끝과 같은 빈 공간을 하나의 문자로 간주하는 것이 좋다.    /^A/g
A stringⓥ
an Aⓘ
/[^A]/g
A stringⓥ
an Aⓘ
$    문자열의 마지막
/t$/
eatⓥ
GREATⓘ
*    0번 이상 반복    /ab*d/g
adⓥ
abdⓥ
abdcdeabbbbdedbⓥ
abⓘ
axdⓘ
+    1번 이상 반복 ( = {1,} )    /ab+d/g
adⓘ
abdⓥ
abdcdeabbbbdedbⓥ
abⓘ
axdⓘ
?    0번 이나 1번    /e?le?/g
angelⓥ
angleⓥ
elementⓥ
/abc\-?d/g
abc-dⓥ
abcdⓥ
.    new line 을 제외한 모든 글자    /.n/g
nay, an apple is on the treeⓥ
nayⓘ
(x)    x를 체크하고 체크한 값을 변수로 저장    /(f..) (b..)/
foo barⓥ
1th :foo
2th :bar
(?:x)    x를 체크하고 체크한 값을 변수로 저장하지 않음    /(?:f..) (b..)/
foo barⓥ
1th :bar
bar fooⓘ
x|y    x 또는 y    /green|red/
green appleⓥ
red appleⓥ
yellow appleⓘ
x(?=y)    x후에 y가 나오고, x부분만 매칭되는 부분으로 간주    /blah(?=soft|hard)/
blahsoftⓥ
blahhardⓥ
blah softⓘ
/blah(?=soft).*/
blahsoftⓥ
blahhardⓘ
blah softⓘ
x(?!y)    x가 나오고 그 뒤에 y가 있으면 안 됨    /blah(?!hard)/
blahsoftⓥ
blahhardⓘ
blah softⓥ
{n}    앞에 지정한 것이 n개    /.{3}/
abⓘ
abcⓥ
abcdⓥ
홍길동ⓥ
{n,}    앞에 지정한 것이 n개 이상    /.{3,}/
abⓘ
abcⓥ
abcdⓥ
{n,m}    앞에 지정한 것이 n~m개    /.{3,5}/
abⓘ
abcⓥ
abcdⓥ
홍길동ⓥ
[xyz]    x나 y나 z. []안에는 얼마든지 쓸 수 있다.    /[abc]{2}/
abⓥ
abcⓥ
adbdⓘ
[x-z]    x에서 z까지    /[a-z]{4,}/g
She sells sea shells by the sea shore는 Very 어렵다!ⓥ
[^xyz]    x,y,z를 제외한 나머지 모든 것    /[^a-z]{2,}/g
I'm a good manⓥ
I am A good Manⓥ
[\b]    백스페이스. \b와 혼동하지 말것.    /[\b]/g
abcdⓥ
일반적인 String에서는 \b가 백스페이스를 의미한다.
\b    단어의 경계.[\b]와 혼동하지 말것.    /\bn[a-z]/g
I am not a boyⓥ
onlineⓘ
nopeⓥ
\B    \b 를 제외한 전부    /\Bn[a-z]/g
noondayⓥ
onlineⓥ
nopeⓘ
\cX    컨트롤X와 매칭. \cM은 컨트롤M과 매칭   
\d    숫자.[0-9]와 같음    /\d/g
7 eight 9ⓥ
123ⓘ
/^0[0-9]{2}/g
0120ⓥ
12011ⓘ
\D    \d 를 제외한 전부    /\D/g
7 eight 9ⓥ
12?3ⓘ
\f    form-feed   
\n    new line   
\r    carriage return   
\s    white space
ex>탭, 띄어쓰기, \n, \r    /k\s/g
koreaⓘ
blank isⓥ
blankⓘ
\S    \s 를 제외한 전부    /k\S/g
koreaⓥ
blank isⓘ
\t    탭   
\v    vertical tab   
\w    알파벳+숫자+_. [A-Za-z0-9_]와 동일    /\w/g
!@#$%^&*()+_-[]{}\|"':;,.<>?/ⓥ
        _가 <b>를 먹여도 별로 티가 안 난다.
\W    \w 빼고 전부    /\W/g
!@#$%^&*()+_-[]{}\|"':;,.<>?/ⓥ
\n    \n이 자연수일때, ()로 지정한 n번째 정규식    /(.{2})e tru\1 is out \1ere/
the truth is out there ...ⓥ
1th :th
(th)가 \1로 지정된다.
\xhh    hh는 hexacode,    /[\x21-\x40]/g
!@#$%^&*()poⓥ
Code table 보기
\uhhhh    hhhh는 hexacode,    /[\u3131-\u3163\uac00-\ud7a3]/g
나는 blah 직원입니다.ㅋㅋⓥ
코드 번호> 3131:ㄱ 3163:ㅣ ac00:가 d7a3:힣 (javascript, java)

4. 정규식 사용 예제

/^[0-9]/
09없다ⓥ
100점ⓥ
집이 10평ⓘ
/^\w+$/
blahsoftⓥ
blah(co)ⓘ
blah softⓘ
/^[a-zA-Z][\w\-]{4,11}$/
blah2010ⓥ
blah-2010!ⓘ
2010blahⓘ
ILikegoooooooooooooooooogleⓘ
/^[0-9]{2,3}-[0-9]{3,4}-[0-9]{4}/
02-6288-2114ⓥ
031-779-7114ⓥ
12-1234-5678ⓥ
02-6288-2114545ⓥ
02-0288-2114ⓥ
/^0\d{1,2}-[1-9]\d{2,3}-\d{4}$/
02-6288-2114ⓥ
031-779-7114ⓥ
12-1234-5678ⓘ
02-2123-12314545ⓘ
02-0288-2114ⓘ
/^[\.a-zA-Z0-9\-]+\.[a-zA-Z]{2,}/
r-d.blah.co.krⓥ
r-d.blah.co.kr입니다.ⓥ
blah..co.krⓥ
a.comⓥ
/^(?:[\w\-]{2,}\.)+[a-zA-Z]{2,}$/
r-d.blah.co.krⓥ
r-d.blah.co.kr입니다.ⓘ
blah..co.krⓘ
a.comⓘ
/^[_a-zA-Z0-9\-]+@[\._a-zA-Z0-9\-]+\.[a-zA-Z]{2,}/
abc@haha.co.krⓥ
abc@haha..co.krⓥ
hwang@a.comⓥ
/^[\w\-]+@(?:(?:[\w\-]{2,}\.)+[a-zA-Z]{2,})$/
abc@haha.co.krⓥ
abc@haha..co.krⓘ
hwang@a.comⓘ
/^([a-z]+):\/\/((?:[a-z\d\-]{2,}\.)+[a-z]{2,})(:\d{1,5})?(\/[^\?]*)?(\?.+)?$/i
http://www.blah.co.kr/main/index.jsp?var=valueⓥ
1th :http
2th :www.blah.co.kr
3th :undefined
4th :/main/index.jsp
5th :?var=value
http://www.blah.co.kr/main/index.jspⓥ
1th :http
2th :www.blah.co.kr
3th :undefined
4th :/main/index.jsp
5th :undefined
http://blah.co.kr/ⓥ
1th :http
2th :blah.co.kr
3th :undefined
4th :/
5th :undefined
http://blah.co.krⓥ
1th :http
2th :blah.co.kr
3th :undefined
4th :undefined
5th :undefined
http://blah.co.kr:8088/main/ⓥ
1th :http
2th :blah.co.kr
3th ::8088
4th :/main/
5th :undefined
/^[ㄱ-ㅣ가-힣]+$/
티맥스소프트ⓥ
ㅜㅜⓥ
ㅎㅎⓥ

5. Javascript 정규식 함수

함수    코드예제    코드설명
Array RegExp.exec (to be checked)   

var myRe=/d(b+)(d)/ig;
var myArray = myRe.exec("cdbBdbsbz");
/d(b+)(d)/gi

cdbBdbsbzⓥ
myArray.index =1 ; (처음으로 매칭되는 위치, 컴터가 늘 그렇듯 위치는 0번째부터 센다.)
myArray.input = cdbBdbsbz; (체크할 대상)
myArray[0] = dbBd;(검사에 통과한 부분)
myArray[1] = bB;(1번째 괄호에서 체크된 부분)
myArray[2] = d;(2번째 괄호에서 체크된 부분)

myRe.lastIndex =5 ; (다음번 체크를 하기위한 위치.)
myRe.ignoreCase = true; (/i 플래그 체크)
myRe.global = true; (/g 플래그 체크)
myRe.multiline = false; (/m 플래그 체크)

RegExp.$_ = cdbBdbsbz;(입력한 스트링)
RegExp.$1 = bB;(1번째 괄호에서 체크된 부분 )
boolean RegExp.test(to be checked)   

var myRe=/d(b+)(d)/ig;
var checked = myRe.test("cdbBdbsbz");
document.write("checked = " + checked +";<br>");
/d(b+)(d)/gi

cdbBdbsbzⓥ
실행결과: checked = true;
String RegExp.toString()   

var myRe=/d(b+)(d)/ig;
var str = myRe.toString();
document.write(str);
실행 결과: /d(b+)(d)/gi
String String.replace(pattern or string, to be replaced)   

var str = "abcdefe";
document.write(str.replace("e" , "f"));
실행 결과: abcdffe

e가 2번 있지만, 첫번째 인자가 정규식이 아니라 문자열일 경우는 첫번째 것만 바꾼다.

var str = "aba";
document.write(str.replace(/^a/ , "c"));
실행 결과: cba

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
newstr = str.replace(re, "$2, $1");
document.write(newstr)
실행 결과: Smith, John

re에 의해서 찾아진 문자열 들은 re에서 ()로 표현된 순서대로 $1, $2와 같이 변수로 저장된다.

var re = /\s(?:http|https):\/\/\S*(?:\s|$)/g;
var str = "url is http://iilii.egloos.com/ !!\n";
str += "blah home: http://www.blah.co.kr";
newstr = str.replace(re, function (str,p1,offset,s) {
     return "<a href='" + str + "'>" + str + "</a>";
  }
).replace(/\n/, "<br>");
document.write(newstr);
url is http://iilii.egloos.com/ !!
blah home: http://www.blah.co.kr

str: 찾은 문자열
p1: ()에서 검색된 1번째 문자열. 마찬가지로 p2,p3 등도 가능
offset: str을 찾은 위치
s : 원본 문자열.
Array String.match(regular expression   

var str = "ABCdEFgHiJKL";
var myResult = str.match(/[a-z]/g );
for(var cnt = 0 ; cnt < myResult.length; cnt++){
    document.write(cnt +":" + myResult[cnt] +"<br>");
}

document.write("비교<br>");

var str = "ABCdEFgHiJKL";
var myResult = /[a-z]/g.exec(str);
for(var cnt = 0 ; cnt < myResult.length; cnt++){
    document.write(cnt +":" + myResult[cnt] +"<br>");
}
실행 결과:
0:d
1:g
2:i
비교
0:d

String.match(RegExp) =>g flag가 있어도 다 찾아낸다.
RegExp.exec(String) =>g flag가 있으면, 한 개만 찾고 끝낸다.
Array String.split([separator[, limit]])   

var str = "ABCdEFgHiJKL";
var myResult = str.split(/[a-z]/g , 3);
for(var cnt = 0 ; cnt < myResult.length; cnt++){
    document.write(cnt +":" + myResult[cnt] +"<br>");
}
실행 결과:
0:ABC
1:EF
2:H

주어진 문자열을 separator를 기준으로 limit 만큼 자른다.
6. 정규식으로 만든 유용한 Javascript 함수

String removeTags(input)

HTML tag부분을 없애준다

function removeTags(input) {
    return input.replace(/<[^>]+>/g, "");
};
example>

var str = "<b>blah</b> <i>soft</i>";
document.write(str +"<br>");
document.write(removeTags(str));
result>
blah soft
blah soft
String String.trim()

문자열의 앞뒤 공백을 없애준다.

String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, '');
};
example>

var str = "         untrimed string            ";
document.write("========" + str+ "==============<br>");
document.write("========" + str.trim() + "==============");
result>
======== untrimed string ==============
========untrimed string==============
String String.capitalize()

단어의 첫 글자를 대문자로 바꿔준다.

String.prototype.capitalize = function() {
    return this.replace(/\b([a-z])/g, function($1){
        return $1.toUpperCase();
    }) ; 
};
example>

var str = "korea first world best";
document.write(str.capitalize());
result>
Korea First World Best
String number_format(input)

입력된 숫자를 ,를 찍은 형태로 돌려준다

function number_format(input){
    var input = String(input);
    var reg = /(\-?\d+)(\d{3})($|\.\d+)/;
    if(reg.test(input)){
        return input.replace(reg, function(str, p1,p2,p3){
                return number_format(p1) + "," + p2 + "" + p3;
            }   
        );
    }else{
        return input;
    }
}
example>

document.write(number_format(1234562.12) + "<br>");
document.write(number_format("-9876543.21987")+ "<br>");
document.write(number_format("-123456789.12")+ "<br>");
result>
1,234,562.12
-9,876,543.21987
-123,456,789.12
7. Java 정규식 함수

 Pattern p = Pattern.compile("(a*)(b)");
Matcher m = p.matcher("aaaaab");
if (m.matches()) {
    for (int i = 0; i < m.groupCount() + 1; i++) {
        System.out.println(i + ":" + m.group(i));
    }
} else {
    System.out.println("not match!");
}

result>
0:aaaaab
1:aaaaa
2:b
0번째는 매칭된 부분.
String a = "I love her";
System.out.println(a.replaceAll("([A-Z])", "\"$1\""));

result>
"I" love her
자바도 $1을 쓸 수 있다.
Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "dog");
    System.out.println(sb.toString());
}
m.appendTail(sb);
System.out.println(sb.toString());

result>
one dog
one dog two dog
one dog two dogs in the yard

[script] 소수점 자리수

프로그래밍/Web 2010. 5. 20. 10:19 Posted by galad
http://www.w3schools.com/jsref/jsref_tofixed.asp

var num = new Number(13.3714);
document.write(num.toFixed()+"<br />");
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

>>
13
13.4
13.371
13.3714000000


var m_browser;
var m_version;

function detectBrowser() { // jQuery로 브라우저 타입/버젼 확인
    if($.browser.msie) {
        m_browser = "msie";
    }
    else if($.browser.safari) {
        m_browser = "safari";
    }
    else if($.browser.opera) {
        m_browser = "opera";
    }
    else if($.browser.mozilla) {
        m_browser = "mozilla";
    }

    m_version = $.browser.version;

    //alert(m_browser + " " + m_version);
}

function setElAttribute(el, attrName, attr) {

    if(attrName == "style") {

        // this.setAttribute("style", "background-color:yellow; font-weight:bolder;");
        // IE6 DOESN'T WORK! Use this.style.setAttribute("cssText", "STYLE");
        if(m_browser.indexOf("msie") == 0 && (m_version.indexOf("6.0") == 0 || m_version.indexOf("7.0") == 0)) {
            el.style.setAttribute("cssText", attr);
        }
        else {
            el.setAttribute("style", attr);
        }
    }
    else {
        el.setAttribute(attrName, attr);
    }
}

6.0만 style.setAttribute 하면 될 줄 알았는데, 7.0도 해야하더라....

'프로그래밍 > Web' 카테고리의 다른 글

[script] 정규식  (0) 2010.05.20
[script] 소수점 자리수  (0) 2010.05.20
[html] shortcut icon 붙이기  (0) 2010.04.15
[html] X-UA-Compatible: IE=EmulateIE7  (0) 2010.04.09
[javascript] 전화번호 형식으로 바꾸기  (0) 2010.03.08

[html] shortcut icon 붙이기

프로그래밍/Web 2010. 4. 15. 14:10 Posted by galad
http://msdn.microsoft.com/en-us/library/ms537656(VS.85).aspx

<head>
<link rel="SHORTCUT ICON" href="http://www.mydomain.com/myicon.ico"/>
<title>My Title</title>
</head>

http://msdn.microsoft.com/ko-kr/library/cc817570.aspx

작업 중에 개발서버에서는 IE8에서 style이 제대로 먹는데, 스테이징서버에서는 안되는 현상이 발생.
도저히 원인을 알 수 없어서 httpWatch로 stream을 잡아보니,

스테이징에서는 헤더가
HTTP/1.1 200 OK
Date: Fri, 09 Apr 2010 06:58:34 GMT
Server: Apache
Content-Length: 6990
X-UA-Compatible: IE=EmulateIE7
P3P: CP='ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI'
Keep-Alive: timeout=10, max=2000
Connection: Keep-Alive
Content-Type: text/html;charset=UTF-8
이렇게 오는 것을 확인.

다른 건 제쳐두고 IE=EmulateIE7으로 오는게 아무래도 이상해서 구글링해보니 역시나...(위 링크 참고)
Windows Internet Explorer 7에서 올바르게 동작하는 기존 웹 페이지를 유지 관리하고 있으며, 최소한의 수정만으로 Windows Internet Explorer 8에서 동작하도록 이 웹 페이지를 업데이트해야 하는 경우

다음 헤더를 보내도록 서버를 구성합니다.

X-UA-Compatible: IE=EmulateIE7


X-UA-Compatible: IE=EmulateIE7 은 결국, IE8에서 IE7처럼 보여주게 하겠다는 뜻.
이러니 IE8에서 제대로 안 보여지는 스타일이 생기지...

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=8"/>

메타 추가하니 잘 되더라...

원래는 서버 설정을 변경해야겠으나, 일단 디자인 깨지는 게 이 페이지 하나라서 이걸로 땜빵했음.

/**
 * 전화번호 형식으로 바꾸기
 * 예)     02282342232 -> 02-8234-2232
 *         0312437845    -> 031-124-7845
 *         01071050616    -> 010-7105-0616
 * @param num
 * @return
 */
function phone_format(num){
    return num.replace(/(^02.{0}|^01.{1}|[0-9]{3})([0-9]+)([0-9]{4})/,"$1-$2-$3");
}

'프로그래밍 > Web' 카테고리의 다른 글

[html] shortcut icon 붙이기  (0) 2010.04.15
[html] X-UA-Compatible: IE=EmulateIE7  (0) 2010.04.09
[javascript] DOM 스크립트  (0) 2010.01.15
[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설명  (0) 2010.01.08

[javascript] DOM 스크립트

프로그래밍/Web 2010. 1. 15. 11:09 Posted by galad
9장 CSS와 DOM 연동하기를 읽으면서 간단 정리

1. DOM의 style 프로퍼티로는 외부 스타일 시트에서 선언한 style 객체 및 문서 내부의 미리 선언한 스타일 정보도 가져올 수 없다.
  오로지 인라인으로 선언된 style 속성의 정보만을 가져올 수 있음.

2. DOM으로 style 변경 시 기존 class 속성에 새 class 속성을 추가하고 싶을 때
  eleme.className += " newClass"; 이런 식으로 공백을 두고 추가.

Summary.
  DOM으로 style을 바꾸는 일이 얼마나 있을지는 모르겠음. 단, CSS에 정의되어 있는 class에 대한 정의를 이용해서 DOM으로 class를 변경하는 것 정도는 사용할지도 모르겠음.

10장 애니메이션 슬라이드쇼 만들기

1. setTimeout/clearTimeout
variable = setTimeout("function", interval);
clearTimeout(variable);

변수명 = setTimeout(함수, 인터벌(밀리초));
clearTimeout(변수명); // 위에서 설정한 timeout을 취소

movement = setTimeout("moveMessage()", 5000);

clearTimeout(movement);

2. parseInt
parseInt(string)

문자열을 정수로 반환
문자열 중 정수만 반환 : parseInt("39 degree") == 39

3. CSS: overflow
  overflow:visible --> 전체를 모두 표시. 내용을 포함하고 있는 요소 밖으로 삐져나가서 표시
  overflow:hidden --> 요소 밖으로 나간 것은 표시하지 않음
  overflow:scroll --> 요소 안의 것만 보이나 스크롤 바가 생김
  overflow:auto --> 내용이 클 경우 스크롤 바가 생김

4. 사용자 지정 프로퍼티
var elem = document.getElementById(elementID);

elem.movement = setTimeout(repeat, interval);

if(elem.movement) {
    clearTime(elem.movement);
}

elementID에 movement라는 프로퍼티를 추가.

5. @import
<style type="text/css" media="screen">
  @import url("styles/layout.css");
</style>

css파일 안에서도 사용가능
js도 가능.

11장 총정리

1. margin, padding
* {
    padding: 0;
    margin: 0;
}

전체 선택자로 마진과 패딩을 0으로 설정 -> 브라우저마다 제각각인 기본 스타일 문제를 해결

부록

DHTMLgoodies.com

'프로그래밍 > Web' 카테고리의 다른 글

[html] X-UA-Compatible: IE=EmulateIE7  (0) 2010.04.09
[javascript] 전화번호 형식으로 바꾸기  (0) 2010.03.08
[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설명  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08

[jstl] jstl 사용하기

프로그래밍/Web 2010. 1. 8. 16:41 Posted by galad
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page import="test.model.*" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="c_rt" uri="http://java.sun.com/jstl/core_rt" %>

<%
    //List<FileBrowsingInfo> fileBrowsingInfoList = (List<FileBrowsingInfo>)request.getAttribute("fileBrowsingInfoList");
%>

<c_rt:set var="fileBrowsingInfoList" value='<%=request.getAttribute("fileBrowsingInfoList")%>' />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>파일 목록</title>
</head>
<body>

<c:forEach items="${fileBrowsingInfoList}" var="info">
    <c:if test="${info.uploadCompleted}">
    </c:if>
    <c:if test="${!info.uploadCompleted}">
    </c:if>

    <c:out value="${info.name}"></c:out>
    <br />
   
    <c:set var="childList" value="${info.childList}"></c:set>
    <c:forEach items="${childList}" var="childInfo">
        &nbsp;&nbsp;&nbsp;&nbsp;
        <c:out value="${childInfo.fileName}"></c:out>
        <br />
    </c:forEach>
</c:forEach>

</body>
</html>

1. jstl 사용시의 변수 scope이 스크립틀릿의 변수와는 약간 다르단다. http://lonelycat.tistory.com/389
  그래서 c_rt:set을 이용해서 변수 정의. (value 가 들어가는 자리에 표현식을 쓰기 위해서는 RT 기반의 태그를 사용해야 된다.)

2.
<c:out value="${info.name}"></c:out> 에서 info 클래스에 name에 대한 getter가 존재해서 사용가능.
  마찬가지로 <c:set var="childList" value="${info.childList}"></c:set> 에서도 childList에 대한 getter가 존재(getChildList).
  getter/setter 만 잘 맞춰주면 문제없는 듯.

3. <c:if test="${info.uploadCompleted}"> 또는 <c:if test="${!info.uploadCompleted}"> 처럼 boolean 형도 사용가능.
  uploadCompleted가 boolean으로, isUploadCompleted/setUploadCompleted의 get/set 메소드가 존재.

'프로그래밍 > Web' 카테고리의 다른 글

[javascript] 전화번호 형식으로 바꾸기  (0) 2010.03.08
[javascript] DOM 스크립트  (0) 2010.01.15
[jsp] jstl 설명  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08
[servlet] 서블릿에서 jsp로 포워드하기  (0) 2010.01.07

[jsp] jstl 설명

프로그래밍/Web 2010. 1. 8. 14:00 Posted by galad
출처: http://greatbeat.tistory.com/tag/JSTL

1           JSTL 개요

1.1          JSTL 이란

커스텀태그를 공부하면서 jsp페이지에서 자바코드를 추출하는데 탁월한 성능을 발휘하는 모습을 보았다. 허나 이것을 만든다고 생각하면, 아직도 좀 아찔한 감이 남아있다. 개발시간은 촉박한데, 로직 부분을 빼낸다고, tld 만들고, 태그핸들러 만들고, 컴파일하고, 잘 동작하는지 테스트해보고 하려면 사실 시간이 더 많이 소요되기 때문에 망설여지는 것이 사실이다.

하지만 커스텀태그 소개하면서 계속 얘기했던 것은 자주 쓰이는 커스텀태그들을 표준으로 정해서 모아놓은 것이 있으니까, 이것들만 잘 찾아서 쓰면 된다고 얘기했다. 정말 알짜들만 모아놓았다. 최정예 커스텀태그들을 모아서 이름을 붙여준 것이 JSP Stadard Tag Library 이고, 줄여서 JSTL 이라고 부른다. JCP(http://www.jcp.org )에서 표준을 제정했다. JSR-52 에서 각계의 전문가들이 심사 후에 알짜들을 모아놓은 것이다.

 

1.2          JSTL 현황

집필하는 현재 JSTL JSP2.0 스펙에 포함되었다. 따라서 JSP2.0 의 표준을 제일 먼저 구현해서 참고를 삼는 톰캣5.0 이 정식으로 발표된다면, 별다른 설치를 하지 않고 바로 JSTL을 사용할 수 있게 된다. (이미 발표된 톰캣5.0 알파버전에는 JSTL의 기능은 빠져 있다. EL 과 심플 커스텀태그와 태그파일의 기능은 들어가 있고, JSTL JSF는 빠져있다.)

JSTL EL 을 이용해서 객체의 접근을 쉽게 할 수 있다. jsp 에서 객체의 접근은 먼저 선언부터 되어야 되지만, EL에서는 별다른 선언없이도 객체를 받아서 처리할 수 있게 되었다. 이에 관해서는 후에 예제를 통해서 살펴보겠다.

JSTL 에 관련된 최신 정보는 sun jstl 홈페이지 http://java.sun.com/products/jsp/jstl 와 자카르타 프로젝트의 taglibs http://jakarta.apache.org/taglibs 를 통해서 얻을 수 있다.

 

1.3          JSTL 처리영역

JSTL은 태생이 커스텀태그이기 때문에 jsp와 밀접하게 관계가 있다. application, session, request, response, pageContext 등의 내장객체에 쉽게 접근하며, 그 외에도 파라메터, 헤더, 쿠키 등을 복잡한 코드를 사용하지않고, 쉽게 직관적으로 사용할 수 있다. 또한 기본적인 연산이나 객체의 비교 등을 .equals() 메소드 등을 이용하는 대신 == 와 같이 쉽게 구현했으며, 조건, 반복, 이동에 대한 태그를 지원하기 때문에 태그만으로도 반복 기능을 구현할 수 있다.

JSTL 의 처리영역은 크게 4가지로 나누어진다. core, format, xml, sql 로 기능이 구분되고, 각각의 기능은 이름이 말해 주듯, 기본기능, 형식화, xml처리, sql처리를 담당한다.

기능

prefix

기본URI

기본기능

c

http://java.sun.com/jstl/core

XML 처리

x

http://java.sun.com/jstl/xml

i18n & 형식화

fmt

http://java.sun.com/jstl/fmt

데이터베이스 작업

sql

http://java.sun.com/jstl/sql

 

2           JSTL 설치

2.1          JSTL 다운로드

JSTL JSP2.0 표준 스펙에 포함이 되었지만 아직 이 스펙을 지원하는 제품이 나오지 않은 상태이기 때문에 기존의 톰캣4에서 사용할 수 있게 설치하는 법을 알아보려고 한다.

이 책의 논외가 되겠지만 sun에서 나온 JWSDP(Java Web Services Developer Pack)에는 톰캣4.1.2 JSTL v1.0.3 이 기본으로 들어있기 때문에 이것만 설치하면 쉽게 JSTL을 사용할 수 있다. 이에 관한 사용법은 다음 주소를 참고하기 바란다. http://java.sun.com/webservices/docs/1.1/tutorial/doc/index.html 

jstl의 기본 설명도 충실하게 잘 나와있고, 웹서비스에 관련된 좋은 안내서이기에 꼭 읽어보기 바란다.

JSTL은 현재 자카르타의 taglibs 서브 프로젝트에서 받아올 수 있다.  http://jakarta.apache.org/taglibs 에 접속하고, Downloads 링크를 클릭한다. Release 버전과 Nightly Build 버전이 있는데, 정식 릴리스 버전은 현재 1.0.3 까지 나와있다.

http://www.apache.org/dist/jakarta/taglibs/standard/ 에 가면 바이너리 빌드를 받아 볼 수 있다. jakarta-taglibs-standard-current.zip 를 다운로드 받아서 적당한 위치에 압축을 푼다.

 

2.2          JSTL 예제 설치

jakarta-taglibs 디렉토리 아래 standard 에서 standard-examples.war 파일을 jstl.war 파일로 이름을 바꾼 뒤에 Tomcat 4 가 설치된 디렉토리의 webapps 디렉토리에 복사한다.

server.xml <Host> unpackWARs="true" 로 설정되어 있다면, jstl 이라는 디렉토리가 자동으로 생기면서 jstl.war 의 압축이 풀린 뒤에 브라우저에서 http://localhost:포트/jstl 로 예제 웹 어플리케이션을 실행해 볼 수 있다.

 

2.3          JSTL add-on 설치

기존의 컨텍스트에서 JSTL을 사용하기 위해서는 웹 어플리케이션의 WEB-INF/lib 디렉토리에 필요한 라이브러리를 복사하면 된다. JSTL 의 주된 라이브러리 파일은 jstl.jar, standard.jar 이고, xml에서 지원되는 기능을 사용하기 위해서 jaxen-full.jar, saxpath.jar,  jaxp-api.jar 파일 등이 필요하다. 이 파일들을 웹어플리케이션의 WEB-INF/lib 에 복사하고, 컨텍스트를 리로드한다. 구체적인 파일들의 명세는 다음과 같다.

이름

설명

파일

JSTL 1.0 API 클래스

jstl 1.0 API 클래스

jstl.jar

JSTL 1.0 구현 클래스

JSTL 구현

standard.jar

Jaxen 1.0

Xpath 엔진

jaxen-full.jar

Saxpath 1.0

Xpath 파싱에 필요 sax 방식

saxpath.jar

Jdbc 2.0 선택 패키지

JDBC 구현 클래스
j2se1.4,
톰캣4 기본포함

jdbc2_0-stdext.jar

Jaxp 1.2 구현

jaxp 1.2 호환 파서 필요

jaxp-api.jar
dom.jar
sax.jar
xercesImpl.jar

Xalan

아파치 xslt 변환기

xalan.jar

만일 톰캣4 ROOT 컨텍스트에 설치를 한 경우에는 webapps/ROOT/WEB-INF/ 아래에 lib 디렉토리를 만들고 jstl 의 필요한 JAR 파일들을 복사해 놓으면 된다.

 

2.4          JSTL tld 파일

tld파일이 없거나, web.xml 파일에 8개의 tld 파일을 등록하지 않아도 표준태그는 사용할 수 있도록 되어 있다.

4가지의 JSTL 태그마다 EL 기반과 RT 기반의 태그로 나눠진다. 태그핸들러의 종류는 똑같지만 차이가 있다면 value 값으로 EL 을 사용하느냐 아니면 스크립트의 표현식을 허용하느냐의 차이다. 이에 관해서는 후에 살펴보겠다.

서버에 따라서 필요한 경우가 있으므로 간략히 방법을 설명하면, jakarta-taglibs standard 디렉토리에 있는 tld 디렉토리의 8개의 tld 파일을 웹 어플리케이션의 WEB-INF/ 아래에 적당한 위치에 복사한 뒤에 이 파일들의 위치를 web.xml 에 등록한다.

 

3           표현언어 EL (Expression Language)

EL은 다양한 위치에 있는 데이터에 접근하기 위한 언어이다. 문법체계가 직관적으로 아주 쉽다. jsp 에서는 모든 변수의 생성과 선언을 반드시 표시를 해주어야 되지만 EL은 그 과정 없이 바로 접근이 가능하다.

 

3.1          EL 표시형식

EL임을 표시하는 형식은 ${} 이다. 이 안에 들어있는 것은 EL 로 처리된다. 내장객체의 접근이 가능하고, 산술연산과 비교연산이 가능하다.

자바스크립트와 비슷한 방법으로 객체 내부의 자원에 접근이 가능하다. dot(.) bracket([]) 모두를 이용해서 접근할 수 있으며, 예를 들면

${header.cookie} ${header['cookie']} 는 같은 결과 값을 얻을 수 있다. 만일 user-agent 처럼 - 와 같이 있을 경우는 ${header['user-agent']} 로 접근하는 것이 좋다.

[] 를 이용해서 객체에 접근할 경우에 index 를 대신해서 사용할 수도 있다.

다음 예제는 이전 내용을 요약한 것이다.

예제 1.   jstlel01.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<h3>header</h3>

<c:forEach items="${header}" var="h">

  <c:out value="${h}"/><br/>

</c:forEach>

<h3>header.cookie</h3>

<c:out value="${header.cookie}"/><br/>

<c:out value='${header["cookie"]}'/>

 

 

header 라는 객체가 갖고 있는 값들을 불러서 보여주는 소스이다. request.getHeader() 로 가져올 수 있는 것인데, 훨씬 깔끔한 소스로 보여진다.

JSTL 태그에서 기본적으로 EL을 사용한다. var 속성은 변수를 지정하는데, 여기에는 문자열 상수로 지정되며, 이 후에 이 변수를 참조하기 위해서는 EL 을 사용한다.

 

3.2          EL 내장객체

EL 로 접근할 수 있는 내장 객체들은 다음과 같다.

pageScope

page scope 의 변수들

requestScope

request scope 의 변수들

sessionScope

session scope 의 변수들

applicationScope

application scope 의 변수들

param

parameter 변수들 문자열

paramValues

parameter 변수들 문자열 배열

header

HTTP request 헤더

headerValues

HTTP request 헤더 문자열 배열

initParam

컨텍스트 초기 변수 web.xml 에서 지정

cookie

쿠키 변수들

pageContext

현재 페이지의 pageContext 객체

 

pageScope 의 변수는 스크립틀릿의 변수와는 틀리며, 이를 이용하려면 조금은 번잡한 과정을 거치게 된다. 따라서 가능하면 스크립틀릿은 사용하지 않기를 권장한다. 이를 활용하는 소스이다.

예제 2.   jstlel02.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="c_rt" uri="http://java.sun.com/jstl/core_rt" %>

<% String[] abc = {"빨강","파랑","노랑"}; %>

 

<c:set var="t" value="hello"/>

<c_rt:set var="color" value="<%=abc%>"/>

 

<h3>pageScope</h3>

<c:forEach items="${pageScope}" var="h">

    <c:out value="${h}"/><br/>

</c:forEach>

 

<h3>colors</h3>

<c:forEach items="${color}" varStatus="i">

    <c:out value="${i.count}"/>.

    <c:out value="${color[i.index]}"/><br/>

</c:forEach>

 

 

<c:forEach/> 를 통해서 pageScope 의 값을 모두 출력해보면, String 배열변수인 abc 는 접근할 수 없게 되어있다. <c:set/> <c_rt:set/> 으로 정해놓은 t color 만 나타나는 것이 보인다.

color 의 값을 출력하는 코드를 보면 color 의 인덱스를 이용해 배열 내용을 뽑아 왔다. varStatus 대신 var 변수를 통해서 바로 내용을 출력할 수도 있다.

 

value 가 들어가는 자리에 표현식을 쓰기 위해서는 RT 기반의 태그를 사용해야 된다. 만일 <c_rt:set var="color" value="<%=abc%>"/> 에서 <c_rt:set/> 대신 <c:set/> 를 사용하면 color 가 갖게 되는 값은 "<%=abc%>" 문자열이 되어버린다.

 

3.3          EL 연산자

null 인지 아닌지 판단하기 위해서는 empty 라는 키워드를 사용한다. 세션 값이 없으면 세션에 값을 저장하고, 있을 경우 하나를 더한 후에 출력하는 코드이다

예제 3.   jstlel03.jsp

<% response.setContentType("text/html;"); %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<c:if test="${!empty hit}">

    <c:set var="hit" value="${hit+1}" scope="session"/>

    <c:out value="${hit}"/> 번 리로드되었습니다.

</c:if>

<c:if test="${empty hit}">

    <c:set var="hit" value="1" scope="session"/>

    세션에 값을 저장했습니다.

</c:if>

<br>

<a href="jstlel03.jsp">reload</a>

 

 

EL 의 장점은 객체의 접근이 쉽다고 했다. ${empty 객체} 를 통해서, 객체의 null 을 확인할 수 있다. ${!empty hit} ${!empty sessionScope.hit} 로 대치해도 같은 결과가 나온다.

EL 의 연산자는 관계연산자, 산술연산자, 논리연산자, empty 연산자가 있고 다음 표와 같다.

연산자 구분

연산자

관계

< lt > gt <= le >= ge == eq != ne

산술

+ - * / div % mod

논리

&& and || or ! not

Empty

empty

 

연산자들간의 우선순위는 다음과 같다.

1. [] .

2. ()

3. - (단항) not ! empty

4. * / div % mod

5. + - (이항)

6. < > <= >= lt gt le ge

7. == != eq ne

8. && and

9. || or

 

4           JSTL Core

core 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

가장 빈번하고 자주 쓰이는 것이다. Core 의 태그들은 다음과 같이 정리된다.

기능

태그

prefix

EL 지원

catch , out , remove , set

c

흐름 제어

choose (when , otherwise) , forEach , forTokens , if

URL 관리

Import (param) , redirect (param) , url (param)

 

4.1          <c:out/>

가장 많이 쓰게 되는 것은 JSP 의 표현식을 대체하는 <c:out/> 이다. 다음과 같은 형식을 갖고 있다.

body 없는 경우

<c:out value="value" [escapeXml="{true|false}"] [default="기본값"] />

 

body 있는 경우

<c:out value="value" [escapeXml="{true|false}"] />

기본값

</c:out>

 

 

[] 으로 둘러 쌓인 부분은 생략 가능한 부분이다. value default 값은 일반 문자열이나 EL 이 들어간다. value 안에 JSP의 표현식을 사용하려 한다면 RT 기반의 <c_rt:out> 을 사용해야 된다는 것은 이전 예제에서 살펴 보았다.

escapeXml 속성은 값 중에 포함된 < > & ' " 문자들을 각각 &lt; &gt; &amp; &#039; &#034; 로 출력한다. 생략될 경우 true 가 기본 값이다.

null 값의 처리에 대해서 JSP expression 의 경우는 "null" 문자열로 출력이 되었던 것을 jstl의 스펙에서는 이 경우 빈 문자열("")또는 기본값으로 처리한다고 명시되어있다.

 

4.2          <c:set/>, <c:remove/>

<c:set/> 의 기본형식은 다음과 같다. scope 속성이 생략될 경우 기본값은 page 이다.

Syntax 1: scope 에 해당하는 변수에 속성 값을 정한다.

<c:set value="value"

var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: scope 에 해당하는 변수에 body 값을 정한다.

<c:set var="varName" [scope="{page|request|session|application}"]>

body content

</c:set>

 

Syntax 3: 속성 값으로 target 객체의 프로퍼티 값을 정한다.

<c:set value="value"

target="target" property="propertyName"/>

 

Syntax 4: body 값으로 target 객체의 프로퍼티 값을 정한다.

<c:set target="target" property="propertyName">

body content

</c:set>

 

변수에 값을 할당한다. 빈과 같은 객체에 할당하기 위해서는 target property속성을 이용한다.

 

<c:remove/> JSP removeAttribute() 와 같은 역할을 한다. 해당 scope 에 있는 변수를 제거하는 역할을 한다.

 

4.3          <c:catch/>

<c:catch/> body 위치에서 실행되는 코드의 예외를 잡아내는 역할을 담당한다. var 속성을 지정해서 변수를 선언하면 그 변수에 예외의 내용이 들어가게 된다.

 

다음 예제는 이상의 태그를 사용한 예제이다.

예제 4.   jstlcore01.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<h3>코어 </h3>

<h4>&lt;c:out></h4>

<pre>

${1+2} <c:out value="${1+2}"/>

${1>3} <c:out value="${1>3}"/>

${1 gt 3} <c:out value="${1 gt 3}"/>

 

${ 표시 <c:out value="${'${'}test}"/>

 

escapeXml 속성; 기본값은 false

false: <c:out value="<b>bold</b> <,>,&,',\" " escapeXml="false"/>

true:  <c:out value="<b>bold</b> <,>,&,',\" " escapeXml="true"/>

 

" 큰따옴표 사용주의; ' 작은따옴표로 대치

&lt;c:out value='&lt;font color="blue">파랑&lt;/font>'/>

<c:out value='<font color="blue">파랑</font>' escapeXml="false"/>

 

<hr><h4>&lt;c:set></h4>

set session scope var "name": <c:set var="name" value="하늘" scope="session"/>

c:out name: <c:out value="${name}"/>

expression name: <%= session.getAttribute("name")%>

 

set page scope var "name": <c:set var="name">

  hello

</c:set>

c:out name: <c:out value="${pageScope.name}"/>

c:out sessionScope.name: <c:out value="${sessionScope.name}"/>

expression name: <%= session.getAttribute("name")%>

 

<hr><h4>&lt;c:remove></h4>

remove session scope var "name": <c:remove var="name" scope="session"/>

expression name: <%= session.getAttribute("name")%>

c:out sessionScope.name: <c:out value="${sessionScope.name}"/>

 

<hr><h4>&lt;c:catch></h4>

<c:catch var="errmsg">

line1

<%=1/0 %>

line2

</c:catch>

<c:out value="${errmsg}"/>

</pre>

 

 

value 속성에 들어가는 값은 문자열과 EL 이다. EL의 경우 ${} 안에서 나온 결과값을 표시한다. 부등호 > gt 는 같은 뜻이다. "${" 를 표시하기 위해서는 EL 로 감싸야 된다. ${'${'} 로 해야 표시된다.

escapeXml 속성은 브라우저에서 특수한 기능을 하는 문자 표시 여부를 결정한다. false 값일 경우는 태그가 먹힌 굵은 글씨의 bold 가 나오고, true 일 경우는 '<' '>'를 각각 '&lt;','&gt;' 로 변환한다. 결과는 <b>bold</b> , 브라우저에서 태그가 보이도록 나온다.

큰따옴표와 작은따옴표는 바꿔서 쓸 수 있다. 대신 짝이 맞아야 된다. 또한 하나로 다 이어서 쓸 경우 변환과정에서 에러가 나기 때문에 주의해야된다.

따옴표 사용 예

외부

문자열내부

사용

<c:out value='<font color="blue">파랑</font>' />

작은

가능

<c:out value="<font color='blue'>파랑</font>" />

작은

가능

<c:out value="<font color="blue">파랑</font>" />

불가

session 스코프에 name 이라는 key "하늘"을 넣는다. <c:out value="${name}"/> 으로 scope 를 지정하지 않아도 내장 객체를 훑어서 sessionScope에서 걸리는 "name"키를 찾아서 출력한다. 이 값은 스크립틀릿에서도 참고할 수 있다.

page 스코프에 같은 key "hello" 라는 값을 넣으면 <c:out value="${name}"/> 은 더 이상 session 에 있는 값을 가져오지 않는다.

<c:remove/> 를 통해서 scope 속성에 지정된 key 값을 제거한다.

 

예제에서 <c:catch/> 태그는 body 실행 도중에 <%=1/0 %> 에서 예외가 발생한 것을 errmsg 라는 변수에 넣는다. 이 후에 <c:out/> 을 통해서 에러 메시지를 표시한다.

 

4.4          <c:if/>

<c:if/> 는 흔히 보는 조건문이다. 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:if test="testCondition"

var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우

<c:if test="testCondition"

[var="varName"] [scope="{page|request|session|application}"]>

body content

</c:if>

 

 

<c:if/> 에서 나온 결과를 varName 변수에 넣고, 나중에 활용이 가능하다. 변수의 scope는 임의로 지정할 수 있고, 생략될 경우 기본값은 page 이다.

 

4.5          <c:choose/>, <c:when/>, <c:otherwise/>

<c:choose/> 태그는 java switch 문과 같지만, 조건에 문자열 비교도 가능하고 쓰임의 범위가 넓다. 또한 <c:if/> 태그에 else 가 없기 때문에 이의 대체 기능도 수행한다.

형식은 다음과 같다.

<c:choose>

body content

(하나 이상의 <when> 과 하나 이하의 <otherwise> 서브태그)

    <c:when test="조건">

        body content

    </c:when>

   

    <c:otherwise>

        conditional block

    </c:otherwise>

</c:choose>

 

조건 판단을 수행하는 간단한 예제이다.

예제 5.   jstlcore02.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<h3>조건</h3>

파라메터 없음:<c:out value="${empty param.name}" />

<h4>&lt;c:if test=""></h4>

<c:if test="${empty param.name}">

<form>

이름을 적어주세요.<br>

    <input type="text" name="name">

    <input type="submit" value="확인">

</form>

</c:if>

<c:if test="${!empty param.name}">

    안녕하세요. <c:out value="${param.name}"/>.

</c:if>

 

<h4>&lt;c:choose> &ltc:when test=""> &ltc:otherwise></h4>

<c:choose>

    <c:when test="${empty param.name}">

        <form>

        이름을 적어주세요.<br>

            <input type="text" name="name">

            <input type="submit" value="확인">

        </form>

    </c:when>

    <c:when test="${param.name=='admin'}">

        안녕하세요. 관리자님.

    </c:when>

    <c:otherwise>

        안녕하세요. <c:out value="${param.name}"/>.

    </c:otherwise>

</c:choose>

파라메터 name 값이 없는 경우 입력 폼을 출력한다. 파라메터 name 의 값이 "admin"일 경우 관리자를 표시하고, 그 외에는 파라메터 값을 그대로 출력한다.

파라메터의 유무는 empty !empty 연산자를 통해서 확인할 수 있다.

 

4.6          <c:forEach/>, <c:forTokens/>

<c:forEach/> 는 강력한 반복실행 태그이다. 형식은 다음과 같다.

Syntax 1: 객체 전체에 걸쳐서 반복

<c:forEach [var="varName"] items="collection"

           [varStatus="varStatusName"]

           [begin="begin"] [end="end"] [step="step"]>

    body content

</c:forEach>

 

Syntax 2: 지정한 횟수만큼 반복

<c:forEach [var="varName"]

           [varStatus="varStatusName"]

           begin="begin" end="end" [step="step"]>

    body content

</c:forEach>

 

<c:forEach/> 태그는 여러가지로 활용이 가능하다. 원하는 구간만큼 반복할 수도 있고, 객체를 받아와서 그 객체의 길이만큼 반복할 수도 있다. begin , end 속성은 시작번호와 끝번호를 지정하고, step 속성을 이용해서 증가 구간을 정할 수 있다. var 속성에서 정한 변수로 반복되는 내부 구간에서 사용할 수 있다.

 

<c:forTokens/> java.util.StringTokenizer 를 이용한 것이다. 형식은 다음과 같다.

Syntax

<c:forTokens items="stringOfTokens" delims="delimiters"

[var="varName"]

[varStatus="varStatusName"]

[begin="begin"] [end="end"] [step="step"]>

body content

</c:forEach>

 

<c:forEach/> <c:forTokens/> 를 활용한 예제이다.

예제 6.   jstlcore03.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<h3>반복</h3>

<h4>&lt;c:forEach></h4>

 

<c:forEach var="one" begin="1" end="10">

    <c:out value="${one}"/>

</c:forEach>

<p><b>header</b></p>

<c:forEach var="h" items="${header}">

    <c:out value="${h.key}:${h.value}"/><br>

</c:forEach>

 

<h4>&lt;c:forTokens></h4>

<c:forTokens var="one"

            items="서울|인천,대전,대구,부산,광주,평양"

            delims="," varStatus="sts">

    <c:out value="${sts.count}:${one}"/>&middot;

</c:forTokens>

<hr>

<c:forTokens var="one"

            items="서울|인천,대전,대구,부산,광주,평양"

            delims=",|" varStatus="sts">

    <c:out value="${sts.count}:${one}"/>&#149;

</c:forTokens>

 

예제의 첫번째 <c:forEach/> 에서는 1에서 10까지 반복하면서 값을 출력한다. 이때 var속성의 one변수에는 진행중인 값이 저장된다.

두번째 <c:forEach/> 반복문을 보면 items 속성에 header 객체를 받아온다. header 객체는 Map 형태이고, getKey() getValue() 메소드의 사용이 가능하기 때문에 h.key h.value 를 통해서 출력할 수 있다.

<c:forTokens/> 태그는 StringTokenizer 와 동일한 기능을 한다. delims 속성에 정해진 char 로 나뉘어지게 된다. 마지막 반복구간에서 마디로 나누는 기준은 , | 두 가지이다.

varStatus 속성에서 정해준 변수는 .index .count 를 사용할 수 있고, 시작 번호는 각각 0 1 이다.

 

4.7          <c:import/>

이제 소개할 <c:import/> 는 아주 강력한 도구이다. 웹 어플리케이션 내부의 자원 접근은 물론이고, http, ftp 같은 외부에 있는 자원도 가져와서 페이지 내에 귀속시킨다. 자유롭게 가공할 수도 있고, 편집도 가능하다. <c:import/> 의 형식은 다음과 같다.

Syntax 1: 해당 주소를 바로 출력하거나 String 에 담아놓는다.

<c:import url="url" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]

        [charEncoding="charEncoding"]>

   <c:param> 서브 태그 위치

</c:import>

 

Syntax 2: 해당 주소의 컨텐츠를 Reader 객체로

<c:import url="url" [context="context"]

        varReader="varReaderName"

        [charEncoding="charEncoding"]>

    varReader 를 사용하는 액션

</c:import>

스트림으로 받아와서 파일로 저장하거나, DB에 입력할 수도 있도록 되어있다.

다음은 간단한 예제이다.

예제 7.   jstlcore04.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:set var="url" value="http://www.google.co.kr/"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<base href="<c:out value="${url}"/>">

    <c:out value="${u}" escapeXml="false"/>

</base>

<hr>

 

<c:set var="url" value="http://www.okjsp.pe.kr"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<pre><c:out value="${u}"/></pre>

<hr>

 

<c:set var="url" value="ftp://ftp.dacom.co.kr"/>

<c:import url="${url}" var="u"/>

<c:out value="${url}"/> 가져옵니다.

<hr>

<pre><c:out value="${u}"/></pre>

<hr>

 

<c:set var="url" value="jstlcore02.jsp"/>

<c:import url="${url}" var="u">

    <c:param name="name" value="admin"/>

</c:import>

<c:out value="${url}"/> 가져옵니다.

<hr>

<c:out value="${u}" escapeXml="false"/>

<hr>

4개의 주소를 불러오는 예제이다.

처음에는 구글사이트를 불러서 그대로 표시한다. escapeXml 속성을 false 로 해야 브라우저에 태그가 나타나지 않는다.

<base href=""> 태그는 소스를 가져왔을 때 상대경로에 있는 주소의 기준점이 된다. 따라서 상대경로로 표시된 이미지 등을 깨지지 않고 표시할 수 있다.

두번째는 okjsp 사이트를 가져와서 소스를 보여준다. escapeXml 속성이 생략되면 true값으로 지정되고, 태그를 볼 수 있게 했다.

세번째는 ftp.dacom.co.kr 에 있는 내용을 가져온다.

마지막에는 앞에서 보았던 jstlcore02.jsp 를 불러오는 예제이다. <c:param/> 태그를 내부에 두어서 파라메터값을 보낼 수 있다.



 

4.8          <c:url/>

<c:url/> 태그는 컨텍스트를 자동으로 추가해서 주소를 자동으로 생성해준다. context 속성이 지정되었을 경우 value context 의 값은 / 로 시작을 해야된다. context 속성이 생략되면 당연히 현재의 컨텍스트가 적용된다. <c:url/> 의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:url value="value" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우 쿼리 스트링 파라메터 지정

<c:url value="value" [context="context"]

        [var="varName"] [scope="{page|request|session|application}"]>

    <c:param> 서브태그

</c:url>

 

다음은 간단한 예제이다.

예제 8.   jstlcore05.jsp

<% response.setContentType("text/html"); %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:url value="/images/tomcat.gif"/>

<img src="<c:url value="/images/tomcat.gif"/>">

코드를 실행하면, <img src="/chap9/images/tomcat.gif">  와 같이 출력이 된다. ROOT 컨텍스트일 경우는 <img src="/images/tomcat.gif"> 와 같이 출력된다.

다른 컨텍스트를 사용하는 경우 정적인 컨텐츠의 주소를 쓰기 위해서는 jsp 에서는 <img src="<%=request.getContextPath()%>/images/tomcat.gif"> 와 같이 처리를 해주어야 되었다. 이런 경우를 대체하는 태그이다.

 

4.9          <c:redirect/>

response.sendRedirect() 를 대체하는 태그이다. 컨텍스트를 지정해서 다른 컨텍스트로 이동이 가능하다.

<c:redirect/> 의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<c:redirect url="value" [context="context"]/>

 

Syntax 2: Body 있는 경우 쿼리 스트링 파라메터 지정

<c:redirect url="value" [context="context"]/>

    <c:param> 서브태그

</c:redirect>

 

다음은 간단한 예제이다.

예제 9.   jstlcore06.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

 

<c:redirect url="/jstlcore01.jsp"/>

<c:url/> 태그와 마찬가지로 context 속성을 지정하면, value context 의 값은 / 로 시작을 해야된다. <c:param/> 태그를 중첩시켜서 사용할 수도 있다.

 

4.10       <c:param/>

<c:param/> 은 다음과 같이 url 에 바로 붙여서 쓸 수도 있다.

<c:import url="/exec/doIt">

  <c:param name="action" value="register"/>

</c:import>

이 방법은 아래 태그와 같은 효과가 있다.

<c:import url="/exec/doIt?action=register"/>

 

이제까지 기본적인 태그인 core 태그들에 대해서 살펴보았다. 다음 섹션에서 출력 형식을 지정하는 fmt 태그를 살펴보도록 하겠다.

 

5           JSTL 국제화 지역화 태그

다국어 문서를 처리할 때 유용하고, 날짜와 숫자 형식을 다루는 fmt 태그는 다음과 같은 종류가 있다.

기능

태그

prefix

Locale 설정

setLocale, requestEncoding

fmt

메시지 처리

bundle, message(param), setBundle

숫자 날짜 형식

formatNumber, formatDate, parseDate, parseNumber, setTimeZone, timeZone

 

fmt 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

 

 

5.1          <fmt:setLocale/>

<fmt:setLocale/> 의 형식은 다음과 같다.

Syntax

<fmt:setLocale value="locale"

        [variant="variant"]

        [scope="{page|request|session|application}"]/>

 

 

다국어 페이지를 만들 경우 사용할 경우 ResourceBundle 로 불러오는 *.properties 파일들과 연계되어서 사용할 수 있다. value 속성에 들어가는 locale 값은 [1]언어코드와 [2]국가코드로 이루어진다. 생략될 경우 톰캣 서버의 기본값으로 설정이 되고, 둘 중에 하나만 사용할 수도 있다. http://java.sun.com/j2se/1.4.1/docs/api/java/util/Locale.html api 에 보다 상세한 설명이 있다.

예제 10.                          jstlfmt01.jsp

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<pre>

default locale : <%= response.getLocale() %>

set locale : ko <fmt:setLocale value="ko" />

now: <%= response.getLocale() %>

set locale : ja <fmt:setLocale value="ja" />

now: <%= response.getLocale() %>

set locale : en <fmt:setLocale value="en" />

now: <%= response.getLocale() %>

</pre>

예제를 값을 변경시켜서 실행하면, response 쪽에 영향을 주는 것을 알 수 있다.

 

5.2          <fmt:requestEncoding/>

다음으로 볼 것은 request.setCharacterEncoding() 역할을 하는 <fmt:requestEncoding/> 태그이다. 형식은 다음과 같다.

Syntax

<fmt:requestEncoding [value="charsetName"]/>

 

파라메터를 MS949 로 인코딩하는 경우 다음과 같이 사용하면 된다.

<fmt:requestEncoding value="MS949"/>

 

예제 11.                         jstlfmt02.jsp

<%@ page contentType="text/html;charset=euc-kr" %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<fmt:requestEncoding value="euc-kr"/>

파라메터:<c:out value="${param.id}"/>

<form method="post">

    <input type="text" name="id">

    <input type="submit">

</form>

페이지 인코딩이 적용된 경우 request 에서 가져오는 parameter 와 맞지 않는 경우에 사용한다. 서버마다 차이가 있기 때문에, 테스트를 통해서 자신의 환경에 맞게 사용해야 된다. 톰캣4.1.19 의 경우 인코딩을 적용하지 않고도, 해결되는데 다음과 같은 형태로 사용할 수 있다.

예제 12.                         jstlfmt02b.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<% response.setContentType("text/html;"); %>

파라메터:<c:out value="${param.id}"/>

<form method="post">

    <input type="text" name="id">

    <input type="submit">

</form>

 

 

5.3          <fmt:bundle/>

properties 확장자를 사용하는 자원 파일을 읽어오는 역할을 하는 <fmt:bundle/> 에 대해서 알아보자. 형식은 다음과 같다.

Syntax

<fmt:bundle basename="basename"

        [prefix="prefix"]>

    body content

</fmt:bundle>

 

basename 속성에 지정된 properties 파일을 찾아서 locale 에 따라 읽어들인다.

properties 파일은 보통 WEB-INF/classes 아래에 위치하며 디렉토리의 깊이에 따라서 패키지형식의 이름을 취한다. TestBundle.properties 파일이 com/itexpert/chap9/msg 디렉토리에 있다면 basename="com.itexpert.chap9.msg.TestBundle" 이라고 지정하면 된다.

locale ko 라면 TestBundle_ko.properties 파일을 읽어오게 되며, locale 이 맞지 않는 경우에는 TestBundle.properties 처럼 코드가 붙지 않은 파일을 읽어온다.

prefix 속성은 key 명칭이 공통적인 부분을 지정해서 body 에서 표현되는 key 를 단축시킨다. import 에서 패키지명을 지정하면 클래스명만 쓸 수 있는 것과 같이 생각할 수 있다.

properties 파일의 경우 j2sdk /bin/native2ascii.exe 를 이용해서 유니코드로 변환될 필요가 있으나, 파일 수가 많을 경우 ant <native2ascii> 태스크를 이용해서 쉽게 처리할 수 있다. chap9.zip 소스에 포함된 build.xml 파일에 보면 다음과 같은 태스크가 지정되어 있다.

<native2ascii encoding="EUC-KR"

            src="${src.home}"

            dest="${build.home}/WEB-INF/classes"

            includes="**/*_ko.properties"/>

 

5.4          <fmt:message/>

번들 태그에서 정한 값들을 가져오는 태그는 <fmt:message/>이다. 다음은 <fmt:message/> 태그의 형식이다.

Syntax 1: body 없는 경우

<fmt:message key="messageKey"

        [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 메시지 파라메터를 지정하는 body가 있는 경우

<fmt:message key="messageKey"

        [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    <fmt:param> 서브태그

</fmt:message>

 

Syntax 3: 키와 선택적 메시지 파라메터를 지정하는 body가 있는 경우

<fmt:message [bundle="resourceBundle"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    key

    선택적 <fmt:param> 서브태그

</fmt:message>

 

번들에 있는 key 값을 불러온다. bundle 속성으로 번들을 직접 설정할 수도 있고, <fmt:bundle/> 태그 사이에 중첩되어서 키값만 받아서 출력할 수 있다.

예제 13.                         TestBundle.properties

greeting=Hello.

admin=kenu

 

예제 14.                         TestBundle_ko.properties

greeting=안녕하세요.

admin=허광남

 

예제 15.                         jstlfmt03.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<fmt:setLocale value="ko"/>

<fmt:bundle basename="com.itexpert.chap9.msg.TestBundle">

 <fmt:message>greeting</fmt:message><br>

 <fmt:message>admin</fmt:message>

</fmt:bundle>

 

locale "ko" 로 지정했기 때문에 TestBundle_ko.properties 파일을 읽어온다. "en"으로 정하거나 맞는 프로퍼티가 없을 경우는 기본프로퍼티인 TestBundle.properties 파일을 읽는다.

<fmt:message> 를 통해서 greeting 키와 admin 키를 읽어와서 표시한다.

 

5.5          <fmt:setBundle/>

페이지 전체에서 사용할 수 있는 번들을 지정할 수 있는데, 이에 대한 지정은 <fmt:setBundle/> 태그가 담당한다. var 속성에서 정한 변수를 이후에 나오는 <fmt:message/> 태그에서 basename 속성에 변수명으로 대체할 수 있다. <fmt:setBundle/> 의 형식은 다음과 같다.

Syntax

<fmt:setBundle basename="basename"

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

예제 15. jstlfmt03.jsp 는 다음과 같이 수정할 수 있다.

예제 16.                         jstlfmt04.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<fmt:setLocale value="ko"/>

<fmt:setBundle var="testBundle"

    basename="com.itexpert.chap9.msg.TestBundle"/>

 

<fmt:message bundle="${testBundle}" key="greeting"/><br>

<fmt:message bundle="${testBundle}" key="admin"/><br>

var 에서 변수를 설정할 때는 EL 을 사용하지 않는다. 다른 태그에서 이것을 불러오는 경우는 EL 을 사용해서 불러온다. testBundle 변수의 사용을 눈여겨 볼만하다.

 

5.6          <fmt:formatNumber/>

다음은 숫자 형식을 표현하는 <fmt:formatNumber/> 태그이고 형식은 다음과 같다.

Syntax 1: body 없는 경우

<fmt:formatNumber value="numericValue"

        [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [currencyCode="currencyCode"]

        [currencySymbol="currencySymbol"]

        [groupingUsed="{true|false}"]

        [maxIntegerDigits="maxIntegerDigits"]

        [minIntegerDigits="minIntegerDigits"]

        [maxFractionDigits="maxFractionDigits"]

        [minFractionDigits="minFractionDigits"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 형식에 맞출 수치가 body에 있는 경우

<fmt:formatNumber [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [currencyCode="currencyCode"]

        [currencySymbol="currencySymbol"]

        [groupingUsed="{true|false}"]

        [maxIntegerDigits="maxIntegerDigits"]

        [minIntegerDigits="minIntegerDigits"]

        [maxFractionDigits="maxFractionDigits"]

        [minFractionDigits="minFractionDigits"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    형식화될 수치

</fmt:formatNumber>

 

 

각 속성을 정리한 표는 다음과 같다.

속성

동적값

Type

설명

value

true

String 또는

Number

형식화될 수치

type

true

String

숫자, 통화, 퍼센트 중 어느 것으로 표시할 지 지정 {number|currency|percent}

pattern

true

String

사용자가 지정한 형식 패턴.

currencyCode

true

String

ISO 4217 통화 코드. 통화 형식일 때만 적용(type="currency")

currencySymbol

true

String

통화 기호. 통화 형식일 때만 적용

(type="currency")

groupingUsed

true

boolean

형식 출력에 그룹 분리기호를 포함할지 여부

maxIntegerDigits

true

int

형식 출력에서 integer 최대 자리수

minIntegerDigits

true

int

형식 출력에서 integer 최소 자리수

maxFractionDigits

true

int

형식 출력에서 소수점 이하 최대 자리수.

minFractionDigits

true

int

형식 출력에서 소수점 이하 최소 자리수.

var

false

String

형식 출력 결과 문자열을 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.7          <fmt:parseNumber/>

반대로 정해진 패턴을 문자열에서 수치를 파싱해내는 태그는 <fmt:parseNumber/>이며 형식은 다음과 같다.

Syntax 1: body가 없는 경우

<fmt:parseNumber value="numericValue"

        [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [parseLocale="parseLocale"]

        [integerOnly="{true|false}"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 파싱할 수치를 body 에 갖고 있는 경우

<fmt:parseNumber [type="{number|currency|percent}"]

        [pattern="customPattern"]

        [parseLocale="parseLocale"]

        [integerOnly="{true|false}"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    파싱할 수치

</fmt:parseNumber>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

String 또는

Number

파싱할 수치

type

true

String

숫자, 통화, 퍼센트 중 어느 것으로 표시할 지 지정 {number|currency|percent}

pattern

true

String

사용자가 지정한 형식 패턴.

parseLocale

true

String 또는

java.util.Locale

파싱 작업의 기본 형식 패턴(숫자, 통화, 퍼센트 각각)을 제공하는 Locale

integerOnly

true

boolean

주어진 값에서 integer 부분만 파싱할지 여부를 지정

var

false

String

파싱 결과 (java.lang.Number 타입)를 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.8          <fmt:formatDate/>

다음은 날짜 형식을 표현하는 <fmt:formatDate/> 태그이고 형식은 다음과 같다.

Syntax

<fmt:formatDate value="date"

        [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

java.util.Date

형식화될 Date time

type

true

String

형식화할 데이터가 시간, 날짜, 모두 인지 셋 중 하나를 지정한다.

dateStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다. type="date", type="body", type속성이 생략된 경우 사용.

timeStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다.

type="time", type="body" 의 경우 사용.

pattern

true

String

사용자 지정 형식 스타일

timeZone

true

String 또는

java.util.TimeZone

형식화 시간에 나타날 타임존

var

false

String

형식 출력 결과 문자열을 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

5.9          <fmt:parseDate/>

정해진 패턴의 문자열에서 날짜를 파싱해내는 태그는 <fmt:parseDate/>이며 형식은 다음과 같다.

Syntax 1: body 없는 경우

<fmt:parseDate value="dateString"

        [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [parseLocale="parseLocale"]

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

Syntax 2: 파싱한 값이 body 에 있는 경우

<fmt:parseDate [type="{time|date|both}"]

        [dateStyle="{default|short|medium|long|full}"]

        [timeStyle="{default|short|medium|long|full}"]

        [pattern="customPattern"]

        [timeZone="timeZone"]

        [parseLocale="parseLocale"]

        [var="varName"]

        [scope="{page|request|session|application}"]>

    파싱할 Date time

</fmt:parseDate>

 

 

각 속성을 정리한 도표는 다음과 같다.

속성

동적값

Type

설명

value

true

java.util.Date

파싱할 Date time

type

true

String

파싱할 데이터가 시간, 날짜, 모두 인지 셋 중 하나를 지정한다.

dateStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다. type="date", type="body", type속성이 생략된 경우 사용.

timeStyle

true

String

미리 정의된 날짜 형식. Java.text.DateFormat 클래스에 정의된 문법을 따른다.

type="time", type="body" 의 경우 사용.

pattern

true

String

사용자 지정 형식 스타일

timeZone

true

String 또는

java.util.TimeZone

형식화 시간에 나타날 타임존

parseLocale

true

String 또는

java.util.Locale

파싱하는 동안 적용될 미리 정의된 형식 스타일의 Locale

var

false

String

파싱 결과(java.util.Date)를 담는 scope에 해당하는 변수명

scope

false

String

var scope

 

다음은 숫자, 날짜에 대한 태그 사용 예제이다.

예제 17.                         jstlfmt05.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>

<pre><fmt:setLocale value="ko_KR"/>

number  : <fmt:formatNumber value="9876543.61" type="number"/>

currency: <fmt:formatNumber value="9876543.61" type="currency"/>

percent : <fmt:formatNumber type="percent">9876543.61</fmt:formatNumber>

 

pattern=".000"    :<fmt:formatNumber value="9876543.61" pattern=".000" />

pattern="#,#00.0#":<fmt:formatNumber value="9876543.612345" pattern="#,#00.0#"/>

 

<jsp:useBean id="now" class="java.util.Date"/>

<c:out value="${now}"/>

date: <fmt:formatDate value="${now}" type="date"/>

time: <fmt:formatDate value="${now}" type="time"/>

both: <fmt:formatDate value="${now}" type="both"/>

 

default:<fmt:formatDate value="${now}"

            type="both" dateStyle="default" timeStyle="default"/>

short  :<fmt:formatDate value="${now}"

            type="both" dateStyle="short"   timeStyle="short"  />

medium :<fmt:formatDate value="${now}"

            type="both" dateStyle="medium"  timeStyle="medium" />

long   :<fmt:formatDate value="${now}"

            type="both" dateStyle="long"    timeStyle="long"   />

full   :<fmt:formatDate value="${now}"

            type="both" dateStyle="full"    timeStyle="full"   />

 

pattern="yyyyMMdd HHmmss"

         <fmt:formatDate value="${now}" type="both"

            pattern="yyyyMMdd HHmmss"/>

</pre>

 

 

5.10       <fmt:setTimeZone/>, <fmt:timeZone/>

특정 스코프의 타임존을 설정하는 <fmt:setTimeZone/> 태그의 형식은 다음과 같다.

Syntax

<fmt:setTimeZone value="timeZone"

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

타임존을 부분 적용하는 <fmt:timeZone/> 태그는 다음과 같은 형식이다.

Syntax

<fmt:timeZone value="timeZone">

    body content

</fmt:timeZone>

 

타임존을 적용한 시간 표시 예제이다.

예제 18.                         jstlfmt06.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt"%>

<pre><fmt:setLocale value="ko_KR"/>

<jsp:useBean id="now" class="java.util.Date"/>

 

default: <c:out value="${now}"/>

Korea   KST  : <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

<fmt:timeZone value="GMT">

Swiss   GMT  : <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

</fmt:timeZone>

<fmt:timeZone value="GMT-8">

NewYork GMT-8: <fmt:formatDate value="${now}" type="both" dateStyle="full"

                   timeStyle="full"/>

</fmt:timeZone>

</pre>

 

 

이상으로 태그를 이용해서 숫자, 날짜, 시간 등을 표현하는 방법을 알아보았다. 태그의 속성들이 직관적이기 때문에 사용에 그리 불편하지 않을 것이다.

 

 

6           JSTL SQL 태그

DataSource 를 이용해서 SQL을 처리하는 sql 태그는 다음과 같은 것들이 있다.

기능

태그

prefix

DataSource 설정

SetDataSource

sql

SQL

query (dateParam, param) , update (dateParam, param) ,

transaction

 

sql 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql"%>

 

6.1          <sql:setDataSource/>

DataSource 를 지정하는 방식은 <sql:setDataSource/> 태그의 사용법은 다음과 같다.

Syntax

<sql:setDataSource

        {dataSource="dataSource" |

            url="jdbcUrl"

            [driver="driverClassName"]

            [user="userName"]

            [password="password"]}

        [var="varName"]

        [scope="{page|request|session|application}"]/>

 

오라클에서 사용을 한다면 다음과 같이 DataSource 를 설정할 수 있다.

<sql:setDataSource

            url="jdbc:oracle:thin:@localhost:1521:ora81"

            driver="oracle.jdbc.driver.OracleDriver"

            user="scott"

            password="tiger"

        var="okjspDS"

        scope="application" />

 

이미 컨텍스트에 JNDI 설정이 되어있다면 다음과 같이 바로 불러서 사용하거나 <sql:query/> 에서 바로 사용할 수 있다.

기존의 dataSource 를 불러와 사용하는 경우

<sql:setDataSource

        dataSource="jdbc/myora81"

        var="okjspDS"

        scope="application" />

 

<sql:query/> 에서 바로 사용하는 경우

<sql:query var="emp"

        dataSource="jdbc/myora81">

 

6.2          <sql:query/>

java 와는 달리 sql 문장을 문자열로 연결하지 않아도 가독성을 높여서 작성할 수 있다. <sql:query/>태그의 형식은 다음과 같다.

 

Syntax 1: body 없는 경우

<sql:query sql="sqlQuery"

        var="varName" [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]/>

 

Syntax 2: body 에 쿼리의 파라메터가 있는 경우

<sql:query sql="sqlQuery"

        var="varName" [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]>

    <sql:param> 액션들

</sql:query>

 

Syntax 3: 쿼리와 파라메터들이 body 에 있는 경우

<sql:query var="varName"

        [scope="{page|request|session|application}"]

        [dataSource="dataSource"]

        [maxRows="maxRows"]

        [startRow="startRow"]>

    sqlQuery

    선택적 <sql:param> 액션들

</sql:query>

 

 

6.3          <sql:dateParam/> , <sql:param/>

파라메터에는 두 가지가 있는데, 날짜 형식의 <sql:dateParam/> 와 일반적인 <sql:param/>태그가 있으며 형식은 다음과 같다.

Syntax

<sql:dateParam value="value" type="[timestamp|time|date]"/>

 

Syntax 1: value 속성에 파라메터 값이 지정된 경우

<sql:param value="value"/>

 

Syntax 2: body 내용에 파라메터 값이 지정된 경우

<sql:param>

    parameter value

</sql:param>

<sql:dateParam/> java.sql.PreparedStatement.setTimestamp() 역할을 하고,

<sql:param/> java.sql.PreparedStatement.setString() 의 역할을 한다. 바인드변수의 순서에 따라서 써주면 된다.

 

7장의 jdbc_resultset.jsp 파일을 JSTL로 바꾸어서 변경한 것이다.

예제 19.                         jstlsql01.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="sql" uri="http://java.sun.com/jstl/sql" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<fmt:setLocale value="ko" />

<sql:query var="emp"

        dataSource="jdbc/myora81">

SELECT  EMPNO AS 사원번호, ENAME AS 이름,

            SAL AS 월급여, HIREDATE AS 입사일

    FROM EMP

</sql:query>

 

<table border="1">

  <tr>

<%-- 필드의 정보를 출력한다.            --%>

  <c:forEach var="columnName" items="${emp.columnNames}">

    <th><c:out value="${columnName}"/></th>

  </c:forEach>

 

<%-- 데이터를 한 줄씩 출력한다.         --%>

  <c:forEach var="row" items="${emp.rowsByIndex}">

    <tr>

<%-- 필드의 길이만큼 반복한다.          --%>

      <c:forEach var="column" items="${row}" varStatus="i">

        <c:choose>

          <c:when test="${i.index==3}">

      <td><fmt:formatDate value="${column}" pattern="yyyy/MM/dd"/></td>

          </c:when>

          <c:otherwise>

      <td><c:out value="${column}"/></td>

          </c:otherwise>

        </c:choose>

      </c:forEach>

  </c:forEach>

</table>

<hr>

<table border="1">

  <c:forEach var="row" items="${emp.rows}">

  <tr>

    <td>번호: <c:out value="${row['사원번호']}"/></td>

    <td>이름: <c:out value="${row['이름']}"/></td>

  </tr>

  </c:forEach>

</table>

 

dataSource="jdbc/myora81" JNDI 7장에서 설명한 것처럼 컨텍스트에 설정된 DataSource 명이다.

SQL문은 보기 좋게 정렬을 해도 문자열로 덧붙일 필요가 없다. body 에 있는 sql문을 실행한 결과는 emp 라는 변수에 담겨서 이후에 사용이 된다. 이 변수는 ResultSet 과 같은데, JSTL에서 확장한 ResultSet 이고, javax.servlet.jsp.jstl.sql public interface Result 클래스로 내부적으로 정의된다. 지원하는 메소드는 다음과 같다.

javax.servlet.jsp.jstl.sql

public interface Result

public java.util.SortedMap[] getRows()

public Object[][] getRowsByIndex()

public String[] getColumnNames()

public int getRowCount()

public boolean isLimitedByMaxRows()

 

 

위와 같은 메소드들이 내부적으로 정의되어있기 때문에 각각의 getter 메소드들을 사용해서 변수 emp를 활용할 수 있다.

<c:forEach/> items 에 있는 ${emp.columnNames} getColumnNames() 메소드를 불렀다는 것을 알 수 있다. 이전의 7장에서 ResultSetMetaData 를 활용해서 뽑아낸 정보와 같은 효과를 볼 수 있다.

테이블 내용을 반환하는 ${emp.rowsByIndex} 도 유념할 만하다. 한 행을 row라는 변수에 넣은 뒤에 다음의 <c:forEach/> 에서 이 row변수의 컬럼별로 내용을 출력한다.

column 이라는 변수에 넣은 뒤에 column index 3일 경우 날짜형식을 출력하기 위해서 <fmt:formatDate/> 태그를 사용했고, 그 외의 경우는 바로 출력하게 했다.

다음 <c:forEach/> 에서는 결과를 SortedMap 배열에 넣은 뒤에 한 줄씩 빼서 컬럼이름으로 빼내는 방식이다.

 

6.4          <sql:update/>

java.sql.Statement.executeUpdate() 메소드에 해당하는 <sql:update/> 태그의 형식은 다음과 같다.

Syntax 1: body 없는 경우

<sql:update sql="sqlUpdate"

        [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]/>

 

Syntax 2: update 파라메터가 body에 있는 경우

<sql:update sql="sqlUpdate"

        [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]>

    <sql:param> 액션들

</sql:update>

 

Syntax 3: update 문과 선택적 update 파라메터가 body에 있는 경우

<sql:update [dataSource="dataSource"]

        [var="varName"] [scope="{page|request|session|application}"]>

    sqlUpdate

    선택적 <sql:param> 액션들

</sql:update>

형식과 동작은 <sql:query/> 태그와 동일하다. 다른 점은 executeUpdate() 메소드를 수행하기 때문에 DB에 변경을 가할 수 있다는 것이다.

 

6.5          <sql:transaction/>

트랜잭션을 구현하는 <sql:transaction/> 태그의 형식은 다음과 같다.

Syntax

<sql:transaction [dataSource="dataSource"]

        [isolation=isolationLevel]>

    <sql:query> <sql:update> 문들

</sql:transaction>

 

isolationLevel ::= "read_committed"

                | "read_uncommitted"

                | "repeatable_read"

                | "serializable"

격리 수준(isolationLevel) java.sql.Connection setTransactionIsolation() 메소드를 사용한다. 정리해 놓은 도표는 7 JDBC Transaction 을 참고하기 바란다.

 

7           JSTL XML 태그

7.1          xml 태그와 XPath

xml 태그를 사용하기 위해서는 XPath 를 먼저 이해할 필요가 있다. xml 소스 트리의 정확한 위치를 지정해주기 위한 경로지정 문법이며 XSLT XPointer 를 위해서 만들어진 것이다. xml 엘리먼트들을 노드(node) 로 접근한다. 파일 시스템과 유사하며 다음과 같은 특성이 있다.

l        / 로 시작하면 절대경로처럼 root node 에서 시작된다.

l        //로 시작할 경우는 모든 영역에서 해당 엘리먼트를 선택하게 된다.

l        표시는 이전 엘리먼트 아래의 모든 자식 엘리먼트를 나타낸다.

l        동일한 엘리먼트들이 있을 경우, [] 안에 포함된 숫자는 엘리먼트의 순번이다. 조건식이 올 경우 해당하는 것이 선택된다. last() 일 경우는 맨 마지막 엘리먼트를 표시한다.

l        속성은 @ 로 시작된다.

l        normalize-space() 함수는 앞뒤 공백을 제거하는 trim() 역할을 한다.

이 장에 나오는 XPath의 기능은 이 정도로 소개하겠고, XPath에 관한 보다 자세한 내용은 이 장의 마지막에 소개한 인터넷 튜토리얼을 참고하기 바란다.

 

JSTL에서 XPath를 통해서 내장객체에 쉽게 접근할 수 있다.

표현

매핑

$foo

pageContext.findAttribute("foo")

$param:foo

request.getParameter("foo")

$header:foo

request.getHeader("foo")

$cookie:foo

maps to the cookie's value for name foo

$initParam:foo

application.getInitParameter("foo")

$pageScope:foo

pageContext.getAttribute(

"foo", PageContext.PAGE_SCOPE)

$requestScope:foo

pageContext.getAttribute(

"foo", PageContext.REQUEST_SCOPE)

$sessionScope:foo

pageContext.getAttribute(

"foo", PageContext.SESSION_SCOPE)

$applicationScope:foo

pageContext.getAttribute(

"foo", PageContext.APPLICATION_SCOPE)

예를 들어서 다음 문장은 parameter 로 받은 "name"의 값이 bar엘리먼트의 x속성의 값과 같은 것들을 선택하게 된다.

/foo/bar[@x=$param:name]

 

xml 태그는 다음과 같은 것들이 있다.

기능

태그

prefix

기본

out, parse, set

x

흐름 제어

choose (when, otherwise), forEach, if

변환

transform (param)

 

xml 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x"%>

 

7.2          <x:out/>

XPath에 지정한 패턴에 따라 xml내용을 출력하는 <x:out/> 태그의 형식은 다음과 같다.

Syntax

<x:out select="XPathExpression" [escapeXml="{true|false}"]/>

 

 

7.3          <x:parse/>

xml문서를 읽어서 파싱하는 <x:parse/> 태그는 다음과 같은 형식이다.

Syntax 1: String 또는 Reader 객체로 지정된 XML 문서

<x:parse xml="XMLDocument"

        {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]}

        [systemId="systemId"]

        [filter="filter"]/>

 

Syntax 2: body 내용으로 지정된 XML 문서

<x:parse

        {var="var" [scope="scopeName"]|varDom="var" [scopeDom="scopeName"]}

        [systemId="systemId"]

        [filter="filter"]>

    파싱할 XML 문서

</x:parse>

scopeName {page|request|session|application} 중의 하나

 

 

7.4          <x:set/>

XPath에 따라 선택된 내용을 변수에 저장하는 <x:set/> 태그의 형식은 다음과 같다.

Syntax

<x:set select="XPathExpression"

        var="varName" [scope="{page|request|session|application}"]/>

 

7.5          <x:if/>

<c:if/> 태그와 마찬가지로 xml태그에도 <x:if/> 가 있고 형식은 <c:if/> 태그와 유사하다. <x:if/>의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<x:if select="XPathExpression"

        var="varName" [scope="{page|request|session|application}"]/>

 

Syntax 2: Body 있는 경우

<x:if select="XPathExpression"

        [var="varName"] [scope="{page|request|session|application}"]>

    body content

</x:if>

test 속성 대신에 select 속성으로 진위를 따지는데, 다음 3가지 기준을 유념할 필요가 있다. 이 세 가지 기준은 <x:choose/> <x:when/> <x:forEach/> 에서도 동일하게 사용된다.

1. number true 인 때는 + 또는 – 0 도 아니고, NaN(Not A Number) 도 아닐 경우

2. node-set true 인 때는 empty 가 아닐 경우

3. string true 인 때는 길이가 0 이 아닐 경우

 

7.6          <x:choose/>,  <x:when/>,  <x:otherwise/>

<c:choose/> 태그와 마찬가지로 xml태그에도 <x:choose/> 가 있고 형식은 <c:choose/> 태그와 유사하다.

Syntax

<x:choose>

    body content (<x:when> and <x:otherwise> 서브태그)

</x:choose>

 

Syntax

<x:when select="XPathExpression">

    body content

</x:when>

 

Syntax

<x:otherwise>

    conditional block

</x:otherwise>

 

7.7          <x:forEach/>

<x:forEach/> 태그는 XPath에 따라서 해당하는 엘리먼트 수만큼 반복하게 된다.

Syntax

<x:forEach [var="varName"] select="XPathExpression">

    body content

</x:forEach>

 

 

xml 태그를 활용한 예제이다.

예제 20.                         jstlxml01.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x" %>

<% response.setContentType("text/html;"); %>

<%-- 파라메터 받아서 출력 --%>

<c:if test="${!empty param.name}">

param: <x:out select="$param:name"/>

</c:if>

<form>

name: <input type="text" name="name">

<input type="submit">

</form>

<hr>

<%-- xml 데이터를 xdata 변수에 할당 --%>

<x:parse var="xdata">

<namecard>

    <person>

        <name>허광남</name>

        <id>남자</id>

        <email>kenu@email.com</email>

        <phone>111-2222-3333</phone>

    </person>

    <person>

        <name>노재춘</name>

        <id>남자</id>

        <email>suribada@email.com</email>

        <phone>222-3333-4444</phone>

    </person>

    <person>

        <name>이선재</name>

        <id>남자</id>

        <email>hsboy@email.com</email>

        <phone>333-4444-5555</phone>

    </person>

</namecard>

</x:parse>

<%-- XPath 를 이용해서 xdata에서 추출 --%>

<x:out select="$xdata//person[1]/name"/>

<x:out select="$xdata//person[last()]/name"/>

<hr>

<%-- person 으로 반복해서 email phone 출력 --%>

<table border="1">

<x:forEach select="$xdata//person">

<tr><td><x:out select="email" /></td>

<td><x:out select="phone" /></td></tr>

</x:forEach>

</table>

 

파라메터 name 의 접근은 EL에서는 ${param.name} 으로 사용하지만 XPath 에서는 $param:name 을 사용한다는 차이가 있다.

파라메터를 받아서 <x:out/> 으로 출력하는 부분이 제일 상단이고, 그 다음은 xml 데이터를 파싱하는 부분이다.

DTD 까지 쓰지 않아도 형식이 잘 갖춰지기만 하면 (well-formed) xml 데이터로 인식을 한다. 이것을 xdata라는 변수에 할당한 다음에 이후에 처리하게 된다.

 

xml 데이터는 파일로 따로 만든 후에 접근할 수 있다. 이때는 <c:import> 를 같이 사용하는데, 다음과 같이 쓸 수 있다.

예제 21.                         namecard.xml

<?xml version="1.0" encoding="euc-kr" ?>

<namecard>

    <person>

        <name>허광남</name>

        <id>남자</id>

        <email>kenu@email.com</email>

        <phone>111-2222-3333</phone>

    </person>

    <person>

        <name>노재춘</name>

        <id>남자</id>

        <email>suribada@email.com</email>

        <phone>222-3333-4444</phone>

    </person>

    <person>

        <name>이선재</name>

        <id>남자</id>

        <email>hsboy@email.com</email>

        <phone>333-4444-5555</phone>

    </person>

</namecard>

 

 

예제 22.                         jstlxml02.jsp

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>

<%@ taglib uri="http://java.sun.com/jstl/xml" prefix="x"%>

<% response.setContentType("text/html;"); %>

<%-- namecard.xml 파일을 불러와 xdata 변수에 할당 --%>

<c:import url="namecard.xml" var="xmldata" />

<x:parse xml="${xmldata}" var="xdata"/>

 

<%-- XPath 를 이용해서 xdata에서 추출 --%>

<x:out select="$xdata//person[1]/name"/>

이하 생략

 

xdata 변수에 들어간 xml 에서 추출하는 방식은 XPath 를 사용한다고 했다.

$select="$xdata//person[1]/name" 에서 person[1] person 으로 사용하는 것과 같다. [] 안에는 순서가 들어가고 생략될 경우 첫 엘리먼트를 찾기 때문이다.

<x:forEache/> 태그로 <person> 엘리먼트 수만큼 반복하게 했다. 이때 자동으로 기준은 <person> 이 되기 때문에 그 이후에 <email> 이나 <phone> 엘리먼트들은 /person/email /person/phone 을 바로 참조하게 된다.

 

7.8          <x:transform/>, <x:param/>

xml xslt 파일을 결합해서 새로운 형식의 문서를 생성해 내는 <x:transform/>의 형식은 다음과 같다.

Syntax 1: Body 없는 경우

<x:transform

        xml="XMLDocument" xslt="XSLTStylesheet"

        [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"]

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

 

Syntax 2: 변환 파라메터를 body에서 지정하는 경우

<x:transform

        xml="XMLDocument" xslt="XSLTStylesheet"

        [xmlSystemId="XMLSystemId"] [xsltSystemId="XSLTSystemId"]

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

    <x:param> 액션들

</x:transform>

 

Syntax 3: XML문서와 선택적 변환 파라메터들이 body에 지정된 경우

<x:transform

        xslt="XSLTStylesheet"

        xmlSystemId="XMLSystemId" xsltSystemId="XSLTSystemId"

        [{var="varName" [scope="scopeName"]|result="resultObject"}]>

    XML Document

    optional <x:param> actions

</x:parse>

scopeName {page|request|session|application} 중에 하나

 

var 속성에 지정된 결과와 result 속성에 지정된 결과의 차이점은 var 속성은 scope 지정해서 다른 곳에서도 사용할 수 있고, result 는 현재 페이지에서만 사용할 수 있다는 것이다.

또한 타입도 차이가 나는데, varorg.w3c.dom.Document , resultjavax.xml.transform.Result 객체로 저장이 된다.

 

xml의 파라메터를 지정하는 <x:param/> 태그의 형식은 다음과 같다.

Syntax

Syntax 1: value 속성에 파라메터 값이 지정된 경우

<x:param name="name" value="value"/>

 

Syntax 2: body 내용에 파라메터 값이 지정된 경우

<x:param name="name">

    parameter value

</x:param>

 

 

여기서 잠깐

<x:transform/> 태그를 사용할 때 jdk1.4 내에 있는 xalan jstl이 충돌을 일으킨다.

이런 경우, 톰캣 실행을 중지하고, jstl WEB-INF/lib디렉토리에 있는 xalan.jar 파일과 xercesImpl.jar 파일 두 개를 <CATALINA_HOME>/common/endorsed 디렉토리에 복사한다. 이전 버전의 xercesImpl.jar 파일을 덮어씌운다. 만일 이 과정이 생략되면, 다음과 같은 예외를 만나게 된다.

org.apache.xml.utils.WrappedRuntimeException: 

The output format must have a '{http://xml.apache.org/xslt}content-handler' property!

<x:transform/> 활용 예제를 보자.

예제 23.                         jstlxml03.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>

 

<html>

<head>

  <title>JSTL: XML Support -- Transform</title>

</head>

<body bgcolor="#FFFFFF">

<c:set var="xml">

    <?xml version="1.0" encoding="MS949"?>

    <namecard>

        <person>

            <name>허광남</name>

            <id>남자</id>

            <email>kenu@email.com</email>

            <phone>111-2222-3333</phone>

        </person>

        <person>

            <name>노재춘</name>

            <id>남자</id>

            <email>suribada@email.com</email>

            <phone>222-3333-4444</phone>

        </person>

        <person>

            <name>이선재</name>

            <id>남자</id>

            <email>hsboy@email.com</email>

            <phone>333-4444-5555</phone>

        </person>

    </namecard>

</c:set>

 

<c:set var="xsl">

    <?xml version="1.0"?>

    <xsl:stylesheet

    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

        <xsl:template match="/">

        <table border="1">

            <tr>

                <th>이름  </th>

                <th>이메일</th>

                <th>연락처</th>

            </tr>

        <xsl:for-each select="namecard/person">

            <tr>

                <td><xsl:value-of select="name" /></td>

                <td><xsl:value-of select="email" /></td>

                <td><xsl:value-of select="phone" /></td>

            </tr>

        </xsl:for-each>

        </table>

        </xsl:template>

 

    </xsl:stylesheet>

</c:set>

 

<x:transform xml="${xml}" xslt="${xsl}"/>

 

</body>

</html>

 

 

jsp 소스 안에 있는 xml(예제 21. namecard.xml) xsl을 따로 파일로 빼놓으면 아래와 같이 바뀐다.

예제 24.                         namecard.xsl

<?xml version="1.0" encoding="euc-kr" ?>

<xsl:stylesheet

xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:template match="/">

    <table border="1">

        <tr>

            <th>이름  </th>

            <th>이메일</th>

            <th>연락처</th>

        </tr>

    <xsl:for-each select="namecard/person">

        <tr>

            <td><xsl:value-of select="name" /></td>

            <td><xsl:value-of select="email" /></td>

            <td><xsl:value-of select="phone" /></td>

        </tr>

    </xsl:for-each>

    </table>

    </xsl:template>

 

</xsl:stylesheet>

 

xsl 에 관한 문법적인 내용은 여기에서 다루지 않겠다.

namecard.xsl 파일은 namecard.xml html 을 입히는 역할을 하게 되며, 데이터를 제외한 html 틀을 갖고 있다고 볼 수 있다.

이 두 개의 파일을 하나로 합쳐서 html 코드를 만들어 내는 소스는 다음과 같다.

예제 25.                         jstlxml04.jsp

<%@ page pageEncoding="MS949" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>

 

<html>

<head>

  <title>JSTL: XML Support -- Transform</title>

</head>

<body bgcolor="#FFFFFF">

<h1>연락처</h1>

<c:import var="xml" url="namecard.xml" charEncoding="MS949"/>

<c:import var="xsl" url="namecard.xsl" charEncoding="MS949"/>

 

<x:transform xml="${xml}" xslt="${xsl}"/>

 

</body>

</html>

 

jstlxml03.jsp 에서 <x:set/> 부분은 <c:import/> 로 바뀌었고, 파일을 불러올 때 charEncoding 속성을 통해서 인코딩해 주었다.

xml 변수와 xsl 변수 두 개를 파싱하지 않고 바로 <x:transform/> 을 통해서, jsp 파일에 출력했다.

<x:transform/> var 속성을 주면 출력되지 않고, 변수에 org.w3c.dom.Document 타입으로 저장된다.

 

 

이렇게 JSTL 4가지 표준 태그에 대해서 알아보았다. 프로그래밍의 기본인 조건, 반복, 연산이 가능하기 때문에 스크립틀릿을 거의 모두 제거할 수 있음을 알 수 있었다.

 

8           참고자료

JSTL 스펙

http://java.sun.com/products/jsp/jstl/

자카르타 taglibs

http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html

Hans Bergsten article

JSTL 1.0: Standardizing JSP, Part 1

http://www.onjava.com/pub/a/onjava/2002/08/14/jstl1.html

JSTL 1.0: What JSP Applications Need, Part 2

http://www.onjava.com/pub/a/onjava/2002/09/11/jstl2.html

JSTL 1.0: What JSP Applications Need, Part 3

http://www.onjava.com/pub/a/onjava/2002/10/30/jstl3.html

JSTL in Action by Alex Garrett

http://www.codercoop.com/Members/alex_garrett/jstlnewapproach

XPath Tutorial

http://www.zvon.org/xxl/XPathTutorial/General/examples.html

XSL Tutorial

http://www.w3schools.com/xsl/

XSLT Tutorial

http://www.zvon.org/xxl/XSLTutorial/Books/Book1/



[1] http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt

[2] http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html


'프로그래밍 > Web' 카테고리의 다른 글

[javascript] DOM 스크립트  (0) 2010.01.15
[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08
[servlet] 서블릿에서 jsp로 포워드하기  (0) 2010.01.07
[javascript] addLoadEvent  (0) 2010.01.04

[jsp] jstl 설치

프로그래밍/Web 2010. 1. 8. 11:30 Posted by galad
출처: http://yangwenry.springnote.com/pages/198199

예) <%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core"  %>

위와같이 JSP 파일에 선언해주면 되는데 하기전에 라이브러리 파일과 tld 파일을 설치해 줘야한다.

- JSTL 설치하기

1. JSTL 다운로드

JSTL 은 아래 두사이트에서 다운로드 할수있다.
  --> 여기서 다운로드를 해봤는데 모든 툴들이 하나로 통합되어 진거 같다.
        JSTL 만 따로 받고싶은 나로선 별로 내키진 않았다.

2) http://apache.org 
  --> 여기서는 jakarta-taglibs-standard-1.1.2.zip 파일을 받으면 된다.


2. 설치
  - WEB-INF/lib 디렉토리에 jstl.jar 와 standard.jar 파일을넣는다.
  - WEB-INF/tld 에다가 tld 폴더를 복사한다.

3. WEB.XML 설정
  --> 처음에 uri="http://java.sun.com/jstl/core" 라고 쓰는걸 보고 sun 에서 해당 url 을 지원해 주는줄 알았으나 그게 아니고 WEB.xml 파일에 아래와같이 설정해 줘야지 쓸수 있는것이다.


             <taglib>
                           <taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
                           <taglib-location>/WEB-INF/tld/c.tld</taglib-location>
             </taglib>
 
             <taglib>
                          <taglib-uri>http://java.sun.com/jstl/xml</taglib-uri>
                          <taglib-location>/WEB-INF/tld/x.tld</taglib-location>
             </taglib>
 
             <taglib>
                           <taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
                          <taglib-location>/WEB-INF/tld/fmt.tld</taglib-location>
             </taglib>


4. JSP 선언
  --> 위에서 말한것처럼 JSP 파일에는 아래와같이 선언해주면 된다.

<%@ taglib prefix="c"  uri="http://java.sun.com/jstl/core"  %>




- EL(expression language) 내장객체

 
pageScope  ::  page 범위에 포함된 속성 값에 접근
requestScope  ::  request 범위에 포함된 속성값에 접근
sessionScope ::  session 범위에 포함된 속성값에 접근
applicationScope  ::  application 범위에 포함된 속성값에 접근
param  ::  request.getParameter("aa")와 동일한 기능. 사용은  $(param.aa)
paramValues  ::  request.getParameterValues의 기능. $(paramValues.aa)
header  ::  request.getHeader('aa") 와 동일.  $(header.aa)
headerValues  ::  request.getHeaderValues("aa")와 동일 $(headerValues.aa)
initParam  ::  컨텍스트의 초기화 파라미터값
cookie  ::  쿠키 정보에 접근
pageContext  :: PageContext 객체   
 

'프로그래밍 > Web' 카테고리의 다른 글

[jstl] jstl 사용하기  (0) 2010.01.08
[jsp] jstl 설명  (0) 2010.01.08
[servlet] 서블릿에서 jsp로 포워드하기  (0) 2010.01.07
[javascript] addLoadEvent  (0) 2010.01.04
[jQuery] 브라우져 알아내기  (0) 2009.12.17
public class FileBrowsingAction extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //super.service(request, response); // 없어야됨. 있으면 슈퍼클래스에서 응답처리됨.
       
        // 파일 목록 얻기
       
       
        String jspName = "/file_browsing.jsp";
       
        getServletConfig().getServletContext().getRequestDispatcher(jspName).forward(request,response);
    }
}

서블릿도 안쓰다보니 까먹었다.

'프로그래밍 > Web' 카테고리의 다른 글

[jsp] jstl 설명  (0) 2010.01.08
[jsp] jstl 설치  (0) 2010.01.08
[javascript] addLoadEvent  (0) 2010.01.04
[jQuery] 브라우져 알아내기  (0) 2009.12.17
[jQuery] jQuery로 현재 페이지에서 스크롤된 높이 알아내기  (0) 2009.12.17

[javascript] addLoadEvent

프로그래밍/Web 2010. 1. 4. 16:29 Posted by galad
출처: http://simon.incutio.com

function addLoadEvent(func) {
    var oldonload = window.onload;

    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        window.onload = function() {
            oldonload();
            func();
        };
    }
}

addLoadEvent(functionA);

기존의 함수(oldonload)와 새 함수(func)를 모두 실행하는 무명함수를 window.onload에 attach.
addLoadEvent(함수명)이 실행될때마다 계속 초기에 실행되는 함수가 증가.

[jQuery] 브라우져 알아내기

프로그래밍/Web 2009. 12. 17. 15:43 Posted by galad
var m_browser;
var m_version;

function detectBrowser() {
    if($.browser.msie) {
        m_browser = "msie";
    }
    else if($.browser.safari) {
        m_browser = "safari";
    }
    else if($.browser.opera) {
        m_browser = "opera";
    }
    else if($.browser.mozilla) {
        m_browser = "mozilla";
    }

    m_version = $.browser.version;

    //alert(m_browser + " " + m_version);
}

$.browser.mozilla
$.browser.version

http://visualjquery.com/ 여기서 Utilites > User Agent 참고
$(window).scrollTop()

간단하군....
div에다가 createElement로 노드들을 추가하면 div의 높이가 변하는게 당연해 보이는데 - IE6에서는 변한다
Firefox, Crome 등의 브라우저에서는 초기에 설정된 값이 변하지 않는다.

여기저기 뒤져서
1. html, body, div의 height를 100%로 주면 된다 - http://www.webmasterworld.com/forum83/200.htm
  하지만 이건 창 크기가 변할 때 쓰는 듯하고.(element가 추가되는 경우에는 제대로 div가 커지지 않았음)

2. min-height를 주면 된다 - http://forum.standardmag.org/viewtopic.php?id=2239
  안된다 ㅠ.ㅠ

등의 글을 참고했지만 안됨...

모르겠음 ㅠ.ㅠ

그냥 추가되는 노드의 수 만큼 직접 height를 수정하는게 나을 듯.