Accessibility

accessibility

What

시각 장애가 있는 사용자를 위해 화면 내용을 음성으로 들려주는 스크린 리더와의 통신을 관리하는 클래스.

Use When

웹사이트 이용에 있어 필수인 부분은 필히 Accessibility를 구현해 주어야 하지 않을까? 특히 swf로 제작되는 네비게이션의 경우에는 필수라고 생각됨.

Why

1. 법률상의 이유

2. 윤리상의 이유

3. 공공봉사의 이유

4. 상업적인 이유

5. 공익적인 이유

2008년 4월부터 실행된 장애인 차별 금지법에 의해 웹사이트가 웹접근성에 맞추어 제작되지 않을 경우 처벌함.

2013년 4월 부터는 모든 법인 웹사이트에 장애인 차별 금지법이 적용될 예정.

How

Accessibility를 위해 구현해야 하는 부분은 크게 두가지이다.

키보드만으로 서비스 이용이 가능할 것.

스크린 리더 사용자를 배려할 것.

1. 키보드 만으로 서비스 이용이 가능할 것.

DisplayObjectContainer 에서 상속된 모든 클래스에는 tabIndex 라는 public 속성이 있다.

탭키를 누르면 tabIndex값이 작은 객체부터 큰 객체까지 순서대로 포커스가 이동한다.

경험적으로 tabIndex는 하나의 클래스에서 일괄관리 하는편이 나은 듯. 예를 들면 메뉴의 데이터를 핸들링하는 클래스에서 tabIndex라는 int타입 변수를 하나 두고 메뉴를 생성할 때마다 숫자를 하나씩 올려주는 방식.

마우스의 클릭 이벤트를 받는 객체에는 필히 키보드 이벤트를 같이 걸어주고 enter 키가 눌러진 경우 클릭 이벤트를 dispatch 해주거나 클릭 이벤트와 동일한 기능을 구현해 준다.

그렇게 되면 장애가 있는 유저는 탭키로 이동하여 엔터키로 선택할 수 있다.

탭키로 메뉴를 이동하는 경우 마우스 오버 / 아웃의 경우는 구현이 곤란하게 된다. 예를 들어 마우스를 오버하면 확장되면서 하위메뉴가 나오는 네비의 경우는 구현이 고민 될 수 있다. 하지만 생각을 조금 달리 해보면 오버시 메뉴가 확장되고 하위메뉴를 바로 선택한다는 개념은 눈이 보이는 사람의 경우에는 맞지만 눈이 안보이는 사용자에게는 오히려 혼란이 될 수 있다. 탭키로 대메뉴를 이동하고 선택된 메뉴의 페이지에서만 확장해서 하위 메뉴를 보여주는 것이 맞다.

마찬가지로 혼란을 피하기 위해 선택되지 않는 하위메뉴 객체의 경우는 visible을 확실히 꺼주는게 좋다. visible을 꺼주면 tabIndex 값에 상관없이 포커스를 받지 않는다.

2. 스크린 리더 사용자를 배려할 것.

Accessibility 클래스를 사용한다.

Accessibility가 기능을 하기 전에 Flash Player에서 스크린 리더에 연결할 수 있는 1~2초간의 지연 시간이 필요하다. setTimeout 메소드를 이용해 2초의 딜레이를 준 후에 Accessibility의 active 속성을 이용해 스크린 리더가 사용가능한지 여부를 체크한다. Accessibility의 속성이나 메소드등은 정적이므로 인스턴스를 생성할 필요가 없다. Accessibility.active 속성은 스크린 리더가 사용가능할 경우에 true를 리턴한다. true가 리턴된 경우(스크린 리더 사용가능) Accessibility클래스의 updateProperties 메소드를 호출해 스크린 리더에 엑세스 가능성 변경 사항을 업데이트 해준다. updateProperties 메소드의 경우는 한번만 호출해 주면 된다. 여러번 호출하면 성능이 떨어진다고 함.

스크린 리더에 의해 읽혀질 내용을 객체의 accessibilityProperties 속성에 설정해 주어야 한다. 모든 DisplayObject 에서 상속된 클래스에는 accessibilityProperties라는 AccessibilityProperties타입의 속성이 있다. AccessibilityProperties타입의 객체를 생성한 후에 생성된 객체의 name속성에 스크린 리더에서 읽혀질 내용을 설정해 주고 스크린 리더에 의해 읽혀질 객체의 accessibilityProperties속성에 설정해 준다. 스크린 리더 프로그램을 설치, 실행한 후에 탭키를 이용해 객체에 포커스를 옮기면 스크린 리더가 설정한 name 속성의 글을 읽어주는 것을 볼 수 있다.’

참고로 무료 스크린 리더기를 찾는 것도 쉽지 않았다. (Accessibility 관련해서는 자료가 별로 없는 편인 듯) 검색창에 “소리눈”을 검색하면 관공서 게시판에 올려진 스크린 리더 프로그램(소리눈)을 받을 수 있다. 제작사 사이트는 문을 닫은 듯(?)

덧붙여- swf를 html에 붙일때 wmode param값이 transparent(배경투명)이면 스크린 리더가 작동하지 않는다. 필히 window(default)로 처리할 것.

Example

1. 메인 클래스에서

private function init():void {
    setTimeout(updateAccessibility, 2000);
}

private function updateAccessibility():void {
    if (Accessibility.active)
        Accessibility.updateProperties();
}

2. 데이터를 처리하는 클래스에서

private var _tabIndex:int;

public function getMenuDatas():Array {
    var i:int, len:int = sampleDatas.length();
    var menuData:MenuData;
    var menuDatas:Array = [];

    for (i = 0; i < len; i++) {
        menuData = new MenuData();
        menuData.name = sampleDatas[i]["@name"];
        menuData.tabIndex = _tabIndex++;
        menuDatas.push(menuData);
    }

    return menuDatas;
}

3. 실제 스크린 리더에서 읽혀질 객체의 클래스에서

private function initListener():void {
    addEventListener(KeyboardEvent.KEY_UP, onKeyUpHandler);
}

private function onKeyUpHandler(e:KeyboardEvent):void {
    switch (e.keyCode) {
        case Keyboard.ENTER:
            dispatchEvent(new MouseEvent(MouseEvent.CLICK));
        break;
    }
}

public function set menuData(value:MenuData):void {
    var accessProps:AccessibilityProperties = new AccessibilityProperties();
    accessProps.name = value.name;
    accessProps.description = value.name;
    accessibilityProperties = accessProps;

    tabIndex = value.tabIdx;
}