반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

JQuery Mobile - Header structure

2012. 7. 23. 07:54 | Posted by 솔웅


반응형

Header structure


헤더는 대개 페이지 윗부분에 위치하며 페이지 타이틀이 표시되거나 왼쪽이나 오른쪽에 버튼이 있어 이전 이후 페이지로 가도록 하는 기능을 제공하는 툴 바입니다. 헤더는 선택에 따라 fixed로 포지션 될 수 있으며 일러 경우 페이지가 스크롤링 될 때 같이 되지 않고 항상 top 에 위치해 있게 됩니다.


타이틀 글자는 대기 H2 heading element를 사용하지만 H1에서 H6까지 여러분들 선택에 따라 사용하실 수 있습니다. 예를 들어 모바일 페이지에는 여러 페이지들이 있을 수 있고 그 중 home page에는 H1을 그 다음 secondary page에는 H2 element를 사용하실 수 있겠죠. 모든 헤딩 레벨은 시각적인 일관성을 주기 위해 styled 되면 더 좋습니다.


<div data-role="header"> 
	<h1>Page Title</h1> 
</div> 


header01.html

예제들은 위 파일을 받아 보시면 있습니다.

이 블로그에서는 실행이 안되서 따로 파일을 만들었습니다.

이 파일을 실행시키면 아래와 같은 화면을 보실 수 있습니다.

다운 받아서 직접 실행해 보시고 소스도 이것저것 바꿔보세요.


Default header features


헤더 툴바는 디폴트로 a swatch로 theme 돼 있습니다. 하지만 여러분이 원하시면 쉽게 theme swatch color 를 하실 수 있습니다.


예제는 이 글 맨 밑에 있는 첨부파일을 보시면 있습니다.


Adding buttons


표준 헤더 configuration에서 텍스트 헤딩 양쪽에 button들을 위한 slot이 있습니다. 각 버튼들은 anchor element이구요 어떤 button markup이든지 사용하실 수 있습니다. 공간을 절약하기 위해서 툴바에 있는 버튼들은 inline styling로 세팅하세요. 그러면 버튼 크기가 자동적으로 그 버튼안에 있는 텍스트와 아이콘의 크기에 맞게 세팅될 겁니다.


Default button positioning


헤더 플러그인은 헤더 콘테이너의 직속 children이라고 할 수 있습니다. 첫번째 링크는 자동적으로 왼쪽 버튼 slot에 세팅을 하고 두번째 링크는 오른쪽에 세팅합니다. 아래 예제에서 Cancel 버튼은 왼쪽 slot에 나타날 것이고 Save는 오른쪽 slot에 나타날 겁니다.


<div data-role="header" data-position="inline">
	<a href="index.html" data-icon="delete">Cancel</a>
	<h1>Edit Contact</h1>
	<a href="index.html" data-icon="check">Save</a>
</div>


Making buttons visually stand out


Buttons automatically adopt the swatch color of the bar they sit in, so a link in a header bar with the "a" color will also be styled as "a" colored buttons. It's simple to make a button visually stand out. Here, we add the data-theme attribute and set the color swatch for the button to "b" to make the "Save" button pop.


<div data-role="header" data-position="inline">
  <a href="index.html" data-icon="delete">Cancel</a>
  <h1>Edit Contact</h1>
  <a href="index.html" data-icon="check" data-theme="b">Save</a>
</div>

Controlling button position with classes


버튼의 위치는 버튼 anchor에 class를 add 함으로서 콘트롤 될 수 있습니다. (이 경우에는 소스의 순서가 아니라 설정된 클래스에 따라 위치가 정해지겠죠.) 아래 경우에는 1개의 버튼을 오른쪽에 표시하고 싶을 때 사용하실 수 있을 겁니다. 버튼의 위치를 정하시려면 ui-btn-leftui-btn-right 클래스를 anchor에 넣어 주세요.


<div data-role="header" data-position="inline"> 
	<h1>Page Title</h1>
	<a href="index.html" data-icon="gear" class="ui-btn-right">Options</a>
</div>


Adding buttons to toolbars without heading


헤더바 안의 헤딩은 약간의 margin을 가지고 있습니다. 이 마진은 bar의 height을 나타냅니다. 헤딩을 사용하지 않는다면 class="ui-title" 와 함께 element를 추가하셔야 합니다. 그러면 그 바는 hight를 얻어서 정확하게 display 할 수 있을 겁니다.


<div data-role="header" data-position="inline"> 
	<a href="index.html" data-icon="gear" class="ui-btn-right">Options</a>
	<span class="ui-title" />
</div>


Adding Back buttons


jQuery Mobile은 어떤 헤더에건 자동적으로 back 버튼을 생성하고 추가할 수 있는 기능이 있습니다. 디폴트로는 이 기능이 disabled 돼 있습니다. 이 경우는 chromeless installed application들에서 아주 유용합니다. 예를 들어 native app webview에서 작동할 때 등에서요. jQuery Mobile 프레임워크에서는 페이지 플러그인의 addBackBtn 옵션이 true일 경우 헤더에 자동적으로 back버튼을 추가해 줍니다. 이 기능은 또한 페이지 div 에 data-add-back-btn="true" attribute로 세팅되어져 있으면 적용됩니다.



앵커에 data-rel="back" attribute를 사용하면 앵커에 어느곳을 클릭하던지 back button을 누른 효과가 날 겁니다. history entry의 바로 이전 화면으로 돌아가고 anchor's의 디폴트 href는 무시할 겁니다. 이 기능을 사용할 때 실제로 돌아가는 페이지가 어떤 페이지인지를 알려 줄 수 있는 표시를 해 주세요. href를 걸어달라는 겁니다. 그러면 C-Grade 브라우저를 사용하는 유저에게도 불편함 없이 사용할 수 없도록 할 겁니다.


history 내의 back 화면으로 가는 것이 아니라 reverse transition을 하기를 원하신다면 data-direction="reverse" attribute를 사용하시면 됩니다.


Customizing the back button text


back button text를 configure 하고 싶으시면 페이지 element에 data-back-btn-text="previous" attribute 를 사용하시면 됩니다. 아니면 페이지 플러그인 옵션을 통해서 프로그래밍으로 set 하실 수도 있습니다.


$.mobile.page.prototype.options.backBtnText = "previous";


Default back button style


백 버튼에 role-theme을 설정하고 싶으시면 아래와 같이 하면 됩니다.


$.mobile.page.prototype.options.backBtnTheme = "a";


이 기능을 프로그래밍적으로 하시려면 이 옵션을 mobileinit 이벤트 핸들러에 넣어 주세요.


Custom header configurations


디폴트 세팅이 아닌 헤더를 만들고 싶으면 그냥 콘테이너에 custom styled markup을 씌우시기만 하시면 됩니다. div 같은 걸로요. 플러그인은 헤더 콘테이너 안의 wrapped 콘테이너에 자동 버튼 로직을 적용하지 않을 겁니다. 그러니까 여러분은 여러분 나름대로의 스타일을 넣으실 수 있습니다.


헤더 data-role을 사용하지 않고도 custom bar를 만들 수 있습니다. 예를 들어 ui-bar를 추가해서 스탠다드 바에 apply 하고 ui-bar-b 클래스를 추가해서 여러분의 theme에서 bar swatch styles를 assign 하시면 됩니다.


<div class="ui-bar ui-bar-b">
    <h3>I'm just a div with bar classes and a
       <a href="#" data-role="button">Button</a></h3>
</div>


ui-bar 는 페이지의 full width로 된 헤더나 footer bar에는 추가하지 말아야 합니다. 이렇게 하면 parent container의 full-width element 세팅을 bread out 할 겁니다. full-width 툴바 안에 패딩을 추가하려면 element 안에 툴바의 content를 wrap 하시고 element 대신 padding을 apply 하세요.

하지만 간단하게 style을 적용함으로서 예제 파일의 마지막 바와 같은 메세지 바를 쉽게 만들 수도 있습니다.




반응형

'jQuery Mobile > JQM Tutorial' 카테고리의 다른 글

JQuery Mobile - Fixed toolbar Methods/Events  (0) 2012.07.29
JQuery Mobile - Fixed toolbar options  (0) 2012.07.29
Fixed toolbars  (0) 2012.07.28
JQuery Mobile - Navbar  (2) 2012.07.25
JQuery Mobile - Footers  (0) 2012.07.24
JQuery Mobile - Toolbar types  (0) 2012.07.21
JQuery Mobile - Theming Page  (0) 2012.07.12
JQuery Mobile - touchOverflow 기능  (0) 2012.07.09
JQuery Mobile - PhoneGap apps  (1) 2012.07.09
JQuery Mobile - Scripting pages  (1) 2012.07.05

JQuery Mobile - Toolbar types

2012. 7. 21. 01:58 | Posted by 솔웅


반응형


이제 jQuery Mobile Tutorial 의 Component 부분 Page & dialog 를 끝마치고 두번째 주제인 Toolbars 로 들어갑니다.


생각보다 시간이 많이 걸리네요. 어쨌든 조금씩 조금씩 공부해 나가다 보면 조만근 끝까지 돌파 하겠죠?

오늘은 Toolbars 의 첫 시간입니다.



Toolbar types


jQuery Mobile에는 두가지 표준 툴바 종류가 있습니다. : Headers and Footers.

  • Header bar는 페이지 title로 사용됩니다. 대부분의 경우 각 mobile page내의 첫번째 엘리먼트가 되죠. 특히 페이지 title이 포함되고 또 두 개의 버튼까지 포함할 수 있습니다.
  • Footer bar는 대개 각 모바일 페이지의 마지막 element 입니다. 그리고 그 내용과 기능면에서 header 보다 더 자유로운 경향이 있죠. 여기에는 text와 버튼들의 조합이 들어가게 됩니다.


header나 footer 안에는 대개 horizontal navigation이나 tab bar 가 들어가는 것이 일반적입니다. jQuery Mobile에는 이런 경우 hirizontal button bar 안에 들어가는 링크들의 리스트 보여줄 수 있는 navbar widget 를 제공하고 있습니다.

이 툴바들에 추가 할 수 있는 attribute들을 모두 보려면 data- attribute reference를 참조하세요.



Toolbar positioning options


header와 footer들은 여러 방법으로 페이지에 위치 지워질 수 있습니다. 디폴트로 툴바들은 inline 포지셔닝 모드를 사용합니다. 이 모드에서는 헤더와 푸터들이 일반적인 문서 flow(default HTML behavior)에 맞게 자리 잡습니다. 이 경우는 JavaScript와 CSS 포지셔닝 지원 여부에 관계 없이 모든 device들에서 작동을 합니다. (visible)


