31.Menu

31.1Menu 소개

Menu 컴포넌트는 다양한 정보를 가지고 있는 사이트에서 정보를 쉽게 찾아갈 수 있도록 안내를 제공하거나 문서도구에서 원하는 기능을 바로 실행할 수 있도록 기능 목록을 제공합니다. 최근에는 Menu 컴포넌트를 변형된 형태로 사용하는 경우가 많지만, 정보를 찾아가는 방식 자체는 크게 다르지 않습니다.

31.1.1사용 예

다양한 정보를 가지는 웹사이트에서 정보를 찾는 방법은 검색창을 사용하거나 메뉴를 사용하는 방식입니다. 특정 제품을 찾는 경우에는 검색창이 빠르겠지만 어떤 제품군 내 상품 목록을 보려하는 경우에는 메뉴에서 원하는 항목을 찾는 방식이 보편적입니다.

넥사크로 스튜디오에서도 원하는 기능을 처리하기 위한 방법 중 하나로 Menu 기능을 사용합니다. 넥사크로 스튜디오와 같은 저작 도구는 메뉴 외에도 단축키, 툴바, 바로가기 등을 사용해 원하는 기능을 처리할 수 있습니다.

31.1.2Menu 만들기

Menu 컴포넌트는 초기 상태에서는 아무런 동작도 하지 않습니다. Menu의 목적이 정보를 찾아가거나 특정 기능을 수행하는 것이기 때문에 어떤 작업을 처리할지 지정해주어야 합니다.

1

Menu 컴포넌트 생성하기

툴바에서 Menu 항목을 선택한 후, Form 위에 드래그 앤 드롭해 생성합니다. 빈 회색 막대가 화면에 표시됩니다.

2

innerdataset 설정하기

속성창에서 innderdataset 항목을 찾아 InnderDataset 편집창을 실행합니다. 화면에 A, B, C 3개의 메뉴 항목을 표시하고 A 항목을 선택하면 A-1, A-2 2개의 메뉴 항목이 표시되도록 하겠습니다. innderdataset 편집창을 실행하면 입력할 항목이 많은데 이 중에서 captioncolumn, levelcolumn 2개 속성값만 지정합니다.

captioncolumn 속성값은 화면에 표시되는 메뉴 항목입니다. levelcolumn 속성값이 0인 경우에는 Menu 컴포넌트가 화면에 보일 때 대메뉴로 보이는 항목입니다. levelcolumn 속성값을 1이상의 값으로 지정하면 속성값이 0인 항목을 선택했을 때 세부 메뉴 항목으로 보입니다.

Menu 컴포넌트는 메뉴 레벨 구조를 순서대로 처리하기 때문에 "A" 항목을 선택했을 때 "A-1"이 표시되도록 하려면 innerdataset 속성값에서 "A" 항목 아래 "A-1" 항목이 지정되어야 합니다.

3

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행합니다. "A" 항목을 선택하면 하위 메뉴 항목을 확인할 수 있습니다.

31.2메뉴 구성하기

Menu 컴포넌트는 정보를 좀 더 쉽고 직관적으로 찾을 수 있도록 몇 가지 추가적인 옵션을 제공합니다. 간단한 메뉴라면 captioncolumn, levelcolumn 속성값만 지정해서 기본 메뉴를 제공할 수 있습니다.

31.2.1예제

17.0.0.100 버전에서 서브 아이템 클릭 시 id 속성값을 처리하지 못하는 오류가 있어 예제가 정상적으로 동작하지 않습니다.

주류와 음료를 판매하는 쇼핑몰에서 제공하는 메뉴입니다. 사용자가 19세 미만이면 주류는 선택할 수 없고 19세 이상이면 모든 메뉴를 선택할 수 있습니다. "Age" 항목에서 나이를 선택하고 선택된 항목은 체크박스로 표시합니다.

sample_menu_01.xfdl

31.2.2예제에서 사용한 핵심 기능

innderdataset

Menu 컴포넌트에서 별도 Dataset 오브젝트를 사용하지 않고 innderdataset 편집창을 사용한다면 자동으로 컬럼항목을 생성하고 Menu 컴포넌트의 관련 속성값(captioncolumn, checkboxcolumn 등)도 지정합니다.

