블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 11. 28. 09:32 HTML5, CSS3/CSS

Bootstrap은 CSS Framework으로 프리젠테이션을 담당하고 jQuery UI 와 Angular.js는 자체 컨트롤도 가지고 있지만 DOM 핸들링을 한다. 만일 서비스를 만드는데 Bootstrap + jQuery UI 조합일 때 또는 Bootstrap + Angular.js 조합일 때 그리고 Bootstrap + jQuery UI + Angular.js 조합 일때 프리젠테이션을 통합하는 방법은 어떤 것들이 있을까? 각 조합에 대해 어떻게 사용할지 알아보자.



1. Twitter Bootstrap 만 사용할 경우 

  - 부트스트랩만 놓고 보면 CSS Framework으로써 기본적인 Fluid Layout 형태와 기본 HTML 컨트롤의 모양을 정의하고 있다

    또한 JavaScript 기반 다양한 component들도 포함한다 

  - 부트스트랩의 CSS 부분을 향상시키고 extra component를 추가한 부분 변경모델은 Bootflat, Bootplus, FlatStrap, LeapStrap

  - 또는 다양한 완성체 템플릿을 startBootstrap같은 곳에서 만들어 제공도 한다 

    



2. Twitter Bootstrap + jQuery UI  함께 사용할 경우 (이제 없어졌다)

  - 문제는 여기서 부터 시작한다 

  - Bootstrap의 CSS 스타일이 존재하고 jQuery UI 도 자체 theme을 CSS로 정의하고 있다

  - Boottrap의 CSS를 jQuery UI에 접목하여 사용할 경우는 jQuery UI Widgets 에 대해서 Bootstrap theme을 입힌 것을 사용한다

    http://addyosmani.github.io/jquery-ui-bootstrap/

    



3. Twitter Bootstrap + Angular.js 함께 사용할 경우

  - Angular에 JavaScript component를 포팅하기 위하여 Directive로 감싸야하는 문제가 있다

  - jQuery UI와 Bootstrap theme을 결합하였다면 Angular.js 와 Bootstrap theme 을 결합하고 있다

  - 하지만 이것은 Bootstrap v2.3.* 버전의 component를 Angular.js Directive로 구현하는 것이다

    http://angular-ui.github.io/bootstrap/

    



4. Twitter Bootstrap + jQuery UI + Angular.js 함께 사용할 경우 

  - 해당 형태는 3번의 연장선으로 보면 된다 

  - Twitter Bootstrap의 javascript component를 Angular.js Directive화 하였듯, jQuery UI component들도 Directive화 한것이다 

    http://angular-ui.github.io/

     

   - 소스 : https://github.com/angular-ui/


기존의 JavaScript Component를 처리하려면 Directive화 과정을 거쳐야 하는데 이런 번거로운 과정을 해소하고자 Bootstrap의 JavaScript Component를 Directive로 만들어 놓은 Angular UI Bootstrap이 나왔다. jQuery UI를 지원하기 위하여 Angular UI 에 상당부분 즐겨 사용하는 JavaScript Component를 포함시켰으나 이 또한 jQuery UI의 모든 것을 커버하고 있지는 못하다. 


이래저래 문제되는 것은 Angular.js를 기반으로 개발할 때 UI를 담당하는 JavaScript Component를 Angular.js의 Directive화를 잘 해야 한다는 것이다. 



<참조>

  - Bootstrap ToolBox : 다양한 UI 컴포넌트들 

posted by 윤영식
2013. 11. 28. 07:08 My Projects/BI Dashboard

BI Dashboard 인 만큼 엑셀의 그리드 형태의 표현은 필수적이다. 오픈소스중에서 가장 많이 사용하고 있는 jqGrid를 Angular.js에 포팅하고 RESTful API를 호출하여 표현하는 방법을 알아보자.  




1. jqGrid 설치하기 

  - 최신버전 v4.5.4

  - jqGrid만을 MIT 라이센스하에서 사용을 할 수 있다. 

// bower 통하여 설치하기

$ bower install jqgrid --save


// index.html 에 설정하기

<!-- build:css(.tmp) styles/main.css -->

    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">

    <link rel="stylesheet" href="bower_components/jqgrid/css/ui.jqgrid.css">

    <link rel="stylesheet" href="styles/main.css">

<!-- endbuild -->

... 중략 ...

<!-- build:js scripts/plugins.js -->

    <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>

    <script src="bower_components/respond/respond.src.js"></script>

    <script src="bower_components/jqgrid/js/i18n/grid.locale-en.js"></script>

    <script src="bower_components/jqgrid/js/jquery.jqGrid.js"></script>

<!-- endbuild -->

  - jqgrid의 theme을 위하여 jquery-ui 의 theme을 입힌다 

// bowe 통하여 설치하기 

$ bower install jquery-ui --save


지금까지의 bower components 목록 버전 의존성

$ bower list

BIDashboard

├── angular#1.2.1 (1.2.2 available)

.. 중략 ..

│ └── angular#1.2.1

├─┬ bootstrap#3.0.2

│ └── jquery#1.9.1 (2.0.3 available)

├── console-shim#05b957a4b1

├── es5-shim#2.0.12 (latest is 2.1.0)

├── jqgrid#4.5.4

├── jquery#1.9.1 (latest is 2.0.3)

├── jquery-migrate#1.2.1

├─┬ jquery-ui#1.10.3

│ └── jquery#1.9.1 (2.0.3 available)

├── json3#3.2.5 (3.2.6 available)

├── modernizr#2.7.0

└── respond#1.3.0


// index.html 에 설정하기 

<!-- build:css(.tmp) styles/main.css -->

    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">

    <link rel="stylesheet" href="bower_components/jquery-ui/themes/smoothness/jquery-ui.css">

    <link rel="stylesheet" href="bower_components/jqgrid/css/ui.jqgrid.css">

    <link rel="stylesheet" href="styles/main.css">

<!-- endbuild -->

... 중략 ...

<!-- build:js scripts/plugins.js -->

    <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>

    <script src="bower_components/respond/respond.src.js"></script>

    <script src="bower_components/jquery-ui/ui/jquery-ui.js"></script>

    <script src="bower_components/jqgrid/js/i18n/grid.locale-en.js"></script>

    <script src="bower_components/jqgrid/js/jquery.jqGrid.js"></script>

<!-- endbuild -->