"fixed" positioning mode 는 툴바들을 CSS fixed positioning 을 지원하는 브라우저의 viewport 안에 있는 top 이나 bottom에 툴바들을 위치시킵니다. CSS fixed positioning은 대부분의 데스크탑 브라우저와 iOS5+, 안드로이드 2.2+, 블랙베리 6 등에서 지원합니다. 이 기능을 지원하지 않는 브라우저들에서는 이 툴바들은 페이지내의 inline position으로 지정이 될 겁니다.


tap-togglingl이 가능하면 스크린을 tapping 하면 fixed toolbar의 visibility가 toggle 될 겁니다. 툴바가 보이지 않을 때 페이지를 tap하면 보이게 될 겁니다. 다시한번 tap 하면 사라지구요. 이 기능은 유저에게 필요하기 전에는 툴바를 보이지 않음으로서 컨텐츠가 좀 더 넓은 화면에서 표시될 수 있게 해 줍니다. 기억해 두셔야 될 것은 fixed toolbar는 실제로는 hide 된게 아니라는 겁니다. fixed와 static positioning 사이에서 왔다 갔다 하는 겁니다. 이 의미는 만약 여러분이 페이지 top 에 있다면 그 헤더 툴바를 안 보이도록 tap-toggle 할 수 없다는겁니다. 문서의 아주 밑으로 scroll 됐을 경우 fixed footer에도 이러한 경우는 마찬가지로 적용됩니다.


이 기능을 헤더와 풋터에 세팅하려면 data-position="fixed" attribute를 헤더나 풋터 element에 추가하세요.


"fullscreen" position mode는  fixed mode가 아닐 때 문서의 한 지점을 점유툴바가 페이지 콘텐츠를 덮는것을 제외하고는 fixed mode와 같습니다. 이 기능은 컨텐츠가 전체 스크린을 차지하고 툴바는 숨고 스크린을 탭 했을 때만 나타나도록 하는 포토나 비디오 뷰어 같은 immersive app일 경우에 아주 유용할 겁니다. 이 경우의 툴바들은 페이지 콘텐츠의 위에 자리잡을 것입니다. 그러니까 특정 상황에서 유용하게 사용될 수 있고 어떤 상황에서는 그렇지 않을 수도 있습니다.



반응형

'jQuery Mobile > JQM Tutorial' 카테고리의 다른 글

JQuery Mobile - Fixed toolbar options  (0) 2012.07.29
Fixed toolbars  (0) 2012.07.28
JQuery Mobile - Navbar  (2) 2012.07.25
JQuery Mobile - Footers  (0) 2012.07.24
JQuery Mobile - Header structure  (0) 2012.07.23
JQuery Mobile - Theming Page  (0) 2012.07.12
JQuery Mobile - touchOverflow 기능  (0) 2012.07.09
JQuery Mobile - PhoneGap apps  (1) 2012.07.09
JQuery Mobile - Scripting pages  (1) 2012.07.05
JQuery Mobile - Dynamically Injecting Pages  (0) 2012.06.28

JQuery Mobile - Theming Page

2012. 7. 12. 20:57 | Posted by 솔웅


반응형

Page Theming


jQuery Mobile 에서는 페이지의 style을 지원하는 rich theming system을 제공하고 있습니다. 각 페이지 위젯에는 자세한 theming documentation이 있습니다. 이 글에서는 어떻게 theming이 apply 되는지 몇개의 high-level 예제들을 살펴보도록 하겠습니다.


data-them attribute는 헤더나 footer 콘테이너에 apply 될 수 있습니다. 이 콘테이너에 apply 되서 lettered theme color swatch들을 적용할 수 있도록 합니다. data-theme attribute가 content container에 적용 될 때에는 data-role="page"가 적용된 div나 콘테이너에 넣으라고 권장 드립니다. 그렇게 하면 배경색이 전체 페이지에 적용될 수 있습니다. 이 작업이 끝나면 페이지의 모든 위젯들은 그 페이지 콘테이너에 적용된 theme을 상속 받게 됩니다. header와 footer에는 디폴트로 theme "a"가 적용 됩니다. 모든 element에 theme "b" 가 적용되기를 원하신다면 이것을 header나 footer에 적용 시키세요. 페이지 div에 data-theme="b"를 하듯이 header와 footer div에도 이렇게 하면 됩니다. 이 디폴트 theme은 다양한 견본(swatches)들을 활용해서 visual texture를 만들고 각각 에 맞는 최상의 contrast를 다양한 element들에 적용하고 있습니다.




위 화면에 대한 소스와 기타 theme a ~ e 까지의 간단한 예제가 있는 소스를 아래에 올립니다.


themingpages.html


그리고 Tutorial Page에 가시면 A~E 까지의 theme들을 적용한 각 form 들을 보여주는 페이지가 있습니다.


이 페이지들을 따로 작업해서 파일로 만들었습니다.

보시면 도움이 될 겁니다.



themingApage.html


themingBpage.html


themingCpage.html


themingDpage.html


themingEpage.html



소스들을 보시면서 이것 저것 바꾸시고 테스트해 보시면 확실히 자기것으로 만들 수 있을 겁니다.


그럼 항상 즐 코딩 하세요.


반응형

'jQuery Mobile > JQM Tutorial' 카테고리의 다른 글

Fixed toolbars  (0) 2012.07.28
JQuery Mobile - Navbar  (2) 2012.07.25
JQuery Mobile - Footers  (0) 2012.07.24
JQuery Mobile - Header structure  (0) 2012.07.23
JQuery Mobile - Toolbar types  (0) 2012.07.21
JQuery Mobile - touchOverflow 기능  (0) 2012.07.09
JQuery Mobile - PhoneGap apps  (1) 2012.07.09
JQuery Mobile - Scripting pages  (1) 2012.07.05
JQuery Mobile - Dynamically Injecting Pages  (0) 2012.06.28
JQuery Mobile - Ajax, hashes & history 02 -  (0) 2012.06.27


반응형

touchOverflowEnabled: Deprecated in 1.1.0

jQuery Mobile 1.1 이전에서는 true fixed toolbar 지원이 touch에 대해 overflow-scrolling 하는 CSS 프로퍼티로 native browser 지원이 가능했었습니다. 지금은 iOS5에서만 지원되고 있습니다. jQuery Mobile 1.1 버전에서는 이 CSS 프로퍼티를 더 이상 사용하지 않습니다. 우리는 이 프로퍼티를 내부적으로 사용하는 부분을 모두 없앴습니다. 하지만 이미 이 프로퍼티를 사용하고 있는 어플리케이션에 문제가 발생하지 않도록 $.mobile 객체에 글로벌하게 정의해 놓고 있습니다. 이 프로퍼티는 remove 하라고 flag 되어 있습니다. 하지만 아직까지 $.support 를 통해서 남아있고 지금 현재로서는 이것을 완전 remove할 계획을 가지고 있지는 않습니다.


touchOverflow: Improved page transitions and true fixed toolbars


현재 보이는 화면과 앞으로 전환될 화면은 viewport에 나란히 있습니다.  이 화면전환이 아래쪽으로 된다면 이 두 페이지가 화면전환이 시작될 때 같은 viewport에 있어야 합니다. 그리고 손가락을 위쪽으로 해서 scroll을 하겠죠. 그러면 그 다음 화면이 밑에서부터 따라 올라올 겁니다. 만약에 back button을 클릭한다면 scroll up 하고 화면전환을 하고 이전 scroll position을 저장해야 합니다 .아직까지 모바일 브라우저의 속도가 느린편이라 이 스크롤 움직임은 실제 유저의 움직임을 따라가지 못할 수 있습니다.


이러한 문제점을 극복할 방법은 두 페이지를 각각의 콘테이너에 담는것입니다. 각각은 나름대로의 internal scroll bark 를 가지고 있습니다. 이 의미는 document를 더 이상 scroll 할 필요가 없다는 것이죠. 혹은 좀 더 자연스럽게 스크롤 포지션을 저장하는 것이 필요하다는 겁니다. fixed toolbar들을 만들어서 internal scrolling 과 함께 바깥의 콘테이너에  넣음으로서 이를 쉽게 구현할 수 있습니다.


How it works


overflow:auto 의 touch-targeted version을 지원하는 iOS5 를 한번 보죠. 여기에서는 native momentum scrolling과 함께 internal scrolling region을 허용합니다. 우리는 여기에 touchOverflow 라는 기능을 추가했습니다. 이 기능은 이 두개의 true "fixed" toolbar들을 사용할 수 있는 새로운 CSS capability들을 가능하게 합니다. 그로 인해 iOS5에서 아주 부드럽게 화면전환이 일어나도록 만들죠. 모두 웹 표준을 사용하고 있고 약간의 코드를 추가했습니다.


이 기능은 touchOverflowEnabled 라고 부르는데 CSS에서 overflow scrolling을 지원할 미래의 브라우저를 위해 디자인 됐습니다. 이 기능은 최고의 퍼포먼스를 위해 아직 테스트와 디버깅이 필요하기 때문에 디폴트로 off 상태입니다. 조만간 이 기능을 on 으로 활성화 할 수 있기를 바랍니다. 아래에 이 global option을 어떻게 enable 시키는지 예제가 있습니다.


<script>
$(document).bind("mobileinit", function(){
  $.mobile.touchOverflowEnabled = true;
});
</script>



이 기능이 activate 되면 프레임워크는 이 두 overflow를 브라우저가 support 하는지 찾게 됩니다. 그리고 -webkit-overflow-scrolling:touch CSS properties 를 찾게 되죠. 이 두가지를 지원하는 브라우저에서는 native overflow와 함께 dual page container 모델로 switch 합니다. 그래서 각각의 안에서 스크롤링을 하게 되어 true fixed toolbars smooth transition이 일어나도록 하죠. 이렇게 하면 native performance에 아주 가까운 인터페이스 build를 가능하도록 해 줍니다.

이 기능의 demo 를 보시려면 iOS5의 이 페이지를 체크하세요.


A few downsides