innerdataset을 직접 지정해 사용하는 경우에는 입력한 데이터를 스크립트에서 수정할 수 없습니다. 그래서 이번 예제에서는 같은 형식으로 Dataset 오브젝트를 만들어 사용했습니다.

this.menuOption._innerdataset 와 같은 방식으로 접근해 Dataset 오브젝트처럼 사용할 수는 있지만, 공식적으로 허용된 방식이 아니므로 이번 예제에서는 적용하지 않았습니다.

checkboxcolumn

해당 컬럼값이 true인 경우에는 메뉴 항목 앞에 체크박스를 표시합니다. 선택된 상태를 지속적으로 표기하기 위해 사용합니다. 넥사크로 스튜디오에서 메뉴[View > Toolbars] 항목을 보면 사용하는 것으로 선택한 툴바 앞에 체크박스가 표시되어 있습니다.

enablecolumn

해당 컬럼값이 false인 경우에는 메뉴 항목을 사용할 수 없습니다. 하위 메뉴가 있는 경우에도 하위 메뉴가 펼쳐지지 않고 메뉴를 선택하더라도 이벤트가 발생하지 않습니다.

idcolumn, userdatacolumn

화면에 표시되지는 않지만 부가적인 정보 제공이 필요할 때 사용합니다. onmenuclick 이벤트 발생 시 idcolumn과 userdatacolumn에 해당하는 값은 아래와 같이 확인할 수 있습니다.

this.menuOption_onmenuclick = function(obj:nexacro.Menu,e:nexacro.MenuClickEventInfo)
{
    trace(e.id); // idcolumn
    trace(e.userdata); // userdatacolumn
};
findRow

Menu 컴포넌트는 선택된 항목에 대한 Dataset 오브젝트의 Row 정보를 제공하지 않아서 컬럼값과 실제 데이터값을 가지고 해당하는 Row 정보를 찾습니다. findRow 메소드는 컬럼값, 데이터값을 가지고 Row 정보를 찾을 수 있습니다. 같은 값이 여러 개 있는 경우에는 첫 번째 값만을 반환하며 시작 인덱스값을 추가로 지정해 찾는 범위를 조정할 수 있습니다.

31.2.3예제 구현 방법

1

화면 구성하기

Menu 컴포넌트를 예제 화면과 같이 배치합니다. innerdataset 속성값을 지정하기 전에는 회색막대만 보일 겁니다.

2

Dataset 오브젝트 생성하기

툴바에서 Dataset 오브젝트를 "invisible object" 영역에 추가합니다. Dataset 오브젝트를 더블클릭하고 [Dataset Editor]에 데이터를 추가합니다. [Dataset Editor] 하단탭에서 "Source"를 선택하면 [Dataset Source Editor]가 실행되어 직접 XML 형식의 데이터를 입력할 수 있습니다.

<ColumnInfo>
  <Column id="captioncolumn" size="256"/>
  <Column id="checkboxcolumn" size="256"/>
  <Column id="enablecolumn" size="256"/>
  <Column id="idcolumn" size="256"/>
  <Column id="levelcolumn" size="256"/>
  <Column id="userdatacolumn" size="256"/>
</ColumnInfo>
<Rows>
  <Row>
    <Col id="captioncolumn">Wines</Col>
    <Col id="levelcolumn">0</Col>
    <Col id="idcolumn">A</Col>
    <Col id="userdatacolumn">19</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">White Wines</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">A-1</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Red Wines</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">A-2</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Spirits</Col>
    <Col id="levelcolumn">0</Col>
    <Col id="idcolumn">B</Col>
    <Col id="userdatacolumn">19</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Vodka</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">B-1</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Plain</Col>
    <Col id="levelcolumn">2</Col>
    <Col id="idcolumn">B-1-1</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Flavoured</Col>
    <Col id="levelcolumn">2</Col>
    <Col id="idcolumn">B-1-2</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Cognac</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">B-2</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Rum</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">B-3</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Teguila</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">B-4</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Soft Drink</Col>
    <Col id="levelcolumn">0</Col>
    <Col id="idcolumn">C</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Coke</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">C-1</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Juice</Col>
    <Col id="levelcolumn">1</Col>
    <Col id="idcolumn">C-2</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Age</Col>
    <Col id="idcolumn">D</Col>
    <Col id="levelcolumn">0</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">Under 19</Col>
    <Col id="idcolumn">D-1</Col>
    <Col id="levelcolumn">1</Col>
  </Row>
  <Row>
    <Col id="captioncolumn">19+</Col>
    <Col id="checkboxcolumn">true</Col>
    <Col id="idcolumn">D-2</Col>
    <Col id="levelcolumn">1</Col>
  </Row>