2. jqGrid 테스트 메뉴 추가하기 

  - 기존 프로그램에서 jqGrid 테스트 메뉴를 추가한다 

    + step-1 : views 폴더 밑으로 jqGridTest.html 파일 생성

    + step-2 : scripts 폴더 밑으로 biz 폴더 만들고 (여기선 sales) jqGridBiz.js 파일 생성 (화면 : 비즈니스모듈 = 1:1)

                   jqGridBiz.js 의 모듈 명칭, 컨트롤러 명칭을 정의한다 

    + step-3 : Main Application (DashboardApp.js) 안에 신규 Biz 모듈 설정 및 Routing 환경 설정

    + step-4 : index.html 안에 jqGridBiz.js 스크립트 태그 추가

    + step-5 : index.html 안의 메뉴설정에 jqGridTest.html이 보일 수 있도록 routing url 설정

// step-1

// views/jqGrid.html 파일 내역

jqGrid Test Page


// step-2

'use strict';

var RestTestBiz = angular.module('DasbhoardApp.JqGridBiz', ['DasbhoardApp.RestfulSvc']);

RestTestBiz.controller('JqGridBiz.salesCtrl', ['$scope', 'RestfulSvcApi', function ($scope, RestfulSvcApi) {


}]);


// step-3

// DashboardApp.js 변경 내역 

'use strict';

var DashboardApp = angular.module('DasbhoardApp', [

  'ngRoute',                                                  

  'ngCookies',

  'ngResource',

  'ngSanitize',

  'DasbhoardApp.CommonCtrl',

  'DasbhoardApp.RestTestBiz',

  'DasbhoardApp.JqGridBiz',

  'DasbhoardApp.RestfulSvc'

]);


DashboardApp.config(['$routeProvider', function ($routeProvider) {

    $routeProvider

      .when('/', {

        templateUrl: 'views/main.html'

      })

      .when('/resttest', {

        templateUrl: 'views/restTest.html',

        controller: 'RestTestBiz.personCtrl'

      })

      .when('/jqgridtest', {

        templateUrl: 'views/jqGridTest.html',

        controller: 'JqGridBiz.salesCtrl'

      })

      .otherwise({

        redirectTo: '/'

      });

  }]);


// step-4

// index.html 에 추가 

<!-- build:js scripts/dashboard-spa.js -->

    <script src="scripts/DashboardApp.js"></script>

    <script src="scripts/common/controllers/CommonCtrl.js"></script>

    <script src="scripts/common/services/RestfulSvc.js"></script>

    <script src="scripts/person/RestTestBiz.js"></script>

    <script src="scripts/sales/JqGridBiz.js"></script>

<!-- endbuild -->


// step-5

// index.html 의 메뉴 부분에 추가 

<ul class="nav navbar-nav">

<li data-ng-class="activeWhen(path()=='/')">

 <a href="" data-ng-click="setRoute('/')">Home</a>

</li>

<li data-ng-class="activeWhen(path()=='/resttest')">

 <a href="" data-ng-click="setRoute('/resttest')">RESTTest</a>

</li>

<li data-ng-class="activeWhen(path()=='/jqgridtest')">

 <a href="" data-ng-click="setRoute('/jqgridtest')">jqGridTest</a>

</li>

</ul>


// final

// 디렉토리 구조

// http://localhost:8080/#/jqgridtest  호출 결과 



3. jqGrid 의 Angular.js 적용전략 - Directive 만들기 

  - jqGridTest.html partial view html 안에 일반적인 jqGrid 표현 내역을 입력하면 화면에 아무것도 출력되지 않는다

    즉, jqGrid 사용하기 와 같은 <table> 태그와 <script> 태그를 jqGridTest.html 넣으면 화면출력이 되지 않는다는 것이다. 

    이는 Angular.js router를 통하여 partial html이 보여질 때 DOMP (DOM Parser)는 html만을 파싱하여 add 할 뿐이고, 

    <script> 태그는 수행되지 않기 때문이다 (참조)

  - jqGrid에 대한  Common Directive 만들기 : JqGridDrtv.js 

// Directive 모듈 JqGridDrtv.js 개발

'use strict';

var jqGridDrtv = angular.module('DashboardApp.JqGridDrtv', [ 'DasbhoardApp.RestfulSvc' ]);


/**

 * mc is Mobile Convergence of MobiConSoft

 * @use : <mc-jq-grid config="config" data="data"></mc-jq-grid>

 * config and data is used in Controller of Angular.js

 */

jqGridDrtv.directive('mcJqGrid', [ 'RestfulSvcApi', function(RestfulSvcApi) {

return {

restrict : 'E',

scope : {

config : '=',

data : '=',

},

link : function(scope, element, attrs) {

var table;

                         // config attribute 값의 변경을 체크하여 반영한다 

scope.$watch('config', function(newValue) {

element.children().empty();

table = angular.element('<table></table>');

element.append(table);

$(table).jqGrid(newValue);

});

                        // data attribute 값의 변경을 체크하여 반영한다 

scope.$watch('data', function(newValue, oldValue) {

var i;

for (i = oldValue.length - 1; i >= 0; i--) {

$(table).jqGrid('delRowData', i);

}

for (i = 0; i < newValue.length; i++) {

$(table).jqGrid('addRowData', i, newValue[i]);

}

});

}

};

} ]);

  - 메뉴에서 동작하도록 적용하기 

    + step-1 : Controller에 JqGridDrtv.js의 config, data attribute에 대한 샘플 데이터 설정을 한다 

    + step-2 : DashboardApp 안에 JqGridDrtv 모듈 의존관계를 설정한다

    + step-3 : index.html 안에 JqGridDrtv.js <script> 태그에 포함시킨다 

    + step-4 : jqGridTest.html 에 <mc-jq-grid> 태그를 포함시킨다 

// step-1 : JqGridBiz.js 에서 config, data 값 설정

'use strict';

var JqGridBiz = angular.module('DasbhoardApp.JqGridBiz', ['DasbhoardApp.RestfulSvc']);


JqGridBiz.controller('JqGridBiz.salesCtrl', ['$scope', 'RestfulSvcApi', function ($scope, RestfulSvcApi) {

$scope.config = {

  datatype: "local",

  height: 150,

    colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'],

    colModel:[

    {name:'id',index:'id', width:60, sorttype:"int"},

    {name:'invdate',index:'invdate', width:90, sorttype:"date"},

    {name:'name',index:'name', width:100},

    {name:'amount',index:'amount', width:80, align:"right",sorttype:"float"},

    {name:'tax',index:'tax', width:80, align:"right",sorttype:"float"},

    {name:'total',index:'total', width:80,align:"right",sorttype:"float"},

    {name:'note',index:'note', width:150, sortable:false}

    ],

    multiselect: true,

    caption: "Manipulating Array Data"

   };

   

$scope.data = [

{id:"1",invdate:"2007-10-01",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},

{id:"2",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},

{id:"3",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},

{id:"4",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},

];

}]);