새 기능인 경우 완벽할 수는 없습니다. 이 기능을 activating 할 때 몇가지 고려해야 할 사항들이 있습니다.


  • 리스트나 form 같은 child element들은 가끔 iOS5에서 overflow된 페이지내의 embedded 일 때 render를 하지 않는 경우가 있습니다. 아주 random 하게 일어나는 현상이지만 그냥 둘 수는 없는 문제죠. 그래서 우리는 translage-z CSS 프로퍼티를 추가해서 IOS가 content를 render 하도록 force 하고 있습니다. 이 경우의 단점은 transform이 apply 됐을 때 모든 elements들은 relative 로 포지션이 set 되서 여러분의 layout에 어떤 이슈가 발생할 수가 있습니다.
  • -webkit-overflow-scrolling:touch는 status bar 를 tap 했을 때 위에서 아래로 스크롤 하는 이벤트가 제대로 작동하지 않는 것 같습니다. 애플에서 이와 관련해서 개선해주기를 바랍니다. 왜냐하면 이 기능은 아주 필요하거든요.
  • overflow이고 -webkit-overflow-scrolling:touch 프로퍼티가 세팅돼 있을 때 iOS는 그 parent의 (우리의 경우는 page) 어떤 overflow:hidden 프로퍼티도 무시하는 현상이 나타납니다. 그래서 viewport보다 넓은 이미지나 코드 블럭이 있다면 horizontal scrolling 이 나타납니다.
  • 이 기능이 active 일 때 메타 viewport 태그를 사용하게 되면 유저 zoom 이 제대로   작동하지 않게 됩니다. 왜냐하면 툴바와 페이지 콘텐트 모두 이상한 size로 zoom될 수 있고 다시 zoom back out 하는것이 무척 어렵기 때문입니다. 이런 이상한 현상을 완화하기 위해 우리는 fixed toolbar와 overflow container를 사용하는 것이 더 중요하게 됩니다.
  • re-load 된 페이지로 되돌아갈 때 스크롤 포지션을 잃어버릴 수가 있습니다. 만약 DOM caching이 on 상태이면 이런 이슈는 거의 발생하지 않을 겁니다.
  • 이 기능은 아직까지 실험적입니다. 그러니까 이런 이상한 현상들이 모두 해결된 상황은 아닙니다. 주의해서 사용하시고 항상 테스트를 하세요.


Don’t other mobile platforms already support overflow?


예 다른 플랫폼도 overflow를 지원합니다. 안드로이드의 허니컴과 블랙베리의 플레이북도 overflow를 지원합니다. 하지만 저희가 테스트해 본 결과 그 기기들에서의 overflow는 부드럽지 않습니다. 페이지들은 버벅거리거나 스크롤링 동안에 잠깐씩 멈칫멈칫 합니다. 저희들은 이 기계 제조사들에게 이 기능이 개선되어야 한다고 의견을 제시하고 있습니다.


더 중요한 것은 overflow가 정확하게 되어야 하는것입니다. 우리가 그냥 간단하게 페이지의 auto CSS rule에 overflow를 설정해 놓으면 안드로이드나 iOS의 이전 버전이면서 많은 사람들이 사용하는 플랫폼에서는 내용의 나머지 부분이 잘려나갈겁니다. (iOS의 경우에는 이런 경우 two-finger scroll을 할 수 있을 겁니다. 하지만 아무도 모르고 있을 겁니다.) iOS5에서 애플은 CSS 프로퍼티 -webkit-overflow-scrolling:touch 를 추가했습니다. 현명한 조치라고 생각합니다. 이렇게 함으로서 저희들은 이 touch 스크롤링 프로퍼티를 테스트할 수 있었습니다. 그래서 만약 이 기능을 지원한다면 그 브라우저에서는 overflow rule을 추가할 수 있겠죠.


우리는 이 CSS-based 프로퍼티들을 지원해 달라고 디바이스와 브라우저 개발사들에게 요청하고 있습니다. 왜냐하면 이 기능이 rich mobile 웹 앱을 만드는데 아주 중요한 요소가 될 거라고 믿기 때문입니다. 만약에 오페라, 파이어폭스, 마이크로 소프트같은 회사에서 이 기능을 지원하면 우리는 이 touch scrolling property를 위해 vender-prefixed additions를 추가할 것입니다. 사람들이 IOS5에서 얼마나 페이지 전환이나 fixed toolbar들이 더 훌륭하게 진행되는지를 보게 되면 다른 브라우저들에서도 하루빨리 이 기능을 적용할 거라고 기대합니다. JS-based scroller script들은 새로운 CSS capability 들이 지원되지 않는 브라우저에 polyfill로서 존재하고 있는 상황입니다. 우리는 모바일 웹의 잠정적인 개선사항을 다루는 툴을 통해 간단하게 이 기능을 볼 수 있을 뿐입니다.


Debugging touchOverflow


일반적으로 touchOverflow 는 overflow area의 touch-scrolling을 지원하는 디바이스에서만 가능합니다. 데스크탑에서는 가능하지 않습니다. 그래서 이 touchOverflow 기능을 디버깅하는것이 어렵습니다. 이 touchOverflow 를 모둔 브라우저에서 가능하도록 하려면 아래 예제처럼 하세요.


<script>
$(document).bind("mobileinit", function() {
  $.support.touchOverflow = true;
  $.mobile.touchOverflowEnabled = true;
});
</script>



반응형

JQuery Mobile - PhoneGap apps

2012. 7. 9. 22:36 | Posted by 솔웅


반응형

Building PhoneGap apps with jQuery Mobile


폰갭(PhoneGap)은 웹 기술로 된 native application 을 개발할 수 있도록 해 주는 HTML5 app 플랫폼 입니다. 애플리케이션은 일반 HTML 페이지로 빌드 됩니다. 이것을 UIWebView나 WebView 안에 넣은 native 어플리케이션 처럼 작동시키도록 package 되는 겁니다. 폰갭은 jQuery Mobile과 잘 어울려서 많이 사용 되고 있습니다. 폰갭과 함께 사용하는데 몇가지 팁을 제공해 드리려고 합니다.


local file:// URL로 폰갭 어픞피케이션에 의해 initial application document가 로드 됩니다. 이 의미는 여러분 회사의 remote server로부터 받은 페이지를 pull in 하고 싶으시다면 그 서버의 절대 URL 경로를 넣어야 한다는 겁니다. 왜냐하면 여러분의 document는 근본적으로 file://URL 형식이고 여러분의 remote 서버로부터 페이지나 assets들을 로딩하는 것은 특정 상황에서는 block 될 수 있는 cross-domain request 이기 때문입니다.


Phone Gap jQuery Mobile 어플리케이션 안에서 cross-domain 페이지들을 접근하는 것은 두가지 중요한 기능을 controll 해야 가능합니다. $.support.cors$.mobile.allowCrossDomainPages 이 그것입니다. 이것은 추후에 폰갭이 버전업해서 기능 추가나 기능 변경이 있게 되면 영향을 받을 수 있습니다.





$.support.cors


jQuery core에는 $.support.cors boolean 이 있습니다. 이것은 cross-domain request를 위한 W3C의 Cross-Origin Resource Sharing 기능을 지원하는 브라우저인지 아닌지를 나타내는 겁니다.


jQuery Mobile은 jQuery core의 $ajax() functionality에 의존하고 있습니다. $.support.cors 는 $ajax에게 cross-domain 페이지들을 로드하라고 하기 위해 반드시 true로 세팅되어야 합니다. 블랙베리캍은 일부 플랫폼에서는 webviews가 지원되지만 $.ajax()가 cross-domain 을 할 수 없도록 $.support.cors 값이 false로 세팅되어 있는 경우가 있다는 report를 받았습니다. 이럴 경우는 페이지나 asset 들의 로딩이 fail 될 수 있습니다. $.support.cors를 true로 세팅해야 합니다.


$.mobile.buttonMarkup.hoverDelay


만약 버튼 down이나 hover 상태가 (lists,buttons,links etc) 약간 버벅거린다고 느껴지시면 $.mobile.buttonMarkup.hoverDelay 가 사용중일 가능성이 있습니다. 이렇게 되면 터치 이벤트와 관계된 클래스와의 작동 시간을 줄일 수도 있지만 동시에 그 클래스가 유저가 스크롤링할 때도 apply 될 수도 있습니다. (예. 긴 리스트의 링크가 있을 때)


$.mobile.allowCrossDomainPages


jQuery Mobile이 external page를 로드하려고 할 때 이 request는 $.mobile.loadPage()를 통해 run 됩니다. 이것은 $.mobile.allowCrossDomainPages confituration 옵션이 true로 세팅되었을 경우의 cross-domain request에서만 해당 도비니다. 왜냐하면 jQuery Mobile은 그 브라우저의 location hash내의 어떤 페이지가 view 되고 있는지를 track 하기 때문입니다. 그러면 cross-site scripting 공격이 가능할 수 있습니다. 질문 안의 XSS 코드가 hash를 조종할 수 있고 그 결과로 cross-domain URL을 세팅할 수 있기 때문입니다. 이것이 $.mobile.allowCrossDomainPages 의 디폴트 값을 false로 하는 주요 이유입니다.


그래서 폰갭 앱 에서는 원격 서버의 assets 로딩을 하게 되는 phone home 일 경우 이 $.support.cors$.mobile.allowCrossDomainPages 반드시 true로 세팅되어 있어야 합니다. $.mobile.allowCrossDomainPages 옵션은 이런 cross-domain request 가 일어나기 전에 세팅되어 있어야 합니다. 그래서 저희는 이것을 mobileinit 핸들러에 wrapping 할 것을 권장합니다.


$( document ).bind( "mobileinit", function() {
    // Make your jQuery Mobile framework configuration changes here!

    $.mobile.allowCrossDomainPages = true;
});


PhoneGap White Listing


PhoneGap 1.0은 폰갭의 internal webview가  cross-domain request를 가능하게 하는 white-listing server에 대한 아이디어를 소개했습니다. 여기에 대한 정보는 PhoneGap wiki에서 보실 수 있습니다.


모든 플랫폼에서 이 white-listing feature 를 지원하는 것은 아닙니다. 그러니까 보다 자세한 사항은 PhoneGap 문서를 확인하세요. 폰갭 1.0 이전 버전은 어떤 서버에든 cross-domain request를 허용합니다.


Still having issues?


Here are a few more tips that aren't specifically related to PhoneGap but are good to know:

아래는 직접적으로 폰갭과 관련이 있지는 않지만 알아 두시면 도움이 될 사항들입니다.