</Rows>

3

innerdataset 속성값 설정하기

생성한 Dataset 오브젝트를 innerdataset 속성값으로 지정하고 captioncolumn, checkboxcolumn, enablecolumn, idcolumn, levelcolumn, userdatacolumn 속성값을 지정합니다.

Dataset 오브젝트의 컬럼값이 Menu 컴포넌트의 속성값과 같을 필요는 없습니다. 다만 개발 편의를 위해 속성값과 컬럼값을 같게 설정했습니다. 실제 개발 단계에서는 내부 코딩 규정에 따라 항목값을 처리할 수 있습니다.

4

Menu 컴포넌트 이벤트 함수 작성하기

Menu 컴포넌트를 선택한 후 onmenuclick 이벤트 함수를 작성합니다. 이벤트 함수 내에서는 "Age" 하위 메뉴 선택에 따라 19세 미만이면 사용할 수 없는 메뉴를 설정합니다.

this.menuOption_onmenuclick = function(obj:nexacro.Menu,e:nexacro.MenuClickEventInfo)
{
    var d1ColumnRow = this.datasetMenu.findRow("idcolumn", "D-1");
    var d2ColumnRow = this.datasetMenu.findRow("idcolumn", "D-2");
    
    if(e.id == "D-1") {
        this.datasetMenu.setColumn(d1ColumnRow, "checkboxcolumn", true);
        this.datasetMenu.setColumn(d2ColumnRow, "checkboxcolumn", false);
        
        var currentAgeColumnRow = -1;
        do {
            currentAgeColumnRow++;
            currentAgeColumnRow = this.datasetMenu.findRow("userdatacolumn", "19", currentAgeColumnRow);
            this.datasetMenu.setColumn(currentAgeColumnRow, "enablecolumn", false);
        } while (currentAgeColumnRow != -1);
    } else if(e.id == "D-2") {
        this.datasetMenu.setColumn(d1ColumnRow, "checkboxcolumn", false);
        this.datasetMenu.setColumn(d2ColumnRow, "checkboxcolumn", true);
        
        var currentAgeColumnRow = -1;
        do {
            currentAgeColumnRow++;
            currentAgeColumnRow = this.datasetMenu.findRow("userdatacolumn", "19", currentAgeColumnRow);
            this.datasetMenu.setColumn(currentAgeColumnRow, "enablecolumn", true);
        } while (currentAgeColumnRow != -1);
    }
};

예제에서 "Age" 하위 메뉴 2개는 변하지 않는 항목이기 때문에 해당 항목의 Row 정보를 찾아 d1ColumnRow, d2ColumnRow 변수에 저장해놓았습니다. 그리고 조건에 따라 해당하는 Row의 checkboxcolumn 항목값을 수정하도록 했습니다.

this.datasetMenu.setColumn(d1ColumnRow, "checkboxcolumn", true);
this.datasetMenu.setColumn(d2ColumnRow, "checkboxcolumn", false);

주류 메뉴는 사용하는 데이터에 따라 늘어날 수 있으므로 userdatacolumn 항목에 "19"라는 정보를 입력하고 해당값을 가진 데이터는 모두 주류 메뉴로 처리하도록 했습니다. 그러기 위해 do~while 문을 사용했습니다. 예제에서는 2개의 메뉴를 주류 메뉴로 지정했는데 해당하는 Row 정보를 currentAgeColumnRow 라는 변수에 담아 처리합니다.