// step-2 : DashboardApp.js에서 의존성 설정

var DashboardApp = angular.module('DasbhoardApp', [

  'ngRoute',                                                  

  'ngCookies',

  'ngResource',

  'ngSanitize',

  'DasbhoardApp.CommonCtrl',

  'DashboardApp.JqGridDrtv',

  'DasbhoardApp.RestTestBiz',

  'DasbhoardApp.JqGridBiz',

  'DasbhoardApp.RestfulSvc'

]);


// step-3 : index.html 에서 <script> 태그 추가 

<!-- build:js scripts/dashboard-4.js -->

    <script src="scripts/DashboardApp.js"></script>

    <script src="scripts/common/controllers/CommonCtrl.js"></script>

    <script src="scripts/common/directives/JqGridDrtv.js"></script>

    <script src="scripts/common/services/RestfulSvc.js"></script>

    <script src="scripts/person/RestTestBiz.js"></script>

    <script src="scripts/sales/JqGridBiz.js"></script>

<!-- endbuild -->


// step-4 : jqGridTest.html 안에 <mc-jq-grid> 태그를 넣는다 

<div id="gridtest" class="container">

<div class="row">

<div class="col-md-8 alert alert-info">

<i class="icon-hand-right"></i> This is jqGrid Directive for AngularJS

</div>

</div>

<mc-jq-grid config="config" data="data"></mc-jq-grid>

</div>


// 최종결과 

// 디렉토리 구조



4. jqGrid에 Bootstrp CSS 적용하기 

  - jqGrid는 기본적으로 jquery-ui theme을 사용한다. Bootstrap으로 기본적인 Layout과 controller를 사용하면 Grid 또한 같은 사용자 경험을 주어야  한다 

  - jqGrid에 Bootstrap과 유사한 CSS 값이 적용된 화면 참조 (소스)

  - 적용 순서

    + styles/main.css 안에 jgGrid.bootstrap.css 내역을 복사하여 넣는다

    + main.css 가 맨밑에 있으므로 jqgrid의 css를 다시 쓰는 역할이다 

<!-- build:css(.tmp) styles/main.css -->

<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">

<link rel="stylesheet" href="bower_components/jquery-ui/themes/smoothness/jquery-ui.css">

<link rel="stylesheet" href="bower_components/jqgrid/css/ui.jqgrid.css">

<link rel="stylesheet" href="styles/main.css">

<!-- endbuild -->

  - 결과 

    



* jQuery UI를 Angular.js에 적용하는 방법

  - Bootstrap 스타일의 CSS를 적용했다면 그다음은 Directive로 만든 jqGrid의 column sorting을 시도해 보자 

  - column우측을 클릭하면 contents 영역에서 "loading..." 메세지만 나오고 sorting이 되지않을 것이다. 해결해 보자 

   


  - jQuery Plugins을 Directive로 만드는 이유 (참조)

// 하기와 같은 코드가 있을 경우 controller scope에서 동작을 하지 않으며, model의 변경도 반영되지 않는다

$('.datepicker').datepicker();


// 안될 경우 Angular.js 의 Directive 생성하여 동작토록 만들어야 한다

// datepicker를 wrapping한 directive 소스 

var directives = angular.module('directives', []);

directives.directive('datepicker', function() {

   return function(scope, element, attrs) {

       element.datepicker({

           inline: true,

           dateFormat: 'dd.mm.yy',

           onSelect: function(dateText) {

               // input field의 jQuery Object

               var modelPath = $(this).attr('ng-model');

               // angular.js $parse와 동일한 역할

               // modelPath = a.b.c , scope = {}, dateText = 2013.11.27 이면 리턴값은 {a : { b : { c: '2013.11.27 }}} 됨

               putObject(modelPath, scope, dateText);  

               scope.$apply();

           }

       });

   }

});


// html 태그에서 datepicker attribute 로 사용한다 

<input type="text" datepicker ng-model="myobj.myvalue" />

  - Directive를 만들어주는 function의 파라미터 값의 의미

    + scope : controller가 관장하는 scope

    + element : jQuery object

    + attrs : 태그의 attribute 속성 key/value

  - datepicker의 callback function을 정의

    + onSelect : 사용자가 date을 선택했을 때 수행할 datepicker의 callback 이다 

    + $apply : 해당 controller scope에 변경값을 적용하기 위하여 scope.$apply를 호출해야 한다 (참조)

  - 데이터가 Object.properties 형태로 관리될 때 좀 더 우아하게 처리하는 방법은 $parse를 이용한다 (참조)

    + step-1 : 선택한 값은 controller의 scope안에 반영시키기 위하여 attrs.ngModel로 가져와서 $parse 파싱한다 

    + step-2 : 날짜의 값을 선택하여 해당 scope의 ngModel에 assign 반영한다 

myApp.directive('datepicker', function ($parse) {

    return function (scope, element, attrs, controller) {

        // step-1

        var ngModel = $parse(attrs.ngModel);

        $(function(){

            element.datepicker({

               ...

               onSelect:function (dateText, inst) {

                    scope.$apply(function(scope){

                        // step-2 Change binded variable

                        ngModel.assign(scope, dateText);

                    });

               }

            });

        });

    }

});

 