앱을 인스톨 할 때 pushState feature 를 disabling하도록 추천합니다. 왜냐하면 이 기능이 있으면 원하지 않은 곳으로 navigation 하는 행위가 일어날 수 있기 때문입니다. webview 안에 URL이 보일 필요가 없다면 이 이 기능을 계속 able 상태로 놓아 둘 필요가 없습니다.


안드로이드에서는 웹뷰에서 loading 하는 시간이 길면 강제로 timeout 하게 합니다. 그런데 그 시간이 여러분이 필요로하는 시간보다 더 짧을 수 있습니다. 이 경우 이클립스 플러그인에서 Java class 가 generated 될 때 수정해서 timeout을 바꿀 수 있습니다.


super.setIntegerProperty("loadUrlTimeoutValue", 60000);



반응형

JQuery Mobile - Scripting pages

2012. 7. 5. 00:22 | Posted by 솔웅


반응형

Scripting pages in jQuery Mobile


jQuery Mobile은 Ajax-powered navigation system을 사용하고 있어서 여러분의 content를 다루는 script를 write 할 때 알아두면 좋을 몇가지가 있습니다. 좀 더 자세한 사항은  global configuration options, events, and methods 같은 mobile API를 읽어보시던가 Ajax navigation model의 technical detail 부분을 파 보시면 도움이 될 겁니다.


Scripts & styles in the head


jQuery Mobile-driven site에서 유저가 클릭할 때 navigation system의 디폴트 behavior는 Ajax request를 formulate 하기 위해 링크의 href를 사용하는 것입니다. (request의 디폴트 link behavior인 requesting에 대한 full page load 하는 href 를 다루는 것을 하는 대신에..). 그 Ajax request가 완료되고 나면 프레임워크는 전체 text content를 받을 겁니다. 하지만 그것은 response 의 body element content 만 inject 할 겁니다. (혹은 특별한 경우 data-role="page"가 제공될 경우 그 엘리먼트를 inject 할 겁니다). 그런데 페이지의 head에는 별 특별한것이 없기 때문에 사용될게 없습니다. (페이지 타이틀 같은게 있기는 하지만 페이지에 표시할 별 다른 특별한 것은 없습니다.)  스크립트는 이런 상황에서 다이나믹하게 로드 됩니다. 이 스크립트가 일반 http request를 통해 로드된다면 로드되는 순서가 항상 같다는 보장은 없습니다. 


이 의미는 페이지의 헤드부분에 있는 어떤 스크립트나 스타일이라도 ajax를 통해서 로드되는 페이지일 때 어떤 effect도 없을거라는 겁니다. 다만 http를 통해 일반적으로 request될 때 excute 될 겁니다. jQuery Mobile 싸이트의 스크립트인 경우는 두 경우 모두를 고려해야 합니다. Ajax를 통해서 request 될 경우 head 부분이 무시될거라는 것은 이런 자바스크립트가 다시 excute 될 가능성이 아주 높다는 겁니다. (같은 스크립트를 모든 페이지에서 참조하는게 일반적인 구조이기 때문이죠.) 이것 때문에 작업하는데 좀 복잡한 점이 있기 때문에 우리는 page-specific script는 개발자에게 excuting 하는 작업을 미루고 있습니다. 그리고 head script는 브라우저 세션별로 딱 한번 execute 될 거라고 가정한 상황에서 작업을 합니다.


jQuery Mobile 싸이트로 만들 때 가장 손 쉬운 접근법은 모든 페이지의 head 부분에서 같은 스타일쉬트와 스크립트 셋트를 참조하는 것입니다. 특정 페이지에서는 특정 스크립트나 특정 스타일 쉬트를 로드해야 한다면 pageInit 이벤트에 로직을 binding 하는 방법(자세한 것은 아래에 있습니다.)을 추천합니다.  이렇게 하면 특정 페이지가 생성될 때 필요한 코드를 run할 수 있습니다. (id attribute나 다른 방법으로 determined 될수 있습니다.) 아래있는 예제는 페이지가 직접 로드되던가 Ajax를 통해 보여지고 pull in 되는 경우 code가 execute될 겁니다.


해당 페이지에만 적용되는 스크립트를 구현하기 위한 다른 접근법은 아무런 data-role=page 엘리먼트가 정의되지 않은 bodey element 의 끝에 script를 include 시키는 방법이 있을 겁니다. 만약 이 방법으로 여러분의 스크립트를 include 시킨다면 이 스크립트는 Ajax나 일반 HTTP를 통해 페이지가 로드될 때 execute 될 겁니다. 그래서 이 스크립트가 매 페이지마다 있으면 문제가 일어날 수도 있습니다. 오직 그 페이지에만 unique한 스크립트는 Ajax를 통해 fetch되는 페이지일 때 실행하도록 그 element 안에 위치시킬 수 있습니다.


pageinit = DOM ready


$(document).ready() 함수를 이용해서 DOM이 준비 되자마자 DOM-specific code를 execute 시키기는 것이 jQuery를 사용하려는 사람들이 처음 배우는 것입니다. jQuery Mobile 사이트와 앱 그리고 페이지들은 유저가 navigate 하는 것과 같은 DOM으로 request 되고 inject 됩니다. 그래서 DOM ready 이벤트를 단지 첫번째 페이지를 execute 하기위해 사용하는 것은 그다지 유용하지는 않습니다. jQuery Mobile에서 새로운 페이지가 로드되고 생성될 때마다 코드를 실행시키기위해 여러분은 pageinit 이벤트에 bind 해 주시면 됩니다.

이 pageinit 이벤트는 그것이 initialized 될 때 페이지에 trigger 됩니다. initialization 된 바로 직후에 실행되죠. 대부분의 jQuery Mobile의 공식 위벳들은 이 이벤트에 근거해서 자동적으로 initialize 됩니다. 여러분의 코드에 대해서도 같은 방식으로 적용하시면 됩니다. 


$( document ).delegate("#aboutPage", "pageinit", function() {
  alert('A page with an ID of "aboutPage" was just created by jQuery Mobile!');
}); 


만약 pageinit 이벤트가 fire 되고 위젯들이 auto-initialized 되기 전에 페이지의 content들을 다루고 싶다면 pagebeforecreate 이벤트를 바인드 하시면 됩니다.


$( document ).delegate("#aboutPage", "pagebeforecreate", function() {
alert('A page with an ID of "aboutPage" is about to be created by jQuery Mobile!'); });


Important note: pageCreate() vs pageInit()


이전의 Beta2 버전에서는 jQuery Mobile의 페이지와 child widget markup을 다루는 방법으로 권장됐던 것이 pagecreate 이벤트를 바인드 하는 것이었습니다. Beta2에서 internal change는 위벳 메소드에 direct call 하는 장소에 pagecreate를 bind 함으로서 각각의 위젯들을 decouple 하도록 만든 것이었습니다. 결과적으로 mobileinit에서 pagecreate로 유저가 바인딩하는 것은 각각의 플러그인에 의해서 enhance 돼있는 markup 이전에 바인딩을 실생시키게 됩니다. jQuery UI 위젯 Factory의 lifecycle을 유지하기위해 initialization 메소드는 create 메소드 이후에 invoke 됩니다. 그래서 pageinit 이벤트는 DOM과 자바스크립트 객체들의 post enhancement manipulation에대해 적절한 타이밍을 제공하게 되는 겁니다.  간단히 말하면 이전에 여러분이 페이지가 보여지기 이전에 enhanced markup을 다루기위해 pagecreate를 사용했다면 지금 버전에서는 대신 pageinit을 사용하면 된다는 얘기입니다.


Changing pages


현재의 active page를 바꾸기를 원하신다면 여러분은 changePage 메소드를 사용하시면 됩니다. 페이지를 바꾸기위한 방법에는 아주 많은 메소드와 프로퍼티들이 있을 수 있습니다. 그중 두가지 예제를 아래에서 다루겠습니다.


//transition to the "about us" page with a slideup transition
$.mobile.changePage( "about/us.html", { transition: "slideup"} );

//transition to the "search results" page, using data 
//from a form with an ID of "search""
$.mobile.changePage( "searchresults.php", { type: "post", data: $("form#search").serialize() });


Loading pages

외부 페이지와 그 콘텐츠 enhance를 로드하기위해 그리고 그럿을 DOM에 넣기 위해 loadPage method를 사용합니다. 페이지를 로딩할 때 여러분이 세팅할 수 있는 메소드와 프로퍼티들은 무수히 많지만 아래 간단한 한가지 예제만 보여 드리겠습니다.


//load the "about us" page into the DOM
$.mobile.loadPage( "about/us.html" );


Enhancing new markup


페이지 플로그인은 pageInit 이벤트를 dispatch 합니다. 대부분의 위젯들은 auto-initialize 하기위해 이것을 이용하죠. 위젯 플러그인 스크립트가 참조 되면 그 페이지에서 찾은 위젯들의 instance를 자동적으로 enhance 하게 됩니다.


만약 여러분이 클라이언트 사이드에서 새로운 markup을 generate 시킨다던가 Ajax를 통해서 콘텐트를 로드한다던가 그 콘텐트를 페이지에 inject 하려고 한다면 create 이벤트를 trigger 하시면 됩니다. 그러면 새로운 markup안에 있는 모든 플러그인들에 대한 auto-initialization을 처리할 수 있습니다. 이것은 어떤 엘리먼트에서도 trigger 될 수 있습니다. (page의 div에서도 가능합니다.) 그렇게 하면 매뉴얼로 각각의 플러그인(listview 버튼, select 등)을 initializing 하는 번거로움을 덜 수가 있습니다.



예를 들어 HTML markup 블럭이 Ajax를 통해서 로드됐다면 enhanced version으로 모든 위젯들을 (login form 이라면 inputs and buttons ) 자동적으로 transform 하기 위해 create 이벤트를 트리거 합니다. 예제는 아래에 있습니다.


$(...new markup that contains widgets...).appendTo(".ui-page").trigger("create");


Create vs. refresh: An important distinction


같은 위젯이 가지고 있는 create 이벤트와 refresh 메소드는 서로 다른 중요한 부분이 있습니다. create 이벤트는 한개 이상의 위젯을 가지고 있는 raw markup에 대한 enhancing에 알맞습니다. 반면에 refresh 메소드는 프로그래밍적으로 처리되고 있고 해당 UI로 update될 필요성이 있는 이미 존재하고 enhance된 위젯을 사용하기 위해 필요합니다.