첫 번째 do~while 문이 실행되는 동안에는 아래와 같이 값이 처리됩니다. findRow 메소드는 시작 인덱스를 기준으로 지정된 컬럼값과 가장 먼저 일치하는 Row를 찾습니다. 시작 인덱스(currentAgeColumnRow)값은 0부터 시작하는데 findRow 메소드를 실행해서 0번째 인덱스에서 같은 값을 찾았기 때문에 currentAgeColumnRow은 여전히 0이 됩니다. 그리고 enablecolumn 컬럼값을 false로 업데이트합니다.

var currentAgeColumnRow = -1; // (do 구문에서 0번째 Row부터 시작하기 위해 초기값을 -1로 지정)
do {
    currentAgeColumnRow++; // 0 (이전에 찾은 값 또는 초기값 다음 Row부터 findRow 메소드를 처리하기 위해 ++ 연산자 사용)
    currentAgeColumnRow = this.datasetMenu.findRow("userdatacolumn", "19", currentAgeColumnRow); // 0 (조건에 맞는 Row 찾기)
    this.datasetMenu.setColumn(currentAgeColumnRow, "enablecolumn", false); // true (조건에 맞는 Row의 enablecolumn 값을 false로 수정)
} while (currentAgeColumnRow != -1); // true (do 구문에서 조건에 맞는 Row를 찾았다면 한 번 더 반복)

++ 연산자는 변수값을 1씩 증가시키는 연산자입니다.

예를 들어 초기값이 0인 변수 i가 있을 때 i++ 라는 연산을 실행하면 i값은 1이 됩니다.

++ 연산자는 위치에 따라 처리 방식이 달라집니다. ++ 연산자가 변수 뒤에 붙으면 변수값을 나중에 증가시키고 ++ 연산자가 변수 앞에 붙으면 변수값을 먼저 증가시킵니다. 아래 코드를 참고하세요.

// i++
var i=0;
trace(i++); //0
trace(i); //1

//++i
var i=0;
trace(++i); //1
trace(i); //1

do~while 문은 while 구문 내의 값이 false이면 반복을 멈추는데 아직 true이므로 한 번 더 반복합니다.

do {
    currentAgeColumnRow++; // 1 (이전에 찾은 값이 0이었기 때문에 ++ 연산 후 다음 Row인 1부터 시작)
    currentAgeColumnRow = this.datasetMenu.findRow("userdatacolumn", "19", currentAgeColumnRow); // 3 (Row 값이 1,2인 경우에는 userdatacolumn 값이 없고 Row 값이 3일 때 찾음)
    this.datasetMenu.setColumn(currentAgeColumnRow, "enablecolumn", false); // true
} while (currentAgeColumnRow != -1); // true

아직 while 구문의 값이 true이기 때문에 한 번 더 반복합니다. 하지만 이번에는 해당하는 값을 찾지 못하고 반복을 멈추게 됩니다. 하위메뉴의 enablecolumn 값은 변경하지 않았는데 상위메뉴의 enablecolumn 값이 false인 경우에는 하위메뉴 자체에 접근할 수 없으므로 상위메뉴만 수정했습니다.

do {
    currentAgeColumnRow++; // 4
    currentAgeColumnRow = this.datasetMenu.findRow("userdatacolumn", "19", currentAgeColumnRow); // -1 (Row 값이 4,5인 경우 userdatacolumn값을 찾지 못하고 -1을 반환)
    this.datasetMenu.setColumn(currentAgeColumnRow, "enablecolumn", false); // false
} while (currentAgeColumnRow != -1); // false (currentAgeColumnRow 값이 -1이 아니라는 조건이 성립되지 못해 반복을 멈추고 다음으로 진행)

5

QuickView로 확인하기

QuickView(Ctrl + F6)로 실행한 후 "Age" 하위 메뉴를 변경한 후 나머지 메뉴의 활성화 여부를 확인해봅니다. "Under 19" 메뉴를 선택한 경우에는 주류 관련 메뉴를 선택할 수 없습니다.