function MyCtrl($scope) {

    $scope.userInfo = {

        person: {

            mDate: '1967-10-07'

        }

    };  

 

 * 다른 jQuery UI 들의 Directive 소스

 * 소스 : https://github.com/ysyun/SPA_Angular_SpringFramework_Eclipse_ENV/tree/feature_jqgrid_angular

 


새로운 Directive IE8 에 적용하기

  - IE8에서는 새로운 directive를 만들어 element 태그로 사용할 경우 

  - IE8 이하일 경우 DOM을 만들어준다 (참조, 호환성가이드)

 <head>

    <!--[if lte IE 8]>

      <script>

        document.createElement('mc-jq-grid');

      </script>

    <![endif]-->

</head>



<참조>

  - Partial View html에서 javascript코드가 적용안되는 이유

  - jqGrid Directives 만들기

  - jqGrid에 Bootstrap CSS 적용하기

  - jQuery UI를 datepicker를 Angular.js Directive로 적용하기

  - jQuery UI를 Angular.js Directive로 만든 소스(GitHub) 

  - $parse를 이용하여 a.b.c 으로 시작하는 것을 json object 형태로 바꾸어주는 방법

posted by 윤영식
2013. 11. 27. 14:37 HTML5, CSS3/CSS

개발자들이 서비스를 만들면서 어렵게 여기는 부분이 디자인이다. 특히 웹 서비스를 만들라 치면 어디서 부터 시작해야 할지 난감할 때가 있는데 이를 해소하고자 CSS Framework를 오픈소스로 제공하는 업체들이 늘어나고 있다. 가장 유명한 Twitter Bootstrap 부터 Pure까지 그 종류도 많은데 어떤 것들이 있는지 정리해 본다. 정리하면서 느끼는 것은 Bootstrap을 확장한 framework인 Bootflat, Maxmertkit같은 것이 좀 더 다양한 느낌의 모듈을 제공하고, Metro UI스타일의 Flat 디자인을 언젠가 꼭 써보고 싶다. 그리고 GroundWork, Foundation, Pure 도 테스트해 볼 필요가 있겠다. 그외의 웹 모듈은 선택한 CSS Framework에 Add할 수 있는지 확인 후 쓰면 되겠다 



Twitter Bootstrap

  - http://getbootstrap.com/

  - CSS 화면 레이아웃과 스타일 제공

  - 화면 구성을 위한 jQuery 접목된 JavaScript 컴포넌트 제공 

  - RWD (반응형 웹디자인) 제공 : RWD 25개 도구들

  - 다양한 곳에서 많이 사용하나 개인적으로 색감이 이젠 식상할 때가 된 듯함

  - Bootstrap 확장 툴박스들 소개  그외 정리한 툴들 (강추)

  - OpenTutorial 동영상으로 배우기

  - Bootstrap v3 으로 화면 만들기

  - 다양한 도구와 컴포넌트 목록 *강추

  - BootStrap Theme 바꾸는 방법




Semantic UI

  - http://semantic-ui.com/

  - Bootstrap같은 기계적인 용어보단 인간친화적인 CSS Class 명칭

  - 좀 더 상업적인 UI 제작에 필요한 다양한 웹 모듈 제공

  - 개인적으로 인간친화적인 따뜻한 색감을 좋아함




Zurb Foundation 

  - http://foundation.zurb.com/

  - 다양한 화면 레이아웃 템플릿 제공으로 빠른 포로토타입핑 가능

  - RWD 제공

  - 웹서비스 페이지 만들기 적합




BootSnipp

  - http://bootsnipp.com/

  - Bootstrap에서 사용하는 코드 템플릿 제공

  - 다른 Template 리소스 사이트들



Start Bootstrap Template

  - http://startbootstrap.com/

  - template을 가지고 시작해 보자 

  - BootPlus에서도 제공함 

  - CodeStrap 또 다른 변형

  - http://bootswatch.com/ 에서는 다양한 Theme 색감의 bootstrap 선택가능



Bootflat

  - http://www.flathemes.com/

  - Bootstrap v3.0 확장판이다 

  - Bootstrap css 파일과 확장된 css를 링크하므로 Bootstrap에서 모자란 부분을 보완할 수 있다

  - https://wrapbootstrap.com/ 의 테마들처럼 Bootstrap 확장 느낌이 난다 



BootPlus

  - http://aozora.github.io/bootplus/

  - Bootflat과 유사한 기능을 제공

  - CSS의 느낌을 좀 더 간결하게 표현함 



FlatStrap

   

  - http://flatstrap.org/index.html

  - Bootflat과 유사함 



LeapStrap

  - http://wilkesalex.github.io/leapstrap/

  - touch smart device 고려 



FuelUX

  - http://exacttarget.github.io/fuelux/

  - Bootstrap 스타일의 다양한 컨트롤러 



PixelKit 

  

  - http://pixelkit.com/

  - 프리미엄 UI Kits 을 Theme별로 제공을 한다 

  - 예제 Sweet Candy

  - 소스 : https://github.com/Pixelkit/PixelKit-Bootstrap-UI-Kits

  - 상용이다 



Maxmertkit

  - http://www.maxmert.com/

  - Bootstrap 과 유사한 느낌을 전달 CSS class가 항시 "-" 또는 "_"로 시작하여 다른 CSS Framework와 충돌방지 

  - Bootflat에서 제공하지 않는 3D 적인 디자인과 효과 좋음 

  - Bootstrap css 파일과 혼용하여 사용할 수 있는지 체크 필요



Metro UI CSS

  - http://metroui.org.ua/

  - MS의 Metro Flat 디자인 제공

  - Bootstrap에서 느끼지 못하는 깔끔함이 있음 

  - RWD 제공




GroundWork

  - http://groundwork.sidereel.com/

  - 웹페이지, 이미지 겔러리, 커머스사이트 레이아웃 예제 제공

  - 다양한 화면사이즈에 대한 테스트 제공 (RWD)

  - 개인적으로 좋아하는 약간 따뜻한 색감 

  - 웹 모듈은 많지 않고 다른 UI 툴과 연계해서 사용하면 좋을 듯함



Pure

  - http://purecss.io/

  - Yahoo 에서 만듦

  - 사이즈 작고 flat한 디자인으로 간결한 맛이 있음 



Ink v.2

  - http://ink.sapo.pt/

  - 빠르게 웹 인터페이스를 개발할 수 있는 툴이다 

  - RWD 제공

  - Bootstrap과 거의 유사

  - Drap 컴포넌트 제공 



UIKit

  - http://getuikit.com/

  - 30가지의 UI 모듈을 제공

  - 다른 CSS Framework엔 없는 효과를 준 모듈 존재



Amazing Web Library

  - http://a-web.me/

  - UIKit과 유사하지만 차트와 그리드에 대한 부분이 강력함 




Brick

  - http://mozilla.github.io/brick/

  - 모질라에서 제공

  - 모바일에 특화된 UX적인 효과 제공

  - 모바일 예제 데모를 충실히 보여줌 



MicroJS

  - http://microjs.com/ (강추)

  - 다양한 웹 컴포넌트 검색 

  - 파일 크기 명시



<참조>

  - 원문 : 10 Free UI Kit

  - 원문 : 18개의 CSS Framework

  - 50개의 Web Developer를 위한 리소스와 툴들

  - Twitter Bootstrap v3 이해하기

  - Yahoo Pure에 대하여

  - HTML5 free Layout Template을 얻고 싶다면

  - UI Kit Maker

  - 유용한 CSS 도구들 (필독)

posted by 윤영식
2013. 11. 21. 06:08 My Projects/BI Dashboard

고객이 사용하는 브라우져중 IE는 v8이상만 지원토록 한다면, 이전의 블로그 소스는 IE8이상에서 제대로 보이지 않을 것이다. IE8 이상 및 Chrome, Safari, Firefox에 지원토록 애플리케이션 환경을 개선해 보자 (사실 IE8에서 돌아가면 다른 곳은 문제되지 않음)




1. Windows OS 에서 소스 셋업하기 

  - GitHub에서 환경파일을 클론하고 Windows 환경 설정이 없는 branch로 이동

  - npm install 수행

$ git clone git@github.com:ysyun/SPA_Angular_SpringFramework_Eclipse_ENV.git

$ git checkout feature_mybatis_mapper

$ npm install .

  - npm install 시에 imgmin 관련 오류가 발생한다. package.json과 Gruntfile.js 에서 이미지 압축설정을 제거한다 

// package.json 에서 두가지 설정 제거 (분홍색)

"grunt-contrib-imagemin": "~0.2.0",

"grunt-svgmin": "~0.2.0",


// Gruntfile.js 에서 imagemin, svgmin 관련 설정 제거 (분홍색)

imagemin: {

.. 중략 ..

},

svgmin: {

.. 중략 ..

},

.. 중략 ..

dist: [

'coffee',

'copy:styles',

'imagemin',

'svgmin',

'htmlmin'

]

  - Mysql 설치하고 사용자 생성

    + WEB-INF/spring/dbpool.properties에서 Database를 생성하고 사용자를 생성한다 

    + 테스트 person table을 만든다 

mysql> GRANT ALL 

          on <DBName>.* 

          to <UserName>@localhost 

          identified by '<Password>' with grant option;

mysql> create database <DBName>;

mysql> flush privileges;

mysql> update mysql.user set password = password('<password>') 

           where host='localhost' and user='<UserName>';

mysql> flush privileges;

mysql> \q

$ mysql -u <UserName> -p <DBName>

Enter password : *****

mysql> create table person( id int, name varchar(30));

  - eclipse에서 Maven Project로 import를 해서 Tomcat 7 버전에서 수행하여 보면 아직은 제대로 나오지 않을 것이다. 



2. jQuery 1.9.* 이상 사용할 때 ie 객체 null 에러 해결 

  - Angular.js와 함께 사용시 jQuery 버전이 1.2 이상을 경우 IE8 에서 window.ie 객체를 찾으면서 오류가 발생한다 

  - 해당 오류를 해결하기 위하여 jquery-migrate을 추가한다 (참조)

// bower를 통하여 bower_components 밑으로 설치한다

$ bower install jquery-migrate --save


// index.html 에 추가한다 

<script src="bower_components/jquery/jquery.js"></script>

<script src="bower_components/jquery-migrate/jquery-migrate.min.js"></script>

<script src="bower_components/angular/angular.js"></script>



3. CDN 문제 해결

  - jquery 또는 angular와 같이 유명한 Javascript 모듈은 Grunt 빌드할 때 구글의 CDN 쪽으로 url을 자동 변경한다. 

  - Gruntfile.js에서 CDN 관련 내역을 삭제한다 

// 분홍색 제거 

cdnify: {

  dist: {

    html: ['<%= yeoman.dist %>/*.html']

  }

},


// 분홍색 제거 

grunt.registerTask('build', [

'clean:dist',

'useminPrepare',

'concurrent:dist',

'autoprefixer',

'concat',

'copy:dist',

'cdnify',



4. Bootstrap RWD 적용 문제 해결

  - Bootstrap v3을 사용할 경우 IE8 에서 MediaQuery를 지원하지 않는 관계로 반응형 웹 디자인(RWD)이 적용되지 않는다 (참조)

  - IE8 이상에서 MediaQuery 지원을 위하여 respond.js 를 설치한다 

// bower 설치

$ bower install respond --save


// index.html 설정 : respond.js 설정은 bootstrap 밑으로 넣는다

<!-- build:js scripts/plugins.js -->

<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>

<script src="bower_components/respond/respond.src.js"></script>

<!-- endbuild -->



5. Minification 으로 인한 Angular.js 애플리케이션 파일 오류 문제 해결

  - Grunt 빌드를 통하여 main.js (controller 파일)이 minification 되면 $scope, $http등도 이름이 축약되어 IE에서 인식을 못 한다 

// index.html 원본 소스

// 하기 <!-- --> 주석처리 된것을 Grunt가 인식하여 scripts 폴더 밑으로 sciprts.js 파일명으로 minification 된다

<!-- build:js({.tmp,app}) scripts/scripts.js -->

<script src="scripts/app.js"></script>

<script src="scripts/controllers/main.js"></script>

<!-- endbuild -->


// dist/index.html 배포된 소스 

<script src="scripts/d41d8cd9.scripts.js"></script>

  - app.js 와 main.js 파일에서 $scope, $http 등과 같은 명칭이 축약되어 어떤것인지 알수 있게 배열 String(문자)로 명시해 준다 (참조)

// app.js 에서 

.config(['$routeProvider', function ($routeProvider) {

$routeProvider

  .when('/', {

    templateUrl: 'views/main.html',

    controller: 'MainCtrl'

  })

  .when('/resttest', {

    templateUrl: 'views/resttest.html',

    controller: 'RestTestCtrl'

  })

  .otherwise({

    redirectTo: '/'

  });

}]);


// main.js 에서 

angular.module('SolarDasbhoardApp')

  .controller('MenuCtrl', ['$scope', '$location', function ($scope, $location) {

    $scope.activeWhen = function (value) {

    return value ? 'active' : '';

    };


    $scope.path = function () {

        return $location.url();

    };

  }])

.. 하위도 동일 



6. HTML 검증 호환을 위해 html 태그 수정 

  - ng-* 로 되어 있는 속성을 전부 data-ng-*로 변경하여 HTML Validation 호환성을 확보한다 (참조

  - *.html 에서 data-를 전부 붙여준다 

// index.html 에서 

<body data-ng-app="SolarDasbhoardApp" data-ng-controller="MenuCtrl">


<ul class="nav navbar-nav">

<li data-ng-class="activeWhen(path()=='/')"><a href="#/">Home</a></li>

<li data-ng-class="activeWhen(path()=='/resttest')"><a href="#/resttest">RESTTest</a></li>

</ul>


<div class="container" data-ng-view=""></div>


// views/restest.html 에서 

<form accept-charset="UTF-8" data-role="form">

                    <fieldset>

      <div class="form-group">

        <input class="form-control" placeholder="ID" data-ng-model="person.id" type="text" value="99">

    </div>

    <div class="form-group">

    <input class="form-control" placeholder="Name" data-ng-model="person.name" type="text" value="dowon">

    </div>

    <input class="btn btn-lg btn-success btn-block" type="submit" value="Save" data-ng-click="save()">

    <input class="btn btn-lg btn-success btn-block" type="submit" value="Update" data-ng-click="update()">

    </fieldset>

</form>

.. 중략 ..

<tr data-ng-repeat="person in persons">

    <td>{{person.id}}</td>

    <td><a data-ng-click="delete(person.id)">{{person.name}}</a></td>

</tr>



7. IE에서 delete 예약어 문제 해결

  - IE에서 수행을 할려면 여전히 main.js 에서 오류가 있다고 나올 것이다

  - $http.delete에서 delete가 ie에서 예약어 이기 때문이다. 따라서 두군에 delete를 수정해 주어야 한다. 

// main.js 에서 

// 기존 코드 

 $scope.delete = function(id) {

    console.log('Delete Person : ', id);

        $http.delete(actionUrl + id).success(function () {

            load();

        });

    }


// 변경 코드 

 $scope.deletePerson = function(id) {

    console.log('Delete Person : ', id);

        $http['delete'](actionUrl + id).success(function () {

            load();

        });

    }


// views/resttest.html 에서 delete호출을 deletePerson 으로 변경

<td><a data-ng-click="deletePerson(person.id)">{{person.name}}</a></td>

 


8. ng-app 명명 문제 해결

  - IE8이상에서 ng-app의 위치와 선언방법을 변경한다 

// 형식

<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="optionalModuleName">


// 변경

<html class="ng-app:DasbhoardApp" id="ng-app" data-ng-app="DasbhoardApp" xmlns:ng="http://angularjs.org">


이제 Angular.js와 Bootstrap v3 을 IE8 버전 이상에서 사용해 보자 

* 소스 : https://github.com/ysyun/SPA_Angular_SpringFramework_Eclipse_ENV/tree/feature_windows_ie8



* 하루종일 삽질해서 알아낸 IE8 내용

  - 위의 소스를 IE8에서 수행하면 RestTest가 제대로 안될 것이다 (하기 내역은 feature_windows_ie8 에 첨부되지 않았음)

  - 문제 : IE 8 초기버전에서 console 객체가 undefined 라는 것 (참조)

// 이런 내용이 들어가야 한다 

/**

 * Protect window.console method calls, e.g. console is not defined on IE

 * unless dev tools are open, and IE doesn't define console.debug

 */

(function() {

  if (!window.console) {

    window.console = {};

  }

  // union of Chrome, FF, IE, and Safari console methods

  var m = [

    "log", "info", "warn", "error", "debug", "trace", "dir", "group",

    "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",

    "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"

  ];

  // define undefined methods as noops to prevent errors

  for (var i = 0; i < m.length; i++) {

    if (!window.console[m[i]]) {

      window.console[m[i]] = function() {};

    }    

  } 

})();


// bower 통하여 console-shim을 설치한다 

$ bower install console-shim --save


// index.html에 선택적으로 설정한다 

    <!--[if lt IE 9]>

      <script src="bower_components/modernizr/modernizr.js"></script>

      <script src="bower_components/es5-shim/es5-shim.js"></script>

      <script src="bower_components/json3/lib/json3.min.js"></script>

      <script src="bower_components/console-shim/console-shim.js"></script>

    <![endif]-->



<참조>

  - Angular.js 공식 IE 호환성 설정

  - IE 버전에 대한 조건부 주석처리하기

  - HTML5와 CSS3 지원을 위한 Modernizr 사용 이유


posted by 윤영식
2013. 6. 22. 12:35 Meteor

오늘은 마지막 수업날. 미티어의 개념과 아키텍쳐 그리고 실업무 프로젝트를 위한 디렉토리 구조에 대해 프로토타입핑해 보고, Twitter Bootstrap이나 Font-Awesome을 접목시켜본다.



1. 미티어 개념 핵심

  - 웹앱의 진화 개념에서 기존의 다른 프레임워크와 차이를 보인다

  - 미티어는 클라이언트와 서버사이에 스토어인 MongoDB가 존재한다

    + WebApp v1.0 : 서버단의 rendering pc 기술

    + WebApp v1.5 : client는 SPA로 진화, server+db의 통합

    + WebApp v2.0 : client <-> db + db <-> server 로 묶인다

  

  - FireBase의 서비스를 보면서 WebApp 2.0 Meteor와 맵핑이 된다 

   + How it works

  


  - 미티어는 이것이다!

    + client <-> db 사이에서 미티어가 하는 일이 핵심 개념이다. 그러나 db <-> server 까지도 통합해 놓았다

    + server는 웹서버 또는 데이터 전달의 역할을 수행한다

    + 미티어를 중심으로 MVC가 구현된다. 

       Model - DX Area (Data eXperience)

       View  - UX Area (User or UI eXperience) 

       Controller - BX Area (Business eXperience)

   

                      <KOSTA 이복영강사님이 생각하시는 미티어의 X 영역들>



2. 프로젝트 기본 구조

  - 미티어를 설치하고 간단한 myapp 을 시작해 보자

    + myapp 디렉토리를 들어가 보면 간단 3개의 파일이 존재한다 : myapp.js, myapp.css, myapp.html

    + 단 3개의 파일을 통하여 client <-> server 코딩이 완료되었다

$ meteor create myapp

myapp: created.

To run your new app:

   cd myapp

   meteor


  - myapp 프로젝트안에서 미티어가 인식하는 디렉토리 구조

    + client, server 디렉토리 밑으로 하위 디렉토리를 만들어서 프로젝트 업무 controller별, 기능별로 나눌 수 있고, 자동 인식된다

    + 각 디렉토리를 만들고 myapp을 실업무 구조로 만들어 본다

· client – 클라이언트에서 수행되는 JavaScript 와 HTML 파일

· server – 서버에서 수해되는 JavaScript 와 HTML 파일

· common – 클라이언트와 서버에서 수행되는 JavaScript 파일

· lib –  다른 모든 JavaScript 파일보다 먼저 수행 할 JavaScript 파일

· public – static application assets such as images.



3. 실업무 구조로 만들어 보기 

  - 링크 사이트의 실습을 따라해 본다

 1) client/movies.html : html 태그를 사용하지 않고 head 와 body 만 존재한다 

<head>

  <title>myapp</title>

</head>


<body>

  <h1>Movies</h1>

  {{> moviesTemplate }}

</body>  


  2) client/moviesTemplate.html 파일 생성 : movies.html안에 포함된다 

<template name="moviesTemplate">

  <ul>

    {{#each movies}}

    <li>

      {{title}}

    </li>

    {{/each}}

  </ul>

</template>


  3) client/movies.js 파일 생성 : moview 컬렉션을 글로벌로 만든다. moviesTemplate.movies 확장 메소드를 정의한다 

Movies = new Meteor.Collection("movies");

Template.moviesTemplate.movies = function () {

  return Movies.find();

};


 4) server/movies.js 파일 생성 : 데이터가 없으면 테스트용 값을 넣는다  

// Declare server Movies collection

Movies = new Meteor.Collection("movies");


// Seed the movie database with a few movies

Meteor.startup(function () {

  if (Movies.find().count() == 0) {

    Movies.insert({ title: "Star Wars", director: "Lucas" });

    Movies.insert({ title: "Memento", director: "Nolan" });

    Movies.insert({ title: "King Kong", director: "Jackson" });

  }

});


  5) client/movieForm.html 파일 생성 및 movies.html 갱신: 무비 등록

// movieForm.html

<template name="movieForm">

  <fieldset>

    <legend>Add New Movie</legend>

    <form>

      <div>

        <label>

          Title:

          <input id="title" />

        </label>

      </div>

      <div>

        <label>

          Director:

          <input id="director" />

        </label>

      </div>

      <div>

        <input type="submit" value="Add Movie" />

      </div>

    </form>

  </fieldset>

</template>


// movies.html 

  {{> moviesTemplate }}

  {{> movieForm }}  <-- 추가



  6) client/movies.js 내역을 갱신한다 : movieForm.events 헬퍼메소드를 정의한다