예를 들어 여러분이 페이지 생성 이후에 data-role=listview 어트리뷰트로 정렬돼 있지 않은 새로운 list를 다이나믹하게 추가해야하는 페이지가 있다면 그 리스트의 parent element에 create를 트리거 함으로서 listview 스타일 위젯으로 그것을 transform 하도록 만들겁니다. 그 다음에 좀 더 많은 아이템들이 프로그램적으로 추가된다면 listview의 refresh 메소드를 부름으로서 enhanced state로 그 새로운 리스트 아이템들을 업데이트하게 되고 이미 존재하는 리스트 아이템들을 untouched로 남아있게 됩니다.


Scrolling to a position within a page


Back button behavior를 유지하기 위해 URL hash를 사용하고 난 후 그 페이지의 어떤 포지션으로 jump down 하기 위해 anchor를 사용하는것은 일반적인 anchor link(#foo)를 사용해서 할 수 없습니다. 스크롤 이벤트 리스너를 trigger 하지 않고 특정 Y 포지션으로 스크롤하기 위해 silentScroll 메소드를 사용해야 합니다. Y 위치로 yPos 인자를 pass 합니다. 아래 예제가 있습니다.


//scroll to Y 300px
$.mobile.silentScroll(300);


Binding to mouse and touch events


모바일에서 또 한가지 중요하게 생각해야 할 것은 마우스와 터치 이벤트를 처리하는 것입니다. 이 이벤트들은 모바일 플랫폼에 따라 많은 차이가 있습니다. 그 중에서도 일반적이고 공통적인것은 click 이벤트가 있다는 겁니다. 대개 500~700ms 의 지연이 있게 되죠. 이 지연은 더블 탭이나 스크롤 혹은 extended hold tap 이벤트가 일어나는지 아닌지를 브라우저가 catch 할 수 있는시간입니다. 이 지연을 피하려면 터치이벤트로 바인드 할 수가 있습니다.(ex. touchstart). 하지만 이 접근법에서 주의해야 할 점은 어떤 모바일 플랫폼에서는 (WP7, Blackberry) touch를 지원하지 않는다는 것입니다. 이 이슈를 해결하기 위해 어떤 플랫폼들은 touch와 mouse 이벤트를 동시에 일으킵니다. 그래서 이 두개 타입을 바인드 한다면 하나의 동작에 duplicate event가 발생할 겁니다. 우리의 해결법은 일반화된 마우스와 터치이벤트인 virtual events 세팅을 생성하는 것입니다.



이렇게 하면 기본적인 마우스 이벤트에 대한 리스너를 register 할 수 있도록 해 줍니다. 예를 들어 mousedown, mousemove, mouseup, click 같은 거죠. 이 플러그인은 해당 디바이스에 맞는 가능한 가장 빠른 시간에 listener가 invoke 되도록 화면 뒤에서 적절한 리스너를 register 하도록 해 줍니다. 하지만 아직까지 일반적인 마우스 이벤트에서 일어나는 이벤트들의 순서 부분이 남아있습니다. 각각 다른 이벤트들에 대해 같은 엘리먼트가 register 되도록 multiple handler가 필요하게 되는 것이죠. virtual mouse system은 jQuery bind event에 대한 다음과 같은 virtual evnet들을 발생 시킵니다. vmouseover, vmousedown, vmousemove, vmouseup, vclick, and vmousecancel.


Passing parameters between pages


jQuery Mobile은 internal/embeded 페이지로 pass 하는 query parameter를 지원하지 않습니다. 예를 들어 프레임워크가 #somePage?someId=1로 된 링크를 보면 이것을 "#somePage" 로 해석하고 somPage의 ID로 페이지 div를 navigate 학 ㅔ됩니다. 다음에 #somePage?someId=1의 data-url을 페이지 컨테이너에 적용하게 됩니다. #somePage?someId=2 같은 다른 params에 대한 이차적인 call들은 같은 div에서 찾을 겁니다. 왜냐하면 jQuery Mobile은 이미 세팅된 div의 data-url을 참조할 것이기 때문입니다.  페이지들 사이에서 query parameter가 필요하다면 이를 지원하는 두가지 plugin 이 있습니다. backbone.js나 spine.js를 사용할 수 있도록 하는 가벼운 플러그인으로는  page params plugin가 있고 좀 더 다양한 기능들이 제공 되는 플러그인으로는 jQuery Mobile router plugin 이 있습니다.


반응형


반응형

jQuery Mobile and Dynamic Page Generation


jQuery Mobile은 default click hijacking behavior나 매뉴얼로 $.mobile.changePage()를 call 하는 것을 통해 다이나믹하게 DOM으로 page이 당겨져 올 수 있도록 해 줍니다. 이것은 서버사이드에서 HTML pages/fragments 를 generate 하는데 아주 좋습니다. 하지만 가끔 JSON이나 다른 포맷으로부터 클라이언트 사이드에서 page content를 다이나믹하게 generate 할 필요가 있습니다. 아마도 네트워크 광역폭이나 퍼포먼스적인 이유로 그런 일이 필요할 겁니다. 혹은 서버와 서로 소통하기 위해 서버가 선택할 데이터 포맷일 수도 있겠죠.


클라이언트 사이드에서 page markup을 generate 할 필요가 있는 어플리케이션을 위해 $.mobile.changePage() call 하는 동안 트리거되는 notification에 대해 이해하고 있는것이 중요합니다. 왜냐하면 해당 시간에 여러분의 content를 generate 할 수 있도록  navigation system 에 hook 하는것을 가능하게 해 주기 때문입니다. changePage()를 call 하게 되면 대개 아래와 같은 event notification이 trigger 됩니다.


  • pagebeforechange
    • Fired off before any page loading or transition.
    • NOTE: This event was formerly known as "beforechangepage".
  • pagechange
    • Fired off after all page loading and transitions.
    • NOTE: this event was formerly known as "changepage".
  • pagechangefailed
    • Fired off if an error has occurred while attempting to dynamically load a new page.


이런 notification들은 페이지의 parent container element(

$.mobile.pageContainer)에서 trigger 됩니다. 그리고 document element와 window에까지 계속 떠 다니게 될 겁니다. JSON이나 in-memory JS object 같은 non HTML data를 이용해서 어플리케이션에 page를 inject 하기를 원한다던가 아니면 빠르게 현재 존재하는 페이지의 내용을 modify 하기를 원한다면 pagebeforechange event 가 아주 유용할 겁니다. pagebeforechange event는 URL이나 page element들을 analyzing 하기위해 hook 할 수 있도록 해 줍니다.  어플리케이션은 load 하거나 switch 할거냐고 질문을 받게 되고 pagebeforechange event에서 preventDefault()를 call 함으로서 default changePage() behavior가 short-circuit 할지에 대해서도 질문을 받게 됩니다.




이 기술을 이용하기 위해 working sample을 한번 살펴 보시기 바랍니다. 이 샘플에서는 유저가 navigate 할 수 있는 카테고리 리스트로 메인페이지가 시작합니다. 각 카테고리의 실제 아이템들은 메모리의 javaScript object에 저장되어 있습니다. 이 데이터들은 어떤 곳에서든지 올 수가 있습니다.


var categoryData = {
	animals: {
	  name: "Animals",
	  description: "All your favorites from aardvarks to zebras.",
		items: [
			{
				name: "Pets"
			},
			{
				name: "Farm Animals"
			},
			{
				name: "Wild Animals"
			}
		]
	},
	colors: {
		name: "Colors",
		description: "Fresh colors from the magic rainbow.",
		items: [
			{
				name: "Blue"
			},
			{
				name: "Green"
			},
			{
				name: "Orange"
			},
			{
				name: "Purple"
			},
			{
				name: "Red"
			},
			{
				name: "Yellow"
			},
			{
				name: "Violet"
			}
		]
	},
	vehicles: {
		name: "Vehicles",
		description: "Everything from cars to planes.",
		items: [
			{
				name: "Cars"
			},
			{
				name: "Planes"
			},
			{
				name: "Construction"
			}
		]
	}
};


이 어플리케이션은 어플리케이션에게 어떤 카테고리 아이템이 display 되어야 하는지를 말해주는 hash를 포함한 url이 있는 링크를 사용합니다.



 <h2>Select a Category Below:</h2>
 <ul data-role="listview" data-inset="true">
    <li><a href="#category-items?category=animals">Animals</a></li>
    <li><a href="#category-items?category=colors">Colors</a></li>
    <li><a href="#category-items?category=vehicles">Vehicles</a></li>
 </ul>


내부적으로 이 링크 중 하나를 클릭하면 어플리케이션은 internal $.mobile.changePage() call을 intercept 합니다. 이 $.mobile.changePage() 는 프레임워크의 default link hijacking behavior에 의해 invoke 된 것이죠. 그러면 이제 로드되기 위해 페이지에 대한 URL을 analyze 하게 됩니다. 그리고 나서 이것이 로딩 자체만을 위한 것인지 아니면 일반적인 changePage() 코드로 처리해야 될 것인지에 대해 판단하게 되죠.

어플리케이션은 도큐먼트 레벨에서 pagebeforechange event로 binding 됨으로서 changePage() 로 그 자체를 insert 할 수 있게 됩니다.



// Listen for any attempts to call changePage().
$(document).bind( "pagebeforechange", function( e, data ) {

// We only want to handle changePage() calls where the caller is
// asking us to load a page by URL.
	if ( typeof data.toPage === "string" ) {

// We are being asked to load a page by URL, but we only
// want to handle URLs that request the data for a specific
// category.
		var u = $.mobile.path.parseUrl( data.toPage ),
			re = /^#category-item/;

		if ( u.hash.search(re) !== -1 ) {

// We're being asked to display the items for a specific category.
// Call our internal method that builds the content for the category
// on the fly based on our in-memory category data structure.
			showCategory( u, data.options );

// Make sure to tell changePage() we've handled this call so it doesn't
// have to do anything.
			e.preventDefault();
		}
	}
});



왜 도큐먼트 레벨에서 listen할까요? 간단히 말하면 deep-linking 때문입니다. 우리는 jQuery Mobile 프레임워크가 initialize 하기전에 active 되기위해 binding이 필요합니다. 그리고 어플리케이션을 invoke 한 initial URL을 어떻게 process 할지 결정하게 됩니다. pagebeforechange binding에 대한 callback이 invoke 됐을 때 callback에 대한 두번째 argument는 initial $.mobile.changePage() call에 pass 될 argument들을 포함한 data object가 될 겁니다. 이 object의 프로퍼티들은 아래와 같습니다.
  • toPage
    • transition 될 페이지를 포함한  jQuery collection object가 될 수도 있고 로드되거나 transition 될 페이지에 대한 URL reference가 될 수 있습니다.
  • options
    • $.mobile.changePage() function 함수의 caller에 의해 pass 된 옵션들을 포함한 Object
    • 옵션의 리스트는 여기에서 찾아 보실 수 있습니다.
우리의 샘플 어플리케이션에서는 URL들이 initial 하게 pass 된 changePage() calls 에 대해서만 관심이 있습니다. 그래서 우리의 callback이 하는 첫번째 일은 toPage의 type을 체크하는 겁니다 그 다음으로는 어떤 URL parsing 유틸리티의 도움을 받아서 우리가 스스로 handling 하기위해 관심을 가지고 있는 hash를 포함한 URL인가에 대해 체크를 합니다. 만약 그렇다면 showCategory()라는 어플리케이션 함수를 call 합니다. 이 함수는 URL hash에 의해 명시된 카테고리에 대한 content를 다이나믹하게 create 할 겁니다. 그리고 이벤트에서 preventDefault()를 call 할 겁니다. pagebeforechange event에서 preventDefault()를 call 하는 것은 다른 작업 없이 exit 하기 위해 $.mobile.changePage() call 을 유발하게 됩니다. 이 이벤트에서 preventDefault() method를 call 하는 것은 changePage() request를 여러분 스스로 핸들링하게되는 jQuery Mobile과 같다고 말할 수 있습니다.


preventDefault()가 call 되지 않는다면 changePage()는 평상시에 하던대로의 작업을 계속 이어나갈 겁니다. 우리의 callback에 pass 된 data object에 대해 짚고 넘어갈 부분은 여러분이 toPage 프로퍼티나 options 프로퍼티에 어떤 change를 했던지 간에 preventDefault()가 call 되지 않으면 changePage() processing에 영향을 줄 것이라는 겁니다. 예를 들어 다른 internal/external 페이지에 특정 URL을 redirect하거나 map 하고 싶다면 우리의 callback은 그 URL이나 redirect 될 페이지의 DOM 엘리먼트로 callback에 data.toPage 프로퍼티를 set 해야 합니다. 마찬가지로 우리는 우리 callback 안의 어떤 옵션에 대한 set이나 un-set을 할 수 있습니다. 그러면 changePage()는 새로운 세팅을 사용하게 될 겁니다.


이제 우리는 어떻게 changePage() call을 intercept 하는지 알게 됐습니다 이제 이 샘플 소스가 그 페이지에 대한 markup을 실제로 어떻게 generate 하는지 자세히 살펴 보겠습니다. 우리의 샘플 소스는 각 카테고리를 display 하기 위해 같은 페이지를 사용하거나 재 사용합니다. 우리의 special link 가 클릭 될 때마다 showCategory()가 invoke 됩니다.


// Load the data for a specific category, based on
// the URL passed in. Generate markup for the items in the
// category, inject it into an embedded page, and then make
// that page the current active page.
function showCategory( urlObj, options )
{
	var categoryName = urlObj.hash.replace( /.*category=/, "" ),

// Get the object that represents the category we
// are interested in. Note, that at this point we could
// instead fire off an ajax request to fetch the data, but
// for the purposes of this sample, it's already in memory.
		category = categoryData[ categoryName ],

// The pages we use to display our content are already in
// the DOM. The id of the page we are going to write our
// content into is specified in the hash before the '?'.
		pageSelector = urlObj.hash.replace( /\?.*$/, "" );

	if ( category ) {
// Get the page we are going to dump our content into.
		var $page = $( pageSelector ),

// Get the header for the page.
		$header = $page.children( ":jqmData(role=header)" ),

// Get the content area element for the page.
		$content = $page.children( ":jqmData(role=content)" ),

// The markup we are going to inject into the content
// area of the page.
		markup = "<p>" + category.description + 
"</p><ul data-role='listview' data-inset='true'>", // The array of items for this category. cItems = category.items, // The number of items in the category. numItems = cItems.length; // Generate a list item for each item in the category // and add it to our markup. for ( var i = 0; i < numItems; i++ ) { markup += "<li>" + cItems[i].name + "</li>"; } markup += "</ul>"; // Find the h1 element in our header and inject the name of // the category into it. $header.find( "h1" ).html( category.name ); // Inject the category items markup into the content element. $content.html( markup ); // Pages are lazily enhanced. We call page() on the page // element to make sure it is always enhanced before we // attempt to enhance the listview markup we just injected. // Subsequent calls to page() are ignored since a page/widget // can only be enhanced once. $page.page(); // Enhance the listview we just injected. $content.find( ":jqmData(role=listview)" ).listview(); // We don't want the data-url of the page we just modified // to be the url that shows up in the browser's location field, // so set the dataUrl option to the URL for the category // we just loaded. options.dataUrl = urlObj.href; // Now call changePage() and tell it to switch to // the page we just modified. $.mobile.changePage( $page, options ); } }


위 샘플에는 우리가 handle 하는 URL의 해쉬는 아래 두가지 부분을 포함하고 있습니다.


#category-items?category=vehicles

? 전에 있는 첫번째 부분은 content를 write할 page의 id입니다.  ? 다음 부분은 어떤 데이터가 사용되고 언제  페이지에 대한 markup을 generate 할지에 대해 알 수 있는 정보 입니다. showCategory()가 하는 첫번째 일은 이 content 를 write 할 페이지의 id를 추출하기 위해 hash를 deconstruct(해채) 하는 겁니다. 그리고 카테고리 이름은 우리의  in-memory JavaScript category object로부터 올바른 data 세트를 찾아올 때 사용됩니다. 어떤 카테고리 데이터를 사용할 지에 대한 작업이 끝난 이후 그 카테고리에 대한 markup을 generate 합니다. 그리고 그것을 그 페이지의 header와 content 부분에 inject 합니다. 그 element에 이전에 있었던 markup들은 모두 씻겨 나갑니다.


이 markup을 inject 한 이후에 막 inject 된 markup list를 잘 사용하기 위해 적당한 jQuery Mobile widget을 call 하게 됩니다. 이 과정은 styled listview에 list markup이 적용되는 일반적인 과정입니다.


이 작업이 일단 끝나면 $.mobile.changePage()를 call 합니다. 그리고 우리가 방금 modify 한 페이지의 DOM 엘리먼트를 pass 합니다. 이 페이지가 보여지기를 원한다고 프레임워크에게 말하기 위해서죠. 이제 이 부분에서 흥미로운 부분은 jQuery Mobile은 보여지는 페이지와 연관된 URL과 함께 브라우저의 location hash를 update 한다는 겁니다. 이러한 일이 일어 날 수 있는 이유는 우리가 각 카테고리에 대해 같은 페이지를 재사용했기 때문입니다. 이것은 이상적인 상황만은 아닙니다. 왜냐하면 그 페이지에 대한 URL은 그것과 관련된 특정 category 정보를 가지고 있지 않기 때문입니다. 이 문제를 해결하기 위해서는 showCategory()가 changePage()에 pass 한 options object에 대한 dataUrl 프로퍼티를 세팅해 주는 일입니다. 우리의 오리지날 URL 대신에 이것을 display 해 달라고 얘기하기 위해서죠.


여기까지가 샘플입니다. 이 샘플이 아주 좋은 예제는 아닙니다. 특히 grade가 낮아서 JavaScript가 turn off 됐을 때에는요. 이 의미는 C-Grade 브라우저에서는 제대로 작동하지 않을 거라는 겁니다. 이렇게 낮은 grade의 브라우저에서 어떻게 제대로 동작할 수 있도록 하는지에 대해서는 나중에 글을 올릴겁니다. 업데이트 된 내용을 보시려면 여기를 참조하세요.



반응형


반응형

Data-url storage


navigation model은 모든 data-role="page" elements에서 data-url attribute를 maintain합니다. 이 data-url attribute는 page element의 근원을 track 하는데 사용됩니다. main application document에 embeded 된 페이지들은 모두 그들의 data-url 파라미터를 가지고 있습니다. 이것은 data-role="page"와 함께 그들의 ID로 세트 됩니다. 유일한 예외상황은 document의 첫번째 페이지에만 해당 됩니다 첫번째 페이지는 특별합니다. 왜냐하면 이 첫번째 페이지는 아이디를 가지고 있다면그 id로 addressed 되거나 document나 base URL (hash fragment가 없이)로 addressed 됩니다.

외부로 가는 페이지들은 ajax를 통해서 다이나믹하게 pull 됩니다. 그리고 그 data-url은 외부페이지와 연관된 경로로 세팅됩니다. 다른 도메인의 외부 페이지 로딩이 가능한 환경이라면 data-url은 absolute URL로 세팅 됩니다.



Auto-generated pages and sub-hash urls


어떤 플러그인들은 페이지 콘텐츠의 일부분을 deep link로 접근할 수 있는 별도의 navigable 페이지로 다이나믹하게 choose 하기도 합니다. 예를 들어 Listview 플러그인을 들 수 있습니다. 그것은 내부에 있는 UL (혹은 OL) 을 별도의 페이지로 분화합니다. 이것은 각각 data-url attribute 가 주어지게 되죠. 그래서 그것은 jQuery Mobile에서 다른 일반적인 페이지들처럼 링크가 걸릴 수 있습니다. 어쨌든 이 페이지들에 링크를 걸기 위해서는 첫번째로 서버로부터 request 되어야 합니다. 이렇게 하기 위해서 플러그인에 의해 자동 generate 되는 페이지들은 다음과 같은 특별한 data-url structure를 사용합니다.


<div data-url="page.html&subpageidentifier">


예를 들어 listview에 의해 generate 된 페이지는 다음과 같은 data-url을 가지게 될 겁니다.


 data-url="artists.html&ui-page=listview-1"


페이지가 request 되면은 jQuery Mobile은 ui-page에서 URL을 split 해야 된다는 것을 압니다. 그리고 그 key 전에 URL의 부분을 HTTP request 합니다. 위에 언급한 listview 예제의 경우 URL은 다음과 같을 겁니다. http://example.com/artists.html&ui-page=listview-1 ...

그리고 jQuery Mobile은 artists.html을 request 할 겁니다. 그 artists.html은 sub page들을 generate 하겠죠. data-url="artists.html&ui-page=listview-1" 와 함께 div도 생성할 겁니다. 그리고 나서 active page로 display 할 겁니다.

전체 URL path를  포함한 element의  data-url attribute 는 단지 &ui-page= 이후에 붙는 부분이라는 의미만이 아닙니다. 이로서 jQuery Mobile은  page data-url attributes와 매치되는 URL의 single consistent mechanism을 유지하게 되는 겁니다.


Cases when Ajax navigation will not be used


특정 상황에서 일반적인 http requests가 Ajax request 대신 사용될 겁니다. 이 경우는 external 웹사이트로 링크를 거는 경우에 해당 됩니다. 여러분은 다음과 같은 link attribute들을 통해 일반적인  http request를 사용하실 수 있습니다.

  • rel=external

  • target (with any value, such as "_blank")



Form submissions


Form submission도 navigation model을 통해서 자동적으로 처리 됩니다. 좀 더 자세한 정보는 forms section 를 참조하세요.


Using the Application Cache


jQuery Mobile에서 application cache를 사용할 때 고려해야할 사항이 있습니다. 어떤 브라우저에서는 cache에 request를 만들 때 성공하면 http status가 0를 report 할 겁니다. 이것은 에러 핸들러를 trigger하기 위해 jQuery Core의 $.ajax를 유발합니다. 이것을 해결하는 방법은 jQuery ajax pre-filter를 사용하는 겁니다. 아래와 같은 방식이 될 겁니다.(credit to jammus for the snippet):


$.ajaxPrefilter( function(options, originalOptions, jqXHR) {
  if ( applicationCache &&
       applicationCache.status != applicationCache.UNCACHED &&
       applicationCache.status != applicationCache.OBSOLETE ) {
       // the important bit
       options.isLocal = true;
  }
});



isLocal을 true로 해서 ajax request가 return 값이 0인 경우 다르게 처리하도록 jQuery Core에 alert 하게 합니다. Local request들은 비슷한 현상이 일어날 겁니다. (예: 0 status) 그리고 Core는 xhr responseText attribute의 content 에 근거해서 성공여부를 결정하기 위해 fall back 할 겁니다.


위와 관련해 한가지 알아두셔야할 점은  manifest 던지 아니던지 가리지 않고 ajax를 통해 만들어진 모든 request들에 대해 isLocal을 true로 세팅할 거라는 겁니다. 그렇게해서 cache가 valid 되는 겁니다. Core가 uncached result에 영향을 주지 않도록 status가 0 일 때 isLocal 값을 컨트롤하기 때문에 지금은 이렇게 작동을 합니다. 하지만 앞으로도 isLocal 이 0 status 값을 처리하기 위한 목적으로만 사용될 지는 보장할 수 없습니다. 만약 그 부분이 바뀌면 여러분의 어플리케이션은 문제를 일으킬 수 있습니다.



Known limitations


jQuery Mobile's page navigation model에 의해 생성된 non-standard environment는 페이지를 만들 때 주의해야 할 아래와 같은 상황들이 있습니다.


  • filename url 없이 디렉토리에 링크를 걸 때 (예를 들어 href="typesofcats/index.html 라고 하지 않고  href="typesofcats/라고 했을 때 ) 여러분은 반드시 trailing slash를 제공하셔야 합니다. 왜냐하면 jQuery Mobile은 url의 / 이후의 글자를 파일이름으로 생각하기 때문입니다. 그렇게 되면 / 이후의 부분은 나중에 참조할 때 사라지게 됩니다.

  • Ajax에 의해 로드된 document는 JQM 페이지 엘리먼트로서 로드 된 document의 DOM에 있는  첫번째 페이지가 select 될겁니다. 그래서 개발자는 로드된 페이지의 ID attribute와 child element를 잘 관리 해야 합니다.  그래야 DOM을 다룰 때 혼란스럽지 않습니다.

  • multipage document에 링크를 걸려면 그 링크에 반드시 data-ajax="false"를 하셔야 합니다. 이렇게 함으로서 Ajax request 에서 로드된 첫번째 페이지만 사용하는 제한을 벗어나서 full page를 사용하게 됩니다. 이 multi-page document를 로드할 수 있도록 하는 툴인 subpage plugin 이 있습니다.

  • jQuery Mobile-driven site에서 페이지에 의해 참조되는 unique assets는 page element 내부에 위치해 있어야 합니다. (page의 data-role attribute의 element). 예를 들어 별도의 페이지로 존재하는 styles와 scripts로의 링크 같은 경우 div 안에서 reference 될 수 있습니다. 어쨌든 바람직한 접근법은 특정 페이지가 로드될 때 특정 script를 실행하기 위해서 jQuery Mobile's page events를 사용하는 겁니다. NOTE : 이미 markup에서 특정된 data-url로 서버로부터 페이지를 return 받을 수 있습니다. 그리고 jQuery Mobile은 hash update를 할 겁니다. 이것은 여러분이 trailing slash로 directory path를 resolve 할 수 있도록 해 줍니다. 그래서 나중에 base url path가 사용될 수 있도록 합니다.

  • 역으로, non-unique assets (site 범위에서 사용되는)의 경우엔 HTML 도큐먼트의 <head> 섹션에서 reference 되어야 합니다. 적어도 page element의 밖에서 reference 되어야 합니다. 그래야지 그 script가 한번 이상 실행되는 것을 방지할 수 있습니다.

  • sub-hash url references에서 사용되는 "ui-page" key name은 여러분이 원하는대로 그 값을 세팅할 수 있습니다. 이 값은 jQuery.mobile.subPageUrlKey에 저장 됩니다.

  • push state plugin 이 enable 된 상태에서 내부나 외부 도큐먼트로부터 jQuery Mobile document로 back 될 때 어떤 브라우저는 잘못된 도큐먼트나 어떤 잘못된 원인이라고 해서 popstate 이벤트를 load하고 trigger 합니다. 여러분이 외부 document를 계속 링크를 걸어야 한다면 이 pushstate support를 disable 시키실 필요가 있습니다.

  • jQuery Mobile은 query parameter를 internal/embedded 페이지로 passing 하는 것을 지원하지 않습니다. 하지만 이 기능을 지원하도록 하는 두개의 플러그인이 있습니다. 가벼운 플러그인으로는 page params plugin이 있고 여러 기능을 제공하는 것으로는 jQuery Mobile router plugin이 있습니다. (이것은 backbone.js나 spine.js를 사용할 수 있도록 합니다.)

  • Back button behavior를 방지하기 위해 URL hash를 사용할 때 traditional anchor link(#foo)를 사용하는 것이 지원되지 않는 페이지를 jump down 하기 위해 page anchor를 사용합니다. scroll eventlistener trigger 하지 않고 특정 Y position을 scroll 하는 방법으로 silentScroll를 사용하는 방법이 있습니다.  yPos argument를 pass해서 그 Y location으로 scroll 할 수 있습니다.


반응형


반응형

jQuery Mobile's navigation model


jQuery Mobile 에서 page는 data-role 어트리뷰트를 page로 세팅한 엘리먼트(대개 div)로 구성됩니다. header,content,footer라는 role과 함께 div 엘리먼트를 주로 사용하게 되는데 일반적인 마크업이나 form 그리고 jQuery Mobile 위젯들을 포함하고 있습니다.


page 로딩의 기본적인 흐름은 아래와 같습니다.
첫째로 페이지는 일반적인 HTTP request 로 request 됩니다. 그리고 나서 그 다음 page들이 request 되고 page의 DOM으로 inject 됩니다. 그래서 DOM은 한번에 그 안에 여러개의 page들을 가지고 있게 됩니다. 그 페이지들은 data-url 어트리뷰트의 링크를 통해 re-visited 될 수 있습니다.


url이 initially request 됐을 때 그 response로 한개 이상의 page들이 있을 겁니다. 그 중에서 가장 첫번째 page가 보여집니다. 한개 이상의 페이지를 저장하는 것의 장점은 다시 방문할 가능성이 있는 page들에 대해 pre-fetch 할 수 있다는 것입니다.





Hash and Ajax driven page navigation


디폴트로 jQuery Mobile의 모든 navigation은 location.hash를 바꾸고 업데이트 하는 방법을 사용합니다. page change는 현재의 page와 다음 page 간의 부드러운 화면 전환을 할 수 있도록 해 줍니다. 그것이 DOM에 있는 페이지 이든 아니든 Ajax를 통해서 자동적으로 로드 됩니다.


jQuery Mobile에 의해 생성된 해쉬값들은 로드된 첫번째 실제 페이지의 URL과 연관된 full path를 사용합니다. 해쉬는 언제나 valid URL로서 유지가 됩니다. 그래서 jQuery Mobile의 어떤 페이지라도 즐겨찾기를 하거나 link로 연결할 수 있습니다. non-hash-based URL을 retrieve 하려면 간단하게 그 주세에서 #를 없애고 page를 refresh 하면 됩니다.


일반적으로 hash changes는 jQuery mobile에서 링크가 클릭 됐을 때마다 생성됩니다. 링크가 클릭되면 jQuery mobile은 그 링크가 local URL을 참조하고 있다는 것을 확인하고 만약 그렇다면 링크의 디폴트 click behavior를 Ajax를 통해서 url이 참조되도록하는 request나 상황이 일어나지 않도록 방지하게 도비니다 . 페이지가 성공적으로 return 되면 새 페이지의 relative url로 location.hash가 새로 세팅될겁니다.


click이외에 독립적으로 hash changes가 일어나는 경우, 예를 들어 유저가 back 버튼을 클릭했을 때라던지 할 때는 hashchange event에 의해 처리 됩니다. 이것은 Ben Alman의 hashchange special event plugin (jQuery Mobile에 include 돼 있음)를 사용해서 window object를 bound 합니다. hash change 가 일어나면 (혹은 첫번째 페이지가 로드될 때) hashchange event handler는 location.hase를 $.mobile.changePage() function으로 전달할 겁니다. $.mobile.changePage() function는 참조페이지를 로드하던가 reveal 하게 됩니다.


한번 그 참조 페이지가 DOM에 탑재되게 되면 $.mobile.changePage() function은 현재 active page와 새로운 페이지 사이에서 화면전환을 적용시키게 됩니다. Page transition은 CSS 애니메이션을 추가하거나 remove 함으로서 작동시키게 됩니다. 예를 들어 slide-left transition은 현재 페이지에는 "slideleft" 클래스를 적용하게 되고 그 다음에 "out" 하게 됩니다. 그리고 새로오는 페이지에는 slideleft 와 in 클래스가 적용 됩니다. 그리고 ui-page-active 도 새로 적용되서 새로운 페이지가 보여지도록 mark를 합니다. 이 애니메이션이 완료되면 in 과 out 클래스들은 remove 됩니다. 그리고 원래 있던 페이지는 ui-page-active 를 잃게 됩니다.


pushState plugin


이것은 옵션 기능인데요, 조금 전에 언급했던 hash-based URL 보다 긴 full document path를 다루고 URL structure에 Ajax tracking transparent를 만듭니다. 이것은 Ajax 링크에 대한 hash-based URL system 의 top에서 좀 더 enhance 된 기능을 제공하려고 만들어 졌습니다. 이름은 이렇지만 이 기능은 현재 버전에서는 기술적으로 history.replaceState (not history.pushState)을 사용해서 hash-based urls을 convert 한다는 것을 유념해 두세요. history.replaceState 를 지원하지 않는 브라우저나 이 기능이 가능하지 않은 경우에는 hash-based URL이 대신 사용될 겁니다.


DOM이 full 로드 됐을 때 플러그인이 initialize 되면 글로벌 configuration option$.mobile.pushStateEnabled 를 document가 준비되기 전에 언제든지 false로 세팅함으로서 이것을 enable 시키거나 disable 시킬 수 있습니다.



Important: rel="external" and $.mobile.ajaxEnabled=false


다양한 브라우저에서 replaceState API의 약간 다른 implementation은 특정 상황에서 이상하게 동작할 수도 있습니다. 예를 들어 어떤 브라우저(데스크탑 브라우저도 포함해서)의 implementation은 외부 링크일 경우나 링크가 이미 pushed/replaced 상태인 페이지로 move back 할 경우  popstate event 가 다르게 implement 됩니다. ajax navigation이 명시적으로 disable 된 jQuery Mobile 어플리케이션이 빌드 될 때 pushState feature 를 disable 시키라고 권고 합니다. 이는 hash based navigation의 좀 더 나은 consistent를 유지할 수 있도록 하기 위해서 입니다. - ajax navigation은 링크에 rel="external" 을 사용해서 disable 시킬수도 있고 $.mobile.ajaxEnabled=false 를 통해서 Ajax navigation을 완전히 disable 시킬 수도 있습니다. -



changePage


프레임워크에서 page changes는 - 페이지가 DOM에 이미 있던지 Ajax를 통해서 로드될 필요가 있던지 - $.mobile.changePage() 함수를 사용합니다. $.mobile.changePage() 에는 페이지를 transition 하는데 필요한 모든 로직이 있습니다. 그리고 page not found 같은 다양한 response 상태에 대해 어떻게 handle 할지에 대해서도 포함하고 있습니다.


$.mobile.changePage()는 externally call 될 수 있고 다음과 같은 argument들을 받을 수 있습니다. (to, transition, back, changeHash). to argument는 스트링(file url, local emdment의 ID 등), 배열(배열의 첫번째 아이템은 화면 전환할 from 페이지이고 두번째 아이템은 to 페이지 임) 혹은 객체(with expected properties: url, type ("get" or "post"), and data (for serialized parameters))를 받을 수 있습니다. 후자의 것은 form data이 경우에 유용하게 페이지를 로딩할 수 있습니다. transition argument는 slide 같이 transition 이름을 스트링으로 받습니다. 그리고 back argument는 transition이 순방향으로 진행할지 역방향으로 진행할지를 boolean을 통해서 지정할 수 있습니다. 마지막으로 changHash argument는 url이 성공적으로 페이지가 변환 된것에 따라 update 할지 여부에 대해 boolean을 사용해서 정합니다.


$.mobile.changePage() function은 jQuery Mobile에서 아주 많이 사용됩니다. 예를 들어 링크가 클릭 됐을 때 그것의 href attribute가 normalize 되고 나서 $.mobile.changePage() 이 나머지를 처리합니다. form 이 submit 됐을 때는 jQury Mobile은 아누 간단하게 몇개의 form의 attribute를 수집합니다. 그리고 그것을 serialize 하고 다시한번 $.mobile.changePage()이 submission과 response를 처리합니다. 또한 dialog를 생성하는 링크도 $.mobile.changePage() 를 사용해서 해당 페이지를 hash에 대한 update 없이 open 합니다. 이것은 history tracking 할 때 dialog를 제외시키는데 유용하게 사용됩니다.


Base element

jQuery Mobile's page navigation model의 또 다른 key point는 base element 입니다. 이것은 head에 삽입되고 모든 page change할 때 modify 됩니다. 이것의 역할은 모든 assets(이미지, CSS, JS 등) 이 정확한 경로를 통해 request 될 것인지에 대한 page 참조를 담당합니다. base emement에 대한 다이나믹 업데이트를 지원하지 않는 브라우저에서는 (파이어폭스 3.6 등) jQury Mobile은 base path를 기반으로 페이지와 prefix된 그들의 href 그리고 src sttribute 등의 assets를 참조해서 루프를 돕니다.


Developer explanation of base url management:

 jQuery Mobile은 generate된 절대 URL 경로와 generate된 <base> element의 href attribute 의 조합을 사용해서 http request를 관리합니다. 이 두 개의 조합은 로드되는 페이지의 full path를 포함하는 URL을 생성할 수 있도록 해 줍니다. base element는 이 로드된 페이지들에 의해 정확한 direct asset request를 만듭니다.


TODO: internal base와 urlHistory object의 decriptiond을 update 하세요.



반응형


반응형

회사에서 해야할 Kurogo 관련 일을 이제 거의 끝마쳤습니다.

JQuery Mobile 쪽을 너무 오래 다루지 않은 것 같아서 지난번 글에 이어서 계속 Tutorial을 정리하겠습니다.


Prefetching pages

여러분 앱의 페이지들을 하나의 큰 템플릿에 보관하는 것 보다 조그만 여러개의 페이지 템플릿(single-page templates)으로 나눠서 보관하는게 더 좋은 생각입니다. 그렇게 하면 페이지의 DOM size를 줄일 수 있습니다.

single-page templates를 사용할 때 DOM에 대해 prefetch pages를 사용하실 수 있습니다. 그러면 유저기 그 페이지를 방문할 때 즉시 서비스를 할 수 있습니다. 페이지를 prefetch 하기 위해서는 link에 data-prefetch 속성을 추가하면 됩니다. JQuery Mobile은 그러면 primary page가 로드된 다음에  target 페이지를 background에서 로드합니다. 그리고 pagecreate event가 trigger 됩니다. 아래 예제가 있습니다.

<a href="prefetchThisPage.html" data-prefetch> ... </a>

여러분이 원하시면 원하시는 대로 linked page에 prefetch를 설정할 수 있습니다. 단지 링크에 data-prefetch 만 추가하시면 됩니다.


또한 $.mobile.loadPage():를 사용해서 프로그램적으로 페이지를 prefetch 하실 수 있습니다.

$.mobile.loadPage( pageUrl, { showLoadMsg: false } );

페이지를 prefetching 하는데에는 또다른 잇점이 있습니다. 유저가 이 prefetch된 페이지를 방문할 때는 Ajax 로딩 메세지를 안 보게 될 겁니다 Ajax 로딩 메세지는 prefetching이 끝나지 않았을 때만 나타날 겁니다.

Prefetching 페이지는 자연스럽게  추가적인 HTTP request를 생성하고 bandwidth를 사용합니다. 그러니까 페이지를 prefetching 하는 것은 자주 방문되는 페이지에 한해 사용하시는 것이 좋습니다. 일반적으로 previous, next 가 많이 사용되는 Photo Gallery 같은데 사용해서 유저가 사진을 보는데 좀 더 빠르게 화면에 표시하도록 만들 필요가 있을 때 사용할 수 있을 겁니다.





DOM size management

animated 된 화면전환을 위해서 화면전환이 일어나는 두 페이지가 모두 DOM 안에 있을 필요가 있습니다. 어쨌든 DOM 에 있는 이전 페이지를 계속 가지고 있으면 브라우저의 메모리를 차지하게 될 것이고 어떤 모바일 브라우저에서는 속도가 저하되거나 crash가 일어날 수도 있을 겁니다.

jQuery Mobile은 DOM에 작게 보관할 수 있는 간단한 메카니즘을 가지고 있습니다. Ajax를 통해서 페이지를 load 할 때마다 jQuery Mobile는 그 페이지를 flag 하고 나중에 그 페이지를 떠 날 때 DOM에서 remove 할 수 있도록 합니다. (기술적으로 말하자면 pagehide event 시 이 일이 일어 납니다.) 만약 유저가 remove 된 페이지를 다시 방문하면 캐쉬에서 그 페이지의 HTML 파일을 retrieve 할 겁니다. 만약 그렇지 않으면 서버에서 refetch 하겠죠. (nested list views 인 경우에는 jQuery Mobile은 필요에 따라 더 이상 관련 없는 nested page를 remove 하게 됩니다.)

multi-page template 안에 있는 페이지들은 이 기능에 영향을 받지 않습니다. - jQuery Mobile은 Ajax 를 통해 로드된 페이지들만 remove 합니다.


Caching pages in the DOM

If you prefer, you can tell jQuery Mobile to keep previously-visited pages in the DOM instead of removing them. This lets you cache pages so that they're available instantly if the user returns to them.


원하시면 이전에 방문했던 페이지를 remove 하지 않고 DOM 에 보관하라고 jQuery Mobile에 지시할 수 있습니다. 그러면 유저가 다시 그 페이지를 방문할 때 빨리 보여줄 수 있겠죠.

To keep all previously-visited pages in the DOM, set the domCache option on the page plugin to true, like this:


방문했던 모든 페이지를 DOM에 보관하려면 domChache 옵션을 true로 세팅하면 됩니다.


$.mobile.page.prototype.options.domCache = true;

특정 페이지만 cache 하시려면 그 페이지의 콘테이너에 data-dom-cache="true" 속성을 추가하시면 됩니다.


<div data-role="page" id="cacheMe" data-dom-cache="true">

programmatically 페이지를 cache 할 수도 있습니다.

pageContainerElement.page({ domCache: true });

DOM caching의 drawback하면 DOM이 아주 크게 될 수 있습니다. 그러면 속도가 느려지거나 어떤 디바이스에서는 저장용량 문제가 발생할 수 있습니다. DOM caching 을 할 때는 이런 부분을 잘 관리하셔야 합니다. 그리고 여러 디바이스에서 충분히 테스트 해 보셔야 합니다.


반응형