Template.moviesTemplate.movies = function () {

  return Movies.find();

};


// Handle movieForm events

Template.movieForm.events = {

  'submit': function (e, tmpl) {

    // Don't postback

    e.preventDefault();


    // create the new movie

    var newMovie = {

      title: tmpl.find("#title").value,

      director: tmpl.find("#director").value

    };


    // add the movie to the DB

    Movies.insert(newMovie);

  }

};


  7) 실제값을 넣어본다 : 화면이 갱신되며, MongoDB에도 데이터가 새롭게 insert된다 : meteor의 몽고 쉘로 들어가서 확인함


$ meteor mongo

MongoDB shell version: 2.4.3

connecting to: 127.0.0.1:3002/meteor

> use meteor

switched to db meteor

> show collections

movies

system.indexes

> db.movies.find()

{ "title" : "Star Wars", "director" : "Lucas", "_id" : "xmTvZ6Lv4CazosgGi" }

{ "title" : "Memento", "director" : "Nolan", "_id" : "M6jf2LgXMhsvTXboB" }

{ "title" : "King Kong", "director" : "Jackson", "_id" : "xxZ6ynrxFPwB7jCoD" }

{ "title" : "hi ", "director" : "dowon", "_id" : "Cwri8WHudNq8sMyXe" }


  8) 심화학습

  + Movies 와 동일하게 Persons를 확장해 보자

$ meteor mongo 

> db.persons.find()

{ "name" : "Yun DoWon", "phone" : "010-1004", "_id" : "7e2Buco4sREFgjDCw" }


  

  + Meteor.Collection 생성을 lib 디렉토리로 옮기게 되면 client/movies.js, server/movies.js 에서 중복 코드를 제거할 수 있다. 

       lib/collections.js 만들기 

Movies = new Meteor.Collection("movies");

Persons = new Meteor.Collection("persons");


  + movies, persons 디렉토리로 구별한다 

  



4. Twitter Bootstrap 입히기

  - http://twitter.github.io/bootstrap/ 사이트에서 파일을 다운로드 받는다

  - bootstrap.zip 파일을 client/bootstrap 디렉토리에 푼다

  - client/persons/personsTemplate.html에서 css를 적용해 본다 

// personsTemplate.html 

<template name="personsTemplate">

  <ul>

    {{#each persons}}

    <li class="btn">

      {{name}}

    </li>

    <li class="alert">

      {{phone}}

    </li>

    {{/each}}

  </ul>

</template> 


// personForm.html

 <input class="btn" type="submit" value="Add Person" />

 


  - Font Awesome css도 넣어보자. Twitter Bootstrap처럼 수동으로 설치하지 않고 meteorite를 통해 설치한다 

    + https://github.com/nate-strauser/meteor-font-awesome 해당 사이트에서 font-awesome 을 설치해야하는 함정이... ^^

    + meteorite는 node.js의 npm과 유사하게 meteor의 package 를 관리해 준다

$ npm install -g meteorite

$ mrt add font-awesome

✓ font-awesome

    tag: https://github.com/nate-strauser/meteor-font-awesome.git#v3.2.0


Done installing smart packages


// packages 디렉토리 밑으로 font-awesome이 설치되었다

// smart.json과 smart.lock 파일은 meteorite 환경파일


  -  client/personForm.html 에 아이콘을 넣는다 

<template name="personForm">

<div class="container">

  <fieldset>

    <legend>Add New Person</legend>

    <form>

      <div>

        <label>

          Name:

          <input id="name" />

        </label>

      </div>

      <div>

        <label>

          Phone:

          <input id="phone" />

        </label>

      </div>

      <div>

        <i class="icon-male"></i> <input class="btn" type="submit" value="Add Person" />

      </div>

    </form>

  </fieldset>


  <!-- test -->

  <a class="btn" href="#">

    <i class="icon-repeat"></i> Reload</a>

  <a class="btn btn-success" href="#">

    <i class="icon-shopping-cart icon-large"></i> Checkout</a>

  <a class="btn btn-large btn-primary" href="#">

    <i class="icon-comment"></i> Comment</a>

  <a class="btn btn-small btn-info" href="#">

    <i class="icon-info-sign"></i> Info</a>

  <a class="btn btn-danger" href="#">

    <i class="icon-trash icon-large"></i> Delete</a>

  <a class="btn btn-small" href="#">

    <i class="icon-cog"></i> Settings</a>

  <a class="btn btn-large btn-danger" href="#">

    <i class="icon-flag icon-2x pull-left"></i> Font Awesome<br>Version 3.2.1</a>

  <a class="btn btn-primary" href="#">

    <i class="icon-refresh icon-spin"></i> Synchronizing Content...</a>




<참조>

  - 미티어 구조 설계하기

  - 미티어 한글번역 : http://docs-ko.meteor.com/

  - 아이콘 확장은 Font Awesome을 사용한다 : http://fortawesome.github.io/Font-Awesome/

  - 심화학습 코드 : .meteor는 포함되지 않았으니 meteor create을 하고서 첨부한다

myapp.tar



posted by 윤영식
2013. 1. 24. 21:58 AngularJS/Concept

Twitter Bootstrap과 Node.js를 이용하여 Single Page App을 만들어 보자. 여기서는 Backbone.js를 배제하고 만드는 방법이다. 외국 블로깅 글을 따라서 실행보면서 정리한다. (총 3 part중 part 1)


서버단 코드 만들기


1) GitHub에서 소스 다운로드 및 사전 설정

  - 소스 다운로드 : $ git clone https://github.com/iatek/one-page-app.git

  - node.js 와 npm 이 설치되어 있어야 한다

  - Express 프레이워크 설치 : npm install express

  - ejs 템플릿 엔진 설치 : npm install ejs npm install ejs-locals

$ npm install ejs-locals

npm http GET https://registry.npmjs.org/ejs-locals

npm http 304 https://registry.npmjs.org/ejs-locals

ejs-locals@1.0.2 node_modules\ejs-locals


// ejs 설치 안하면 에러 발생함 

UserXP@NUKNALEA /d/Git_repositories/one-page-app (master)

$ node server


module.js:340

    throw err;

          ^

Error: Cannot find module 'ejs'

    at Function.Module._resolveFilename (module.js:338:15)

    at Function.Module._load (module.js:280:25)

    at Module.require (module.js:362:17)

    at require (module.js:378:17)

    at Object.<anonymous> (d:\Git_repositories\one-page-app\node_modules\ejs-locals\index.js:1:73)

    at Module._compile (module.js:449:26)

    at Object.Module._extensions..js (module.js:467:10)

    at Module.load (module.js:356:32)

    at Function.Module._load (module.js:312:12)

    at Module.require (module.js:362:17)


UserXP@NUKNALEA /d/Git_repositories/one-page-app (master)

$ npm install ejs

npm http GET https://registry.npmjs.org/ejs

npm http 304 https://registry.npmjs.org/ejs

ejs@0.8.3 node_modules\ejs


// 정상 수행됨 

UserXP@NUKNALEA /d/Git_repositories/one-page-app (master)

$ node server

Listening on port 4000 in development mode


// 로컬에서 브라우져 호출시 reponsive web으로 반응한다 -width를 줄이면 메뉴자동변경됨- (데모확인)


  


2) Express 환경파일 설정

  - app.js

app.js


// ejs template engine 사용
var express = require('express'),
	engine = require('ejs-locals'),   
	app = express();

// init export
exports.init = function(port) {
    app.locals({
		_layoutFile:'layout.ejs'
	})
	
    app.configure(function(){
    	app.set('views', __dirname + '/views');
    	app.set('view engine', 'ejs');
    	app.use(express.bodyParser());
    	app.use(express.methodOverride());
        // Static pages 서비스 
        app.use(express.static(__dirname + '/static'));
        // Session과 Cookie 관리 
        app.use(express.cookieParser());
        app.use(express.cookieSession({cookie:{path:'/',httpOnly:true,maxAge:null},secret:'skeletor'}));
    	app.use(app.router);
    	//app.enable("jsonp callback");
    });

    app.engine('ejs', engine);	
    app.configure('development', function(){
        app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
        // app.use(express.logger({ format: ':method :url' }));
    });

    app.configure('production', function(){
	   app.use(express.errorHandler()); 
    });

    app.use(function(err, req, res, next){
	   res.render('500.ejs', { locals: { error: err },status: 500 });	
    });
	
    server = app.listen(port);
    console.log("Listening on port %d in %s mode", server.address().port, app.settings.env);
    return app;
}


3) Routing 만들기 

  - server.js : app이 시작하는 초기 파일이다. app route를 정의한다

server.js


  - "app.get", "app.post", "app.del" 을 사용한다 

  - 4개의 HTTP get routing 호출  

    /(default homepage)

    /login

    /logout

    /admin

var port = process.env.PORT || 4000,
    app = require('./app').init(port),
	dirty = require('dirty');
	
var locals = {
	author:'in1'
	// add other vars here
};

var userDb = dirty('user.db');

app.get('/', function(req,res){
    locals.date = new Date().toLocaleDateString();
	
	var appDb = dirty('app.db'),
		sectionsDb;
	
	appDb.on('load', function() {
		sectionsDb = dirty('sections.db');
		sectionsDb.on('load', function() {
			/*
			sectionsDb.forEach(function(key, val) {
				console.log('Found key: %s, val: %j', key, val);
			});
			*/
			res.render('index.ejs', {locals:locals,sections:sectionsDb,app:appDb.get('app'),page:appDb.get('page')});
		});
	});
});
... 중략 ...
app.post('/contact', function(req,res){
	appDb = dirty('app.db');
	console.log('contact form submit.');
	
	appDb.on('load', function() {
		console.log('Form submitted.');
		res.send('Thank you.');
	});
});

/* The 404 Route (ALWAYS Keep this as the last route) */
app.get('/*', function(req, res){
    res.render('404.ejs', locals);
});


4) Persistence 유지 하기 

  - Node-Dirty를 이용하여 disk log형태로 가벼운 데이터베이스겸으로 사용한다

  - 5개의 database 파일안에 관련 표현할 내역이 .db파일에 들어있음 (백만 record 미만 사용하는 앱에 적당)

    app.db : 애플리케이션 래벨 설정

    sections.db : 섹션 설정과 내용 저장

    user.db : 사용자 credential 과 admin 권한

    snippet.db : 미리 생성할 섹션 내용을 위한 코드 조각 저장

    post.db : 연락처와 이메일 폼 결과 저장 

  - server.js에서 require('dirty')


> 다음은 UI Part to be continued...


<참조>

  - Single Page App with Twitter Bootstrap and Node.js : 데모사이트

  - One page app GitHub 소스

  - SPA를 위한 storage : node-dirty

  - Node.js 기초 강의 동영상

  - Node의 MVC Framework : Express.js

  - Bootstrap 확장판

posted by 윤영식
prev 1 next